Skip to content

Commit

Permalink
Include local symbols in the dynamic symbol table
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasSte committed Jan 21, 2025
1 parent 97c03b9 commit 838a68c
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 2 deletions.
40 changes: 38 additions & 2 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2167,8 +2167,44 @@ void SymbolTableBaseSection::sortSymTabSymbols() {

void SymbolTableBaseSection::addSymbol(Symbol *b) {
// Adding a local symbol to a .dynsym is a bug.
assert(this->type != SHT_DYNSYM || !b->isLocal());
symbols.push_back({b, strTabSec.addString(b->getName(), false)});
// In SBF, we require all function symbols to be in the dynamic symbol table,
// no matter their visibility, so adding local symbols is not a bug for
// SBFv3.
assert(this->type != SHT_DYNSYM || !b->isLocal() ||
(config->emachine == EM_SBF && config->eflags == 0x3));

unsigned Offset;
if (this->type == SHT_DYNSYM && b->isLocal() &&
config->strip != StripPolicy::None) {
// Including the symbol name to the dynamic symbol table may increase the
// contract size in more than 20kb, so whenever we want to strip
// information, we can assign the same symbol to all local functions.
const static unsigned HiddenOffset =
strTabSec.addString("hidden_func", false);
Offset = HiddenOffset;
} else {
Offset = strTabSec.addString(b->getName(), false);
}

symbols.push_back({b, Offset});
}

void SymbolTableBaseSection::sortAndDedupSymbolsByValue() {
// The SBFv3 loader requires the symbol table to be sorted by st_value.
llvm::stable_sort(symbols,
[](const SymbolTableEntry &a, const SymbolTableEntry &b) {
return a.sym->getVA() < b.sym->getVA();
});

// The linker can assign the same address to two different functions if
// their code is the same. When that happens, we must deduplicate symbols
// by st_value.
symbols.erase(
std::unique(symbols.begin(), symbols.end(),
[](const SymbolTableEntry &a, const SymbolTableEntry &b) {
return a.sym->getVA() == b.sym->getVA();
}),
symbols.end());
}

size_t SymbolTableBaseSection::getSymbolIndex(Symbol *sym) {
Expand Down
1 change: 1 addition & 0 deletions lld/ELF/SyntheticSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ class SymbolTableBaseSection : public SyntheticSection {
unsigned getNumSymbols() const { return symbols.size() + 1; }
size_t getSymbolIndex(Symbol *sym);
ArrayRef<SymbolTableEntry> getSymbols() const { return symbols; }
void sortAndDedupSymbolsByValue();

protected:
void sortSymTabSymbols();
Expand Down
28 changes: 28 additions & 0 deletions lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@ static OutputSection *findSection(StringRef name, unsigned partition = 1) {
return nullptr;
}

static bool isSbfV3() {
return config->emachine == EM_SBF && config->eflags == 0x3;
}

template <class ELFT> void elf::createSyntheticSections() {
// Initialize all pointers with NULL. This is needed because
// you can call lld::elf::main more than once as a library.
Expand Down Expand Up @@ -773,6 +777,11 @@ static void demoteAndCopyLocalSymbols() {
demoteDefined(*dr, sectionIndexMap);
else if (in.symTab && includeInSymtab(*b) && shouldKeepInSymtab(*dr))
in.symTab->addSymbol(b);

// We want local functions in the dynamic symbol table for SBFv3
if (isSbfV3() && includeInSymtab(*b) && shouldKeepInSymtab(*dr) &&
b->type == STT_FUNC)
partitions[b->partition - 1].dynSymTab->addSymbol(b);
}
}
}
Expand Down Expand Up @@ -1692,6 +1701,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
AArch64Err843419Patcher a64p;
ARMErr657417Patcher a32p;
script->assignAddresses();
bool SbfDuplicateRemoval = false;
// .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they
// do require the relative addresses of OutputSections because linker scripts
// can assign Virtual Addresses to OutputSections that are not monotonically
Expand Down Expand Up @@ -1742,6 +1752,17 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
}

const Defined *changedSym = script->assignAddresses();

if (!SbfDuplicateRemoval && isSbfV3()) {
// When we deduplicate symbols, the address dependent content must be
// recalculated as the symbol table might have been shortened.
for (Partition &part: partitions) {
part.dynSymTab->sortAndDedupSymbolsByValue();
}
SbfDuplicateRemoval = true;
changed = true;
}

if (!changed) {
// Some symbols may be dependent on section addresses. When we break the
// loop, the symbol values are finalized because a previous
Expand Down Expand Up @@ -2073,6 +2094,13 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (auto *file = dyn_cast_or_null<SharedFile>(sym->file))
if (file->isNeeded && !sym->isUndefined())
addVerneed(sym);
} else if (isSbfV3() && includeInSymtab(*sym) && isa<Defined>(sym) &&
sym->type == STT_FUNC) {
// We need want local functions in the dynamic symbol table for SBFv3
const Defined *Def = dyn_cast<Defined>(sym);
if (shouldKeepInSymtab(*Def)) {
partitions[sym->partition - 1].dynSymTab->addSymbol(sym);
}
}
}

Expand Down

0 comments on commit 838a68c

Please sign in to comment.