1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[yaml2obj][obj2yaml] Support custom ELF section header string table name

This patch adds support for a new field in the FileHeader, which states
the name to use for the section header string table. This also allows
combining the string table with another string table in the object, e.g.
the symbol name string table. The field is optional. By default,
.shstrtab will continue to be used.

This partially fixes https://bugs.llvm.org/show_bug.cgi?id=50506.

Reviewed by: Higuoxing

Differential Revision: https://reviews.llvm.org/D104035
This commit is contained in:
James Henderson 2021-06-10 15:33:41 +01:00
parent 5506e18140
commit a516a14043
7 changed files with 1108 additions and 31 deletions

View File

@ -118,6 +118,7 @@ struct FileHeader {
Optional<ELF_EM> Machine;
ELF_EF Flags;
llvm::yaml::Hex64 Entry;
Optional<StringRef> SectionHeaderStringTable;
Optional<llvm::yaml::Hex64> EPhOff;
Optional<llvm::yaml::Hex16> EPhEntSize;

View File

@ -177,15 +177,24 @@ template <class ELFT> class ELFState {
enum class SymtabType { Static, Dynamic };
/// The future ".strtab" section.
/// The future symbol table string section.
StringTableBuilder DotStrtab{StringTableBuilder::ELF};
/// The future ".shstrtab" section.
/// The future section header string table section, if a unique string table
/// is needed. Don't reference this variable direectly: use the
/// ShStrtabStrings member instead.
StringTableBuilder DotShStrtab{StringTableBuilder::ELF};
/// The future ".dynstr" section.
/// The future dynamic symbol string section.
StringTableBuilder DotDynstr{StringTableBuilder::ELF};
/// The name of the section header string table section. If it is .strtab or
/// .dynstr, the section header strings will be written to the same string
/// table as the static/dynamic symbols respectively. Otherwise a dedicated
/// section will be created with that name.
StringRef SectionHeaderStringTableName = ".shstrtab";
StringTableBuilder *ShStrtabStrings = &DotShStrtab;
NameToIdxMap SN2I;
NameToIdxMap SymN2I;
NameToIdxMap DynSymN2I;
@ -327,6 +336,18 @@ template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }
template <class ELFT>
ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
: Doc(D), ErrHandler(EH) {
// The input may explicitly request to store the section header table strings
// in the same string table as dynamic or static symbol names. Set the
// ShStrtabStrings member accordingly.
if (Doc.Header.SectionHeaderStringTable) {
SectionHeaderStringTableName = *Doc.Header.SectionHeaderStringTable;
if (*Doc.Header.SectionHeaderStringTable == ".strtab")
ShStrtabStrings = &DotStrtab;
else if (*Doc.Header.SectionHeaderStringTable == ".dynstr")
ShStrtabStrings = &DotDynstr;
// Otherwise, the unique table will be used.
}
std::vector<ELFYAML::Section *> Sections = Doc.getSections();
// Insert SHT_NULL section implicitly when it is not defined in YAML.
if (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL)
@ -363,19 +384,35 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
"' at YAML section/fill number " + Twine(I));
}
std::vector<StringRef> ImplicitSections;
if (Doc.DynamicSymbols)
ImplicitSections.insert(ImplicitSections.end(), {".dynsym", ".dynstr"});
if (Doc.Symbols)
ImplicitSections.push_back(".symtab");
SmallSetVector<StringRef, 8> ImplicitSections;
if (Doc.DynamicSymbols) {
if (SectionHeaderStringTableName == ".dynsym")
reportError("cannot use '.dynsym' as the section header name table when "
"there are dynamic symbols");
ImplicitSections.insert(".dynsym");
ImplicitSections.insert(".dynstr");
}
if (Doc.Symbols) {
if (SectionHeaderStringTableName == ".symtab")
reportError("cannot use '.symtab' as the section header name table when "
"there are symbols");
ImplicitSections.insert(".symtab");
}
if (Doc.DWARF)
for (StringRef DebugSecName : Doc.DWARF->getNonEmptySectionNames()) {
std::string SecName = ("." + DebugSecName).str();
ImplicitSections.push_back(StringRef(SecName).copy(StringAlloc));
// TODO: For .debug_str it should be possible to share the string table,
// in the same manner as the symbol string tables.
if (SectionHeaderStringTableName == SecName)
reportError("cannot use '" + SecName +
"' as the section header name table when it is needed for "
"DWARF output");
ImplicitSections.insert(StringRef(SecName).copy(StringAlloc));
}
ImplicitSections.insert(ImplicitSections.end(), {".strtab"});
// TODO: Only create the .strtab here if any symbols have been requested.
ImplicitSections.insert(".strtab");
if (!SecHdrTable || !SecHdrTable->NoHeaders.getValueOr(false))
ImplicitSections.insert(ImplicitSections.end(), {".shstrtab"});
ImplicitSections.insert(SectionHeaderStringTableName);
// Insert placeholders for implicit sections that are not
// defined explicitly in YAML.
@ -387,7 +424,9 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
ELFYAML::Chunk::ChunkKind::RawContent, true /*IsImplicit*/);
Sec->Name = SecName;
if (SecName == ".dynsym")
if (SecName == SectionHeaderStringTableName)
Sec->Type = ELF::SHT_STRTAB;
else if (SecName == ".dynsym")
Sec->Type = ELF::SHT_DYNSYM;
else if (SecName == ".symtab")
Sec->Type = ELF::SHT_SYMTAB;
@ -480,8 +519,9 @@ void ELFState<ELFT>::writeELFHeader(raw_ostream &OS) {
if (Doc.Header.EShStrNdx)
Header.e_shstrndx = *Doc.Header.EShStrNdx;
else if (SectionHeaders.Offset && !ExcludedSectionHeaders.count(".shstrtab"))
Header.e_shstrndx = SN2I.get(".shstrtab");
else if (SectionHeaders.Offset &&
!ExcludedSectionHeaders.count(SectionHeaderStringTableName))
Header.e_shstrndx = SN2I.get(SectionHeaderStringTableName);
else
Header.e_shstrndx = 0;
@ -615,16 +655,16 @@ bool ELFState<ELFT>::initImplicitHeader(ContiguousBlobAccumulator &CBA,
if (Header.sh_offset)
return false;
if (SecName == ".symtab")
initSymtabSectionHeader(Header, SymtabType::Static, CBA, YAMLSec);
else if (SecName == ".strtab")
if (SecName == ".strtab")
initStrtabSectionHeader(Header, SecName, DotStrtab, CBA, YAMLSec);
else if (SecName == ".shstrtab")
initStrtabSectionHeader(Header, SecName, DotShStrtab, CBA, YAMLSec);
else if (SecName == ".dynsym")
initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);
else if (SecName == ".dynstr")
initStrtabSectionHeader(Header, SecName, DotDynstr, CBA, YAMLSec);
else if (SecName == SectionHeaderStringTableName)
initStrtabSectionHeader(Header, SecName, *ShStrtabStrings, CBA, YAMLSec);
else if (SecName == ".symtab")
initSymtabSectionHeader(Header, SymtabType::Static, CBA, YAMLSec);
else if (SecName == ".dynsym")
initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);
else if (SecName.startswith(".debug_")) {
// If a ".debug_*" section's type is a preserved one, e.g., SHT_DYNAMIC, we
// will not treat it as a debug section.
@ -671,7 +711,7 @@ uint64_t ELFState<ELFT>::getSectionNameOffset(StringRef Name) {
// the string table.
if (ExcludedSectionHeaders.count(Name))
return 0;
return DotShStrtab.getOffset(Name);
return ShStrtabStrings->getOffset(Name);
}
static uint64_t writeContent(ContiguousBlobAccumulator &CBA,
@ -995,7 +1035,7 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
StringTableBuilder &STB,
ContiguousBlobAccumulator &CBA,
ELFYAML::Section *YAMLSec) {
SHeader.sh_name = getSectionNameOffset(Name);
SHeader.sh_name = getSectionNameOffset(ELFYAML::dropUniqueSuffix(Name));
SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_STRTAB;
SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1;
@ -1817,10 +1857,8 @@ template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {
llvm_unreachable("buildSectionIndex() failed");
if (!ExcludedSectionHeaders.count(S->Name))
DotShStrtab.add(ELFYAML::dropUniqueSuffix(S->Name));
ShStrtabStrings->add(ELFYAML::dropUniqueSuffix(S->Name));
}
DotShStrtab.finalize();
}
template <class ELFT> void ELFState<ELFT>::buildSymbolIndexes() {
@ -1870,6 +1908,11 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
}
DotDynstr.finalize();
// Don't finalize the section header string table a second time if it has
// already been finalized due to being one of the symbol string tables.
if (ShStrtabStrings != &DotStrtab && ShStrtabStrings != &DotDynstr)
ShStrtabStrings->finalize();
}
template <class ELFT>
@ -1879,14 +1922,16 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
if (State.HasError)
return false;
// Finalize .strtab and .dynstr sections. We do that early because want to
// finalize the string table builders before writing the content of the
// sections that might want to use them.
State.finalizeStrings();
// Build the section index, which adds sections to the section header string
// table first, so that we can finalise the section header string table.
State.buildSectionIndex();
State.buildSymbolIndexes();
// Finalize section header string table and the .strtab and .dynstr sections.
// We do this early because we want to finalize the string table builders
// before writing the content of the sections that might want to use them.
State.finalizeStrings();
if (State.HasError)
return false;

View File

@ -1007,6 +1007,7 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,
IO.mapOptional("Machine", FileHdr.Machine);
IO.mapOptional("Flags", FileHdr.Flags, ELFYAML::ELF_EF(0));
IO.mapOptional("Entry", FileHdr.Entry, Hex64(0));
IO.mapOptional("SectionHeaderStringTable", FileHdr.SectionHeaderStringTable);
// obj2yaml does not dump these fields.
assert(!IO.outputting() ||

View File

@ -11,6 +11,7 @@
# CHECK-NEXT: Class: ELFCLASS64
# CHECK-NEXT: Data: ELFDATA2LSB
# CHECK-NEXT: Type: ET_REL
# CHECK-NEXT: SectionHeaderStringTable: {{.*}}
# CHECK-NEXT: Sections:
# CHECK-NEXT: - Name: "{{.*}}"
# CHECK-NEXT: Type: SHT_PROGBITS

View File

@ -0,0 +1,447 @@
## Show that the SectionHeaderStringTable field in the document header is set,
## iff the section name is not ".shstrtab".
## Also show that no section appears in the Sections table for this section,
## unless some property is different to the default.
## Show the case when the name is a custom string (the key should be set).
# RUN: yaml2obj --docnum=1 %s -o %t1.o
# RUN: obj2yaml %t1.o > %t1.yaml
# RUN: FileCheck %s --input-file=%t1.yaml --check-prefix=CUSTOM
# CUSTOM: --- !ELF
# CUSTOM-NEXT: FileHeader:
# CUSTOM-NEXT: Class: ELFCLASS64
# CUSTOM-NEXT: Data: ELFDATA2LSB
# CUSTOM-NEXT: Type: ET_EXEC
# CUSTOM-NEXT: SectionHeaderStringTable: .foo
# CUSTOM-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .foo
## Show the case when the e_shstrndx value is 0 and the name is not ".shstrtab"
## (the key should be set).
# RUN: yaml2obj --docnum=2 %s -o %t2.o
# RUN: obj2yaml %t2.o > %t2.yaml
# RUN: FileCheck %s --input-file=%t2.yaml --check-prefix=XINDEX
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
EShStrNdx: 0xffff
SectionHeaderStringTable: .foo
Sections:
- Type: SHT_NULL
Link: .foo
# XINDEX: --- !ELF
# XINDEX-NEXT: FileHeader:
# XINDEX-NEXT: Class: ELFCLASS64
# XINDEX-NEXT: Data: ELFDATA2LSB
# XINDEX-NEXT: Type: ET_EXEC
# XINDEX-NEXT: SectionHeaderStringTable: .foo
# XINDEX-NEXT: Sections:
# XINDEX-NEXT: - Type: SHT_NULL
# XINDEX-NEXT: Link: .foo
# XINDEX-NEXT: Size: 0x0
# XINDEX-NEXT: ...
## Show the case when the string table section is also the symbol table's string
## table (the key should be set).
# RUN: yaml2obj --docnum=3 %s -o %t3.o
# RUN: obj2yaml %t3.o > %t3.yaml
# RUN: FileCheck %s --input-file=%t3.yaml --check-prefix=STRTAB
# STRTAB: --- !ELF
# STRTAB-NEXT: FileHeader:
# STRTAB-NEXT: Class: ELFCLASS64
# STRTAB-NEXT: Data: ELFDATA2LSB
# STRTAB-NEXT: Type: ET_EXEC
# STRTAB-NEXT: SectionHeaderStringTable: .strtab
# STRTAB-NEXT: Symbols:
# STRTAB-NEXT: - Name: boz
# STRTAB-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: ".strtab"
Symbols:
- Name: boz
## Document the case when the string table section is also the symbol table's
## dynamic string table (the key should be set).
## FIXME: Regardless of whether it is shared with the section header string
## table or not, the dynstr (and also the dynsym) should be omitted if
## they match the default behaviour.
# RUN: yaml2obj --docnum=4 %s -o %t4.o
# RUN: obj2yaml %t4.o > %t4.yaml
# RUN: FileCheck %s --input-file=%t4.yaml --check-prefix=DYNSTR
# DYNSTR: --- !ELF
# DYNSTR-NEXT: FileHeader:
# DYNSTR-NEXT: Class: ELFCLASS64
# DYNSTR-NEXT: Data: ELFDATA2LSB
# DYNSTR-NEXT: Type: ET_EXEC
# DYNSTR-NEXT: SectionHeaderStringTable: .dynstr
# DYNSTR-NEXT: Sections:
# DYNSTR-NEXT: - Name: .dynsym
# DYNSTR-NEXT: Type: SHT_DYNSYM
# DYNSTR-NEXT: Flags: [ SHF_ALLOC ]
# DYNSTR-NEXT: Link: .dynstr
# DYNSTR-NEXT: AddressAlign: 0x8
# DYNSTR-NEXT: - Name: .dynstr
# DYNSTR-NEXT: Type: SHT_STRTAB
# DYNSTR-NEXT: Flags: [ SHF_ALLOC ]
# DYNSTR-NEXT: Address: 0x30
# DYNSTR-NEXT: AddressAlign: 0x1
# DYNSTR-NEXT: DynamicSymbols:
# DYNSTR-NEXT: - Name: boz
# DYNSTR-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: ".dynstr"
DynamicSymbols:
- Name: boz
## Show the case when the name is the default ".shstrtab" (the key should not be
## set).
# RUN: yaml2obj --docnum=5 %s -o %t5.o
# RUN: obj2yaml %t5.o > %t5.yaml
# RUN: FileCheck %s --input-file=%t5.yaml --check-prefix=DEFAULT
# DEFAULT: --- !ELF
# DEFAULT-NEXT: FileHeader:
# DEFAULT-NEXT: Class: ELFCLASS64
# DEFAULT-NEXT: Data: ELFDATA2LSB
# DEFAULT-NEXT: Type: ET_EXEC
# DEFAULT-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
## Show the case when the e_shstrndx value is 0 and the name is ".shstrtab" (the
## key should not be set).
# RUN: yaml2obj --docnum=6 %s -o %t6.o
# RUN: obj2yaml %t6.o > %t6.yaml
# RUN: FileCheck %s --input-file=%t6.yaml --check-prefix=DEFXINDEX
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
EShStrNdx: 0xffff
Sections:
- Type: SHT_NULL
Link: .shstrtab
# DEFXINDEX: --- !ELF
# DEFXINDEX-NEXT: FileHeader:
# DEFXINDEX-NEXT: Class: ELFCLASS64
# DEFXINDEX-NEXT: Data: ELFDATA2LSB
# DEFXINDEX-NEXT: Type: ET_EXEC
# DEFXINDEX-NEXT: Sections:
# DEFXINDEX-NEXT: - Type: SHT_NULL
# DEFXINDEX-NEXT: Link: .shstrtab
# DEFXINDEX-NEXT: Size: 0x0
# DEFXINDEX-NEXT: ...
## Show that if there are no section headers, the key is not set.
# RUN: yaml2obj --docnum=7 %s -o %t7.o
# RUN: obj2yaml %t7.o > %t7.yaml
# RUN: FileCheck %s --input-file=%t7.yaml --check-prefix=NOHDRS
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Type: SectionHeaderTable
NoHeaders: true
# NOHDRS: --- !ELF
# NOHDRS-NEXT: FileHeader:
# NOHDRS-NEXT: Class: ELFCLASS64
# NOHDRS-NEXT: Data: ELFDATA2LSB
# NOHDRS-NEXT: Type: ET_EXEC
## FIXME: There should be a SectionHeaderTable key as per the input.
# NOHDRS-NEXT: ...
## Show that a custom-named section header string table can be in a reordered
## section header table.
# RUN: yaml2obj --docnum=8 %s -o %t8.o
# RUN: obj2yaml %t8.o > %t8.yaml
# RUN: FileCheck %s --input-file=%t8.yaml --check-prefix=REORDER
# REORDER: --- !ELF
# REORDER-NEXT: FileHeader:
# REORDER-NEXT: Class: ELFCLASS64
# REORDER-NEXT: Data: ELFDATA2LSB
# REORDER-NEXT: Type: ET_EXEC
# REORDER-NEXT: SectionHeaderStringTable: .foo
# REORDER-NEXT: Sections:
# REORDER-NEXT: - Name: .baz
# REORDER-NEXT: Type: SHT_PROGBITS
# REORDER-NEXT: Offset: 0x180
# REORDER-NEXT: - Name: .bar
# REORDER-NEXT: Type: SHT_PROGBITS
## FIXME: This should be at the start of the sections list.
# REORDER-NEXT: - Type: SectionHeaderTable
# REORDER-NEXT: Sections:
# REORDER-NEXT: - Name: .baz
# REORDER-NEXT: - Name: .foo
# REORDER-NEXT: - Name: .bar
# REORDER-NEXT: - Name: .strtab
# REORDER-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .foo
Sections:
- Type: SectionHeaderTable
Sections:
- Name: .baz
- Name: .foo
- Name: .bar
## FIXME: we shouldn't need a .strtab section if there are no symbols.
- Name: .strtab
- Name: .baz
Type: SHT_PROGBITS
- Name: .bar
Type: SHT_PROGBITS
## Document what happens when a custom-named section header string table is
## placed in between other sections.
## FIXME: obj2yaml should preserve the ordering in the Sections list, but it
## doesn't for custom or default named tables.
# RUN: yaml2obj --docnum=9 %s -o %t9.o
# RUN: obj2yaml %t9.o > %t9.yaml
# RUN: FileCheck %s --input-file=%t9.yaml --check-prefix=PLACED
# PLACED: --- !ELF
# PLACED-NEXT: FileHeader:
# PLACED-NEXT: Class: ELFCLASS64
# PLACED-NEXT: Data: ELFDATA2LSB
# PLACED-NEXT: Type: ET_EXEC
# PLACED-NEXT: SectionHeaderStringTable: .foo
# PLACED-NEXT: Sections:
# PLACED-NEXT: - Name: .baz
# PLACED-NEXT: Type: SHT_PROGBITS
# PLACED-NEXT: - Name: .bar
# PLACED-NEXT: Type: SHT_PROGBITS
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .foo
Sections:
- Name: .baz
Type: SHT_PROGBITS
- Name: .foo
Type: SHT_STRTAB
- Name: .bar
Type: SHT_PROGBITS
## Show that a custom-named section header string table can be given different
## properties.
# RUN: yaml2obj --docnum=10 %s -o %t10.o
# RUN: obj2yaml %t10.o > %t10.yaml
# RUN: FileCheck %s --input-file=%t10.yaml --check-prefix=PROPS
# PROPS: --- !ELF
# PROPS-NEXT: FileHeader:
# PROPS-NEXT: Class: ELFCLASS64
# PROPS-NEXT: Data: ELFDATA2LSB
# PROPS-NEXT: Type: ET_EXEC
# PROPS-NEXT: SectionHeaderStringTable: .foo
# PROPS-NEXT: Sections:
# PROPS-NEXT: - Name: .foo
# PROPS-NEXT: Type: SHT_STRTAB
# PROPS-NEXT: Flags: [ SHF_ALLOC ]
# PROPS-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .foo
Sections:
- Name: .foo
Type: SHT_STRTAB
Flags: [ SHF_ALLOC ]
## Show that an error is reported if the section header string table name cannot
## be read.
# RUN: yaml2obj --docnum=11 %s -o %t11.o
# RUNasda: not obj2yaml %t11.o 2>&1 | FileCheck %s --check-prefix=ERR -DFILE=%t11.o
# ERR: Error reading file: [[FILE]]: unable to read section header string table name: a section [index 1] has an invalid sh_name (0x10000) offset which goes past the end of the section name string table
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .shstrtab
Type: SHT_STRTAB
ShName: 0x10000
## Show that the name is uniquified if necessary.
## Case 1: generic name.
# RUN: yaml2obj --docnum=12 %s -o %t12.o
# RUN: obj2yaml %t12.o > %t12.yaml
# RUN: FileCheck %s --input-file=%t12.yaml --check-prefix=UNIQUIFY1
# UNIQUIFY1: --- !ELF
# UNIQUIFY1-NEXT: FileHeader:
# UNIQUIFY1-NEXT: Class: ELFCLASS64
# UNIQUIFY1-NEXT: Data: ELFDATA2LSB
# UNIQUIFY1-NEXT: Type: ET_EXEC
# UNIQUIFY1-NEXT: SectionHeaderStringTable: '.strings (1)'
# UNIQUIFY1-NEXT: Sections:
# UNIQUIFY1-NEXT: - Name: .strings
# UNIQUIFY1-NEXT: Type: SHT_PROGBITS
# UNIQUIFY1-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: '.strings (1)'
Sections:
- Name: '.strings (2)'
Type: SHT_PROGBITS
## Case 2: '.strtab' when symbols are present.
# RUN: yaml2obj --docnum=13 %s -o %t13.o '-DNAME=".strtab (1)"'
# RUN: obj2yaml %t13.o > %t13.yaml
# RUN: FileCheck %s --input-file=%t13.yaml --check-prefix=UNIQUIFY2 \
# RUN: -DNAME=.strtab
# UNIQUIFY2: --- !ELF
# UNIQUIFY2-NEXT: FileHeader:
# UNIQUIFY2-NEXT: Class: ELFCLASS64
# UNIQUIFY2-NEXT: Data: ELFDATA2LSB
# UNIQUIFY2-NEXT: Type: ET_EXEC
# UNIQUIFY2-NEXT: SectionHeaderStringTable: '[[NAME]] (1)'
# UNIQUIFY2-NEXT: Symbols:
# UNIQUIFY2-NEXT: - Name: foo
# UNIQUIFY2-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: [[NAME]]
Symbols:
- Name: foo
## Case 3: '.symtab' when symbols are present.
# RUN: yaml2obj --docnum=13 %s -o %t14.o '-DNAME=".symtab (1)"'
# RUN: obj2yaml %t14.o > %t14.yaml
# RUN: FileCheck %s --input-file=%t14.yaml --check-prefix=UNIQUIFY2 \
# RUN: -DNAME=.symtab
## Case 4: '.dynstr' when dynamic symbols are present.
# RUN: yaml2obj --docnum=14 %s -o %t15.o '-DNAME=".dynstr (1)"'
# RUN: obj2yaml %t15.o > %t15.yaml
# RUN: FileCheck %s --input-file=%t15.yaml --check-prefix=UNIQUIFY3 \
# RUN: -DNAME=.dynstr
# UNIQUIFY3: --- !ELF
# UNIQUIFY3-NEXT: FileHeader:
# UNIQUIFY3-NEXT: Class: ELFCLASS64
# UNIQUIFY3-NEXT: Data: ELFDATA2LSB
# UNIQUIFY3-NEXT: Type: ET_EXEC
# UNIQUIFY3-NEXT: SectionHeaderStringTable: '[[NAME]] (1)'
## FIXME: The .dynsym and .dynstr sections shouldn't need to be emitted, since
## their values are the default produced by yaml2obj.
# UNIQUIFY3-NEXT: Sections:
# UNIQUIFY3-NEXT: - Name: .dynsym
# UNIQUIFY3-NEXT: Type: SHT_DYNSYM
# UNIQUIFY3-NEXT: Flags: [ SHF_ALLOC ]
# UNIQUIFY3-NEXT: Link: .dynstr
# UNIQUIFY3-NEXT: AddressAlign: 0x8
# UNIQUIFY3-NEXT: - Name: .dynstr
# UNIQUIFY3-NEXT: Type: SHT_STRTAB
# UNIQUIFY3-NEXT: Flags: [ SHF_ALLOC ]
# UNIQUIFY3-NEXT: Address: 0x30
# UNIQUIFY3-NEXT: AddressAlign: 0x1
# UNIQUIFY3-NEXT: DynamicSymbols:
# UNIQUIFY3-NEXT: - Name: foo
# UNIQUIFY3-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: [[NAME]]
DynamicSymbols:
- Name: foo
## Case 5: '.dynsym' when dynamic symbols are present.
# RUN: yaml2obj --docnum=14 %s -o %t16.o '-DNAME=".dynsym (1)"'
# RUN: obj2yaml %t16.o > %t16.yaml
# RUN: FileCheck %s --input-file=%t16.yaml --check-prefix=UNIQUIFY3 \
# RUN: -DNAME=.dynsym
## Case 6: Document what happens for '.debug_str' when DWARF debug strings are
## requested. The dwarf2yaml code uses the last .debug_* named section
## to populate the corresponding DWARF block. As a result, the original
## .debug_str content is lost.
## TODO: We should prevent the dwarf2yaml code from using the section header
## string table to populate the DWARF block.
# RUN: yaml2obj --docnum=15 %s -o %t17.o
# RUN: obj2yaml %t17.o > %t17.yaml
# RUN: FileCheck %s --input-file=%t17.yaml --check-prefix=UNIQUIFY6
# UNIQUIFY6: --- !ELF
# UNIQUIFY6-NEXT: FileHeader:
# UNIQUIFY6-NEXT: Class: ELFCLASS64
# UNIQUIFY6-NEXT: Data: ELFDATA2LSB
# UNIQUIFY6-NEXT: Type: ET_EXEC
# UNIQUIFY6-NEXT: SectionHeaderStringTable: '.debug_str (1)'
# UNIQUIFY6-NEXT: DWARF:
# UNIQUIFY6-NEXT: debug_str:
# UNIQUIFY6-NEXT: - ''
# UNIQUIFY6-NEXT: - .debug_str
# UNIQUIFY6-NEXT: - .strtab
# UNIQUIFY6-NEXT: ...
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: '.debug_str (1)'
DWARF:
debug_str:
- string

View File

@ -0,0 +1,545 @@
## A user should be able to specify any arbitrary string table as the section
## header string table, including the symbol string table. This test covers
## various cases to do with this.
## Case 1: custom name specified for string table.
# RUN: yaml2obj --docnum=1 %s -o %t1 -DSHSTRTAB=.strings
# RUN: llvm-readelf -S -p=.strings %t1 | FileCheck %s --check-prefix=CASE1
# CASE1: There are 5 section headers
# CASE1-EMPTY:
# CASE1-NEXT: Section Headers:
# CASE1-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE1-NEXT: [ 0] NULL
# CASE1-NEXT: [ 1] .foo{{ }}
# CASE1-NEXT: [ 2] .bar{{ }}
# CASE1-NEXT: [ 3] .strtab{{ }}
# CASE1-NEXT: [ 4] .strings STRTAB 0000000000000000 [[#%x,]] 00001c 00 0 0 1
# CASE1: String dump of section '.strings':
# CASE1-NEXT: [ 1] .strings{{$}}
# CASE1-NEXT: [ a] .bar{{$}}
# CASE1-NEXT: [ f] .foo{{$}}
# CASE1-NEXT: [ 14] .strtab{{$}}
# CASE1-EMPTY:
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: [[SHSTRTAB=<none>]]
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Name: [[OTHER=.bar]]
Type: SHT_PROGBITS
## Case 2: reuse symbol string table.
# RUN: yaml2obj --docnum=2 %s -o %t2 -DSHSTRTAB=.strtab
# RUN: llvm-readelf -S -s -p=.strtab %t2 | FileCheck %s --check-prefix=CASE2
# CASE2: There are 5 section headers
# CASE2-EMPTY:
# CASE2-NEXT: Section Headers:
# CASE2-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE2-NEXT: [ 0] NULL
# CASE2-NEXT: [ 1] .foo{{ }}
# CASE2-NEXT: [ 2] .bar{{ }}
# CASE2-NEXT: [ 3] .symtab{{ }}
# CASE2-NEXT: [ 4] .strtab STRTAB 0000000000000000 [[#%x,]] 000023 00 0 0 1
# CASE2: Symbol table '.symtab' contains 3 entries:
# CASE2-NEXT: Num: {{.*}} Ndx Name
# CASE2-NEXT: 0: {{.*}} UND {{$}}
# CASE2-NEXT: 1: {{.*}} baz{{$}}
# CASE2-NEXT: 2: {{.*}} bob{{$}}
# CASE2: String dump of section '.strtab':
# CASE2-NEXT: [ 1] baz{{$}}
# CASE2-NEXT: [ 5] .bar{{$}}
# CASE2-NEXT: [ a] .foo{{$}}
# CASE2-NEXT: [ f] bob{{$}}
# CASE2-NEXT: [ 13] .strtab{{$}}
# CASE2-NEXT: [ 1b] .symtab{{$}}
# CASE2-EMPTY:
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: [[SHSTRTAB]]
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Name: .bar
Type: SHT_PROGBITS
Symbols:
- Name: baz
- Name: bob
## Case 3: reuse dynamic string table.
# RUN: yaml2obj --docnum=3 %s -o %t3 -DSHSTRTAB=.dynstr
# RUN: llvm-readelf -S --dyn-syms -p=.dynstr %t3 | FileCheck %s --check-prefix=CASE3
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: [[SHSTRTAB]]
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Name: .bar
Type: SHT_PROGBITS
DynamicSymbols:
- Name: baz
- Name: bob
# CASE3: There are 6 section headers
# CASE3-EMPTY:
# CASE3-NEXT: Section Headers:
# CASE3-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE3-NEXT: [ 0] NULL
# CASE3-NEXT: [ 1] .foo{{ }}
# CASE3-NEXT: [ 2] .bar{{ }}
# CASE3-NEXT: [ 3] .dynsym{{ }}
# CASE3-NEXT: [ 4] .dynstr STRTAB 0000000000000048 [[#%x,]] 00002b 00 A 0 0 1
# CASE3-NEXT: [ 5] .strtab{{ }}
# CASE3: Symbol table '.dynsym' contains 3 entries:
# CASE3-NEXT: Num: {{.*}} Ndx Name
# CASE3-NEXT: 0: {{.*}} UND {{$}}
# CASE3-NEXT: 1: {{.*}} baz{{$}}
# CASE3-NEXT: 2: {{.*}} bob{{$}}
# CASE3: String dump of section '.dynstr':
# CASE3-NEXT: [ 1] baz{{$}}
# CASE3-NEXT: [ 5] .dynstr{{$}}
# CASE3-NEXT: [ d] .bar{{$}}
# CASE3-NEXT: [ 12] .foo{{$}}
# CASE3-NEXT: [ 17] .dynsym{{$}}
# CASE3-NEXT: [ 1f] bob{{$}}
# CASE3-NEXT: [ 23] .strtab{{$}}
# CASE3-EMPTY:
## Case 4: shstrtab specified to be otherwise ungenerated non-strtab implicit
## section.
# RUN: yaml2obj --docnum=1 %s -o %t4 -DSHSTRTAB=.symtab
# RUN: llvm-readelf -S -p=.symtab %t4 | FileCheck %s --check-prefix=CASE4
# CASE4: There are 5 section headers
# CASE4-EMPTY:
# CASE4-NEXT: Section Headers:
# CASE4-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE4-NEXT: [ 0] NULL
# CASE4-NEXT: [ 1] .foo{{ }}
# CASE4-NEXT: [ 2] .bar{{ }}
# CASE4-NEXT: [ 3] .strtab{{ }}
# CASE4-NEXT: [ 4] .symtab STRTAB 0000000000000000 [[#%x,]] 00001b 00 0 0 1
# CASE4: String dump of section '.symtab':
# CASE4-NEXT: [ 1] .bar{{$}}
# CASE4-NEXT: [ 6] .foo{{$}}
# CASE4-NEXT: [ b] .strtab{{$}}
# CASE4-NEXT: [ 13] .symtab{{$}}
## Case 5: shstrtab specified to be otherwise ungenerated .dynstr section. In
## this case, the SHF_ALLOC flag will be set.
# RUN: yaml2obj --docnum=1 %s -o %t5 -DSHSTRTAB=.dynstr
# RUN: llvm-readelf -S -p=.dynstr %t5 | FileCheck %s --check-prefix=CASE5
# CASE5: There are 5 section headers
# CASE5-EMPTY:
# CASE5-NEXT: Section Headers:
# CASE5-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE5-NEXT: [ 0] NULL
# CASE5-NEXT: [ 1] .foo{{ }}
# CASE5-NEXT: [ 2] .bar{{ }}
# CASE5-NEXT: [ 3] .strtab{{ }}
# CASE5-NEXT: [ 4] .dynstr STRTAB 0000000000000001 [[#%x,]] 00001b 00 A 0 0 1
# CASE5: String dump of section '.dynstr':
# CASE5-NEXT: [ 1] .dynstr{{$}}
# CASE5-NEXT: [ 9] .bar{{$}}
# CASE5-NEXT: [ e] .foo{{$}}
# CASE5-NEXT: [ 13] .strtab{{$}}
## Case 6: shstrtab specified to be otherwise ungenerated .debug_str section. In
## this case, the sh_entsize will be set to 1.
# RUN: yaml2obj --docnum=1 %s -o %t6 -DSHSTRTAB=.debug_str
# RUN: llvm-readelf -S -p=.debug_str %t6 | FileCheck %s --check-prefix=CASE6
# CASE6: There are 5 section headers
# CASE6-EMPTY:
# CASE6-NEXT: Section Headers:
# CASE6-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE6-NEXT: [ 0] NULL
# CASE6-NEXT: [ 1] .foo{{ }}
# CASE6-NEXT: [ 2] .bar{{ }}
# CASE6-NEXT: [ 3] .strtab{{ }}
# CASE6-NEXT: [ 4] .debug_str STRTAB 0000000000000000 [[#%x,]] 00001e 01 0 0 1
# CASE6: String dump of section '.debug_str':
# CASE6-NEXT: [ 1] .debug_str{{$}}
# CASE6-NEXT: [ c] .bar{{$}}
# CASE6-NEXT: [ 11] .foo{{$}}
# CASE6-NEXT: [ 16] .strtab{{$}}
## Case 7: shstrtab specified to be the .symtab section, when there are symbols.
## This triggers an error (since the symbols cannot be represented in the
## section as section names).
# RUN: not yaml2obj --docnum=2 %s -o %t7 -DSHSTRTAB=.symtab 2>&1 | FileCheck %s --check-prefix=ERR1
# ERR1: error: cannot use '.symtab' as the section header name table when there are symbols
## Case 8: shstrtab specified to be the .dynsym section, when there are dynamic
## symbols. This triggers an error (since the symbols cannot be represented in
## the section as section names).
# RUN: not yaml2obj --docnum=3 %s -o %t8 -DSHSTRTAB=.dynsym 2>&1 | FileCheck %s --check-prefix=ERR2
# ERR2: error: cannot use '.dynsym' as the section header name table when there are dynamic symbols
## Case 9: shstrtab specified to be the .debug_str section, when there are DWARF
## debug strings. This triggers an error.
# RUN: not yaml2obj --docnum=4 %s -o %t9 2>&1 | FileCheck %s --check-prefix=ERR3
# ERR3: error: cannot use '.debug_str' as the section header name table when it is needed for DWARF output
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .debug_str
DWARF:
debug_str:
- a
## Case 10: can explicitly specifiy ".shstrtab" as shstrtab. Output will be the
## same as if it wasn't sepcified at all.
# RUN: yaml2obj --docnum=1 %s -o %t10 -DSHSTRTAB=.shstrtab
# RUN: llvm-readelf -S -p=.shstrtab %t10 | FileCheck %s --check-prefix=CASE10
# RUN: yaml2obj --docnum=1 %s -o %t10.default
# RUN: cmp %t10 %t10.default
# CASE10: There are 5 section headers
# CASE10-EMPTY:
# CASE10-NEXT: Section Headers:
# CASE10-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE10-NEXT: [ 0] NULL
# CASE10-NEXT: [ 1] .foo{{ }}
# CASE10-NEXT: [ 2] .bar{{ }}
# CASE10-NEXT: [ 3] .strtab{{ }}
# CASE10-NEXT: [ 4] .shstrtab STRTAB 0000000000000000 [[#%x,]] 00001d 00 0 0 1
# CASE10: String dump of section '.shstrtab':
# CASE10-NEXT: [ 1] .bar{{$}}
# CASE10-NEXT: [ 6] .foo{{$}}
# CASE10-NEXT: [ b] .shstrtab{{$}}
# CASE10-NEXT: [ 15] .strtab{{$}}
# CASE10-EMPTY:
## Case 11: can specify custom shstrtab properties.
## FIXME: when the section is listed explicitly, the sh_addralign value is 0 if
## not overwritten, which is inconsistent with when the section is not
## specified at all.
# RUN: yaml2obj --docnum=5 %s -o %t11 -DENTSIZE=2
# RUN: llvm-readelf -S -p=.strings %t11 | FileCheck %s --check-prefix=CASE11
# CASE11: There are 5 section headers
# CASE11-EMPTY:
# CASE11-NEXT: Section Headers:
# CASE11-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE11-NEXT: [ 0] NULL
# CASE11-NEXT: [ 1] .foo{{ }}
# CASE11-NEXT: [ 2] .strings STRTAB 0000000000000000 [[#%x,]] 00001c 02 0 0 0
# CASE11-NEXT: [ 3] .bar{{ }}
# CASE11-NEXT: [ 4] .strtab{{ }}
# CASE11: String dump of section '.strings':
# CASE11-NEXT: [ 1] .strings{{$}}
# CASE11-NEXT: [ a] .bar{{$}}
# CASE11-NEXT: [ f] .foo{{$}}
# CASE11-NEXT: [ 14] .strtab{{$}}
# CASE11-EMPTY:
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .strings
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Name: .strings
Type: [[TYPE=SHT_STRTAB]]
EntSize: [[ENTSIZE=<none>]]
Size: [[SIZE=<none>]]
Content: [[CONTENT=<none>]]
- Name: .bar
Type: SHT_PROGBITS
## Case 12: shstrtab does not have SHT_STRTAB type. Default properties will be
## derived from the specified section type.
# RUN: yaml2obj --docnum=5 %s -o %t12 -DTYPE=SHT_RELA
# RUN: llvm-readelf -S %t12 | FileCheck %s --check-prefix=CASE12
# CASE12: There are 5 section headers
# CASE12-EMPTY:
# CASE12-NEXT: Section Headers:
# CASE12-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE12-NEXT: [ 0] NULL
# CASE12-NEXT: [ 1] .foo{{ }}
# CASE12-NEXT: [ 2] .strings RELA 0000000000000000 [[#%x,]] 00001c 18 0 0 0
# CASE12-NEXT: [ 3] .bar{{ }}
# CASE12-NEXT: [ 4] .strtab{{ }}
## Case 13: shstrtab has specified Content. The specified content overrides the
## implicitly generated content.
# RUN: yaml2obj --docnum=5 %s -o %t13 -DCONTENT="00616263646566676800696a6b6c006d6e6f70007172737475767700787a7b7c00"
# RUN: llvm-readelf -S %t13 | FileCheck %s --check-prefix=CASE13
# CASE13: There are 5 section headers
# CASE13-EMPTY:
# CASE13-NEXT: Section Headers:
# CASE13-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE13-NEXT: [ 0] NULL
# CASE13-NEXT: [ 1] mnop{{ }}
# CASE13-NEXT: [ 2] abcdefgh STRTAB 0000000000000000 [[#%x,]] 000021 00 0 0 0
# CASE13-NEXT: [ 3] ijkl{{ }}
# CASE13-NEXT: [ 4] qrstuvw{{ }}
## Case 14: shstrtab has specified Size. The section will be filled with zeros
## to the requested size.
# RUN: yaml2obj --docnum=5 %s -o %t14 -DSIZE=32
# RUN: llvm-readelf -S -p=2 %t14 | FileCheck %s --check-prefix=CASE14
# CASE14: There are 5 section headers
# CASE14-EMPTY:
# CASE14-NEXT: Section Headers:
# CASE14-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE14-NEXT: [ 0] NULL
# CASE14-NEXT: [ 1] PROGBITS
# CASE14-NEXT: [ 2] STRTAB 0000000000000000 [[#%x,]] 000020 00 0 0 0
# CASE14-NEXT: [ 3] PROGBITS
# CASE14-NEXT: [ 4] STRTAB
# CASE14: String dump of section '':
# CASE14-EMPTY:
## Case 15: custom shstrtab and no section header table. The section header
## names shouldn't appear anywhere in the output file.
# RUN: yaml2obj --docnum=6 %s -o %t15
# RUN: FileCheck %s --input-file=%t15 \
# RUN: --implicit-check-not=.strings --implicit-check-not=.foo \
# RUN: --implicit-check-not=.bar
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .strings
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Name: .bar
Type: SHT_PROGBITS
- Type: SectionHeaderTable
NoHeaders: true
## Case 16: custom shstrtab can be reordered in the section header table.
# RUN: yaml2obj --docnum=7 %s -o %t16
# RUN: llvm-readelf -S %t16 | FileCheck %s --check-prefix=CASE16
# CASE16: There are 5 section headers
# CASE16-EMPTY:
# CASE16-NEXT: Section Headers:
# CASE16-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE16-NEXT: [ 0] NULL
# CASE16-NEXT: [ 1] .foo{{ }}
# CASE16-NEXT: [ 2] .strings STRTAB 0000000000000000 [[#%x,]] 00001c 00 0 0 1
# CASE16-NEXT: [ 3] .bar{{ }}
# CASE16-NEXT: [ 4] .strtab{{ }}
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .strings
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Name: .bar
Type: SHT_PROGBITS
- Type: SectionHeaderTable
Sections:
- Name: .foo
- Name: .strings
- Name: .bar
- Name: .strtab
## Case 17: custom shstrtab section header can be excluded.
# RUN: yaml2obj --docnum=8 %s -o %t17
# RUN: llvm-readelf -h -S %t17 | FileCheck %s --check-prefix=CASE17
# CASE17: Section header string table index: 0
# CASE17: There are 4 section headers
# CASE17-EMPTY:
# CASE17-NEXT: Section Headers:
# CASE17-NEXT: [Nr] Name Type
# CASE17-NEXT: [ 0] <no-strings> NULL
# CASE17-NEXT: [ 1] <no-strings> PROGBITS
# CASE17-NEXT: [ 2] <no-strings> PROGBITS
# CASE17-NEXT: [ 3] <no-strings> STRTAB
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .strings
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Name: .bar
Type: SHT_PROGBITS
- Type: SectionHeaderTable
Sections:
- Name: .foo
- Name: .bar
- Name: .strtab
Excluded:
- Name: .strings
## Case 18: section name for excluded section does not appear in custom
## shstrtab.
# RUN: yaml2obj --docnum=9 %s -o %t18
# RUN: llvm-readelf -S -p=.strings %t18 | FileCheck %s --check-prefix=CASE18
# CASE18: There are 4 section headers
# CASE18-EMPTY:
# CASE18-NEXT: Section Headers:
# CASE18-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE18-NEXT: [ 0] NULL
# CASE18-NEXT: [ 1] .foo{{ }}
# CASE18-NEXT: [ 2] .strings STRTAB 0000000000000000 [[#%x,]] 000017 00 0 0 1
# CASE18-NEXT: [ 3] .strtab{{ }}
# CASE18: String dump of section '.strings':
# CASE18-NEXT: [ 1] .strings
# CASE18-NEXT: [ a] .foo
# CASE18-NEXT: [ f] .strtab
# CASE18-EMPTY:
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
SectionHeaderStringTable: .strings
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Name: .bar
Type: SHT_PROGBITS
- Type: SectionHeaderTable
Sections:
- Name: .foo
- Name: .strings
- Name: .strtab
Excluded:
- Name: .bar
## Case 19: custom shstrtab can have a uniqued name.
# RUN: yaml2obj --docnum=1 %s -o %t19 '-DSHSTRTAB=.strings (1)' '-DOTHER=.strings (0)'
# RUN: llvm-readelf -S -p=4 %t19 | FileCheck %s --check-prefix=CASE19
# CASE19: There are 5 section headers
# CASE19-EMPTY:
# CASE19-NEXT: Section Headers:
# CASE19-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE19-NEXT: [ 0] NULL
# CASE19-NEXT: [ 1] .foo{{ }}
# CASE19-NEXT: [ 2] .strings PROGBITS
# CASE19-NEXT: [ 3] .strtab{{ }}
# CASE19-NEXT: [ 4] .strings STRTAB 0000000000000000 [[#%x,]] 000017 00 0 0 1
# CASE19: String dump of section '.strings':
# CASE19-NEXT: [ 1] .strings{{$}}
# CASE19-NEXT: [ a] .foo{{$}}
# CASE19-NEXT: [ f] .strtab{{$}}
# CASE19-EMPTY:
## Case 20: custom shstrtab named ".strtab" with uniquifying ID.
# RUN: yaml2obj --docnum=2 %s -o %t20 '-DSHSTRTAB=.strtab (1)'
# RUN: llvm-readelf -S -s -p=4 -p=5 %t20 | FileCheck %s --check-prefix=CASE20
# CASE20: There are 6 section headers
# CASE20-EMPTY:
# CASE20-NEXT: Section Headers:
# CASE20-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE20-NEXT: [ 0] NULL
# CASE20-NEXT: [ 1] .foo{{ }}
# CASE20-NEXT: [ 2] .bar{{ }}
# CASE20-NEXT: [ 3] .symtab{{ }}
# CASE20-NEXT: [ 4] .strtab STRTAB [[#%x,]] [[#%x,]] 000009 00 0 0 1
# CASE20-NEXT: [ 5] .strtab STRTAB 0000000000000000 [[#%x,]] 00001b 00 0 0 1
# CASE20: Symbol table '.symtab' contains 3 entries:
# CASE20-NEXT: Num: {{.*}} Ndx Name
# CASE20-NEXT: 0: {{.*}} UND {{$}}
# CASE20-NEXT: 1: {{.*}} baz{{$}}
# CASE20-NEXT: 2: {{.*}} bob{{$}}
# CASE20: String dump of section '.strtab':
# CASE20-NEXT: [ 1] baz
# CASE20-NEXT: [ 5] bob
# CASE20-EMPTY:
# CASE20: String dump of section '.strtab':
# CASE20-NEXT: [ 1] .bar{{$}}
# CASE20-NEXT: [ 6] .foo{{$}}
# CASE20-NEXT: [ b] .strtab{{$}}
# CASE20-NEXT: [ 13] .symtab{{$}}
# CASE20-EMPTY:
## Case 21: custom shstrtab named ".dynstr" with uniquifying ID.
# RUN: yaml2obj --docnum=3 %s -o %t21 '-DSHSTRTAB=.dynstr (1)'
# RUN: llvm-readelf -S --dyn-syms -p=4 -p=6 %t21 | FileCheck %s --check-prefix=CASE21
# CASE21: There are 7 section headers
# CASE21-EMPTY:
# CASE21-NEXT: Section Headers:
# CASE21-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# CASE21-NEXT: [ 0] NULL
# CASE21-NEXT: [ 1] .foo{{ }}
# CASE21-NEXT: [ 2] .bar{{ }}
# CASE21-NEXT: [ 3] .dynsym{{ }}
# CASE21-NEXT: [ 4] .dynstr STRTAB [[#%x,]] [[#%x,]] 000009 00 A 0 0 1
# CASE21-NEXT: [ 5] .strtab{{ }}
# CASE21-NEXT: [ 6] .dynstr STRTAB 0000000000000000 [[#%x,]] 000023 00 0 0 1
# CASE21: Symbol table '.dynsym' contains 3 entries:
# CASE21-NEXT: Num: {{.*}} Ndx Name
# CASE21-NEXT: 0: {{.*}} UND {{$}}
# CASE21-NEXT: 1: {{.*}} baz{{$}}
# CASE21-NEXT: 2: {{.*}} bob{{$}}
# CASE21: String dump of section '.dynstr':
# CASE21-NEXT: [ 1] baz
# CASE21-NEXT: [ 5] bob
# CASE21-EMPTY:
# CASE21: String dump of section '.dynstr':
# CASE21-NEXT: [ 1] .dynstr{{$}}
# CASE21-NEXT: [ 9] .bar{{$}}
# CASE21-NEXT: [ e] .foo{{$}}
# CASE21-NEXT: [ 13] .dynsym{{$}}
# CASE21-NEXT: [ 1b] .strtab{{$}}
# CASE21-EMPTY:

View File

@ -31,6 +31,7 @@ class ELFDumper {
DenseMap<StringRef, uint32_t> UsedSectionNames;
std::vector<std::string> SectionNames;
Optional<uint32_t> ShStrTabIndex;
DenseMap<StringRef, uint32_t> UsedSymbolNames;
std::vector<std::string> SymbolNames;
@ -289,6 +290,13 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
Sections = *SectionsOrErr;
SectionNames.resize(Sections.size());
if (Sections.size() > 0) {
ShStrTabIndex = Obj.getHeader().e_shstrndx;
if (*ShStrTabIndex == ELF::SHN_XINDEX)
ShStrTabIndex = Sections[0].sh_link;
// TODO: Set EShStrndx if the value doesn't represent a real section.
}
// Normally an object that does not have sections has e_shnum == 0.
// Also, e_shnum might be 0, when the the number of entries in the section
// header table is larger than or equal to SHN_LORESERVE (0xff00). In this
@ -398,6 +406,29 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
return !shouldPrintSection(S, Sections[S.OriginalSecNdx], Y->DWARF);
});
// The section header string table by default is assumed to be called
// ".shstrtab" and be in its own unique section. However, it's possible for it
// to be called something else and shared with another section. If the name
// isn't the default, provide this in the YAML.
if (ShStrTabIndex && *ShStrTabIndex != ELF::SHN_UNDEF &&
*ShStrTabIndex < Sections.size()) {
StringRef ShStrtabName;
if (SymTab && SymTab->sh_link == *ShStrTabIndex) {
// Section header string table is shared with the symbol table. Use that
// section's name (usually .strtab).
ShStrtabName = cantFail(Obj.getSectionName(Sections[SymTab->sh_link]));
} else if (DynSymTab && DynSymTab->sh_link == *ShStrTabIndex) {
// Section header string table is shared with the dynamic symbol table.
// Use that section's name (usually .dynstr).
ShStrtabName = cantFail(Obj.getSectionName(Sections[DynSymTab->sh_link]));
} else {
// Otherwise, the section name potentially needs uniquifying.
ShStrtabName = cantFail(getUniquedSectionName(Sections[*ShStrTabIndex]));
}
if (ShStrtabName != ".shstrtab")
Y->Header.SectionHeaderStringTable = ShStrtabName;
}
Y->Chunks = std::move(Chunks);
return Y.release();
}
@ -486,6 +517,12 @@ Optional<DWARFYAML::Data> ELFDumper<ELFT>::dumpDWARFSections(
if (ELFYAML::RawContentSection *RawSec =
dyn_cast<ELFYAML::RawContentSection>(C.get())) {
// FIXME: The debugDebug* functions should take the content as stored in
// RawSec. Currently, they just use the last section with the matching
// name, which defeats this attempt to skip reading a section header
// string table with the same name as a DWARF section.
if (ShStrTabIndex && RawSec->OriginalSecNdx == *ShStrTabIndex)
continue;
Error Err = Error::success();
cantFail(std::move(Err));