diff options
Diffstat (limited to 'llvm/lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | llvm/lib/MC/ELFObjectWriter.cpp | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index fe11768..08d1b12 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -547,9 +547,27 @@ void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex, 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; z1 = z; .symver y, y@v1`, z, + // z1, and y@v1's st_size equals y's. However, `Base` is `x` which will give + // us 2. Follow the MCSymbolRefExpr assignment chain, which covers most + // needs. MCBinaryExpr is not handled. + const MCSymbolELF *Sym = &Symbol; + while (Sym->isVariable()) { + if (auto *Expr = + dyn_cast<MCSymbolRefExpr>(Sym->getVariableValue(false))) { + Sym = cast<MCSymbolELF>(&Expr->getSymbol()); + if (!Sym->getSize()) + continue; + ESize = Sym->getSize(); + } + break; + } + } + if (ESize) { int64_t Res; if (!ESize->evaluateKnownAbsolute(Res, Layout)) |