[ELF] Pass Ctx &

This commit is contained in:
Fangrui Song
2024-10-10 21:36:51 -07:00
parent 3cb4d20d5b
commit bf81bd800f
5 changed files with 46 additions and 19 deletions

View File

@@ -48,6 +48,10 @@ public:
bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
private:
void encodeAluGroup(uint8_t *loc, const Relocation &rel, uint64_t val,
int group, bool check) const;
};
enum class CodeState { Data = 0, Thumb = 2, Arm = 4 };
} // namespace
@@ -534,8 +538,8 @@ static std::pair<uint32_t, uint32_t> getRemAndLZForGroup(unsigned group,
return {rem, lz};
}
static void encodeAluGroup(uint8_t *loc, const Relocation &rel, uint64_t val,
int group, bool check) {
void ARM::encodeAluGroup(uint8_t *loc, const Relocation &rel, uint64_t val,
int group, bool check) const {
// ADD/SUB (immediate) add = bit23, sub = bit22
// immediate field carries is a 12-bit modified immediate, made up of a 4-bit
// even rotate right and an 8-bit immediate.

View File

@@ -159,7 +159,7 @@ static bool isJirl(uint32_t insn) {
return (insn & 0xfc000000) == JIRL;
}
static void handleUleb128(uint8_t *loc, uint64_t val) {
static void handleUleb128(Ctx &ctx, uint8_t *loc, uint64_t val) {
const uint32_t maxcount = 1 + 64 / 7;
uint32_t count;
const char *error = nullptr;
@@ -700,7 +700,7 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
write64le(loc, read64le(loc) + val);
return;
case R_LARCH_ADD_ULEB128:
handleUleb128(loc, val);
handleUleb128(ctx, loc, val);
return;
case R_LARCH_SUB6:
*loc = (*loc & 0xc0) | ((*loc - val) & 0x3f);
@@ -718,7 +718,7 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
write64le(loc, read64le(loc) - val);
return;
case R_LARCH_SUB_ULEB128:
handleUleb128(loc, -val);
handleUleb128(ctx, loc, -val);
return;
case R_LARCH_MARK_LA:

View File

@@ -39,6 +39,12 @@ public:
RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
private:
void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
};
} // namespace
@@ -344,7 +350,8 @@ void X86::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
}
static void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
void X86::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
if (rel.type == R_386_TLS_GD) {
// Convert (loc[-2] == 0x04)
// leal x@tlsgd(, %ebx, 1), %eax
@@ -379,7 +386,8 @@ static void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
}
}
static void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) {
void X86::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
if (rel.type == R_386_TLS_GD) {
// Convert (loc[-2] == 0x04)
// leal x@tlsgd(, %ebx, 1), %eax
@@ -413,7 +421,8 @@ static void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) {
// In some conditions, relocations can be optimized to avoid using GOT.
// This function does that for Initial Exec to Local Exec case.
static void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
void X86::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
// Ulrich's document section 6.2 says that @gotntpoff can
// be used with MOVL or ADDL instructions.
// @indntpoff is similar to @gotntpoff, but for use in
@@ -450,7 +459,8 @@ static void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
write32le(loc, val);
}
static void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
void X86::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
if (rel.type == R_386_TLS_LDO_32) {
write32le(loc, val);
return;

View File

@@ -50,6 +50,12 @@ public:
bool deleteFallThruJmpInsn(InputSection &is, InputFile *file,
InputSection *nextIS) const override;
bool relaxOnce(int pass) const override;
private:
void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
};
} // namespace
@@ -460,7 +466,8 @@ RelType X86_64::getDynRel(RelType type) const {
return R_X86_64_NONE;
}
static void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
if (rel.type == R_X86_64_TLSGD) {
// Convert
// .byte 0x66
@@ -500,7 +507,8 @@ static void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
}
}
static void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) {
void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
if (rel.type == R_X86_64_TLSGD) {
// Convert
// .byte 0x66
@@ -541,7 +549,8 @@ static void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) {
// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
// R_X86_64_TPOFF32 so that it does not use GOT.
static void relaxTlsIeToLe(uint8_t *loc, const Relocation &, uint64_t val) {
void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
uint8_t *inst = loc - 3;
uint8_t reg = loc[-1] >> 3;
uint8_t *regSlot = loc - 1;
@@ -582,7 +591,8 @@ static void relaxTlsIeToLe(uint8_t *loc, const Relocation &, uint64_t val) {
write32le(loc, val + 4);
}
static void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
void X86_64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
const uint8_t inst[] = {
0x66, 0x66, // .word 0x6666
0x66, // .byte 0x66

View File

@@ -479,7 +479,7 @@ static void sortSections(MutableArrayRef<InputSectionBase *> vec,
// --sort-section is handled as an inner SORT command.
// 3. If one SORT command is given, and if it is SORT_NONE, don't sort.
// 4. If no SORT command is given, sort according to --sort-section.
static void sortInputSections(MutableArrayRef<InputSectionBase *> vec,
static void sortInputSections(Ctx &ctx, MutableArrayRef<InputSectionBase *> vec,
SortSectionPolicy outer,
SortSectionPolicy inner) {
if (outer == SortSectionPolicy::None)
@@ -517,6 +517,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
for (size_t i = begin; i != end; ++i)
ret[i] = sections[indexes[i]];
sortInputSections(
ctx,
MutableArrayRef<InputSectionBase *>(ret).slice(begin, end - begin),
ctx.arg.sortSection, SortSectionPolicy::None);
};
@@ -584,6 +585,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
// ret[sizeBeforeCurrPat,ret.size()) are already in the input order, so we
// just sort by sortOuter and sortInner.
sortInputSections(
ctx,
MutableArrayRef<InputSectionBase *>(ret).slice(sizeBeforeCurrPat),
pat.sortOuter, pat.sortInner);
sizeAfterPrevSort = ret.size();
@@ -865,7 +867,8 @@ static OutputDesc *createSection(InputSectionBase *isec, StringRef outsecName) {
return osd;
}
static OutputDesc *addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
static OutputDesc *addInputSec(Ctx &ctx,
StringMap<TinyPtrVector<OutputSection *>> &map,
InputSectionBase *isec, StringRef outsecName) {
// Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r
// option is given. A section with SHT_GROUP defines a "section group", and
@@ -983,7 +986,7 @@ void LinkerScript::addOrphanSections() {
} else if (OutputSection *sec = findByName(sectionCommands, name)) {
sec->recordSection(s);
} else {
if (OutputDesc *osd = addInputSec(map, s, name))
if (OutputDesc *osd = addInputSec(ctx, map, s, name))
v.push_back(osd);
assert(isa<MergeInputSection>(s) ||
s->getOutputSection()->sectionIndex == UINT32_MAX);
@@ -1114,7 +1117,7 @@ LinkerScript::findMemoryRegion(OutputSection *sec, MemoryRegion *hint) {
return {nullptr, nullptr};
}
static OutputSection *findFirstSection(PhdrEntry *load) {
static OutputSection *findFirstSection(Ctx &ctx, PhdrEntry *load) {
for (OutputSection *sec : ctx.outputSections)
if (sec->ptLoad == load)
return sec;
@@ -1187,7 +1190,7 @@ bool LinkerScript::assignOffsets(OutputSection *sec) {
// Propagate state->lmaOffset to the first "non-header" section.
if (PhdrEntry *l = sec->ptLoad)
if (sec == findFirstSection(l))
if (sec == findFirstSection(ctx, l))
l->lmaOffset = state->lmaOffset;
// We can call this method multiple times during the creation of
@@ -1462,7 +1465,7 @@ void LinkerScript::allocateHeaders(SmallVector<PhdrEntry *, 0> &phdrs) {
ctx.out.elfHeader->ptLoad = nullptr;
ctx.out.programHeaders->ptLoad = nullptr;
firstPTLoad->firstSec = findFirstSection(firstPTLoad);
firstPTLoad->firstSec = findFirstSection(ctx, firstPTLoad);
llvm::erase_if(phdrs,
[](const PhdrEntry *e) { return e->p_type == PT_PHDR; });