[lld] r292910 - [ELF] Correct sh_info for static symbol table
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 24 12:08:57 PST 2017
Looks like the cleanest (no conflict) way to backport this is to port 4 patches:
r292594: Do not crash when assign common symbol's values in script
r292789: Stop handling local symbols in a special way.
r292910: Correct sh_info for static symbol table
r292940: Fixed crash after incrementing end iterator.
r292594 is probably a good idea to port anyway. I can fix the
conflicts and leave r292789 out if you want. A combined patch to 4.0
is attached.
Cheers,
Rafael
On 24 January 2017 at 14:26, Rui Ueyama <ruiu at google.com> wrote:
> But if you do, please cherry pick r292940 too because this patch introduced
> a new issue of creating an invalid iterator.
>
> On Tue, Jan 24, 2017 at 11:25 AM, Rui Ueyama <ruiu at google.com> wrote:
>>
>> That's OK.
>>
>> On Tue, Jan 24, 2017 at 10:02 AM, Rafael Avila de Espindola
>> <rafael.espindola at gmail.com> wrote:
>>>
>>>
>>> Thanks!
>>>
>>> I think we should port this to 4.0. Is that OK?
>>>
>>> Cheers,
>>> Rafael
>>>
>>> Peter Smith via llvm-commits <llvm-commits at lists.llvm.org> writes:
>>>
>>> > Author: psmith
>>> > Date: Tue Jan 24 04:43:40 2017
>>> > New Revision: 292910
>>> >
>>> > URL: http://llvm.org/viewvc/llvm-project?rev=292910&view=rev
>>> > Log:
>>> > [ELF] Correct sh_info for static symbol table
>>> >
>>> > The sh_info field of the SHT_SYMTAB section holds the index for the
>>> > first non-local symbol. When there are global symbols that are output
>>> > with STB_LOCAL binding due to having hidden visibility or matching
>>> > the local version from a version script, the calculated value of
>>> > NumLocals + 1 does not account for them. This change accounts for
>>> > global symbols being output with local binding.
>>> >
>>> > Differential Revision: https://reviews.llvm.org/D28950
>>> >
>>> > Modified:
>>> > lld/trunk/ELF/SyntheticSections.cpp
>>> > lld/trunk/test/ELF/basic-mips.s
>>> > lld/trunk/test/ELF/basic-ppc.s
>>> >
>>> > Modified: lld/trunk/ELF/SyntheticSections.cpp
>>> > URL:
>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=292910&r1=292909&r2=292910&view=diff
>>> >
>>> > ==============================================================================
>>> > --- lld/trunk/ELF/SyntheticSections.cpp (original)
>>> > +++ lld/trunk/ELF/SyntheticSections.cpp Tue Jan 24 04:43:40 2017
>>> > @@ -1073,11 +1073,13 @@ template <class ELFT> void SymbolTableSe
>>> >
>>> > if (!StrTabSec.isDynamic()) {
>>> > auto GlobBegin = Symbols.begin() + NumLocals;
>>> > - std::stable_sort(GlobBegin, Symbols.end(), [](const
>>> > SymbolTableEntry &L,
>>> > - const
>>> > SymbolTableEntry &R) {
>>> > - return L.Symbol->symbol()->computeBinding() == STB_LOCAL &&
>>> > - R.Symbol->symbol()->computeBinding() != STB_LOCAL;
>>> > - });
>>> > + auto It = std::stable_partition(
>>> > + GlobBegin, Symbols.end(), [](const SymbolTableEntry &S) {
>>> > + return S.Symbol->symbol()->computeBinding() == STB_LOCAL;
>>> > + });
>>> > + // update sh_info with number of Global symbols output with
>>> > computed
>>> > + // binding of STB_LOCAL
>>> > + this->OutSec->Info = this->Info = 1 + It - Symbols.begin();
>>> > return;
>>> > }
>>> >
>>> >
>>> > Modified: lld/trunk/test/ELF/basic-mips.s
>>> > URL:
>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/basic-mips.s?rev=292910&r1=292909&r2=292910&view=diff
>>> >
>>> > ==============================================================================
>>> > --- lld/trunk/test/ELF/basic-mips.s (original)
>>> > +++ lld/trunk/test/ELF/basic-mips.s Tue Jan 24 04:43:40 2017
>>> > @@ -176,7 +176,7 @@ __start:
>>> > # CHECK-NEXT: Offset: 0x20010
>>> > # CHECK-NEXT: Size: 48
>>> > # CHECK-NEXT: Link: 10
>>> > -# CHECK-NEXT: Info: 1
>>> > +# CHECK-NEXT: Info: 2
>>> > # CHECK-NEXT: AddressAlignment: 4
>>> > # CHECK-NEXT: EntrySize: 16
>>> > # CHECK-NEXT: }
>>> >
>>> > Modified: lld/trunk/test/ELF/basic-ppc.s
>>> > URL:
>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/basic-ppc.s?rev=292910&r1=292909&r2=292910&view=diff
>>> >
>>> > ==============================================================================
>>> > --- lld/trunk/test/ELF/basic-ppc.s (original)
>>> > +++ lld/trunk/test/ELF/basic-ppc.s Tue Jan 24 04:43:40 2017
>>> > @@ -178,7 +178,7 @@
>>> > // CHECK-NEXT: Offset: 0x2038
>>> > // CHECK-NEXT: Size: 32
>>> > // CHECK-NEXT: Link: 9
>>> > -// CHECK-NEXT: Info: 1
>>> > +// CHECK-NEXT: Info: 2
>>> > // CHECK-NEXT: AddressAlignment: 4
>>> > // CHECK-NEXT: EntrySize: 16
>>> > // CHECK-NEXT: SectionData (
>>> >
>>> >
>>> > _______________________________________________
>>> > llvm-commits mailing list
>>> > llvm-commits at lists.llvm.org
>>> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>>
>
-------------- next part --------------
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 73dda7b..9588806 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -180,10 +180,6 @@ public:
// R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
uint32_t MipsGp0 = 0;
- // The number is the offset in the string table. It will be used as the
- // st_name of the symbol.
- std::vector<std::pair<const DefinedRegular<ELFT> *, unsigned>> KeptLocalSyms;
-
// Name of source file obtained from STT_FILE symbol value,
// or empty string if there is no such symbol in object file
// symbol table.
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index 3580042..6b1e928 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -246,7 +246,8 @@ void InputSection<ELFT>::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
if (Config->Rela)
P->r_addend = getAddend<ELFT>(Rel);
P->r_offset = RelocatedSection->getOffset(Rel.r_offset);
- P->setSymbolAndType(Body.DynsymIndex, Type, Config->Mips64EL);
+ P->setSymbolAndType(In<ELFT>::SymTab->getSymbolIndex(&Body), Type,
+ Config->Mips64EL);
}
}
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index 887ca12..3cc2353 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -918,12 +918,7 @@ const OutputSectionBase *LinkerScript<ELFT>::getSymbolSection(StringRef S) {
return CurOutSec ? CurOutSec : (*OutputSections)[0];
}
- if (auto *DR = dyn_cast_or_null<DefinedRegular<ELFT>>(Sym))
- return DR->Section ? DR->Section->OutSec : nullptr;
- if (auto *DS = dyn_cast_or_null<DefinedSynthetic>(Sym))
- return DS->Section;
-
- return nullptr;
+ return SymbolTableSection<ELFT>::getOutputSection(Sym);
}
// Returns indices of ELF headers containing specific section, identified
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index f09b60b..5d318c7 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -1065,22 +1065,21 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
this->OutSec->Info = this->Info = NumLocals + 1;
this->OutSec->Entsize = this->Entsize;
- if (Config->Relocatable) {
- size_t I = NumLocals;
- for (const SymbolTableEntry &S : Symbols)
- S.Symbol->DynsymIndex = ++I;
+ if (Config->Relocatable)
return;
- }
if (!StrTabSec.isDynamic()) {
- std::stable_sort(
- Symbols.begin(), Symbols.end(),
- [](const SymbolTableEntry &L, const SymbolTableEntry &R) {
- return L.Symbol->symbol()->computeBinding() == STB_LOCAL &&
- R.Symbol->symbol()->computeBinding() != STB_LOCAL;
+ auto GlobBegin = Symbols.begin() + NumLocals;
+ auto It = std::stable_partition(
+ GlobBegin, Symbols.end(), [](const SymbolTableEntry &S) {
+ return S.Symbol->symbol()->computeBinding() == STB_LOCAL;
});
+ // update sh_info with number of Global symbols output with computed
+ // binding of STB_LOCAL
+ this->OutSec->Info = this->Info = 1 + (It - Symbols.begin());
return;
}
+
if (In<ELFT>::GnuHashTab)
// NB: It also sorts Symbols to meet the GNU hash table requirements.
In<ELFT>::GnuHashTab->addSymbols(Symbols);
@@ -1094,10 +1093,23 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
S.Symbol->DynsymIndex = ++I;
}
-template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) {
+template <class ELFT> void SymbolTableSection<ELFT>::addGlobal(SymbolBody *B) {
Symbols.push_back({B, StrTabSec.addString(B->getName(), false)});
}
+template <class ELFT> void SymbolTableSection<ELFT>::addLocal(SymbolBody *B) {
+ assert(!StrTabSec.isDynamic());
+ ++NumLocals;
+ Symbols.push_back({B, StrTabSec.addString(B->getName())});
+}
+
+template <class ELFT>
+size_t SymbolTableSection<ELFT>::getSymbolIndex(SymbolBody *Body) {
+ auto I = llvm::find_if(
+ Symbols, [&](const SymbolTableEntry &E) { return E.Symbol == Body; });
+ return I - Symbols.begin() + 1;
+}
+
template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
Buf += sizeof(Elf_Sym);
@@ -1113,26 +1125,24 @@ template <class ELFT>
void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
// Iterate over all input object files to copy their local symbols
// to the output symbol table pointed by Buf.
- for (ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
- for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P :
- File->KeptLocalSyms) {
- const DefinedRegular<ELFT> &Body = *P.first;
- InputSectionBase<ELFT> *Section = Body.Section;
- auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
-
- if (!Section) {
- ESym->st_shndx = SHN_ABS;
- ESym->st_value = Body.Value;
- } else {
- const OutputSectionBase *OutSec = Section->OutSec;
- ESym->st_shndx = OutSec->SectionIndex;
- ESym->st_value = OutSec->Addr + Section->getOffset(Body);
- }
- ESym->st_name = P.second;
- ESym->st_size = Body.template getSize<ELFT>();
- ESym->setBindingAndType(STB_LOCAL, Body.Type);
- Buf += sizeof(*ESym);
+
+ for (auto I = Symbols.begin(); I != Symbols.begin() + NumLocals; ++I) {
+ const DefinedRegular<ELFT> &Body = *cast<DefinedRegular<ELFT>>(I->Symbol);
+ InputSectionBase<ELFT> *Section = Body.Section;
+ auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
+
+ if (!Section) {
+ ESym->st_shndx = SHN_ABS;
+ ESym->st_value = Body.Value;
+ } else {
+ const OutputSectionBase *OutSec = Section->OutSec;
+ ESym->st_shndx = OutSec->SectionIndex;
+ ESym->st_value = OutSec->Addr + Section->getOffset(Body);
}
+ ESym->st_name = I->StrTabOffset;
+ ESym->st_size = Body.template getSize<ELFT>();
+ ESym->setBindingAndType(STB_LOCAL, Body.Type);
+ Buf += sizeof(*ESym);
}
}
@@ -1141,7 +1151,9 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
// Write the internal symbol table contents to the output symbol table
// pointed by Buf.
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
- for (const SymbolTableEntry &S : Symbols) {
+
+ for (auto I = Symbols.begin() + NumLocals; I != Symbols.end(); ++I) {
+ const SymbolTableEntry &S = *I;
SymbolBody *Body = S.Symbol;
size_t StrOff = S.StrTabOffset;
diff --git a/ELF/SyntheticSections.h b/ELF/SyntheticSections.h
index dfefb38..df67e07 100644
--- a/ELF/SyntheticSections.h
+++ b/ELF/SyntheticSections.h
@@ -366,23 +366,26 @@ public:
void finalize() override;
void writeTo(uint8_t *Buf) override;
size_t getSize() const override { return getNumSymbols() * sizeof(Elf_Sym); }
- void addSymbol(SymbolBody *Body);
+ void addGlobal(SymbolBody *Body);
+ void addLocal(SymbolBody *Body);
StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
- unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; }
+ unsigned getNumSymbols() const { return Symbols.size() + 1; }
+ size_t getSymbolIndex(SymbolBody *Body);
ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; }
- unsigned NumLocals = 0;
- StringTableSection<ELFT> &StrTabSec;
+ static const OutputSectionBase *getOutputSection(SymbolBody *Sym);
private:
void writeLocalSymbols(uint8_t *&Buf);
void writeGlobalSymbols(uint8_t *Buf);
- const OutputSectionBase *getOutputSection(SymbolBody *Sym);
-
// A vector of symbols and their string table offsets.
std::vector<SymbolTableEntry> Symbols;
+
+ StringTableSection<ELFT> &StrTabSec;
+
+ unsigned NumLocals = 0;
};
// Outputs GNU Hash section. For detailed explanation see:
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 4f2f919..fbb05ef 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -455,11 +455,7 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
InputSectionBase<ELFT> *Sec = DR->Section;
if (!shouldKeepInSymtab<ELFT>(Sec, B->getName(), *B))
continue;
- ++In<ELFT>::SymTab->NumLocals;
- if (Config->Relocatable)
- B->DynsymIndex = In<ELFT>::SymTab->NumLocals;
- F->KeptLocalSyms.push_back(std::make_pair(
- DR, In<ELFT>::SymTab->StrTabSec.addString(B->getName())));
+ In<ELFT>::SymTab->addLocal(B);
}
}
}
@@ -1024,10 +1020,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (!includeInSymtab<ELFT>(*Body))
continue;
if (In<ELFT>::SymTab)
- In<ELFT>::SymTab->addSymbol(Body);
+ In<ELFT>::SymTab->addGlobal(Body);
if (In<ELFT>::DynSymTab && S->includeInDynsym()) {
- In<ELFT>::DynSymTab->addSymbol(Body);
+ In<ELFT>::DynSymTab->addGlobal(Body);
if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
if (SS->file()->isNeeded())
In<ELFT>::VerNeed->addSymbol(SS);
diff --git a/test/ELF/basic-mips.s b/test/ELF/basic-mips.s
index 67b58f8..57181ca 100644
--- a/test/ELF/basic-mips.s
+++ b/test/ELF/basic-mips.s
@@ -176,7 +176,7 @@ __start:
# CHECK-NEXT: Offset: 0x20010
# CHECK-NEXT: Size: 48
# CHECK-NEXT: Link: 10
-# CHECK-NEXT: Info: 1
+# CHECK-NEXT: Info: 2
# CHECK-NEXT: AddressAlignment: 4
# CHECK-NEXT: EntrySize: 16
# CHECK-NEXT: }
diff --git a/test/ELF/basic-ppc.s b/test/ELF/basic-ppc.s
index e08c7a3..aae81fe 100644
--- a/test/ELF/basic-ppc.s
+++ b/test/ELF/basic-ppc.s
@@ -178,7 +178,7 @@
// CHECK-NEXT: Offset: 0x2038
// CHECK-NEXT: Size: 32
// CHECK-NEXT: Link: 9
-// CHECK-NEXT: Info: 1
+// CHECK-NEXT: Info: 2
// CHECK-NEXT: AddressAlignment: 4
// CHECK-NEXT: EntrySize: 16
// CHECK-NEXT: SectionData (
diff --git a/test/ELF/linkerscript/common-assign.s b/test/ELF/linkerscript/common-assign.s
new file mode 100644
index 0000000..4244ae3
--- /dev/null
+++ b/test/ELF/linkerscript/common-assign.s
@@ -0,0 +1,48 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; pfoo = foo; pbar = bar; }" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-readobj -symbols %t1 | FileCheck %s
+
+# CHECK: Symbol {
+# CHECK: Name: bar
+# CHECK-NEXT: Value: 0x134
+# CHECK-NEXT: Size: 4
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: Object
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .bss
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo
+# CHECK-NEXT: Value: 0x138
+# CHECK-NEXT: Size: 4
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: Object
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .bss
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: pfoo
+# CHECK-NEXT: Value: 0x138
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .bss
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: pbar
+# CHECK-NEXT: Value: 0x134
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .bss
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+.comm foo,4,4
+.comm bar,4,4
+movl $1, foo(%rip)
+movl $2, bar(%rip)
More information about the llvm-commits
mailing list