Skip to content

Commit

Permalink
[JITLink][ELF] Support duplicated section names from object file
Browse files Browse the repository at this point in the history
ELF object files can contain duplicated sections (thus section symbols
as well), espeically when comdats/section groups are present. This patch
adds support for generating LinkGraph from object files that have
duplicated section names. This is the first step to properly model
comdats/section groups.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D114753
  • Loading branch information
cachemeifyoucan committed Jan 18, 2022
1 parent 347d4d7 commit 091e364
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 49 deletions.
67 changes: 33 additions & 34 deletions llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
Expand Up @@ -77,14 +77,14 @@ class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
return Obj.getHeader().e_type == llvm::ELF::ET_REL;
}

void setGraphSection(ELFSectionIndex SecIndex, Section &Sec) {
assert(!GraphSections.count(SecIndex) && "Duplicate section at index");
GraphSections[SecIndex] = &Sec;
void setGraphBlock(ELFSectionIndex SecIndex, Block *B) {
assert(!GraphBlocks.count(SecIndex) && "Duplicate section at index");
GraphBlocks[SecIndex] = B;
}

Section *getGraphSection(ELFSectionIndex SecIndex) {
auto I = GraphSections.find(SecIndex);
if (I == GraphSections.end())
Block *getGraphBlock(ELFSectionIndex SecIndex) {
auto I = GraphBlocks.find(SecIndex);
if (I == GraphBlocks.end())
return nullptr;
return I->second;
}
Expand Down Expand Up @@ -139,9 +139,9 @@ class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
const typename ELFFile::Elf_Shdr *SymTabSec = nullptr;
StringRef SectionStringTab;

// Maps ELF section indexes to LinkGraph Sections.
// Only SHF_ALLOC sections will have graph sections.
DenseMap<ELFSectionIndex, Section *> GraphSections;
// Maps ELF section indexes to LinkGraph Blocks.
// Only SHF_ALLOC sections will have graph blocks.
DenseMap<ELFSectionIndex, Block *> GraphBlocks;
DenseMap<ELFSymbolIndex, Symbol *> GraphSymbols;
DenseMap<const typename ELFFile::Elf_Shdr *,
ArrayRef<typename ELFFile::Elf_Word>>
Expand Down Expand Up @@ -316,20 +316,27 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
else
Prot = MemProt::Read | MemProt::Write;

auto &GraphSec = G->createSection(*Name, Prot);
// Look for existing sections first.
auto *GraphSec = G->findSectionByName(*Name);
if (!GraphSec)
GraphSec = &G->createSection(*Name, Prot);
assert(GraphSec->getMemProt() == Prot && "MemProt should match");

Block *B = nullptr;
if (Sec.sh_type != ELF::SHT_NOBITS) {
auto Data = Obj.template getSectionContentsAsArray<char>(Sec);
if (!Data)
return Data.takeError();

G->createContentBlock(GraphSec, *Data, orc::ExecutorAddr(Sec.sh_addr),
Sec.sh_addralign, 0);
B = &G->createContentBlock(*GraphSec, *Data,
orc::ExecutorAddr(Sec.sh_addr),
Sec.sh_addralign, 0);
} else
G->createZeroFillBlock(GraphSec, Sec.sh_size,
orc::ExecutorAddr(Sec.sh_addr), Sec.sh_addralign,
0);
B = &G->createZeroFillBlock(*GraphSec, Sec.sh_size,
orc::ExecutorAddr(Sec.sh_addr),
Sec.sh_addralign, 0);

setGraphSection(SecIndex, GraphSec);
setGraphBlock(SecIndex, B);
}

return Error::success();
Expand Down Expand Up @@ -427,28 +434,20 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
return NdxOrErr.takeError();
Shndx = *NdxOrErr;
}
if (auto *GraphSec = getGraphSection(Shndx)) {
Block *B = nullptr;
{
auto Blocks = GraphSec->blocks();
assert(Blocks.begin() != Blocks.end() && "No blocks for section");
assert(std::next(Blocks.begin()) == Blocks.end() &&
"Multiple blocks for section");
B = *Blocks.begin();
}

if (auto *B = getGraphBlock(Shndx)) {
LLVM_DEBUG({
dbgs() << " " << SymIndex
<< ": Creating defined graph symbol for ELF symbol \"" << *Name
<< "\"\n";
});

if (Sym.getType() == ELF::STT_SECTION)
*Name = GraphSec->getName();

// Model the section symbols as anonymous symbol.
auto &GSym =
G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L, S,
Sym.getType() == ELF::STT_FUNC, false);
Sym.getType() == ELF::STT_SECTION
? G->addAnonymousSymbol(*B, Sym.getValue(), Sym.st_size, false,
false)
: G->addDefinedSymbol(*B, Sym.getValue(), *Name, Sym.st_size, L,
S, Sym.getType() == ELF::STT_FUNC, false);
setGraphSymbol(SymIndex, GSym);
}
} else if (Sym.isUndefined() && Sym.isExternal()) {
Expand Down Expand Up @@ -500,8 +499,8 @@ Error ELFLinkGraphBuilder<ELFT>::forEachRelocation(
}

// Lookup the link-graph node corresponding to the target section name.
Section *GraphSect = G->findSectionByName(*Name);
if (!GraphSect)
auto *BlockToFix = getGraphBlock(RelSect.sh_info);
if (!BlockToFix)
return make_error<StringError>(
"Refencing a section that wasn't added to the graph: " + *Name,
inconvertibleErrorCode());
Expand All @@ -512,7 +511,7 @@ Error ELFLinkGraphBuilder<ELFT>::forEachRelocation(

// Let the callee process relocation entries one by one.
for (const typename ELFT::Rela &R : *RelEntries)
if (Error Err = Func(R, **FixupSection, *GraphSect))
if (Error Err = Func(R, **FixupSection, *BlockToFix))
return Err;

LLVM_DEBUG(dbgs() << "\n");
Expand Down
9 changes: 4 additions & 5 deletions llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
Expand Up @@ -101,7 +101,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {

Error addSingleRelocation(const typename ELFT::Rela &Rel,
const typename ELFT::Shdr &FixupSect,
Section &GraphSection) {
Block &BlockToFix) {
using Base = ELFLinkGraphBuilder<ELFT>;

uint32_t SymbolIndex = Rel.getSymbol(false);
Expand All @@ -124,18 +124,17 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
return Kind.takeError();

int64_t Addend = Rel.r_addend;
Block *BlockToFix = *(GraphSection.blocks().begin());
orc::ExecutorAddr FixupAddress =
orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
Edge::OffsetT Offset = FixupAddress - BlockToFix->getAddress();
Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
Edge GE(*Kind, Offset, *GraphSymbol, Addend);
LLVM_DEBUG({
dbgs() << " ";
printEdge(dbgs(), *BlockToFix, GE, aarch64::getEdgeKindName(*Kind));
printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(*Kind));
dbgs() << "\n";
});

BlockToFix->addEdge(std::move(GE));
BlockToFix.addEdge(std::move(GE));
return Error::success();
}

Expand Down
9 changes: 4 additions & 5 deletions llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
Expand Up @@ -349,7 +349,7 @@ class ELFLinkGraphBuilder_riscv : public ELFLinkGraphBuilder<ELFT> {

Error addSingleRelocation(const typename ELFT::Rela &Rel,
const typename ELFT::Shdr &FixupSect,
Section &GraphSection) {
Block &BlockToFix) {
using Base = ELFLinkGraphBuilder<ELFT>;

uint32_t SymbolIndex = Rel.getSymbol(false);
Expand All @@ -372,17 +372,16 @@ class ELFLinkGraphBuilder_riscv : public ELFLinkGraphBuilder<ELFT> {
return Kind.takeError();

int64_t Addend = Rel.r_addend;
Block *BlockToFix = *(GraphSection.blocks().begin());
auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
Edge::OffsetT Offset = FixupAddress - BlockToFix->getAddress();
Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
Edge GE(*Kind, Offset, *GraphSymbol, Addend);
LLVM_DEBUG({
dbgs() << " ";
printEdge(dbgs(), *BlockToFix, GE, riscv::getEdgeKindName(*Kind));
printEdge(dbgs(), BlockToFix, GE, riscv::getEdgeKindName(*Kind));
dbgs() << "\n";
});

BlockToFix->addEdge(std::move(GE));
BlockToFix.addEdge(std::move(GE));
return Error::success();
}

Expand Down
9 changes: 4 additions & 5 deletions llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
Expand Up @@ -172,7 +172,7 @@ class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {

Error addSingleRelocation(const typename ELFT::Rela &Rel,
const typename ELFT::Shdr &FixupSection,
Section &GraphSection) {
Block &BlockToFix) {
using Base = ELFLinkGraphBuilder<ELFT>;

uint32_t SymbolIndex = Rel.getSymbol(false);
Expand Down Expand Up @@ -248,17 +248,16 @@ class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
}
}

Block *BlockToFix = *(GraphSection.blocks().begin());
auto FixupAddress = orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset;
Edge::OffsetT Offset = FixupAddress - BlockToFix->getAddress();
Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
Edge GE(Kind, Offset, *GraphSymbol, Addend);
LLVM_DEBUG({
dbgs() << " ";
printEdge(dbgs(), *BlockToFix, GE, x86_64::getEdgeKindName(Kind));
printEdge(dbgs(), BlockToFix, GE, x86_64::getEdgeKindName(Kind));
dbgs() << "\n";
});

BlockToFix->addEdge(std::move(GE));
BlockToFix.addEdge(std::move(GE));
return Error::success();
}

Expand Down
27 changes: 27 additions & 0 deletions llvm/test/ExecutionEngine/JITLink/X86/ELF_comdat.s
@@ -0,0 +1,27 @@
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t
// RUN: llvm-jitlink -noexec %t

.section .foo,"axG",@progbits,g1,comdat
.globl g1
g1:
call test1
retq

.section .baz,"axG",@progbits,g1,comdat
test1:
retq

.section .bar,"axG",@progbits,g2,comdat
.globl g2
g2:
call test2
retq

.section .baz,"axG",@progbits,g2,comdat
test2:
retq

.text
.globl main
main:
retq

0 comments on commit 091e364

Please sign in to comment.