const Elf_Shdr &SymTable = **SymTableOrErr;
if (SymTable.sh_type != ELF::SHT_SYMTAB &&
SymTable.sh_type != ELF::SHT_DYNSYM)
- // TODO: this error is untested.
- return createError("invalid sh_type");
+ return createError("SHT_SYMTAB_SHNDX section is linked with " +
+ object::getELFSectionTypeName(getHeader()->e_machine,
+ SymTable.sh_type) +
+ " section (expected SHT_SYMTAB/SHT_DYNSYM)");
+
if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym)))
return createError("SHT_SYMTAB_SHNDX section has sh_size (" +
Twine(SymTable.sh_size) +
NoBits,
Verdef,
Verneed,
+ SymtabShndxSection,
Symver,
MipsABIFlags
};
}
};
+struct SymtabShndxSection : Section {
+ std::vector<uint32_t> Entries;
+
+ SymtabShndxSection() : Section(SectionKind::SymtabShndxSection) {}
+
+ static bool classof(const Section *S) {
+ return S->Kind == SectionKind::SymtabShndxSection;
+ }
+};
+
// Represents .MIPS.abiflags section
struct MipsABIFlags : Section {
llvm::yaml::Hex16 Version;
ContiguousBlobAccumulator &CBA);
bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group,
ContiguousBlobAccumulator &CBA);
+ bool writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::SymtabShndxSection &Shndx,
+ ContiguousBlobAccumulator &CBA);
bool writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::SymverSection &Section,
ContiguousBlobAccumulator &CBA);
} else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
if (!writeSectionContent(SHeader, *S, CBA))
return false;
+ } else if (auto S = dyn_cast<ELFYAML::SymtabShndxSection>(Sec)) {
+ if (!writeSectionContent(SHeader, *S, CBA))
+ return false;
} else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec)) {
if (!writeSectionContent(SHeader, *S, CBA))
return false;
return true;
}
+template <class ELFT>
+bool ELFState<ELFT>::writeSectionContent(
+ Elf_Shdr &SHeader, const ELFYAML::SymtabShndxSection &Shndx,
+ ContiguousBlobAccumulator &CBA) {
+ raw_ostream &OS =
+ CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
+
+ for (uint32_t E : Shndx.Entries)
+ support::endian::write<uint32_t>(OS, E, ELFT::TargetEndianness);
+
+ SHeader.sh_entsize = Shndx.EntSize ? (uint64_t)*Shndx.EntSize : 4;
+ SHeader.sh_size = Shndx.Entries.size() * SHeader.sh_entsize;
+ return true;
+}
+
template <class ELFT>
bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::Group &Section,
ECase(SHN_HEXAGON_SCOMMON_4);
ECase(SHN_HEXAGON_SCOMMON_8);
#undef ECase
- IO.enumFallback<Hex32>(Value);
+ IO.enumFallback<Hex16>(Value);
}
void ScalarEnumerationTraits<ELFYAML::ELF_STB>::enumeration(
ELFYAML::Symbol &Symbol) {
if (Symbol.Index && Symbol.Section.data())
return "Index and Section cannot both be specified for Symbol";
- if (Symbol.Index && *Symbol.Index == ELFYAML::ELF_SHN(ELF::SHN_XINDEX))
- return "Large indexes are not supported";
if (Symbol.NameIndex && !Symbol.Name.empty())
return "Name and NameIndex cannot both be specified for Symbol";
return StringRef();
IO.mapRequired("Members", Group.Members);
}
+static void sectionMapping(IO &IO, ELFYAML::SymtabShndxSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapRequired("Entries", Section.Entries);
+}
+
void MappingTraits<ELFYAML::SectionOrType>::mapping(
IO &IO, ELFYAML::SectionOrType §ionOrType) {
IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType);
Section.reset(new ELFYAML::VerneedSection());
sectionMapping(IO, *cast<ELFYAML::VerneedSection>(Section.get()));
break;
+ case ELF::SHT_SYMTAB_SHNDX:
+ if (!IO.outputting())
+ Section.reset(new ELFYAML::SymtabShndxSection());
+ sectionMapping(IO, *cast<ELFYAML::SymtabShndxSection>(Section.get()));
+ break;
default:
if (!IO.outputting())
Section.reset(new ELFYAML::RawContentSection());
# RUN: yaml2obj %s --docnum=11 -o %t11
# RUN: not llvm-readobj --symbols %t11 2>&1 | FileCheck --check-prefix=INVALID-XINDEX-SIZE %s
-# INVALID-XINDEX-SIZE: error: {{.*}}: SHT_SYMTAB_SHNDX section has sh_size (24) which is not equal to the number of symbols (6)
+# INVALID-XINDEX-SIZE: error: {{.*}}: SHT_SYMTAB_SHNDX section has sh_size (24) which is not equal to the number of symbols (2)
--- !ELF
FileHeader:
Sections:
- Name: .symtab_shndx
Type: SHT_SYMTAB_SHNDX
- Size: 0x18
- EntSize: 4
+ Entries: [ 0, 1 ]
Link: .symtab
## Check that llvm-readobj reports an error if the e_phentsize field is broken.
- Name: symtab_shndx
Type: SHT_SYMTAB_SHNDX
Link: .symtab
- EntSize: 0x4
- Content: "0000000000000000"
+ Entries: [ 0, 1 ]
- Name: relr
Type: SHT_RELR
- Name: android_rel
--- /dev/null
+## Check that obj2yaml is able to dump a normal object which
+## contains the SHT_SYMTAB_SHNDX section and symbols with
+## section index == SHN_XINDEX.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=CASE1
+
+# CASE1: --- !ELF
+# CASE1-NEXT: FileHeader:
+# CASE1-NEXT: Class: ELFCLASS64
+# CASE1-NEXT: Data: ELFDATA2LSB
+# CASE1-NEXT: Type: ET_REL
+# CASE1-NEXT: Machine: EM_X86_64
+# CASE1-NEXT: Sections:
+# CASE1-NEXT: - Name: bar
+# CASE1-NEXT: Type: SHT_PROGBITS
+# CASE1-NEXT: - Name: .symtab_shndx
+# CASE1-NEXT: Type: SHT_SYMTAB_SHNDX
+# CASE1-NEXT: Link: .symtab
+# CASE1-NEXT: EntSize: 0x0000000000000004
+# CASE1-NEXT: Entries: [ 0, 1, 2 ]
+# CASE1-NEXT: Symbols:
+# CASE1-NEXT: - Name: bar
+# CASE1-NEXT: Type: STT_SECTION
+# CASE1-NEXT: Index: SHN_XINDEX
+# CASE1-NEXT: - Name: .symtab_shndx
+# CASE1-NEXT: Type: STT_SECTION
+# CASE1-NEXT: Index: SHN_XINDEX
+# CASE1-NEXT: ...
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: bar
+ Type: SHT_PROGBITS
+ - Name: .symtab_shndx
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0, 1, 2 ]
+ Link: .symtab
+Symbols:
+ - Type: STT_SECTION
+ Index: SHN_XINDEX
+ - Type: STT_SECTION
+ Index: SHN_XINDEX
+
+## Check that yaml2obj is unable to dump an object, which has
+## symbols with section index == SHN_XINDEX, but no SHT_SYMTAB_SHNDX section.
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: not obj2yaml %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=CASE2
+
+# CASE2: Error reading file: [[FILE]]: extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Symbols:
+ - Type: STT_SECTION
+ Index: SHN_XINDEX
+
+## Check that yaml2obj is unable to dump an object, which has symbols with
+## section index == SHN_XINDEX, but SHT_SYMTAB_SHNDX table contains invalid indices
+## that are larger than total number of the sections.
+
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: not obj2yaml %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=CASE3
+
+# CASE3: Error reading file: [[FILE]]: invalid section index: 254
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: bar
+ Type: SHT_PROGBITS
+ - Name: .symtab_shndx
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0, 254 ]
+ Link: .symtab
+Symbols:
+ - Type: STT_SECTION
+ Index: SHN_XINDEX
+
+## Check that yaml2obj is unable to dump an object, which has symbols with
+## section index == SHN_XINDEX, but SHT_SYMTAB_SHNDX table contains more
+## entries than the number of symbols in .symtab.
+
+# RUN: yaml2obj --docnum=4 %s -o %t4
+# RUN: not obj2yaml %t4 2>&1 | FileCheck %s -DFILE=%t4 --check-prefix=CASE4
+
+## FIXME: The error message below needs rewording. Size should not be equal to the number of symbols.
+## CASE4: Error reading file: [[FILE]]: SHT_SYMTAB_SHNDX section has sh_size (48) which is not equal to the number of symbols (3)
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: bar
+ Type: SHT_PROGBITS
+ - Name: .symtab_shndx
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0, 1, 2 ]
+ Link: .symtab
+Symbols:
+ - Type: STT_SECTION
+ Index: SHN_XINDEX
+
+## ELF gABI allows having multiple SHT_SYMTAB_SHNDX sections.
+## We only support having one associated with .symtab now.
+
+# RUN: yaml2obj --docnum=5 %s -o %t5
+# RUN: not obj2yaml %t5 2>&1 | FileCheck %s -DFILE=%t5 --check-prefix=CASE5
+
+# CASE5: Error reading file: [[FILE]]: multiple SHT_SYMTAB_SHNDX sections are not supported
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .symtab_shndx1
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0 ]
+ EntSize: 4
+ Link: .symtab
+ - Name: .symtab_shndx2
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0 ]
+ Link: .symtab
+
+## Check that yaml2obj can't dump the object if SHT_SYMTAB_SHNDX is
+## not associated with a SHT_SYMTAB section (this case is illegal).
+
+# RUN: yaml2obj --docnum=6 %s -o %t6
+# RUN: not obj2yaml %t6 2>&1 | FileCheck %s -DFILE=%t6 --check-prefix=CASE6
+
+# CASE6: Error reading file: [[FILE]]: SHT_SYMTAB_SHNDX section is linked with SHT_PROGBITS section (expected SHT_SYMTAB/SHT_DYNSYM)
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .symtab_shndx
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0 ]
+ Link: .foo
+ - Name: .foo
+ Type: SHT_PROGBITS
+
+## Check that yaml2obj can't dump the object if SHT_SYMTAB_SHNDX is
+## associated with a SHT_DYNSYM section (not implemented yet).
+
+# RUN: yaml2obj --docnum=7 %s -o %t7
+# RUN: not obj2yaml %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=CASE7
+
+# CASE7: Error reading file: [[FILE]]: only SHT_SYMTAB_SHNDX associated with SHT_SYMTAB are supported
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .symtab_shndx
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0, 1 ]
+ Link: .dynsym
+DynamicSymbols:
+ - Type: STT_SECTION
+ Index: SHN_XINDEX
# CHECK-NEXT: Index: SHN_HEXAGON_SCOMMON_1
# CHECK-NEXT: Binding: STB_GLOBAL
# CHECK-NEXT: - Name: unknown_index
-# CHECK-NEXT: Index: 0x0000FFFE
+# CHECK-NEXT: Index: 0xFFFE
# CHECK-NEXT: Binding: STB_GLOBAL
!ELF
- Name: unknown_index
Index: 0xfffe
Binding: STB_GLOBAL
-
-## shn_xindex.o contains a symbol with st_shndx == SHN_XINDEX.
-## We do not support it at this moment.
-# RUN: not obj2yaml %S/Inputs/shn_xindex.o 2>&1 | FileCheck %s --check-prefix=ERR
-# ERR: Error reading file: {{.*}}shn_xindex.o: SHN_XINDEX symbols are not supported
--- /dev/null
+## Check that yaml2obj is able to produce output
+## when a symbol with section index SHN_XINDEX is used,
+## but no SHT_SYMTAB_SHNDX section is defined.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: not llvm-readobj --symbols 2>&1 %t1 | FileCheck %s --check-prefix=CASE1
+
+# CASE1: error: extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: bar
+ Type: SHT_PROGBITS
+Symbols:
+ - Type: STT_SECTION
+ Index: SHN_XINDEX
+
+## Check that yaml2obj keeps the SHT_SYMTAB_SHNDX section in the output
+## even when symbol's section index value is low enough to not require the extended symtab.
+## Also, check that symbols in .symtab still have the SHN_XINDEX index.
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: llvm-readobj --sections --symbols --section-data 2>&1 %t2 | FileCheck %s --check-prefix=CASE2
+
+# CASE2: Section {
+# CASE2: Name: .symtab_shndx (1)
+# CASE2-NEXT: Type: SHT_SYMTAB_SHNDX (0x12)
+
+# CASE2: Name: .symtab
+# CASE2: SectionData (
+# CASE2-NEXT: 0000: 00000000 00000000 00000000 00000000
+# CASE2-NEXT: 0010: 00000000 00000000 00000000 0300FFFF
+## ^-- 0xFFFF here is a SHN_XINDEX.
+# CASE2-NEXT: 0020: 00000000 00000000 00000000 00000000
+# CASE2-NEXT: )
+
+# CASE2: Symbol {
+# CASE2: Name: bar (0)
+# CASE2-NEXT: Value: 0x0
+# CASE2-NEXT: Size: 0
+# CASE2-NEXT: Binding: Local (0x0)
+# CASE2-NEXT: Type: Section (0x3)
+# CASE2-NEXT: Other: 0
+# CASE2-NEXT: Section: bar (0x1)
+# CASE2-NEXT: }
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: bar
+ Type: SHT_PROGBITS
+ - Name: .symtab_shndx
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0, 1 ]
+ Link: .symtab
+Symbols:
+ - Type: STT_SECTION
+ Index: SHN_XINDEX
+
+## Check that yaml2obj allows producing broken SHT_SYMTAB_SHNDX section
+## content (in the case below it contains 0xff as an index of a section,
+## which is larger than the total number of sections in the file).
+
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: not llvm-readobj --symbols 2>&1 %t3 | FileCheck %s --check-prefix=CASE3
+
+# CASE3: error: invalid section index: 255
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: bar
+ Type: SHT_PROGBITS
+ - Name: .symtab_shndx
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0, 255 ]
+ Link: .symtab
+Symbols:
+ - Type: STT_SECTION
+ Index: SHN_XINDEX
+
+## Check that yaml2obj reports an error if a symbol index does not fit into 2 bytes.
+
+# RUN: not yaml2obj --docnum=4 %s -o %t4 2>&1 | FileCheck %s --check-prefix=CASE4
+
+# CASE4: error: out of range hex16 number
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Symbols:
+ - Type: STT_SECTION
+ Index: 65536
+
+## Check we can set a custom sh_entsize for SHT_SYMTAB_SHNDX section.
+
+# RUN: yaml2obj --docnum=5 %s -o %t5
+# RUN: not llvm-readelf -S 2>&1 %t5 | FileCheck %s -DFILE=%t5 --check-prefix=CASE5
+
+# CASE5: error: '[[FILE]]': section [index 1] has an invalid sh_entsize: 2
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .symtab_shndx
+ Type: SHT_SYMTAB_SHNDX
+ Entries: [ 0 ]
+ EntSize: 2
+ Link: .symtab
Expected<ELFYAML::RelocationSection *> dumpRelocSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::RawContentSection *>
dumpContentSection(const Elf_Shdr *Shdr);
+ Expected<ELFYAML::SymtabShndxSection *>
+ dumpSymtabShndxSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::VerdefSection *> dumpVerdefSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::SymverSection *> dumpSymverSection(const Elf_Shdr *Shdr);
// Dump symbols. We need to do this early because other sections might want
// to access the deduplicated symbol names that we also create here.
+ const Elf_Shdr *SymTab = nullptr;
+ const Elf_Shdr *SymTabShndx = nullptr;
+ const Elf_Shdr *DynSymTab = nullptr;
+
for (const Elf_Shdr &Sec : Sections) {
- if (Sec.sh_type == ELF::SHT_SYMTAB)
- if (Error E = dumpSymbols(&Sec, Y->Symbols))
- return std::move(E);
- if (Sec.sh_type == ELF::SHT_DYNSYM)
- if (Error E = dumpSymbols(&Sec, Y->DynamicSymbols))
- return std::move(E);
+ if (Sec.sh_type == ELF::SHT_SYMTAB) {
+ SymTab = &Sec;
+ } else if (Sec.sh_type == ELF::SHT_DYNSYM) {
+ DynSymTab = &Sec;
+ } else if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) {
+ // ABI allows us to have one SHT_SYMTAB_SHNDX for each symbol table.
+ // We only support having the SHT_SYMTAB_SHNDX for SHT_SYMTAB now.
+ if (SymTabShndx)
+ return createStringError(obj2yaml_error::not_implemented,
+ "multiple SHT_SYMTAB_SHNDX sections are not supported");
+ SymTabShndx = &Sec;
+ }
}
+ // We need to locate the SHT_SYMTAB_SHNDX section early, because it might be
+ // needed for dumping symbols.
+ if (SymTabShndx) {
+ if (!SymTab || SymTabShndx->sh_link != SymTab - Sections.begin())
+ return createStringError(
+ obj2yaml_error::not_implemented,
+ "only SHT_SYMTAB_SHNDX associated with SHT_SYMTAB are supported");
+
+ auto TableOrErr = Obj.getSHNDXTable(*SymTabShndx);
+ if (!TableOrErr)
+ return TableOrErr.takeError();
+ ShndxTable = *TableOrErr;
+ }
+ if (SymTab)
+ if (Error E = dumpSymbols(SymTab, Y->Symbols))
+ return std::move(E);
+ if (DynSymTab)
+ if (Error E = dumpSymbols(DynSymTab, Y->DynamicSymbols))
+ return std::move(E);
+
for (const Elf_Shdr &Sec : Sections) {
switch (Sec.sh_type) {
case ELF::SHT_DYNAMIC: {
// Do not dump these sections.
break;
case ELF::SHT_SYMTAB_SHNDX: {
- auto TableOrErr = Obj.getSHNDXTable(Sec);
- if (!TableOrErr)
- return TableOrErr.takeError();
- ShndxTable = *TableOrErr;
+ Expected<ELFYAML::SymtabShndxSection *> SecOrErr =
+ dumpSymtabShndxSection(&Sec);
+ if (!SecOrErr)
+ return SecOrErr.takeError();
+ Y->Sections.emplace_back(*SecOrErr);
break;
}
case ELF::SHT_REL:
S.Name = SymbolNameOrErr.get();
if (Sym->st_shndx >= ELF::SHN_LORESERVE) {
- if (Sym->st_shndx == ELF::SHN_XINDEX)
- return createStringError(obj2yaml_error::not_implemented,
- "SHN_XINDEX symbols are not supported");
S.Index = (ELFYAML::ELF_SHN)Sym->st_shndx;
return Error::success();
}
return S.release();
}
+template <class ELFT>
+Expected<ELFYAML::SymtabShndxSection *>
+ELFDumper<ELFT>::dumpSymtabShndxSection(const Elf_Shdr *Shdr) {
+ auto S = make_unique<ELFYAML::SymtabShndxSection>();
+ if (Error E = dumpCommonSection(Shdr, *S))
+ return std::move(E);
+
+ auto EntriesOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(Shdr);
+ if (!EntriesOrErr)
+ return EntriesOrErr.takeError();
+ for (const Elf_Word &E : *EntriesOrErr)
+ S->Entries.push_back(E);
+ return S.release();
+}
+
template <class ELFT>
Expected<ELFYAML::NoBitsSection *>
ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) {