Index: include/llvm/Object/ELF.h =================================================================== --- include/llvm/Object/ELF.h +++ include/llvm/Object/ELF.h @@ -632,8 +632,11 @@ 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) + Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -563,7 +563,7 @@ ECase(SHN_HEXAGON_SCOMMON_4); ECase(SHN_HEXAGON_SCOMMON_8); #undef ECase - IO.enumFallback(Value); + IO.enumFallback(Value); } void ScalarEnumerationTraits::enumeration( @@ -897,8 +897,6 @@ 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(); Index: test/tools/obj2yaml/elf-sht-symtab-shndx.yaml =================================================================== --- /dev/null +++ test/tools/obj2yaml/elf-sht-symtab-shndx.yaml @@ -0,0 +1,195 @@ +## 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: Content: '000000000100000002000000' +# 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 + Content: "000000000100000002000000" + EntSize: 4 + Link: .symtab +Symbols: + - Type: STT_SECTION + Index: SHN_XINDEX + - Type: STT_SECTION + Index: SHN_XINDEX + +## Check that yaml2obj is unable to dump the object that 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 the object that has symbols with +## section index == SHN_XINDEX, but SHT_SYMTAB_SHNDX table contain 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 + Content: "00000000fe000000" + EntSize: 4 + Link: .symtab +Symbols: + - Type: STT_SECTION + Index: SHN_XINDEX + +## Check that yaml2obj is unable to dump the object that 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 + +## TODO: 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 + Content: "0000000001000000ffffffff" + EntSize: 4 + Link: .symtab +Symbols: + - Type: STT_SECTION + Index: SHN_XINDEX + +## ELF gABI allows having multiple SHT_SYMTAB_SHNDX sections. +## We only support having one and 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 + Content: "00000000" + EntSize: 4 + Link: .symtab + - Name: .symtab_shndx2 + Type: SHT_SYMTAB_SHNDX + Content: "00000000" + EntSize: 4 + Link: .symtab + +## Check that yaml2obj can't dump the object if SHT_SYMTAB_SHNDX is +## associated not 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 + Content: "00000000" + EntSize: 4 + Link: .foo + - Name: .foo + Type: SHT_PROGBITS + +## Check that yaml2obj can't dump the object if SHT_SYMTAB_SHNDX is +## associated with 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 + Content: "0000000001000000" + EntSize: 4 + Link: .dynsym +DynamicSymbols: + - Type: STT_SECTION + Index: SHN_XINDEX Index: test/tools/obj2yaml/special-symbol-indices.yaml =================================================================== --- test/tools/obj2yaml/special-symbol-indices.yaml +++ test/tools/obj2yaml/special-symbol-indices.yaml @@ -18,7 +18,7 @@ # 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 @@ -47,8 +47,3 @@ - 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 Index: test/tools/yaml2obj/elf-sht-symtab-shndx.yaml =================================================================== --- /dev/null +++ test/tools/yaml2obj/elf-sht-symtab-shndx.yaml @@ -0,0 +1,104 @@ +## Check that yaml2obj is able to produce the 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. +## Note: obj2yaml test suite checks that symbols still have the SHN_XINDEX index, +## it is not possible to check this with llvm-readobj/llvm-readelf. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: llvm-readobj --sections --symbols 2>&1 %t2 | FileCheck %s --check-prefix=CASE2 + +# CASE2: Section { +# CASE2: Name: .symtab_shndx (1) +# CASE2-NEXT: Type: SHT_SYMTAB_SHNDX (0x12) + +# 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 + Content: "0000000001000000" + EntSize: 4 + Link: .symtab +Symbols: + - Type: STT_SECTION + Index: SHN_XINDEX + +## Check that yaml2obj allows producing the broken SHT_SYMTAB_SHNDX section +## content (in the case below it contains 0xff as an index of section, +## which is larger than 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 + Content: "00000000ff000000" + EntSize: 4 + Link: .symtab +Symbols: + - Type: STT_SECTION + Index: SHN_XINDEX + +## Check that yaml2obj reports an error if 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 Index: tools/obj2yaml/elf2yaml.cpp =================================================================== --- tools/obj2yaml/elf2yaml.cpp +++ tools/obj2yaml/elf2yaml.cpp @@ -158,15 +158,44 @@ // 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; + } } + // SHT_SYMTAB_SHNDX section might be used when dumping all symbols below. + 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: { @@ -182,13 +211,6 @@ case ELF::SHT_DYNSYM: // Do not dump these sections. break; - case ELF::SHT_SYMTAB_SHNDX: { - auto TableOrErr = Obj.getSHNDXTable(Sec); - if (!TableOrErr) - return TableOrErr.takeError(); - ShndxTable = *TableOrErr; - break; - } case ELF::SHT_REL: case ELF::SHT_RELA: { Expected SecOrErr = dumpRelocSection(&Sec); @@ -298,9 +320,6 @@ 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(); }