diff options
| author | Fangrui Song <i@maskray.me> | 2024-12-01 12:03:35 -0800 |
|---|---|---|
| committer | Fangrui Song <i@maskray.me> | 2024-12-01 12:03:35 -0800 |
| commit | 9becc4a3c966d46b95ddfcf856b3c433c030db1e (patch) | |
| tree | 4f20a861453c6bed66d4f156b6130f17285e9cb7 /lld | |
| parent | 77767986ed423f868805d8ee9652f6dcc85c6adc (diff) | |
[ELF] ObjFile::parse: check EM_AARCH64 for SHT_AARCH64_MEMTAG_GLOBAL_STATIC
and reorder sh_type checks to make SHT_PROGBITS/SHT_GROUP fast.
Diffstat (limited to 'lld')
| -rw-r--r-- | lld/ELF/InputFiles.cpp | 135 |
1 files changed, 71 insertions, 64 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 30fbb5d9fe45..f262e537a6d0 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -556,12 +556,45 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) { sections.resize(size); for (size_t i = 0; i != size; ++i) { const Elf_Shdr &sec = objSections[i]; + if (LLVM_LIKELY(sec.sh_type == SHT_PROGBITS)) + continue; + if (LLVM_LIKELY(sec.sh_type == SHT_GROUP)) { + StringRef signature = getShtGroupSignature(objSections, sec); + ArrayRef<Elf_Word> entries = + CHECK2(obj.template getSectionContentsAsArray<Elf_Word>(sec), this); + if (entries.empty()) + Fatal(ctx) << this << ": empty SHT_GROUP"; + + Elf_Word flag = entries[0]; + if (flag && flag != GRP_COMDAT) + Fatal(ctx) << this << ": unsupported SHT_GROUP format"; + + bool keepGroup = !flag || ignoreComdats || + ctx.symtab->comdatGroups + .try_emplace(CachedHashStringRef(signature), this) + .second; + if (keepGroup) { + if (!ctx.arg.resolveGroups) + sections[i] = createInputSection( + i, sec, check(obj.getSectionName(sec, shstrtab))); + } else { + // Otherwise, discard group members. + for (uint32_t secIndex : entries.slice(1)) { + if (secIndex >= size) + Fatal(ctx) << this + << ": invalid section index in group: " << secIndex; + sections[secIndex] = &InputSection::discarded; + } + } + continue; + } + if (sec.sh_type == SHT_LLVM_DEPENDENT_LIBRARIES && !ctx.arg.relocatable) { StringRef name = check(obj.getSectionName(sec, shstrtab)); ArrayRef<char> data = CHECK2( this->getObj().template getSectionContentsAsArray<char>(sec), this); if (!data.empty() && data.back() != '\0') { - ErrAlways(ctx) + Err(ctx) << this << ": corrupted dependent libraries section (unterminated string): " << name; @@ -572,74 +605,48 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) { d += s.size() + 1; } } - this->sections[i] = &InputSection::discarded; + sections[i] = &InputSection::discarded; continue; } - if (sec.sh_type == SHT_ARM_ATTRIBUTES && ctx.arg.emachine == EM_ARM) { - ARMAttributeParser attributes; - ArrayRef<uint8_t> contents = - check(this->getObj().getSectionContents(sec)); - StringRef name = check(obj.getSectionName(sec, shstrtab)); - this->sections[i] = &InputSection::discarded; - if (Error e = attributes.parse(contents, ekind == ELF32LEKind - ? llvm::endianness::little - : llvm::endianness::big)) { - InputSection isec(*this, sec, name); - Warn(ctx) << &isec << ": " << std::move(e); - } else { - updateSupportedARMFeatures(ctx, attributes); - updateARMVFPArgs(ctx, attributes, this); - - // FIXME: Retain the first attribute section we see. The eglibc ARM - // dynamic loaders require the presence of an attribute section for - // dlopen to work. In a full implementation we would merge all attribute - // sections. - if (ctx.in.attributes == nullptr) { - ctx.in.attributes = std::make_unique<InputSection>(*this, sec, name); - this->sections[i] = ctx.in.attributes.get(); + switch (ctx.arg.emachine) { + case EM_ARM: + if (sec.sh_type == SHT_ARM_ATTRIBUTES) { + ARMAttributeParser attributes; + ArrayRef<uint8_t> contents = + check(this->getObj().getSectionContents(sec)); + StringRef name = check(obj.getSectionName(sec, shstrtab)); + sections[i] = &InputSection::discarded; + if (Error e = attributes.parse(contents, ekind == ELF32LEKind + ? llvm::endianness::little + : llvm::endianness::big)) { + InputSection isec(*this, sec, name); + Warn(ctx) << &isec << ": " << std::move(e); + } else { + updateSupportedARMFeatures(ctx, attributes); + updateARMVFPArgs(ctx, attributes, this); + + // FIXME: Retain the first attribute section we see. The eglibc ARM + // dynamic loaders require the presence of an attribute section for + // dlopen to work. In a full implementation we would merge all + // attribute sections. + if (ctx.in.attributes == nullptr) { + ctx.in.attributes = + std::make_unique<InputSection>(*this, sec, name); + sections[i] = ctx.in.attributes.get(); + } } } - } - - // Producing a static binary with MTE globals is not currently supported, - // remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as they're unused - // medatada, and we don't want them to end up in the output file for static - // executables. - if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && - !canHaveMemtagGlobals(ctx)) { - this->sections[i] = &InputSection::discarded; - continue; - } - - if (sec.sh_type != SHT_GROUP) - continue; - StringRef signature = getShtGroupSignature(objSections, sec); - ArrayRef<Elf_Word> entries = - CHECK2(obj.template getSectionContentsAsArray<Elf_Word>(sec), this); - if (entries.empty()) - Fatal(ctx) << this << ": empty SHT_GROUP"; - - Elf_Word flag = entries[0]; - if (flag && flag != GRP_COMDAT) - Fatal(ctx) << this << ": unsupported SHT_GROUP format"; - - bool keepGroup = (flag & GRP_COMDAT) == 0 || ignoreComdats || - ctx.symtab->comdatGroups - .try_emplace(CachedHashStringRef(signature), this) - .second; - if (keepGroup) { - if (!ctx.arg.resolveGroups) - this->sections[i] = createInputSection( - i, sec, check(obj.getSectionName(sec, shstrtab))); - continue; - } - - // Otherwise, discard group members. - for (uint32_t secIndex : entries.slice(1)) { - if (secIndex >= size) - Fatal(ctx) << this << ": invalid section index in group: " << secIndex; - this->sections[secIndex] = &InputSection::discarded; + break; + case EM_AARCH64: + // Producing a static binary with MTE globals is not currently supported, + // remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as they're unused + // medatada, and we don't want them to end up in the output file for + // static executables. + if (sec.sh_type == SHT_AARCH64_MEMTAG_GLOBALS_STATIC && + !canHaveMemtagGlobals(ctx)) + sections[i] = &InputSection::discarded; + break; } } |
