diff options
Diffstat (limited to 'ELF/InputSection.cpp')
-rw-r--r-- | ELF/InputSection.cpp | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp index 4af05c1a187b..e82f8c3016fa 100644 --- a/ELF/InputSection.cpp +++ b/ELF/InputSection.cpp @@ -20,6 +20,7 @@ #include "Target.h" #include "Thunks.h" #include "llvm/Object/Decompressor.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Path.h" @@ -72,6 +73,16 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, this->Alignment = V; } +// Drop SHF_GROUP bit unless we are producing a re-linkable object file. +// SHF_GROUP is a marker that a section belongs to some comdat group. +// That flag doesn't make sense in an executable. +static uint64_t getFlags(uint64_t Flags) { + Flags &= ~(uint64_t)SHF_INFO_LINK; + if (!Config->Relocatable) + Flags &= ~(uint64_t)SHF_GROUP; + return Flags; +} + // GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of // March 2017) fail to infer section types for sections starting with // ".init_array." or ".fini_array.". They set SHT_PROGBITS instead of @@ -94,7 +105,7 @@ template <class ELFT> InputSectionBase::InputSectionBase(elf::ObjectFile<ELFT> *File, const typename ELFT::Shdr *Hdr, StringRef Name, Kind SectionKind) - : InputSectionBase(File, Hdr->sh_flags & ~SHF_INFO_LINK, + : InputSectionBase(File, getFlags(Hdr->sh_flags), getType(Hdr->sh_type, Name), Hdr->sh_entsize, Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign, getSectionContents(File, Hdr), Name, SectionKind) { @@ -308,23 +319,21 @@ OutputSection *InputSection::getParent() const { return cast_or_null<OutputSection>(Parent); } -void InputSection::copyShtGroup(uint8_t *Buf) { - assert(this->Type == SHT_GROUP); +// Copy SHT_GROUP section contents. Used only for the -r option. +template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) { + // ELFT::Word is the 32-bit integral type in the target endianness. + typedef typename ELFT::Word u32; + ArrayRef<u32> From = getDataAs<u32>(); + auto *To = reinterpret_cast<u32 *>(Buf); - ArrayRef<uint32_t> From = getDataAs<uint32_t>(); - uint32_t *To = reinterpret_cast<uint32_t *>(Buf); - - // First entry is a flag word, we leave it unchanged. + // The first entry is not a section number but a flag. *To++ = From[0]; - // Here we adjust indices of sections that belong to group as it - // might change during linking. + // Adjust section numbers because section numbers in an input object + // files are different in the output. ArrayRef<InputSectionBase *> Sections = this->File->getSections(); - for (uint32_t Val : From.slice(1)) { - uint32_t Index = read32(&Val, Config->Endianness); - write32(To++, Sections[Index]->getOutputSection()->SectionIndex, - Config->Endianness); - } + for (uint32_t Idx : From.slice(1)) + *To++ = Sections[Idx]->getOutputSection()->SectionIndex; } InputSectionBase *InputSection::getRelocatedSection() { @@ -682,7 +691,7 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) { // Patch a nop (0x60000000) to a ld. if (BufLoc + 8 <= BufEnd && read32be(BufLoc + 4) == 0x60000000) write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1) - // fallthrough + LLVM_FALLTHROUGH; default: Target->relocateOne(BufLoc, Type, TargetVA); break; @@ -712,10 +721,9 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { return; } - // If -r is given, linker should keep SHT_GROUP sections. We should fixup - // them, see copyShtGroup(). + // If -r is given, we may have a SHT_GROUP section. if (this->Type == SHT_GROUP) { - copyShtGroup(Buf + OutSecOff); + copyShtGroup<ELFT>(Buf + OutSecOff); return; } |