mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-02 13:12:09 +00:00
[ELF] Move SHT_REL/SHT_RELA handling from createInputSection to initializeSections
This simplifies the code a bit. While here, * change the `multiple relocation sections` diagnostic from `fatal` to `error` and include the relocated section name. * drop less useful name from `getRelocTarget`. Without -r/--emit-relocs we don't need to get SHT_REL/SHT_RELA names.
This commit is contained in:
parent
41d05e29c0
commit
288082d45d
@ -643,12 +643,52 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
|
|||||||
continue;
|
continue;
|
||||||
const Elf_Shdr &sec = objSections[i];
|
const Elf_Shdr &sec = objSections[i];
|
||||||
|
|
||||||
if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA)
|
if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA) {
|
||||||
this->sections[i] = createInputSection(i, sec, shstrtab);
|
// Find a relocation target section and associate this section with that.
|
||||||
|
// Target may have been discarded if it is in a different section group
|
||||||
|
// and the group is discarded, even though it's a violation of the spec.
|
||||||
|
// We handle that situation gracefully by discarding dangling relocation
|
||||||
|
// sections.
|
||||||
|
const uint32_t info = sec.sh_info;
|
||||||
|
InputSectionBase *s = getRelocTarget(i, sec, info);
|
||||||
|
if (!s)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// ELF spec allows mergeable sections with relocations, but they are rare,
|
||||||
|
// and it is in practice hard to merge such sections by contents, because
|
||||||
|
// applying relocations at end of linking changes section contents. So, we
|
||||||
|
// simply handle such sections as non-mergeable ones. Degrading like this
|
||||||
|
// is acceptable because section merging is optional.
|
||||||
|
if (auto *ms = dyn_cast<MergeInputSection>(s)) {
|
||||||
|
s = make<InputSection>(ms->file, ms->flags, ms->type, ms->alignment,
|
||||||
|
ms->data(), ms->name);
|
||||||
|
sections[info] = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->relSecIdx != 0)
|
||||||
|
error(
|
||||||
|
toString(s) +
|
||||||
|
": multiple relocation sections to one section are not supported");
|
||||||
|
s->relSecIdx = i;
|
||||||
|
|
||||||
|
// Relocation sections are usually removed from the output, so return
|
||||||
|
// `nullptr` for the normal case. However, if -r or --emit-relocs is
|
||||||
|
// specified, we need to copy them to the output. (Some post link analysis
|
||||||
|
// tools specify --emit-relocs to obtain the information.)
|
||||||
|
if (config->copyRelocs) {
|
||||||
|
auto *isec = make<InputSection>(
|
||||||
|
*this, sec, check(obj.getSectionName(sec, shstrtab)));
|
||||||
|
// If the relocated section is discarded (due to /DISCARD/ or
|
||||||
|
// --gc-sections), the relocation section should be discarded as well.
|
||||||
|
s->dependentSections.push_back(isec);
|
||||||
|
sections[i] = isec;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// A SHF_LINK_ORDER section with sh_link=0 is handled as if it did not have
|
// A SHF_LINK_ORDER section with sh_link=0 is handled as if it did not have
|
||||||
// the flag.
|
// the flag.
|
||||||
if (!(sec.sh_flags & SHF_LINK_ORDER) || !sec.sh_link)
|
if (!sec.sh_link || !(sec.sh_flags & SHF_LINK_ORDER))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
InputSectionBase *linkSec = nullptr;
|
InputSectionBase *linkSec = nullptr;
|
||||||
@ -828,9 +868,9 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
InputSectionBase *ObjFile<ELFT>::getRelocTarget(uint32_t idx, StringRef name,
|
InputSectionBase *ObjFile<ELFT>::getRelocTarget(uint32_t idx,
|
||||||
const Elf_Shdr &sec) {
|
const Elf_Shdr &sec,
|
||||||
uint32_t info = sec.sh_info;
|
uint32_t info) {
|
||||||
if (info < this->sections.size()) {
|
if (info < this->sections.size()) {
|
||||||
InputSectionBase *target = this->sections[info];
|
InputSectionBase *target = this->sections[info];
|
||||||
|
|
||||||
@ -844,18 +884,11 @@ InputSectionBase *ObjFile<ELFT>::getRelocTarget(uint32_t idx, StringRef name,
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
error(toString(this) + Twine(": relocation section ") + name + " (index " +
|
error(toString(this) + Twine(": relocation section (index ") + Twine(idx) +
|
||||||
Twine(idx) + ") has invalid sh_info (" + Twine(info) + ")");
|
") has invalid sh_info (" + Twine(info) + ")");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a regular InputSection class that has the same contents
|
|
||||||
// as a given section.
|
|
||||||
static InputSection *toRegularSection(MergeInputSection *sec) {
|
|
||||||
return make<InputSection>(sec->file, sec->flags, sec->type, sec->alignment,
|
|
||||||
sec->data(), sec->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
|
InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
|
||||||
const Elf_Shdr &sec,
|
const Elf_Shdr &sec,
|
||||||
@ -908,10 +941,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (sec.sh_type) {
|
if (sec.sh_type == SHT_LLVM_DEPENDENT_LIBRARIES && !config->relocatable) {
|
||||||
case SHT_LLVM_DEPENDENT_LIBRARIES: {
|
|
||||||
if (config->relocatable)
|
|
||||||
break;
|
|
||||||
ArrayRef<char> data =
|
ArrayRef<char> data =
|
||||||
CHECK(this->getObj().template getSectionContentsAsArray<char>(sec), this);
|
CHECK(this->getObj().template getSectionContentsAsArray<char>(sec), this);
|
||||||
if (!data.empty() && data.back() != '\0') {
|
if (!data.empty() && data.back() != '\0') {
|
||||||
@ -927,45 +957,6 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
|
|||||||
}
|
}
|
||||||
return &InputSection::discarded;
|
return &InputSection::discarded;
|
||||||
}
|
}
|
||||||
case SHT_RELA:
|
|
||||||
case SHT_REL: {
|
|
||||||
// Find a relocation target section and associate this section with that.
|
|
||||||
// Target may have been discarded if it is in a different section group
|
|
||||||
// and the group is discarded, even though it's a violation of the
|
|
||||||
// spec. We handle that situation gracefully by discarding dangling
|
|
||||||
// relocation sections.
|
|
||||||
InputSectionBase *target = getRelocTarget(idx, name, sec);
|
|
||||||
if (!target)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// ELF spec allows mergeable sections with relocations, but they are
|
|
||||||
// rare, and it is in practice hard to merge such sections by contents,
|
|
||||||
// because applying relocations at end of linking changes section
|
|
||||||
// contents. So, we simply handle such sections as non-mergeable ones.
|
|
||||||
// Degrading like this is acceptable because section merging is optional.
|
|
||||||
if (auto *ms = dyn_cast<MergeInputSection>(target)) {
|
|
||||||
target = toRegularSection(ms);
|
|
||||||
this->sections[sec.sh_info] = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target->relSecIdx != 0)
|
|
||||||
fatal(toString(this) +
|
|
||||||
": multiple relocation sections to one section are not supported");
|
|
||||||
target->relSecIdx = idx;
|
|
||||||
|
|
||||||
// Relocation sections are usually removed from the output, so return
|
|
||||||
// `nullptr` for the normal case. However, if -r or --emit-relocs is
|
|
||||||
// specified, we need to copy them to the output. (Some post link analysis
|
|
||||||
// tools specify --emit-relocs to obtain the information.)
|
|
||||||
if (!config->copyRelocs)
|
|
||||||
return nullptr;
|
|
||||||
InputSection *relocSec = make<InputSection>(*this, sec, name);
|
|
||||||
// If the relocated section is discarded (due to /DISCARD/ or
|
|
||||||
// --gc-sections), the relocation section should be discarded as well.
|
|
||||||
target->dependentSections.push_back(relocSec);
|
|
||||||
return relocSec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.startswith(".n")) {
|
if (name.startswith(".n")) {
|
||||||
// The GNU linker uses .note.GNU-stack section as a marker indicating
|
// The GNU linker uses .note.GNU-stack section as a marker indicating
|
||||||
|
@ -286,8 +286,8 @@ private:
|
|||||||
void initializeSymbols();
|
void initializeSymbols();
|
||||||
void initializeJustSymbols();
|
void initializeJustSymbols();
|
||||||
|
|
||||||
InputSectionBase *getRelocTarget(uint32_t idx, StringRef name,
|
InputSectionBase *getRelocTarget(uint32_t idx, const Elf_Shdr &sec,
|
||||||
const Elf_Shdr &sec);
|
uint32_t info);
|
||||||
InputSectionBase *createInputSection(uint32_t idx, const Elf_Shdr &sec,
|
InputSectionBase *createInputSection(uint32_t idx, const Elf_Shdr &sec,
|
||||||
StringRef shstrtab);
|
StringRef shstrtab);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# RUN: yaml2obj --docnum=1 %s -o %t1.o
|
# RUN: yaml2obj --docnum=1 %s -o %t1.o
|
||||||
# RUN: not ld.lld %t1.o -o /dev/null 2>&1 | FileCheck %s
|
# RUN: not ld.lld %t1.o -o /dev/null 2>&1 | FileCheck %s
|
||||||
# CHECK: error: {{.*}}.o: relocation section .rela.text (index 2) has invalid sh_info (0)
|
# CHECK: error: {{.*}}.o: relocation section (index 2) has invalid sh_info (0)
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
@ -25,7 +25,7 @@ Symbols:
|
|||||||
|
|
||||||
# RUN: yaml2obj --docnum=2 %s -o %t2.o
|
# RUN: yaml2obj --docnum=2 %s -o %t2.o
|
||||||
# RUN: not ld.lld %t2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2
|
# RUN: not ld.lld %t2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2
|
||||||
# ERR2: error: {{.*}}.o: relocation section .rela.text (index 2) has invalid sh_info (99)
|
# ERR2: error: {{.*}}.o: relocation section (index 2) has invalid sh_info (99)
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# RUN: yaml2obj %s -o %t1.o
|
# RUN: yaml2obj %s -o %t1.o
|
||||||
# RUN: not ld.lld %t1.o -o /dev/null 2>&1 | FileCheck %s
|
# RUN: not ld.lld %t1.o -o /dev/null 2>&1 | FileCheck %s
|
||||||
# CHECK: error: {{.*}}1.o: multiple relocation sections to one section are not supported
|
# CHECK: error: {{.*}}1.o:(.text): multiple relocation sections to one section are not supported
|
||||||
|
|
||||||
## The file has two relocation sections referring to a single target section.
|
## The file has two relocation sections referring to a single target section.
|
||||||
## Multiple relocation sections to one section are not supported, check we report this case.
|
## Multiple relocation sections to one section are not supported, check we report this case.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user