Skip to content

Commit 5c1639f

Browse files
committed
[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
1 parent fef3bfb commit 5c1639f

File tree

7 files changed

+1108
-31
lines changed

7 files changed

+1108
-31
lines changed

llvm/include/llvm/ObjectYAML/ELFYAML.h

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ struct FileHeader {
118118
Optional<ELF_EM> Machine;
119119
ELF_EF Flags;
120120
llvm::yaml::Hex64 Entry;
121+
Optional<StringRef> SectionHeaderStringTable;
121122

122123
Optional<llvm::yaml::Hex64> EPhOff;
123124
Optional<llvm::yaml::Hex16> EPhEntSize;

llvm/lib/ObjectYAML/ELFEmitter.cpp

+76-31
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,24 @@ template <class ELFT> class ELFState {
177177

178178
enum class SymtabType { Static, Dynamic };
179179

180-
/// The future ".strtab" section.
180+
/// The future symbol table string section.
181181
StringTableBuilder DotStrtab{StringTableBuilder::ELF};
182182

183-
/// The future ".shstrtab" section.
183+
/// The future section header string table section, if a unique string table
184+
/// is needed. Don't reference this variable direectly: use the
185+
/// ShStrtabStrings member instead.
184186
StringTableBuilder DotShStrtab{StringTableBuilder::ELF};
185187

186-
/// The future ".dynstr" section.
188+
/// The future dynamic symbol string section.
187189
StringTableBuilder DotDynstr{StringTableBuilder::ELF};
188190

191+
/// The name of the section header string table section. If it is .strtab or
192+
/// .dynstr, the section header strings will be written to the same string
193+
/// table as the static/dynamic symbols respectively. Otherwise a dedicated
194+
/// section will be created with that name.
195+
StringRef SectionHeaderStringTableName = ".shstrtab";
196+
StringTableBuilder *ShStrtabStrings = &DotShStrtab;
197+
189198
NameToIdxMap SN2I;
190199
NameToIdxMap SymN2I;
191200
NameToIdxMap DynSymN2I;
@@ -327,6 +336,18 @@ template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }
327336
template <class ELFT>
328337
ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
329338
: Doc(D), ErrHandler(EH) {
339+
// The input may explicitly request to store the section header table strings
340+
// in the same string table as dynamic or static symbol names. Set the
341+
// ShStrtabStrings member accordingly.
342+
if (Doc.Header.SectionHeaderStringTable) {
343+
SectionHeaderStringTableName = *Doc.Header.SectionHeaderStringTable;
344+
if (*Doc.Header.SectionHeaderStringTable == ".strtab")
345+
ShStrtabStrings = &DotStrtab;
346+
else if (*Doc.Header.SectionHeaderStringTable == ".dynstr")
347+
ShStrtabStrings = &DotDynstr;
348+
// Otherwise, the unique table will be used.
349+
}
350+
330351
std::vector<ELFYAML::Section *> Sections = Doc.getSections();
331352
// Insert SHT_NULL section implicitly when it is not defined in YAML.
332353
if (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL)
@@ -363,19 +384,35 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
363384
"' at YAML section/fill number " + Twine(I));
364385
}
365386

366-
std::vector<StringRef> ImplicitSections;
367-
if (Doc.DynamicSymbols)
368-
ImplicitSections.insert(ImplicitSections.end(), {".dynsym", ".dynstr"});
369-
if (Doc.Symbols)
370-
ImplicitSections.push_back(".symtab");
387+
SmallSetVector<StringRef, 8> ImplicitSections;
388+
if (Doc.DynamicSymbols) {
389+
if (SectionHeaderStringTableName == ".dynsym")
390+
reportError("cannot use '.dynsym' as the section header name table when "
391+
"there are dynamic symbols");
392+
ImplicitSections.insert(".dynsym");
393+
ImplicitSections.insert(".dynstr");
394+
}
395+
if (Doc.Symbols) {
396+
if (SectionHeaderStringTableName == ".symtab")
397+
reportError("cannot use '.symtab' as the section header name table when "
398+
"there are symbols");
399+
ImplicitSections.insert(".symtab");
400+
}
371401
if (Doc.DWARF)
372402
for (StringRef DebugSecName : Doc.DWARF->getNonEmptySectionNames()) {
373403
std::string SecName = ("." + DebugSecName).str();
374-
ImplicitSections.push_back(StringRef(SecName).copy(StringAlloc));
404+
// TODO: For .debug_str it should be possible to share the string table,
405+
// in the same manner as the symbol string tables.
406+
if (SectionHeaderStringTableName == SecName)
407+
reportError("cannot use '" + SecName +
408+
"' as the section header name table when it is needed for "
409+
"DWARF output");
410+
ImplicitSections.insert(StringRef(SecName).copy(StringAlloc));
375411
}
376-
ImplicitSections.insert(ImplicitSections.end(), {".strtab"});
412+
// TODO: Only create the .strtab here if any symbols have been requested.
413+
ImplicitSections.insert(".strtab");
377414
if (!SecHdrTable || !SecHdrTable->NoHeaders.getValueOr(false))
378-
ImplicitSections.insert(ImplicitSections.end(), {".shstrtab"});
415+
ImplicitSections.insert(SectionHeaderStringTableName);
379416

380417
// Insert placeholders for implicit sections that are not
381418
// defined explicitly in YAML.
@@ -387,7 +424,9 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
387424
ELFYAML::Chunk::ChunkKind::RawContent, true /*IsImplicit*/);
388425
Sec->Name = SecName;
389426

390-
if (SecName == ".dynsym")
427+
if (SecName == SectionHeaderStringTableName)
428+
Sec->Type = ELF::SHT_STRTAB;
429+
else if (SecName == ".dynsym")
391430
Sec->Type = ELF::SHT_DYNSYM;
392431
else if (SecName == ".symtab")
393432
Sec->Type = ELF::SHT_SYMTAB;
@@ -480,8 +519,9 @@ void ELFState<ELFT>::writeELFHeader(raw_ostream &OS) {
480519

481520
if (Doc.Header.EShStrNdx)
482521
Header.e_shstrndx = *Doc.Header.EShStrNdx;
483-
else if (SectionHeaders.Offset && !ExcludedSectionHeaders.count(".shstrtab"))
484-
Header.e_shstrndx = SN2I.get(".shstrtab");
522+
else if (SectionHeaders.Offset &&
523+
!ExcludedSectionHeaders.count(SectionHeaderStringTableName))
524+
Header.e_shstrndx = SN2I.get(SectionHeaderStringTableName);
485525
else
486526
Header.e_shstrndx = 0;
487527

@@ -615,16 +655,16 @@ bool ELFState<ELFT>::initImplicitHeader(ContiguousBlobAccumulator &CBA,
615655
if (Header.sh_offset)
616656
return false;
617657

618-
if (SecName == ".symtab")
619-
initSymtabSectionHeader(Header, SymtabType::Static, CBA, YAMLSec);
620-
else if (SecName == ".strtab")
658+
if (SecName == ".strtab")
621659
initStrtabSectionHeader(Header, SecName, DotStrtab, CBA, YAMLSec);
622-
else if (SecName == ".shstrtab")
623-
initStrtabSectionHeader(Header, SecName, DotShStrtab, CBA, YAMLSec);
624-
else if (SecName == ".dynsym")
625-
initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);
626660
else if (SecName == ".dynstr")
627661
initStrtabSectionHeader(Header, SecName, DotDynstr, CBA, YAMLSec);
662+
else if (SecName == SectionHeaderStringTableName)
663+
initStrtabSectionHeader(Header, SecName, *ShStrtabStrings, CBA, YAMLSec);
664+
else if (SecName == ".symtab")
665+
initSymtabSectionHeader(Header, SymtabType::Static, CBA, YAMLSec);
666+
else if (SecName == ".dynsym")
667+
initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);
628668
else if (SecName.startswith(".debug_")) {
629669
// If a ".debug_*" section's type is a preserved one, e.g., SHT_DYNAMIC, we
630670
// will not treat it as a debug section.
@@ -671,7 +711,7 @@ uint64_t ELFState<ELFT>::getSectionNameOffset(StringRef Name) {
671711
// the string table.
672712
if (ExcludedSectionHeaders.count(Name))
673713
return 0;
674-
return DotShStrtab.getOffset(Name);
714+
return ShStrtabStrings->getOffset(Name);
675715
}
676716

677717
static uint64_t writeContent(ContiguousBlobAccumulator &CBA,
@@ -995,7 +1035,7 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
9951035
StringTableBuilder &STB,
9961036
ContiguousBlobAccumulator &CBA,
9971037
ELFYAML::Section *YAMLSec) {
998-
SHeader.sh_name = getSectionNameOffset(Name);
1038+
SHeader.sh_name = getSectionNameOffset(ELFYAML::dropUniqueSuffix(Name));
9991039
SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_STRTAB;
10001040
SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1;
10011041

@@ -1817,10 +1857,8 @@ template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {
18171857
llvm_unreachable("buildSectionIndex() failed");
18181858

18191859
if (!ExcludedSectionHeaders.count(S->Name))
1820-
DotShStrtab.add(ELFYAML::dropUniqueSuffix(S->Name));
1860+
ShStrtabStrings->add(ELFYAML::dropUniqueSuffix(S->Name));
18211861
}
1822-
1823-
DotShStrtab.finalize();
18241862
}
18251863

18261864
template <class ELFT> void ELFState<ELFT>::buildSymbolIndexes() {
@@ -1870,6 +1908,11 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
18701908
}
18711909

18721910
DotDynstr.finalize();
1911+
1912+
// Don't finalize the section header string table a second time if it has
1913+
// already been finalized due to being one of the symbol string tables.
1914+
if (ShStrtabStrings != &DotStrtab && ShStrtabStrings != &DotDynstr)
1915+
ShStrtabStrings->finalize();
18731916
}
18741917

18751918
template <class ELFT>
@@ -1879,14 +1922,16 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
18791922
if (State.HasError)
18801923
return false;
18811924

1882-
// Finalize .strtab and .dynstr sections. We do that early because want to
1883-
// finalize the string table builders before writing the content of the
1884-
// sections that might want to use them.
1885-
State.finalizeStrings();
1886-
1925+
// Build the section index, which adds sections to the section header string
1926+
// table first, so that we can finalise the section header string table.
18871927
State.buildSectionIndex();
18881928
State.buildSymbolIndexes();
18891929

1930+
// Finalize section header string table and the .strtab and .dynstr sections.
1931+
// We do this early because we want to finalize the string table builders
1932+
// before writing the content of the sections that might want to use them.
1933+
State.finalizeStrings();
1934+
18901935
if (State.HasError)
18911936
return false;
18921937

llvm/lib/ObjectYAML/ELFYAML.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,
10071007
IO.mapOptional("Machine", FileHdr.Machine);
10081008
IO.mapOptional("Flags", FileHdr.Flags, ELFYAML::ELF_EF(0));
10091009
IO.mapOptional("Entry", FileHdr.Entry, Hex64(0));
1010+
IO.mapOptional("SectionHeaderStringTable", FileHdr.SectionHeaderStringTable);
10101011

10111012
// obj2yaml does not dump these fields.
10121013
assert(!IO.outputting() ||

llvm/test/tools/obj2yaml/ELF/invalid-section-name.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# CHECK-NEXT: Class: ELFCLASS64
1212
# CHECK-NEXT: Data: ELFDATA2LSB
1313
# CHECK-NEXT: Type: ET_REL
14+
# CHECK-NEXT: SectionHeaderStringTable: {{.*}}
1415
# CHECK-NEXT: Sections:
1516
# CHECK-NEXT: - Name: "{{.*}}"
1617
# CHECK-NEXT: Type: SHT_PROGBITS

0 commit comments

Comments
 (0)