Start recording the section of symbols in the symbol table.
Support for more than 64 K sections to follow shortly. llvm-svn: 245868
This commit is contained in:
parent
6c61288716
commit
832b93f219
|
@ -17,6 +17,7 @@ namespace lld {
|
|||
namespace elf2 {
|
||||
|
||||
template <class ELFT> class ObjectFile;
|
||||
template <class ELFT> class OutputSection;
|
||||
|
||||
// A chunk corresponding a section of an input file.
|
||||
template <class ELFT> class SectionChunk {
|
||||
|
@ -43,6 +44,9 @@ public:
|
|||
uintX_t getAlign() { return Header->sh_addralign; }
|
||||
void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; }
|
||||
|
||||
void setOutputSection(OutputSection<ELFT> *O) { Out = O; }
|
||||
OutputSection<ELFT> *getOutputSection() const { return Out; }
|
||||
|
||||
private:
|
||||
// The offset from beginning of the output sections this chunk was assigned
|
||||
// to. The writer sets a value.
|
||||
|
@ -51,6 +55,8 @@ private:
|
|||
// A file this chunk was created from.
|
||||
llvm::object::ELFFile<ELFT> *Obj;
|
||||
|
||||
OutputSection<ELFT> *Out = nullptr;
|
||||
|
||||
const Elf_Shdr *Header;
|
||||
};
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ template <class ELFT> void elf2::ObjectFile<ELFT>::parse() {
|
|||
|
||||
template <class ELFT> void elf2::ObjectFile<ELFT>::initializeChunks() {
|
||||
uint64_t Size = ELFObj->getNumSections();
|
||||
Chunks.reserve(Size);
|
||||
Chunks.resize(Size);
|
||||
unsigned I = 0;
|
||||
for (const Elf_Shdr &Sec : ELFObj->sections()) {
|
||||
switch (Sec.sh_type) {
|
||||
case SHT_SYMTAB:
|
||||
|
@ -51,10 +52,10 @@ template <class ELFT> void elf2::ObjectFile<ELFT>::initializeChunks() {
|
|||
case SHT_REL:
|
||||
break;
|
||||
default:
|
||||
auto *C = new (Alloc) SectionChunk<ELFT>(this->getObj(), &Sec);
|
||||
Chunks.push_back(C);
|
||||
Chunks[I] = new (Alloc) SectionChunk<ELFT>(this->getObj(), &Sec);
|
||||
break;
|
||||
}
|
||||
++I;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,17 +82,18 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
|
|||
ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable);
|
||||
error(NameOrErr.getError());
|
||||
StringRef Name = *NameOrErr;
|
||||
uint16_t SecIndex = Sym->st_shndx;
|
||||
switch (Sym->getBinding()) {
|
||||
default:
|
||||
error("unexpected binding");
|
||||
case STB_GLOBAL:
|
||||
if (Sym->isUndefined())
|
||||
return new (Alloc) Undefined<ELFT>(Name, *Sym);
|
||||
return new (Alloc) DefinedRegular<ELFT>(Name, *Sym);
|
||||
return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, *Chunks[SecIndex]);
|
||||
case STB_WEAK:
|
||||
if (Sym->isUndefined())
|
||||
return new (Alloc) UndefinedWeak<ELFT>(Name, *Sym);
|
||||
return new (Alloc) DefinedWeak<ELFT>(Name, *Sym);
|
||||
return new (Alloc) DefinedWeak<ELFT>(Name, *Sym, *Chunks[SecIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#ifndef LLD_ELF_SYMBOLS_H
|
||||
#define LLD_ELF_SYMBOLS_H
|
||||
|
||||
#include "Chunks.h"
|
||||
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
|
||||
|
@ -106,13 +108,16 @@ template <class ELFT> class Defined : public ELFSymbolBody<ELFT> {
|
|||
public:
|
||||
typedef typename Base::Elf_Sym Elf_Sym;
|
||||
|
||||
explicit Defined(Kind K, StringRef N, const Elf_Sym &Sym)
|
||||
: ELFSymbolBody<ELFT>(K, N, Sym) {}
|
||||
explicit Defined(Kind K, StringRef N, const Elf_Sym &Sym,
|
||||
SectionChunk<ELFT> &Section)
|
||||
: ELFSymbolBody<ELFT>(K, N, Sym), Section(Section) {}
|
||||
|
||||
static bool classof(const SymbolBody *S) {
|
||||
Kind K = S->kind();
|
||||
return Base::DefinedFirst <= K && K <= Base::DefinedLast;
|
||||
}
|
||||
|
||||
const SectionChunk<ELFT> &Section;
|
||||
};
|
||||
|
||||
// Regular defined symbols read from object file symbol tables.
|
||||
|
@ -121,8 +126,9 @@ template <class ELFT> class DefinedRegular : public Defined<ELFT> {
|
|||
typedef typename Base::Elf_Sym Elf_Sym;
|
||||
|
||||
public:
|
||||
explicit DefinedRegular(StringRef N, const Elf_Sym &Sym)
|
||||
: Defined<ELFT>(Base::DefinedRegularKind, N, Sym) {}
|
||||
explicit DefinedRegular(StringRef N, const Elf_Sym &Sym,
|
||||
SectionChunk<ELFT> &Section)
|
||||
: Defined<ELFT>(Base::DefinedRegularKind, N, Sym, Section) {}
|
||||
|
||||
static bool classof(const SymbolBody *S) {
|
||||
return S->kind() == Base::DefinedRegularKind;
|
||||
|
@ -134,8 +140,9 @@ template <class ELFT> class DefinedWeak : public Defined<ELFT> {
|
|||
typedef typename Base::Elf_Sym Elf_Sym;
|
||||
|
||||
public:
|
||||
explicit DefinedWeak(StringRef N, const Elf_Sym &Sym)
|
||||
: Defined<ELFT>(Base::DefinedWeakKind, N, Sym) {}
|
||||
explicit DefinedWeak(StringRef N, const Elf_Sym &Sym,
|
||||
SectionChunk<ELFT> &Section)
|
||||
: Defined<ELFT>(Base::DefinedWeakKind, N, Sym, Section) {}
|
||||
|
||||
static bool classof(const SymbolBody *S) {
|
||||
return S->kind() == Base::DefinedWeakKind;
|
||||
|
|
|
@ -51,6 +51,9 @@ public:
|
|||
StringRef getName() { return Name; }
|
||||
void setNameOffset(uintX_t Offset) { Header.sh_name = Offset; }
|
||||
|
||||
unsigned getSectionIndex() const { return SectionIndex; }
|
||||
void setSectionIndex(unsigned I) { SectionIndex = I; }
|
||||
|
||||
// Returns the size of the section in the output file.
|
||||
uintX_t getSize() { return Header.sh_size; }
|
||||
uintX_t getFlags() { return Header.sh_flags; }
|
||||
|
@ -63,11 +66,14 @@ public:
|
|||
protected:
|
||||
StringRef Name;
|
||||
HeaderT Header;
|
||||
unsigned SectionIndex;
|
||||
~OutputSectionBase() = default;
|
||||
};
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
class OutputSection final : public OutputSectionBase<ELFT::Is64Bits> {
|
||||
class lld::elf2::OutputSection final
|
||||
: public OutputSectionBase<ELFT::Is64Bits> {
|
||||
public:
|
||||
typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
|
||||
OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
|
||||
|
@ -80,6 +86,7 @@ private:
|
|||
std::vector<SectionChunk<ELFT> *> Chunks;
|
||||
};
|
||||
|
||||
namespace {
|
||||
template <bool Is64Bits>
|
||||
class StringTableSection final : public OutputSectionBase<Is64Bits> {
|
||||
llvm::StringTableBuilder &StrTabBuilder;
|
||||
|
@ -159,6 +166,11 @@ private:
|
|||
StringTableSection<ELFT::Is64Bits> StringTable;
|
||||
|
||||
unsigned NumSections;
|
||||
|
||||
void addOutputSection(OutputSectionBase<ELFT::Is64Bits> *Sec) {
|
||||
OutputSections.push_back(Sec);
|
||||
Sec->setSectionIndex(OutputSections.size());
|
||||
}
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -189,6 +201,7 @@ template <class ELFT> void Writer<ELFT>::run() {
|
|||
template <class ELFT>
|
||||
void OutputSection<ELFT>::addChunk(SectionChunk<ELFT> *C) {
|
||||
Chunks.push_back(C);
|
||||
C->setOutputSection(this);
|
||||
uint32_t Align = C->getAlign();
|
||||
if (Align > this->Header.sh_addralign)
|
||||
this->Header.sh_addralign = Align;
|
||||
|
@ -223,15 +236,22 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
uint8_t Binding;
|
||||
SymbolBody *Body = Sym->Body;
|
||||
uint8_t Type = 0;
|
||||
|
||||
const SectionChunk<ELFT> *Section = nullptr;
|
||||
|
||||
switch (Body->kind()) {
|
||||
case SymbolBody::UndefinedKind:
|
||||
case SymbolBody::UndefinedSyntheticKind:
|
||||
llvm_unreachable("Should be defined by now");
|
||||
case SymbolBody::DefinedRegularKind:
|
||||
case SymbolBody::DefinedRegularKind: {
|
||||
Binding = STB_GLOBAL;
|
||||
Type = cast<DefinedRegular<ELFT>>(Body)->Sym.getType();
|
||||
auto *Def = cast<DefinedRegular<ELFT>>(Body);
|
||||
Type = Def->Sym.getType();
|
||||
Section = &Def->Section;
|
||||
break;
|
||||
}
|
||||
case SymbolBody::DefinedWeakKind:
|
||||
Section = &cast<Defined<ELFT>>(Body)->Section;
|
||||
case SymbolBody::UndefinedWeakKind:
|
||||
Binding = STB_WEAK;
|
||||
Type = cast<ELFSymbolBody<ELFT>>(Body)->Sym.getType();
|
||||
|
@ -239,6 +259,11 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
}
|
||||
ESym->setBindingAndType(Binding, Type);
|
||||
|
||||
if (Section) {
|
||||
OutputSection<ELFT> *Out = Section->getOutputSection();
|
||||
ESym->st_shndx = Out->getSectionIndex();
|
||||
}
|
||||
|
||||
Buf += sizeof(Elf_Sym);
|
||||
}
|
||||
}
|
||||
|
@ -294,6 +319,8 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
|||
for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.ObjectFiles) {
|
||||
auto &File = cast<ObjectFile<ELFT>>(*FileB);
|
||||
for (SectionChunk<ELFT> *C : File.getChunks()) {
|
||||
if (!C)
|
||||
continue;
|
||||
const Elf_Shdr *H = C->getSectionHdr();
|
||||
SectionKey<ELFT::Is64Bits> Key{C->getSectionName(), H->sh_type,
|
||||
H->sh_flags};
|
||||
|
@ -301,7 +328,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
|||
if (!Sec) {
|
||||
Sec = new (CAlloc.Allocate())
|
||||
OutputSection<ELFT>(Key.Name, Key.sh_type, Key.sh_flags);
|
||||
OutputSections.push_back(Sec);
|
||||
addOutputSection(Sec);
|
||||
}
|
||||
Sec->addChunk(C);
|
||||
}
|
||||
|
@ -325,8 +352,8 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
|||
std::stable_sort(OutputSections.begin(), OutputSections.end(),
|
||||
compSec<ELFT::Is64Bits>);
|
||||
|
||||
OutputSections.push_back(&SymTable);
|
||||
OutputSections.push_back(&StringTable);
|
||||
addOutputSection(&SymTable);
|
||||
addOutputSection(&StringTable);
|
||||
StringTableIndex = OutputSections.size();
|
||||
SymTable.setStringTableIndex(StringTableIndex);
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@ foo:
|
|||
.weak bar
|
||||
.long bar
|
||||
|
||||
.data
|
||||
.globl zed
|
||||
zed:
|
||||
|
||||
// CHECK: Symbols [
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: (0)
|
||||
|
@ -26,13 +30,22 @@ foo:
|
|||
// CHECK-NEXT: Section: Undefined (0x0)
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: zed
|
||||
// CHECK-NEXT: Value: 0x0
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global (0x1)
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .data
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: _start
|
||||
// CHECK-NEXT: Value: 0x0
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global (0x1)
|
||||
// CHECK-NEXT: Type: Function
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Undefined (0x0)
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: bar
|
||||
|
@ -50,6 +63,6 @@ foo:
|
|||
// CHECK-NEXT: Binding: Weak (0x2)
|
||||
// CHECK-NEXT: Type: Object
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Undefined (0x0)
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ]
|
||||
|
|
Loading…
Reference in New Issue