Index: include/llvm/ObjectYAML/COFFYAML.h =================================================================== --- include/llvm/ObjectYAML/COFFYAML.h +++ include/llvm/ObjectYAML/COFFYAML.h @@ -58,7 +58,13 @@ 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 { Index: lib/ObjectYAML/COFFYAML.cpp =================================================================== --- lib/ObjectYAML/COFFYAML.cpp +++ lib/ObjectYAML/COFFYAML.cpp @@ -407,7 +407,8 @@ 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) { Index: test/tools/yaml2obj/coff-symbol-index.yaml =================================================================== --- /dev/null +++ test/tools/yaml2obj/coff-symbol-index.yaml @@ -0,0 +1,87 @@ +# 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 (2) +# RELOCS-NEXT: 0x11 IMAGE_REL_AMD64_REL32 foo (4) +# 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: 2 +# 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: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 488B0500000000488B0500000000488B0500000000 + Relocations: + - VirtualAddress: 3 + SymbolTableIndex: 0 + Type: IMAGE_REL_AMD64_REL32 + - VirtualAddress: 10 + SymbolTableIndex: 2 + Type: IMAGE_REL_AMD64_REL32 + - VirtualAddress: 17 + SymbolName: foo + Type: IMAGE_REL_AMD64_REL32 + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 1 + SectionData: '00' + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] + 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 + SectionDefinition: + Length: 1 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 4 + - Name: .rdata + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 1 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 1996959894 + Number: 3 + Selection: IMAGE_COMDAT_SELECT_ANY + - Name: foo + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... Index: tools/obj2yaml/coff2yaml.cpp =================================================================== --- tools/obj2yaml/coff2yaml.cpp +++ 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 @@ 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 @@ 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); Index: tools/yaml2obj/yaml2coff.cpp =================================================================== --- tools/yaml2obj/yaml2coff.cpp +++ 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 @@ 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);