diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -547,9 +547,19 @@ uint64_t Size = 0; const MCExpr *ESize = MSD.Symbol->getSize(); - if (!ESize && Base) + if (!ESize && Base) { + // For expressions like .set y, x+1, if y's size is unset, inherit from x. ESize = Base->getSize(); + // For `.size x, 2; y = x; .size y, 1; z = y; .symver y, y@v1`, z and y@v1's + // st_size equals y's. However, `Base` is `x` which will give us 2. Just + // detect the SymbolRef case which cover most needs. We'd still get wrong + // st_size for `z1 = z` but such chained assignments are rare. + if (Symbol.isVariable()) + if (auto *Sym = dyn_cast(Symbol.getVariableValue(false))) + ESize = cast(Sym->getSymbol()).getSize(); + } + if (ESize) { int64_t Res; if (!ESize->evaluateKnownAbsolute(Res, Layout)) diff --git a/llvm/test/MC/ELF/offset.s b/llvm/test/MC/ELF/offset.s --- a/llvm/test/MC/ELF/offset.s +++ b/llvm/test/MC/ELF/offset.s @@ -2,12 +2,13 @@ // Test that a variable declared with "var = other_var + cst" is in the same // section as other_var and its value is the value of other_var + cst. +// In addition, its st_size inherits from other_var. .data .globl sym_a - .size sym_a, 42 .byte 42 .type sym_a, @object + .size sym_a, 42 sym_a: // CHECK: Symbol { @@ -62,16 +63,42 @@ .globl sym_f sym_f = sym_a + (1 - 1) +.size sym_f, 41 // CHECK: Symbol { // CHECK: Name: sym_f // CHECK-NEXT: Value: 0x1 -// CHECK-NEXT: Size: 42 +// CHECK-NEXT: Size: 41 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object // CHECK-NEXT: Other: 0 // CHECK-NEXT: Section: .data // CHECK-NEXT: } +/// sym_g's st_size equals sym_f's st_size instead of sym_a's. +.globl sym_g +.set sym_g, sym_f +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym_g +// CHECK-NEXT: Value: 0x1 +// CHECK-NEXT: Size: 41 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: Object +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .data +// CHECK-NEXT: } + +/// FIXME sym_g's st_size should be 41. This long chained assignments are uncommon. +.globl sym_h +.set sym_h, sym_g +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym_h +// CHECK-NEXT: Value: 0x1 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: Object +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .data +// CHECK-NEXT: } .globl test2_a .globl test2_b @@ -85,6 +112,10 @@ .long 0 test2_d = test2_c test2_e = test2_d - test2_b + +/// sym_f@v1's st_size equals sym_f's st_size. +.symver sym_f, sym_f@v1 + // CHECK: Symbol { // CHECK: Name: test2_a // CHECK-NEXT: Value: 0x5 @@ -130,3 +161,12 @@ // CHECK-NEXT: Other: 0 // CHECK-NEXT: Section: Absolute // CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: sym_f@v1 +// CHECK-NEXT: Value: 0x1 +// CHECK-NEXT: Size: 41 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: Object +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .data +// CHECK-NEXT: }