From da0464bee6769aa56ebddbf1fdb8667d32bafaa1 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Mon, 7 Jan 2019 20:55:33 +0000 Subject: [PATCH] [ObjectYAML] [COFF] Support multiple symbols with the same name Differential Revision: https://reviews.llvm.org/D56294 llvm-svn: 350566 --- include/llvm/ObjectYAML/COFFYAML.h | 6 ++ lib/ObjectYAML/COFFYAML.cpp | 3 +- test/tools/yaml2obj/coff-symbol-index.yaml | 74 ++++++++++++++++++++++ tools/obj2yaml/coff2yaml.cpp | 18 +++++- tools/yaml2obj/yaml2coff.cpp | 11 +++- 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 test/tools/yaml2obj/coff-symbol-index.yaml diff --git a/include/llvm/ObjectYAML/COFFYAML.h b/include/llvm/ObjectYAML/COFFYAML.h index 78f021fc038..253c627dd68 100644 --- a/include/llvm/ObjectYAML/COFFYAML.h +++ b/include/llvm/ObjectYAML/COFFYAML.h @@ -58,7 +58,13 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, AuxSymbolType) struct Relocation { uint32_t VirtualAddress; uint16_t Type; + + // Normally a Relocation can refer to the symbol via its name. + // It can also use a direct symbol table index instead (with no name + // specified), allowing disambiguating between multiple symbols with the + // same name or crafting intentionally broken files for testing. StringRef SymbolName; + Optional SymbolTableIndex; }; struct Section { diff --git a/lib/ObjectYAML/COFFYAML.cpp b/lib/ObjectYAML/COFFYAML.cpp index 9351ef96beb..fdd94f4054e 100644 --- a/lib/ObjectYAML/COFFYAML.cpp +++ b/lib/ObjectYAML/COFFYAML.cpp @@ -407,7 +407,8 @@ struct NDLLCharacteristics { void MappingTraits::mapping(IO &IO, COFFYAML::Relocation &Rel) { IO.mapRequired("VirtualAddress", Rel.VirtualAddress); - IO.mapRequired("SymbolName", Rel.SymbolName); + IO.mapOptional("SymbolName", Rel.SymbolName, StringRef()); + IO.mapOptional("SymbolTableIndex", Rel.SymbolTableIndex); COFF::header &H = *static_cast(IO.getContext()); if (H.Machine == COFF::IMAGE_FILE_MACHINE_I386) { diff --git a/test/tools/yaml2obj/coff-symbol-index.yaml b/test/tools/yaml2obj/coff-symbol-index.yaml new file mode 100644 index 00000000000..592ecb38b1d --- /dev/null +++ b/test/tools/yaml2obj/coff-symbol-index.yaml @@ -0,0 +1,74 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj -relocations %t | FileCheck %s --check-prefix=RELOCS +# RUN: obj2yaml %t | FileCheck %s --check-prefix=YAML + +# RELOCS: Relocations [ +# RELOCS-NEXT: Section (1) .text { +# RELOCS-NEXT: 0x3 IMAGE_REL_AMD64_REL32 .rdata (0) +# RELOCS-NEXT: 0xA IMAGE_REL_AMD64_REL32 .rdata (1) +# RELOCS-NEXT: 0x11 IMAGE_REL_AMD64_REL32 foo (2) +# RELOCS-NEXT: } +# RELOCS-NEXT: ] + +# Check that we usually output relocations with SymbolName. +# For relocations with a non-unique symbol name, output +# SymbolTableIndex instead. + +# YAML: Relocations: +# YAML-NEXT: - VirtualAddress: 3 +# YAML-NEXT: SymbolTableIndex: 0 +# YAML-NEXT: Type: IMAGE_REL_AMD64_REL32 +# YAML-NEXT: - VirtualAddress: 10 +# YAML-NEXT: SymbolTableIndex: 1 +# YAML-NEXT: Type: IMAGE_REL_AMD64_REL32 +# YAML-NEXT: - VirtualAddress: 17 +# YAML-NEXT: SymbolName: foo +# YAML-NEXT: Type: IMAGE_REL_AMD64_REL32 + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ ] + Alignment: 4 + SectionData: 488B0500000000488B0500000000488B0500000000 + Relocations: + - VirtualAddress: 3 + SymbolTableIndex: 0 + Type: IMAGE_REL_AMD64_REL32 + - VirtualAddress: 10 + SymbolTableIndex: 1 + Type: IMAGE_REL_AMD64_REL32 + - VirtualAddress: 17 + SymbolName: foo + Type: IMAGE_REL_AMD64_REL32 + - Name: .rdata + Characteristics: [ ] + Alignment: 1 + SectionData: '00' + - Name: .rdata + Characteristics: [ ] + Alignment: 1 + SectionData: '01' +symbols: + - Name: .rdata + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .rdata + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: foo + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp index 6835dcf71ff..3b44780fac5 100644 --- a/tools/obj2yaml/coff2yaml.cpp +++ b/tools/obj2yaml/coff2yaml.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "obj2yaml.h" +#include "llvm/ADT/StringMap.h" #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" @@ -142,6 +143,18 @@ void COFFDumper::dumpSections(unsigned NumSections) { codeview::StringsAndChecksumsRef SC; initializeFileAndStringTable(Obj, SC); + StringMap SymbolUnique; + for (const auto &S : Obj.symbols()) { + object::COFFSymbolRef Symbol = Obj.getCOFFSymbol(S); + StringRef Name; + Obj.getSymbolName(Symbol, Name); + StringMap::iterator It; + bool Inserted; + std::tie(It, Inserted) = SymbolUnique.insert(std::make_pair(Name, true)); + if (!Inserted) + It->second = false; + } + for (const auto &ObjSection : Obj.sections()) { const object::coff_section *COFFSection = Obj.getCOFFSection(ObjSection); COFFYAML::Section NewYAMLSection; @@ -192,7 +205,10 @@ void COFFDumper::dumpSections(unsigned NumSections) { OS.flush(); report_fatal_error(Buf); } - Rel.SymbolName = *SymbolNameOrErr; + if (SymbolUnique.lookup(*SymbolNameOrErr)) + Rel.SymbolName = *SymbolNameOrErr; + else + Rel.SymbolTableIndex = reloc->SymbolTableIndex; Rel.VirtualAddress = reloc->VirtualAddress; Rel.Type = reloc->Type; Relocations.push_back(Rel); diff --git a/tools/yaml2obj/yaml2coff.cpp b/tools/yaml2obj/yaml2coff.cpp index f9d255e1ad2..4fe9ab09041 100644 --- a/tools/yaml2obj/yaml2coff.cpp +++ b/tools/yaml2obj/yaml2coff.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include @@ -520,7 +521,15 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) { assert(S.Header.SizeOfRawData >= S.SectionData.binary_size()); OS << num_zeros(S.Header.SizeOfRawData - S.SectionData.binary_size()); for (const COFFYAML::Relocation &R : S.Relocations) { - uint32_t SymbolTableIndex = SymbolTableIndexMap[R.SymbolName]; + uint32_t SymbolTableIndex; + if (R.SymbolTableIndex) { + if (!R.SymbolName.empty()) + WithColor::error() + << "Both SymbolName and SymbolTableIndex specified\n"; + SymbolTableIndex = *R.SymbolTableIndex; + } else { + SymbolTableIndex = SymbolTableIndexMap[R.SymbolName]; + } OS << binary_le(R.VirtualAddress) << binary_le(SymbolTableIndex) << binary_le(R.Type);