Skip to content

Commit e07dfa5

Browse files
committed
[MC][ELF] Improve st_size propagation rule
`.symver foo, foo@ver` creates the MCSymbolELF `foo@ver` whose almost all attributes (including st_size) should inherit from `foo` (GNU as behavior). a041ef1 added st_size propagation which works for many cases but fails for the following one: ``` .set __GLIBC_2_12_sys_errlist, _sys_errlist_internal .type __GLIBC_2_12_sys_errlist,@object .size __GLIBC_2_12_sys_errlist, 1080 .symver __GLIBC_2_12_sys_errlist, sys_errlist@GLIBC_2.12 ... _sys_errlist_internal: .size _sys_errlist_internal, 1072 ``` `sys_errlist@GLIBC_2.12`'s st_size is 1072 (incorrect), which does not match `__GLIBC_2_12_sys_errlist`'s st_size: 1080. The problem is that `Base` is (the final) `_sys_errlist_internal` while we want to respect (the intermediate) `__GLIBC_2_12_sys_errlist`'s st_size. Fix this by following the MCSymbolRefExpr assignment chain and finding the closest non-null `getSize()`, which covers most needs. Notably MCBinaryExpr is not handled, but it is rare enough to matter. Reviewed By: peter.smith Differential Revision: https://reviews.llvm.org/D123283
1 parent 67acc34 commit e07dfa5

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

llvm/lib/MC/ELFObjectWriter.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,9 +547,27 @@ void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
547547
uint64_t Size = 0;
548548

549549
const MCExpr *ESize = MSD.Symbol->getSize();
550-
if (!ESize && Base)
550+
if (!ESize && Base) {
551+
// For expressions like .set y, x+1, if y's size is unset, inherit from x.
551552
ESize = Base->getSize();
552553

554+
// For `.size x, 2; y = x; .size y, 1; z = y; z1 = z; .symver y, y@v1`, z,
555+
// z1, and y@v1's st_size equals y's. However, `Base` is `x` which will give
556+
// us 2. Follow the MCSymbolRefExpr assignment chain, which covers most
557+
// needs. MCBinaryExpr is not handled.
558+
const MCSymbolELF *Sym = &Symbol;
559+
while (Sym->isVariable()) {
560+
if (auto *Expr =
561+
dyn_cast<MCSymbolRefExpr>(Sym->getVariableValue(false))) {
562+
Sym = cast<MCSymbolELF>(&Expr->getSymbol());
563+
if (!Sym->getSize())
564+
continue;
565+
ESize = Sym->getSize();
566+
}
567+
break;
568+
}
569+
}
570+
553571
if (ESize) {
554572
int64_t Res;
555573
if (!ESize->evaluateKnownAbsolute(Res, Layout))

llvm/test/MC/ELF/offset.s

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
# CHECK-NEXT: 000000000000000d 42 OBJECT GLOBAL DEFAULT [[#A]] d1
1515
# CHECK-NEXT: 000000000000000d 42 OBJECT GLOBAL DEFAULT [[#A]] d2
1616
# CHECK-NEXT: 0000000000000001 41 OBJECT GLOBAL DEFAULT [[#A]] e
17-
# CHECK-NEXT: 0000000000000001 42 OBJECT GLOBAL DEFAULT [[#A]] e1
18-
# CHECK-NEXT: 0000000000000001 42 OBJECT GLOBAL DEFAULT [[#A]] e2
17+
# CHECK-NEXT: 0000000000000001 41 OBJECT GLOBAL DEFAULT [[#A]] e1
18+
# CHECK-NEXT: 0000000000000001 41 OBJECT GLOBAL DEFAULT [[#A]] e2
1919
# CHECK-NEXT: 0000000000000002 42 OBJECT GLOBAL DEFAULT [[#A]] e3
2020
# CHECK-NEXT: 0000000000000005 0 NOTYPE GLOBAL DEFAULT [[#A]] test2_a
2121
# CHECK-NEXT: 0000000000000005 0 NOTYPE GLOBAL DEFAULT [[#A]] test2_b
2222
# CHECK-NEXT: 0000000000000009 0 NOTYPE GLOBAL DEFAULT [[#A]] test2_c
2323
# CHECK-NEXT: 0000000000000009 0 NOTYPE GLOBAL DEFAULT [[#A]] test2_d
2424
# CHECK-NEXT: 0000000000000004 0 NOTYPE GLOBAL DEFAULT ABS test2_e
25-
# CHECK-NEXT: 0000000000000001 42 OBJECT GLOBAL DEFAULT [[#A]] e@v1
25+
# CHECK-NEXT: 0000000000000001 41 OBJECT GLOBAL DEFAULT [[#A]] e@v1
2626

2727

2828
.data
@@ -45,7 +45,8 @@ d2 = d1
4545

4646
e = a + (1 - 1)
4747
.size e, 41
48-
## FIXME These st_size fields inherit from e instead of a.
48+
## These st_size fields inherit from e instead of a.
49+
## TODO e3's st_size should inherit from e.
4950
.set e1, e
5051
.set e2, e1
5152
e3 = e1 + 1

0 commit comments

Comments
 (0)