Add a comment.

Naively it seemed at first like getVA had the responsibility of adding
the addend, and getSymVA had the responsibility of getting the symbol
VA.
So it was not obvious to me at first why getVA passes Addend to
getSymVA. In fact, it passes it as a mutable reference.

It turns out that it only matters for SHF_MERGE sections, and in
particular only for STT_SECTION symbols that are used as a hack for
reducing the number of local symbols (e.g. to avoid a local symbol for
each string in the string table).

llvm-svn: 296448
This commit is contained in:
Sean Silva 2017-02-28 08:32:56 +00:00
parent cc33fc8722
commit a9ba450c52
1 changed files with 11 additions and 0 deletions

View File

@ -58,10 +58,21 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body, int64_t &Addend) {
return D.Value;
uintX_t Offset = D.Value;
// An object in an SHF_MERGE section might be referenced via a
// section symbol (as a hack for reducing the number of local
// symbols).
// We must incorporate the addend into the section offset (and
// zero out the addend for later processing) so that we find the
// right object in the section.
// Note that for an ordinary symbol we do not perform this
// adjustment and thus effectively assume that the addend cannot
// cross the boundaries of mergeable objects.
if (D.isSection()) {
Offset += Addend;
Addend = 0;
}
const OutputSection *OutSec = IS->getOutputSection<ELFT>();
uintX_t VA = (OutSec ? OutSec->Addr : 0) + IS->getOffset<ELFT>(Offset);
if (D.isTls() && !Config->Relocatable) {