Merge identical strings.

This avoids the need to have reserve and addString in sync.

We avoid hashing the global symbols again. This means that we don't
merge a global symbol that has the same name as some other string, but
that doesn't seem very common. The string table size is the same in
clang an scylladb with or without hashing global symbols again.

llvm-svn: 259136
This commit is contained in:
Rafael Espindola 2016-01-29 01:24:25 +00:00
parent fa7ae77af4
commit e2c2461a6b
9 changed files with 88 additions and 103 deletions

View File

@ -129,7 +129,9 @@ public:
// R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations. // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
uint32_t getMipsGp0() const; uint32_t getMipsGp0() const;
std::vector<const Elf_Sym *> KeptLocalSyms; // 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 Elf_Sym *, unsigned>> KeptLocalSyms;
private: private:
void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups); void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups);

View File

@ -379,7 +379,6 @@ InterpSection<ELFT>::InterpSection()
template <class ELFT> template <class ELFT>
void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *SHdr) { void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *SHdr) {
Header.sh_name = Out<ELFT>::ShStrTab->addString(Name);
*SHdr = Header; *SHdr = Header;
} }
@ -428,7 +427,9 @@ template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
Elf_Word *Buckets = P; Elf_Word *Buckets = P;
Elf_Word *Chains = P + NumSymbols; Elf_Word *Chains = P + NumSymbols;
for (SymbolBody *Body : Out<ELFT>::DynSymTab->getSymbols()) { for (const std::pair<SymbolBody *, unsigned> &P :
Out<ELFT>::DynSymTab->getSymbols()) {
SymbolBody *Body = P.first;
StringRef Name = Body->getName(); StringRef Name = Body->getName();
unsigned I = Body->DynamicSymbolTableIndex; unsigned I = Body->DynamicSymbolTableIndex;
uint32_t Hash = hashSysv(Name) % NumSymbols; uint32_t Hash = hashSysv(Name) % NumSymbols;
@ -560,15 +561,18 @@ static bool includeInGnuHashTable(SymbolBody *B) {
} }
template <class ELFT> template <class ELFT>
void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolBody *> &Symbols) { void GnuHashTableSection<ELFT>::addSymbols(
std::vector<SymbolBody *> NotHashed; std::vector<std::pair<SymbolBody *, unsigned>> &Symbols) {
std::vector<std::pair<SymbolBody *, unsigned>> NotHashed;
NotHashed.reserve(Symbols.size()); NotHashed.reserve(Symbols.size());
HashedSymbols.reserve(Symbols.size()); HashedSymbols.reserve(Symbols.size());
for (SymbolBody *B : Symbols) { for (const std::pair<SymbolBody *, unsigned> &P : Symbols) {
SymbolBody *B = P.first;
if (includeInGnuHashTable(B)) if (includeInGnuHashTable(B))
HashedSymbols.push_back(HashedSymbolData{B, hashGnu(B->getName())}); HashedSymbols.push_back(
HashedSymbolData{B, P.second, hashGnu(B->getName())});
else else
NotHashed.push_back(B); NotHashed.push_back(P);
} }
if (HashedSymbols.empty()) if (HashedSymbols.empty())
return; return;
@ -581,7 +585,7 @@ void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolBody *> &Symbols) {
Symbols = std::move(NotHashed); Symbols = std::move(NotHashed);
for (const HashedSymbolData &Item : HashedSymbols) for (const HashedSymbolData &Item : HashedSymbols)
Symbols.push_back(Item.Body); Symbols.push_back(std::make_pair(Item.Body, Item.STName));
} }
template <class ELFT> template <class ELFT>
@ -606,18 +610,21 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
Elf_Shdr &Header = this->Header; Elf_Shdr &Header = this->Header;
Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex; Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
// Reserve strings. We know that these are the last string to be added to auto Add = [=](Entry E) { Entries.push_back(E); };
// Add strings. We know that these are the last strings to be added to
// DynStrTab and doing this here allows this function to set DT_STRSZ. // DynStrTab and doing this here allows this function to set DT_STRSZ.
if (!Config->RPath.empty()) if (!Config->RPath.empty())
Out<ELFT>::DynStrTab->reserve(Config->RPath); Add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
if (!Config->SoName.empty()) Out<ELFT>::DynStrTab->addString(Config->RPath)});
Out<ELFT>::DynStrTab->reserve(Config->SoName);
for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
if (F->isNeeded()) if (F->isNeeded())
Out<ELFT>::DynStrTab->reserve(F->getSoName()); Add({DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName())});
if (!Config->SoName.empty())
Add({DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName)});
Out<ELFT>::DynStrTab->finalize(); Out<ELFT>::DynStrTab->finalize();
auto Add = [=](Entry E) { Entries.push_back(E); };
if (Out<ELFT>::RelaDyn->hasRelocs()) { if (Out<ELFT>::RelaDyn->hasRelocs()) {
bool IsRela = Out<ELFT>::RelaDyn->isRela(); bool IsRela = Out<ELFT>::RelaDyn->isRela();
@ -643,13 +650,6 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
if (Out<ELFT>::HashTab) if (Out<ELFT>::HashTab)
Add({DT_HASH, Out<ELFT>::HashTab}); Add({DT_HASH, Out<ELFT>::HashTab});
if (!Config->RPath.empty())
Add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
Out<ELFT>::DynStrTab->addString(Config->RPath)});
if (!Config->SoName.empty())
Add({DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName)});
if (PreInitArraySec) { if (PreInitArraySec) {
Add({DT_PREINIT_ARRAY, PreInitArraySec}); Add({DT_PREINIT_ARRAY, PreInitArraySec});
Add({DT_PREINIT_ARRAYSZ, PreInitArraySec->getSize()}); Add({DT_PREINIT_ARRAYSZ, PreInitArraySec->getSize()});
@ -663,10 +663,6 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
Add({DT_FINI_ARRAYSZ, (uintX_t)FiniArraySec->getSize()}); Add({DT_FINI_ARRAYSZ, (uintX_t)FiniArraySec->getSize()});
} }
for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
if (F->isNeeded())
Add({DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName())});
if (SymbolBody *B = SymTab.find(Config->Init)) if (SymbolBody *B = SymTab.find(Config->Init))
Add({DT_INIT, B}); Add({DT_INIT, B});
if (SymbolBody *B = SymTab.find(Config->Fini)) if (SymbolBody *B = SymTab.find(Config->Fini))
@ -1349,30 +1345,21 @@ StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic)
this->Header.sh_addralign = 1; this->Header.sh_addralign = 1;
} }
// String tables are created in two phases. First you call reserve() // Adds a string to the string table. If HashIt is true we hash and check for
// to reserve room in the string table, and then call addString() to actually // duplicates. It is optional because the name of global symbols are already
// add that string. // uniqued and hashing them again has a big cost for a small value: uniquing
// // them with some other string that happens to be the same.
// Why two phases? We want to know the size of the string table as early as template <class ELFT>
// possible to fix file layout. So we have separated finalize(), which unsigned StringTableSection<ELFT>::addString(StringRef S, bool HashIt) {
// determines the size of the section, from writeTo(), which writes the section if (HashIt) {
// contents to the output buffer. If we merge reserve() with addString(), auto R = StringMap.insert(std::make_pair(S, Size));
// we need a plumbing work for finalize() and writeTo() so that offsets if (!R.second)
// we obtained in the former function can be written in the latter. return R.first->second;
// This design eliminated that need. }
template <class ELFT> void StringTableSection<ELFT>::reserve(StringRef S) { unsigned Ret = Size;
Reserved += S.size() + 1; // +1 for NUL Size += S.size() + 1;
}
// Adds a string to the string table. You must call reserve() with the
// same string before calling addString().
template <class ELFT> size_t StringTableSection<ELFT>::addString(StringRef S) {
size_t Pos = Used;
Strings.push_back(S); Strings.push_back(S);
Used += S.size() + 1; return Ret;
Reserved -= S.size() + 1;
assert((int64_t)Reserved >= 0);
return Pos;
} }
template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) { template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) {
@ -1390,7 +1377,7 @@ SymbolTableSection<ELFT>::SymbolTableSection(
: OutputSectionBase<ELFT>(StrTabSec.isDynamic() ? ".dynsym" : ".symtab", : OutputSectionBase<ELFT>(StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB, StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0), StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
Table(Table), StrTabSec(StrTabSec) { StrTabSec(StrTabSec), Table(Table) {
this->Header.sh_entsize = sizeof(Elf_Sym); this->Header.sh_entsize = sizeof(Elf_Sym);
this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
} }
@ -1400,10 +1387,11 @@ SymbolTableSection<ELFT>::SymbolTableSection(
// See "Global Offset Table" in Chapter 5 in the following document // See "Global Offset Table" in Chapter 5 in the following document
// for detailed description: // for detailed description:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
static bool sortMipsSymbols(SymbolBody *L, SymbolBody *R) { static bool sortMipsSymbols(const std::pair<SymbolBody *, unsigned> &L,
if (!L->isInGot() || !R->isInGot()) const std::pair<SymbolBody *, unsigned> &R) {
return R->isInGot(); if (!L.first->isInGot() || !R.first->isInGot())
return L->GotIndex < R->GotIndex; return R.first->isInGot();
return L.first->GotIndex < R.first->GotIndex;
} }
template <class ELFT> void SymbolTableSection<ELFT>::finalize() { template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
@ -1416,9 +1404,10 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
if (!StrTabSec.isDynamic()) { if (!StrTabSec.isDynamic()) {
std::stable_sort(Symbols.begin(), Symbols.end(), std::stable_sort(Symbols.begin(), Symbols.end(),
[](SymbolBody *L, SymbolBody *R) { [](const std::pair<SymbolBody *, unsigned> &L,
return getSymbolBinding(L) == STB_LOCAL && const std::pair<SymbolBody *, unsigned> &R) {
getSymbolBinding(R) != STB_LOCAL; return getSymbolBinding(L.first) == STB_LOCAL &&
getSymbolBinding(R.first) != STB_LOCAL;
}); });
return; return;
} }
@ -1428,20 +1417,14 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
else if (Config->EMachine == EM_MIPS) else if (Config->EMachine == EM_MIPS)
std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols); std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);
size_t I = 0; size_t I = 0;
for (SymbolBody *B : Symbols) for (const std::pair<SymbolBody *, unsigned> &P : Symbols)
B->DynamicSymbolTableIndex = ++I; P.first->DynamicSymbolTableIndex = ++I;
}
template <class ELFT>
void SymbolTableSection<ELFT>::addLocalSymbol(StringRef Name) {
StrTabSec.reserve(Name);
++NumLocals;
} }
template <class ELFT> template <class ELFT>
void SymbolTableSection<ELFT>::addSymbol(SymbolBody *Body) { void SymbolTableSection<ELFT>::addSymbol(SymbolBody *Body) {
StrTabSec.reserve(Body->getName()); Symbols.push_back(
Symbols.push_back(Body); std::make_pair(Body, StrTabSec.addString(Body->getName(), false)));
} }
template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
@ -1460,10 +1443,8 @@ void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
// Iterate over all input object files to copy their local symbols // Iterate over all input object files to copy their local symbols
// to the output symbol table pointed by Buf. // to the output symbol table pointed by Buf.
for (const std::unique_ptr<ObjectFile<ELFT>> &File : Table.getObjectFiles()) { for (const std::unique_ptr<ObjectFile<ELFT>> &File : Table.getObjectFiles()) {
for (const Elf_Sym *Sym : File->KeptLocalSyms) { for (const std::pair<const Elf_Sym *, unsigned> &P : File->KeptLocalSyms) {
ErrorOr<StringRef> SymNameOrErr = Sym->getName(File->getStringTable()); const Elf_Sym *Sym = P.first;
fatal(SymNameOrErr);
StringRef SymName = *SymNameOrErr;
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
uintX_t VA = 0; uintX_t VA = 0;
@ -1480,7 +1461,7 @@ void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
if (Config->EMachine != EM_AMDGPU) if (Config->EMachine != EM_AMDGPU)
VA += OutSec->getVA(); VA += OutSec->getVA();
} }
ESym->st_name = StrTabSec.addString(SymName); ESym->st_name = P.second;
ESym->st_size = Sym->st_size; ESym->st_size = Sym->st_size;
ESym->setBindingAndType(Sym->getBinding(), Sym->getType()); ESym->setBindingAndType(Sym->getBinding(), Sym->getType());
ESym->st_value = VA; ESym->st_value = VA;
@ -1504,7 +1485,8 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
// Write the internal symbol table contents to the output symbol table // Write the internal symbol table contents to the output symbol table
// pointed by Buf. // pointed by Buf.
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
for (SymbolBody *Body : Symbols) { for (const std::pair<SymbolBody *, unsigned> &P : Symbols) {
SymbolBody *Body = P.first;
const OutputSectionBase<ELFT> *OutSec = nullptr; const OutputSectionBase<ELFT> *OutSec = nullptr;
switch (Body->kind()) { switch (Body->kind()) {
@ -1534,8 +1516,7 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
break; break;
} }
StringRef Name = Body->getName(); ESym->st_name = P.second;
ESym->st_name = StrTabSec.addString(Name);
unsigned char Type = STT_NOTYPE; unsigned char Type = STT_NOTYPE;
uintX_t Size = 0; uintX_t Size = 0;

View File

@ -12,7 +12,6 @@
#include "lld/Core/LLVM.h" #include "lld/Core/LLVM.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/MC/StringTableBuilder.h" #include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
@ -73,6 +72,7 @@ public:
void setVA(uintX_t VA) { Header.sh_addr = VA; } void setVA(uintX_t VA) { Header.sh_addr = VA; }
uintX_t getVA() const { return Header.sh_addr; } uintX_t getVA() const { return Header.sh_addr; }
void setFileOffset(uintX_t Off) { Header.sh_offset = Off; } void setFileOffset(uintX_t Off) { Header.sh_offset = Off; }
void setSHName(unsigned Val) { Header.sh_name = Val; }
void writeHeaderTo(Elf_Shdr *SHdr); void writeHeaderTo(Elf_Shdr *SHdr);
StringRef getName() { return Name; } StringRef getName() { return Name; }
@ -195,12 +195,16 @@ public:
void finalize() override; void finalize() override;
void writeTo(uint8_t *Buf) override; void writeTo(uint8_t *Buf) override;
void addLocalSymbol(StringRef Name);
void addSymbol(SymbolBody *Body); void addSymbol(SymbolBody *Body);
StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; } StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; } unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; }
ArrayRef<SymbolBody *> getSymbols() const { return Symbols; } ArrayRef<std::pair<SymbolBody *, unsigned>> getSymbols() const {
return Symbols;
}
unsigned NumLocals = 0;
StringTableSection<ELFT> &StrTabSec;
private: private:
void writeLocalSymbols(uint8_t *&Buf); void writeLocalSymbols(uint8_t *&Buf);
@ -209,9 +213,7 @@ private:
static uint8_t getSymbolBinding(SymbolBody *Body); static uint8_t getSymbolBinding(SymbolBody *Body);
SymbolTable<ELFT> &Table; SymbolTable<ELFT> &Table;
StringTableSection<ELFT> &StrTabSec; std::vector<std::pair<SymbolBody *, unsigned>> Symbols;
std::vector<SymbolBody *> Symbols;
unsigned NumLocals = 0;
}; };
template <class ELFT> template <class ELFT>
@ -328,18 +330,17 @@ class StringTableSection final : public OutputSectionBase<ELFT> {
public: public:
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
StringTableSection(StringRef Name, bool Dynamic); StringTableSection(StringRef Name, bool Dynamic);
void reserve(StringRef S); unsigned addString(StringRef S, bool HashIt = true);
size_t addString(StringRef S);
void writeTo(uint8_t *Buf) override; void writeTo(uint8_t *Buf) override;
size_t getSize() const { return Used + Reserved; } unsigned getSize() const { return Size; }
void finalize() override { this->Header.sh_size = getSize(); } void finalize() override { this->Header.sh_size = getSize(); }
bool isDynamic() const { return Dynamic; } bool isDynamic() const { return Dynamic; }
private: private:
const bool Dynamic; const bool Dynamic;
llvm::DenseMap<StringRef, unsigned> StringMap;
std::vector<StringRef> Strings; std::vector<StringRef> Strings;
size_t Used = 1; // ELF string tables start with a NUL byte, so 1. unsigned Size = 1; // ELF string tables start with a NUL byte, so 1.
size_t Reserved = 0;
}; };
template <class ELFT> template <class ELFT>
@ -367,7 +368,7 @@ public:
// Adds symbols to the hash table. // Adds symbols to the hash table.
// Sorts the input to satisfy GNU hash section requirements. // Sorts the input to satisfy GNU hash section requirements.
void addSymbols(std::vector<SymbolBody *> &Symbols); void addSymbols(std::vector<std::pair<SymbolBody *, unsigned>> &Symbols);
private: private:
static unsigned calcNBuckets(unsigned NumHashed); static unsigned calcNBuckets(unsigned NumHashed);
@ -379,6 +380,7 @@ private:
struct HashedSymbolData { struct HashedSymbolData {
SymbolBody *Body; SymbolBody *Body;
unsigned STName;
uint32_t Hash; uint32_t Hash;
}; };

View File

@ -431,8 +431,9 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
if (!Section->isLive()) if (!Section->isLive())
continue; continue;
} }
Out<ELFT>::SymTab->addLocalSymbol(SymName); ++Out<ELFT>::SymTab->NumLocals;
F->KeptLocalSyms.push_back(&Sym); F->KeptLocalSyms.push_back(std::make_pair(
&Sym, Out<ELFT>::SymTab->StrTabSec.addString(SymName)));
} }
} }
} }
@ -907,7 +908,7 @@ template <class ELFT> bool Writer<ELFT>::createSections() {
} }
for (OutputSectionBase<ELFT> *Sec : OutputSections) for (OutputSectionBase<ELFT> *Sec : OutputSections)
Out<ELFT>::ShStrTab->reserve(Sec->getName()); Sec->setSHName(Out<ELFT>::ShStrTab->addString(Sec->getName()));
// Finalizers fix each section's size. // Finalizers fix each section's size.
// .dynsym is finalized early since that may fill up .gnu.hash. // .dynsym is finalized early since that may fill up .gnu.hash.

View File

@ -43,6 +43,7 @@
// CHECK: DynamicSection [ // CHECK: DynamicSection [
// CHECK-NEXT: Tag Type Name/Value // CHECK-NEXT: Tag Type Name/Value
// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x0000000000000017 JMPREL // CHECK-NEXT: 0x0000000000000017 JMPREL
// CHECK-NEXT: 0x0000000000000002 PLTRELSZ 24 (bytes) // CHECK-NEXT: 0x0000000000000002 PLTRELSZ 24 (bytes)
// CHECK-NEXT: 0x0000000000000003 PLTGOT // CHECK-NEXT: 0x0000000000000003 PLTGOT
@ -52,7 +53,6 @@
// CHECK-NEXT: 0x0000000000000005 STRTAB // CHECK-NEXT: 0x0000000000000005 STRTAB
// CHECK-NEXT: 0x000000000000000A STRSZ // CHECK-NEXT: 0x000000000000000A STRSZ
// CHECK-NEXT: 0x0000000000000004 HASH // CHECK-NEXT: 0x0000000000000004 HASH
// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x0000000000000015 DEBUG 0x0 // CHECK-NEXT: 0x0000000000000015 DEBUG 0x0
// CHECK-NEXT: 0x0000000000000000 NULL 0x0 // CHECK-NEXT: 0x0000000000000000 NULL 0x0
// CHECK-NEXT: ] // CHECK-NEXT: ]

View File

@ -22,7 +22,7 @@
# SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-DEFAULT: 5 .shstrtab 00000002 {{[0-9a-f]*}} # SEC-DEFAULT: 5 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-DEFAULT: 6 .symtab 00000030 {{[0-9a-f]*}} # SEC-DEFAULT: 6 .symtab 00000030 {{[0-9a-f]*}}
# SEC-DEFAULT: 7 .shstrtab 0000003c {{[0-9a-f]*}} # SEC-DEFAULT: 7 .shstrtab 00000032 {{[0-9a-f]*}}
# SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}} # SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}}
# Sections are put in order specified in linker script. # Sections are put in order specified in linker script.
@ -42,7 +42,7 @@
# SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA # SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA
# SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}} # SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-ORDER: 4 .shstrtab 0000003c {{[0-9a-f]*}} # SEC-ORDER: 4 .shstrtab 00000032 {{[0-9a-f]*}}
# SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}} # SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}}
# SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}} # SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}}
# SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA # SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA
@ -63,7 +63,7 @@
# SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-SWAP-NAMES: 5 .shstrtab 00000002 {{[0-9a-f]*}} # SEC-SWAP-NAMES: 5 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-SWAP-NAMES: 6 .symtab 00000030 {{[0-9a-f]*}} # SEC-SWAP-NAMES: 6 .symtab 00000030 {{[0-9a-f]*}}
# SEC-SWAP-NAMES: 7 .shstrtab 0000003c {{[0-9a-f]*}} # SEC-SWAP-NAMES: 7 .shstrtab 00000032 {{[0-9a-f]*}}
# SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}} # SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}}
# .shstrtab from the input object file is discarded. # .shstrtab from the input object file is discarded.
@ -100,7 +100,7 @@
# SEC-MULTI: 3 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-MULTI: 3 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-MULTI: 4 .shstrtab 00000002 {{[0-9a-f]*}} # SEC-MULTI: 4 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-MULTI: 5 .symtab 00000030 {{[0-9a-f]*}} # SEC-MULTI: 5 .symtab 00000030 {{[0-9a-f]*}}
# SEC-MULTI: 6 .shstrtab 00000036 {{[0-9a-f]*}} # SEC-MULTI: 6 .shstrtab 0000002c {{[0-9a-f]*}}
# SEC-MULTI: 7 .strtab 00000008 {{[0-9a-f]*}} # SEC-MULTI: 7 .strtab 00000008 {{[0-9a-f]*}}
.globl _start; .globl _start;

View File

@ -20,12 +20,12 @@
// CHECK: DynamicSection [ // CHECK: DynamicSection [
// CHECK-NEXT: Tag Type Name/Value // CHECK-NEXT: Tag Type Name/Value
// CHECK-NEXT: 0x000000000000001D RUNPATH foo:bar
// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x0000000000000007 RELA [[RELADDR]] // CHECK-NEXT: 0x0000000000000007 RELA [[RELADDR]]
// CHECK-NEXT: 0x0000000000000008 RELASZ [[RELSIZE]] (bytes) // CHECK-NEXT: 0x0000000000000008 RELASZ [[RELSIZE]] (bytes)
// CHECK-NEXT: 0x0000000000000009 RELAENT [[RELENT]] (bytes) // CHECK-NEXT: 0x0000000000000009 RELAENT [[RELENT]] (bytes)
// CHECK: 0x000000000000001D RUNPATH foo:bar // CHECK: 0x0000000000000015 DEBUG 0x0
// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x0000000000000015 DEBUG 0x0
// CHECK-NEXT: 0x0000000000000000 NULL 0x0 // CHECK-NEXT: 0x0000000000000000 NULL 0x0
// CHECK-NEXT: ] // CHECK-NEXT: ]

View File

@ -243,6 +243,8 @@
// CHECK: DynamicSection [ // CHECK: DynamicSection [
// CHECK-NEXT: Tag Type Name/Value // CHECK-NEXT: Tag Type Name/Value
// CHECK-NEXT: 0x0000001D RUNPATH foo:bar
// CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x00000011 REL [[RELADDR]] // CHECK-NEXT: 0x00000011 REL [[RELADDR]]
// CHECK-NEXT: 0x00000012 RELSZ [[RELSIZE]] (bytes) // CHECK-NEXT: 0x00000012 RELSZ [[RELSIZE]] (bytes)
// CHECK-NEXT: 0x00000013 RELENT [[RELENT]] (bytes) // CHECK-NEXT: 0x00000013 RELENT [[RELENT]] (bytes)
@ -251,8 +253,6 @@
// CHECK-NEXT: 0x00000005 STRTAB [[DYNSTRADDR]] // CHECK-NEXT: 0x00000005 STRTAB [[DYNSTRADDR]]
// CHECK-NEXT: 0x0000000A STRSZ // CHECK-NEXT: 0x0000000A STRSZ
// CHECK-NEXT: 0x00000004 HASH [[HASHADDR]] // CHECK-NEXT: 0x00000004 HASH [[HASHADDR]]
// CHECK-NEXT: 0x0000001D RUNPATH foo:bar
// CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x00000015 DEBUG 0x0 // CHECK-NEXT: 0x00000015 DEBUG 0x0
// CHECK-NEXT: 0x00000000 NULL 0x0 // CHECK-NEXT: 0x00000000 NULL 0x0
// CHECK-NEXT: ] // CHECK-NEXT: ]

View File

@ -59,9 +59,8 @@ _start:
// CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: EntrySize: 0
// CHECK-NEXT: SectionData ( // CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 00626172 002E7465 78740066 6F6F6261 |.bar..text.fooba| // CHECK-NEXT: 0000: 00626172 002E7465 78740066 6F6F6261 |.bar..text.fooba|
// CHECK-NEXT: 0010: 7200666F 6F626172 00666F6F 62617200 |r.foobar.foobar.| // CHECK-NEXT: 0010: 72002E73 796D7461 62002E73 68737472 |r..symtab..shstr|
// CHECK-NEXT: 0020: 2E73796D 74616200 2E736873 74727461 |.symtab..shstrta| // CHECK-NEXT: 0020: 74616200 2E737472 74616200 |tab..strtab.|
// CHECK-NEXT: 0030: 62002E73 74727461 6200 |b..strtab.|
// CHECK-NEXT: ) // CHECK-NEXT: )
// CHECK-NEXT:} // CHECK-NEXT:}
// CHECK: Name: .strtab // CHECK: Name: .strtab