From 6d191534f63b0ece222e2d6e418144b123c81c0c Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 19 Mar 2014 04:47:47 +0000 Subject: Object: Provide a richer means of describing auxiliary symbols The current state of affairs has auxiliary symbols described as a big bag of bytes. This is less than satisfying, it detracts from the YAML file as being human readable. Instead, allow for symbols to optionally contain their auxiliary data. This allows us to have a much higher level way of describing things like weak symbols, function definitions and section definitions. This depends on D3105. Differential Revision: http://llvm-reviews.chandlerc.com/D3092 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204214 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/COFF.h | 31 ++++++++++ include/llvm/Object/COFFYAML.h | 47 ++++++++++++++- include/llvm/Support/COFF.h | 15 ++++- include/llvm/Support/YAMLTraits.h | 26 +++++++++ lib/Object/COFFObjectFile.cpp | 2 +- lib/Object/COFFYAML.cpp | 103 ++++++++++++++++++++++++++++++++- test/Object/Inputs/COFF/i386.yaml | 16 ++++-- test/Object/Inputs/COFF/x86-64.yaml | 16 ++++-- test/Object/obj2yaml.test | 32 ++++++++--- tools/llvm-nm/llvm-nm.cpp | 3 +- tools/llvm-objdump/llvm-objdump.cpp | 3 +- tools/llvm-readobj/COFFDumper.cpp | 23 ++------ tools/obj2yaml/coff2yaml.cpp | 112 +++++++++++++++++++++++++++++++++++- tools/yaml2obj/yaml2coff.cpp | 82 +++++++++++++++++++++++--- 14 files changed, 457 insertions(+), 54 deletions(-) diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 4d5783ddce..67afe35ae9 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -202,6 +202,37 @@ struct coff_symbol { uint8_t getBaseType() const { return Type & 0x0F; } uint8_t getComplexType() const { return (Type & 0xF0) >> 4; } + + bool isFunctionDefinition() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && + getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && + COFF::isReservedSectionNumber(SectionNumber); + } + + bool isWeakExternal() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL || + (StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + SectionNumber == COFF::IMAGE_SYM_UNDEFINED && Value == 0); + } + + bool isFileRecord() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_FILE; + } + + bool isSectionDefinition() const { + // C++/CLI creates external ABS symbols for non-const appdomain globals. + // These are also followed by an auxiliary section definition. + bool isAppdomainGlobal = StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + SectionNumber == COFF::IMAGE_SYM_ABSOLUTE; + bool isOrdinarySection = + StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && Value == 0; + return isAppdomainGlobal || isOrdinarySection; + } + + bool isCLRToken() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; + } }; struct coff_section { diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h index 3fa3ec6c12..b5f9cccf85 100644 --- a/include/llvm/Object/COFFYAML.h +++ b/include/llvm/Object/COFFYAML.h @@ -14,6 +14,7 @@ #ifndef LLVM_OBJECT_COFFYAML_H #define LLVM_OBJECT_COFFYAML_H +#include "llvm/ADT/Optional.h" #include "llvm/Object/YAML.h" #include "llvm/Support/COFF.h" @@ -35,6 +36,10 @@ inline SectionCharacteristics operator|(SectionCharacteristics a, // The structure of the yaml files is not an exact 1:1 match to COFF. In order // to use yaml::IO, we use these structures which are closer to the source. namespace COFFYAML { + LLVM_YAML_STRONG_TYPEDEF(uint8_t, COMDATType) + LLVM_YAML_STRONG_TYPEDEF(uint32_t, WeakExternalCharacteristics) + LLVM_YAML_STRONG_TYPEDEF(uint8_t, AuxSymbolType) + struct Relocation { uint32_t VirtualAddress; uint16_t Type; @@ -54,7 +59,12 @@ namespace COFFYAML { COFF::symbol Header; COFF::SymbolBaseType SimpleType; COFF::SymbolComplexType ComplexType; - object::yaml::BinaryRef AuxiliaryData; + Optional FunctionDefinition; + Optional bfAndefSymbol; + Optional WeakExternal; + StringRef File; + Optional SectionDefinition; + Optional CLRToken; StringRef Name; Symbol(); }; @@ -75,6 +85,21 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Relocation) namespace llvm { namespace yaml { +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFFYAML::WeakExternalCharacteristics &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFFYAML::AuxSymbolType &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFFYAML::COMDATType &Value); +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, COFF::MachineTypes &Value); @@ -120,6 +145,26 @@ struct MappingTraits { static void mapping(IO &IO, COFF::header &H); }; +template <> struct MappingTraits { + static void mapping(IO &IO, COFF::AuxiliaryFunctionDefinition &AFD); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, COFF::AuxiliarybfAndefSymbol &AAS); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, COFF::AuxiliaryWeakExternal &AWE); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, COFF::AuxiliarySectionDefinition &ASD); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, COFF::AuxiliaryCLRToken &ACT); +}; + template <> struct MappingTraits { static void mapping(IO &IO, COFFYAML::Symbol &S); diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 5586253309..dca7fc6ee8 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -212,6 +212,10 @@ namespace COFF { SCT_COMPLEX_TYPE_SHIFT = 4 }; + enum AuxSymbolType { + IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF = 1 + }; + struct section { char Name[NameSize]; uint32_t VirtualSize; @@ -337,7 +341,7 @@ namespace COFF { uint32_t TotalSize; uint32_t PointerToLinenumber; uint32_t PointerToNextFunction; - uint8_t unused[2]; + char unused[2]; }; struct AuxiliarybfAndefSymbol { @@ -372,7 +376,14 @@ namespace COFF { uint32_t CheckSum; uint16_t Number; uint8_t Selection; - uint8_t unused[3]; + char unused[3]; + }; + + struct AuxiliaryCLRToken { + uint8_t AuxType; + uint8_t unused1; + uint32_t SymbolTableIndex; + char unused2[12]; }; union Auxiliary { diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index e704bf17fe..ea217c39fc 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -13,6 +13,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -420,6 +421,11 @@ public: this->processKey(Key, Val, false); } + template + void mapOptional(const char* Key, Optional &Val) { + processKeyWithDefault(Key, Val, Optional(), /*Required=*/false); + } + template typename std::enable_if::value,void>::type mapOptional(const char* Key, T& Val) { @@ -432,6 +438,26 @@ public: } private: + template + void processKeyWithDefault(const char *Key, Optional &Val, + const Optional &DefaultValue, bool Required) { + assert(DefaultValue.hasValue() == false && + "Optional shouldn't have a value!"); + void *SaveInfo; + bool UseDefault; + const bool sameAsDefault = outputting() && !Val.hasValue(); + if (!outputting() && !Val.hasValue()) + Val = T(); + if (this->preflightKey(Key, Required, sameAsDefault, UseDefault, + SaveInfo)) { + yamlize(*this, Val.getValue(), Required); + this->postflightKey(SaveInfo); + } else { + if (UseDefault) + Val = DefaultValue; + } + } + template void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue, bool Required) { diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 039bc4ef48..8036ab1812 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -174,7 +174,7 @@ error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { Result = SymbolRef::ST_Unknown; - } else if (Symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { + } else if (Symb->isFunctionDefinition()) { Result = SymbolRef::ST_Function; } else { uint32_t Characteristics = 0; diff --git a/lib/Object/COFFYAML.cpp b/lib/Object/COFFYAML.cpp index 2a0c07a391..94b72ffcbf 100644 --- a/lib/Object/COFFYAML.cpp +++ b/lib/Object/COFFYAML.cpp @@ -23,6 +23,31 @@ Object::Object() { memset(&Header, 0, sizeof(COFF::header)); } } namespace yaml { +void ScalarEnumerationTraits::enumeration( + IO &IO, COFFYAML::COMDATType &Value) { + IO.enumCase(Value, "0", 0); + ECase(IMAGE_COMDAT_SELECT_NODUPLICATES); + ECase(IMAGE_COMDAT_SELECT_ANY); + ECase(IMAGE_COMDAT_SELECT_SAME_SIZE); + ECase(IMAGE_COMDAT_SELECT_EXACT_MATCH); + ECase(IMAGE_COMDAT_SELECT_ASSOCIATIVE); + ECase(IMAGE_COMDAT_SELECT_LARGEST); + ECase(IMAGE_COMDAT_SELECT_NEWEST); +} + +void +ScalarEnumerationTraits::enumeration( + IO &IO, COFFYAML::WeakExternalCharacteristics &Value) { + ECase(IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY); + ECase(IMAGE_WEAK_EXTERN_SEARCH_LIBRARY); + ECase(IMAGE_WEAK_EXTERN_SEARCH_ALIAS); +} + +void ScalarEnumerationTraits::enumeration( + IO &IO, COFFYAML::AuxSymbolType &Value) { + ECase(IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF); +} + void ScalarEnumerationTraits::enumeration( IO &IO, COFF::MachineTypes &Value) { ECase(IMAGE_FILE_MACHINE_UNKNOWN); @@ -187,6 +212,24 @@ void ScalarBitSetTraits::bitset( #undef BCase namespace { +struct NSectionSelectionType { + NSectionSelectionType(IO &) + : SelectionType(COFFYAML::COMDATType(0)) {} + NSectionSelectionType(IO &, uint8_t C) + : SelectionType(COFFYAML::COMDATType(C)) {} + uint8_t denormalize(IO &) { return SelectionType; } + COFFYAML::COMDATType SelectionType; +}; + +struct NWeakExternalCharacteristics { + NWeakExternalCharacteristics(IO &) + : Characteristics(COFFYAML::WeakExternalCharacteristics(0)) {} + NWeakExternalCharacteristics(IO &, uint32_t C) + : Characteristics(COFFYAML::WeakExternalCharacteristics(C)) {} + uint32_t denormalize(IO &) { return Characteristics; } + COFFYAML::WeakExternalCharacteristics Characteristics; +}; + struct NSectionCharacteristics { NSectionCharacteristics(IO &) : Characteristics(COFF::SectionCharacteristics(0)) {} @@ -196,6 +239,15 @@ struct NSectionCharacteristics { COFF::SectionCharacteristics Characteristics; }; +struct NAuxTokenType { + NAuxTokenType(IO &) + : AuxType(COFFYAML::AuxSymbolType(0)) {} + NAuxTokenType(IO &, uint8_t C) + : AuxType(COFFYAML::AuxSymbolType(C)) {} + uint32_t denormalize(IO &) { return AuxType; } + COFFYAML::AuxSymbolType AuxType; +}; + struct NStorageClass { NStorageClass(IO &) : StorageClass(COFF::SymbolStorageClass(0)) {} NStorageClass(IO &, uint8_t S) : StorageClass(COFF::SymbolStorageClass(S)) {} @@ -247,6 +299,48 @@ void MappingTraits::mapping(IO &IO, COFF::header &H) { IO.mapOptional("Characteristics", NC->Characteristics); } +void MappingTraits::mapping( + IO &IO, COFF::AuxiliaryFunctionDefinition &AFD) { + IO.mapRequired("TagIndex", AFD.TagIndex); + IO.mapRequired("TotalSize", AFD.TotalSize); + IO.mapRequired("PointerToLinenumber", AFD.PointerToLinenumber); + IO.mapRequired("PointerToNextFunction", AFD.PointerToNextFunction); +} + +void MappingTraits::mapping( + IO &IO, COFF::AuxiliarybfAndefSymbol &AAS) { + IO.mapRequired("Linenumber", AAS.Linenumber); + IO.mapRequired("PointerToNextFunction", AAS.PointerToNextFunction); +} + +void MappingTraits::mapping( + IO &IO, COFF::AuxiliaryWeakExternal &AWE) { + MappingNormalization NWEC( + IO, AWE.Characteristics); + IO.mapRequired("TagIndex", AWE.TagIndex); + IO.mapRequired("Characteristics", NWEC->Characteristics); +} + +void MappingTraits::mapping( + IO &IO, COFF::AuxiliarySectionDefinition &ASD) { + MappingNormalization NSST( + IO, ASD.Selection); + + IO.mapRequired("Length", ASD.Length); + IO.mapRequired("NumberOfRelocations", ASD.NumberOfRelocations); + IO.mapRequired("NumberOfLinenumbers", ASD.NumberOfLinenumbers); + IO.mapRequired("CheckSum", ASD.CheckSum); + IO.mapRequired("Number", ASD.Number); + IO.mapOptional("Selection", NSST->SelectionType, COFFYAML::COMDATType(0)); +} + +void MappingTraits::mapping( + IO &IO, COFF::AuxiliaryCLRToken &ACT) { + MappingNormalization NATT(IO, ACT.AuxType); + IO.mapRequired("AuxType", NATT->AuxType); + IO.mapRequired("SymbolTableIndex", ACT.SymbolTableIndex); +} + void MappingTraits::mapping(IO &IO, COFFYAML::Symbol &S) { MappingNormalization NS(IO, S.Header.StorageClass); @@ -256,9 +350,12 @@ void MappingTraits::mapping(IO &IO, COFFYAML::Symbol &S) { IO.mapRequired("SimpleType", S.SimpleType); IO.mapRequired("ComplexType", S.ComplexType); IO.mapRequired("StorageClass", NS->StorageClass); - IO.mapOptional("NumberOfAuxSymbols", S.Header.NumberOfAuxSymbols, - (uint8_t) 0); - IO.mapOptional("AuxiliaryData", S.AuxiliaryData, object::yaml::BinaryRef()); + IO.mapOptional("FunctionDefinition", S.FunctionDefinition); + IO.mapOptional("bfAndefSymbol", S.bfAndefSymbol); + IO.mapOptional("WeakExternal", S.WeakExternal); + IO.mapOptional("File", S.File, StringRef()); + IO.mapOptional("SectionDefinition", S.SectionDefinition); + IO.mapOptional("CLRToken", S.CLRToken); } void MappingTraits::mapping(IO &IO, COFFYAML::Section &Sec) { diff --git a/test/Object/Inputs/COFF/i386.yaml b/test/Object/Inputs/COFF/i386.yaml index 1badad8d59..7873df0a7e 100644 --- a/test/Object/Inputs/COFF/i386.yaml +++ b/test/Object/Inputs/COFF/i386.yaml @@ -39,8 +39,12 @@ symbols: SimpleType: IMAGE_SYM_TYPE_NULL # (0) ComplexType: IMAGE_SYM_DTYPE_NULL # (0) StorageClass: IMAGE_SYM_CLASS_STATIC # (3) - NumberOfAuxSymbols: 1 - AuxiliaryData: !hex "240000000300000000000000010000000000" # |$.................| + SectionDefinition: + Length: 36 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 1 - !Symbol Name: .data @@ -49,8 +53,12 @@ symbols: SimpleType: IMAGE_SYM_TYPE_NULL # (0) ComplexType: IMAGE_SYM_DTYPE_NULL # (0) StorageClass: IMAGE_SYM_CLASS_STATIC # (3) - NumberOfAuxSymbols: 1 - AuxiliaryData: !hex "0D0000000000000000000000020000000000" # |..................| + SectionDefinition: + Length: 13 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 2 - !Symbol Name: _main diff --git a/test/Object/Inputs/COFF/x86-64.yaml b/test/Object/Inputs/COFF/x86-64.yaml index b775ae9cdf..1dc2b10cf4 100644 --- a/test/Object/Inputs/COFF/x86-64.yaml +++ b/test/Object/Inputs/COFF/x86-64.yaml @@ -38,8 +38,12 @@ symbols: SimpleType: IMAGE_SYM_TYPE_NULL # (0) ComplexType: IMAGE_SYM_DTYPE_NULL # (0) StorageClass: IMAGE_SYM_CLASS_STATIC # (3) - NumberOfAuxSymbols: 1 - AuxiliaryData: !hex "260000000300000000000000010000000000" # |&.................| + SectionDefinition: + Length: 38 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 1 - !Symbol Name: .data @@ -48,8 +52,12 @@ symbols: SimpleType: IMAGE_SYM_TYPE_NULL # (0) ComplexType: IMAGE_SYM_DTYPE_NULL # (0) StorageClass: IMAGE_SYM_CLASS_STATIC # (3) - NumberOfAuxSymbols: 1 - AuxiliaryData: !hex "0D0000000000000000000000020000000000" # |..................| + SectionDefinition: + Length: 13 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 2 - !Symbol Name: main diff --git a/test/Object/obj2yaml.test b/test/Object/obj2yaml.test index 49541336c6..d96275fe2c 100644 --- a/test/Object/obj2yaml.test +++ b/test/Object/obj2yaml.test @@ -36,8 +36,12 @@ COFF-I386-NEXT: SectionNumber: 1 COFF-I386-NEXT: SimpleType: IMAGE_SYM_TYPE_NULL COFF-I386-NEXT: ComplexType: IMAGE_SYM_DTYPE_NULL COFF-I386-NEXT: StorageClass: IMAGE_SYM_CLASS_STATIC -COFF-I386-NEXT: NumberOfAuxSymbols: 1 -COFF-I386-NEXT: AuxiliaryData: 240000000300000000000000010000000000 +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 36 +COFF-I386-NEXT: NumberOfRelocations: 3 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386-NEXT: CheckSum: 0 +COFF-I386-NEXT: Number: 1 COFF-I386: - Name: .data COFF-I386-NEXT: Value: 0 @@ -45,8 +49,12 @@ COFF-I386-NEXT: SectionNumber: 2 COFF-I386-NEXT: SimpleType: IMAGE_SYM_TYPE_NULL COFF-I386-NEXT: ComplexType: IMAGE_SYM_DTYPE_NULL COFF-I386-NEXT: StorageClass: IMAGE_SYM_CLASS_STATIC -COFF-I386-NEXT: NumberOfAuxSymbols: 1 -COFF-I386-NEXT: AuxiliaryData: 0D0000000000000000000000020000000000 +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 13 +COFF-I386-NEXT: NumberOfRelocations: 0 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386-NEXT: CheckSum: 0 +COFF-I386-NEXT: Number: 2 COFF-I386: - Name: _main COFF-I386-NEXT: Value: 0 @@ -111,8 +119,12 @@ COFF-X86-64-NEXT: SectionNumber: 1 COFF-X86-64-NEXT: SimpleType: IMAGE_SYM_TYPE_NULL COFF-X86-64-NEXT: ComplexType: IMAGE_SYM_DTYPE_NULL COFF-X86-64-NEXT: StorageClass: IMAGE_SYM_CLASS_STATIC -COFF-X86-64-NEXT: NumberOfAuxSymbols: 1 -COFF-X86-64-NEXT: AuxiliaryData: 260000000300000000000000010000000000 +COFF-X86-64-NEXT: SectionDefinition: +COFF-X86-64-NEXT: Length: 38 +COFF-X86-64-NEXT: NumberOfRelocations: 3 +COFF-X86-64-NEXT: NumberOfLinenumbers: 0 +COFF-X86-64-NEXT: CheckSum: 0 +COFF-X86-64-NEXT: Number: 1 COFF-X86-64: - Name: .data COFF-X86-64-NEXT: Value: 0 @@ -120,8 +132,12 @@ COFF-X86-64-NEXT: SectionNumber: 2 COFF-X86-64-NEXT: SimpleType: IMAGE_SYM_TYPE_NULL COFF-X86-64-NEXT: ComplexType: IMAGE_SYM_DTYPE_NULL COFF-X86-64-NEXT: StorageClass: IMAGE_SYM_CLASS_STATIC -COFF-X86-64-NEXT: NumberOfAuxSymbols: 1 -COFF-X86-64-NEXT: AuxiliaryData: 0D0000000000000000000000020000000000 +COFF-X86-64-NEXT: SectionDefinition: +COFF-X86-64-NEXT: Length: 13 +COFF-X86-64-NEXT: NumberOfRelocations: 0 +COFF-X86-64-NEXT: NumberOfLinenumbers: 0 +COFF-X86-64-NEXT: CheckSum: 0 +COFF-X86-64-NEXT: Number: 2 COFF-X86-64: - Name: main COFF-X86-64-NEXT: Value: 0 diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 100a1f20a1..22e019a8a5 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -344,8 +344,7 @@ static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { return 'i'; // Check for section symbol. - else if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && - Symb->Value == 0) + else if (Symb->isSectionDefinition()) return 's'; } diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 3f871471bc..f5328a959e 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -663,8 +663,7 @@ static void PrintCOFFSymbolTable(const COFFObjectFile *coff) { for (int i = 0, e = header->NumberOfSymbols; i != e; ++i) { if (aux_count--) { // Figure out which type of aux this is. - if (symbol->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC - && symbol->Value == 0) { // Section definition. + if (symbol->isSectionDefinition()) { // Section definition. const coff_aux_section_definition *asd; if (error(coff->getAuxSymbol(i, asd))) return; diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index d2275f0aab..cd40da7d6c 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -946,12 +946,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printNumber("AuxSymbolCount", Symbol->NumberOfAuxSymbols); for (unsigned I = 0; I < Symbol->NumberOfAuxSymbols; ++I) { - if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - Symbol->getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && - Symbol->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && - Symbol->SectionNumber != COFF::IMAGE_SYM_DEBUG && - Symbol->SectionNumber != COFF::IMAGE_SYM_ABSOLUTE && - Symbol->SectionNumber != COFF::IMAGE_SYM_UNDEFINED) { + if (Symbol->isFunctionDefinition()) { const coff_aux_function_definition *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) break; @@ -963,11 +958,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printHex("PointerToNextFunction", Aux->PointerToNextFunction); W.printBinary("Unused", makeArrayRef(Aux->Unused)); - } else if ( - Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL || - (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - Symbol->SectionNumber == COFF::IMAGE_SYM_UNDEFINED && - Symbol->Value == 0)) { + } else if (Symbol->isWeakExternal()) { const coff_aux_weak_external *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) break; @@ -987,7 +978,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { makeArrayRef(WeakExternalCharacteristics)); W.printBinary("Unused", makeArrayRef(Aux->Unused)); - } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_FILE) { + } else if (Symbol->isFileRecord()) { const coff_aux_file_record *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) break; @@ -995,11 +986,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { DictScope AS(W, "AuxFileRecord"); W.printString("FileName", StringRef(Aux->FileName)); - // C++/CLI creates external ABS symbols for non-const appdomain globals. - // These are also followed by an auxiliary section definition. - } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC || - (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - Symbol->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE)) { + } else if (Symbol->isSectionDefinition()) { const coff_aux_section_definition *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) break; @@ -1026,7 +1013,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printNumber("AssocSection", AssocName, Aux->Number); } - } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN) { + } else if (Symbol->isCLRToken()) { const coff_aux_clr_token *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) break; diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp index 6cf79aeabc..b003029407 100644 --- a/tools/obj2yaml/coff2yaml.cpp +++ b/tools/obj2yaml/coff2yaml.cpp @@ -78,6 +78,61 @@ void COFFDumper::dumpSections(unsigned NumSections) { } } +static void +dumpFunctionDefinition(COFFYAML::Symbol *Sym, + const object::coff_aux_function_definition *ObjFD) { + COFF::AuxiliaryFunctionDefinition YAMLFD; + YAMLFD.TagIndex = ObjFD->TagIndex; + YAMLFD.TotalSize = ObjFD->TotalSize; + YAMLFD.PointerToLinenumber = ObjFD->PointerToLinenumber; + YAMLFD.PointerToNextFunction = ObjFD->PointerToNextFunction; + + Sym->FunctionDefinition = YAMLFD; +} + +static void +dumpbfAndEfLineInfo(COFFYAML::Symbol *Sym, + const object::coff_aux_bf_and_ef_symbol *ObjBES) { + COFF::AuxiliarybfAndefSymbol YAMLAAS; + YAMLAAS.Linenumber = ObjBES->Linenumber; + YAMLAAS.PointerToNextFunction = ObjBES->PointerToNextFunction; + + Sym->bfAndefSymbol = YAMLAAS; +} + +static void dumpWeakExternal(COFFYAML::Symbol *Sym, + const object::coff_aux_weak_external *ObjWE) { + COFF::AuxiliaryWeakExternal YAMLWE; + YAMLWE.TagIndex = ObjWE->TagIndex; + YAMLWE.Characteristics = ObjWE->Characteristics; + + Sym->WeakExternal = YAMLWE; +} + +static void +dumpSectionDefinition(COFFYAML::Symbol *Sym, + const object::coff_aux_section_definition *ObjSD) { + COFF::AuxiliarySectionDefinition YAMLASD; + YAMLASD.Length = ObjSD->Length; + YAMLASD.NumberOfRelocations = ObjSD->NumberOfRelocations; + YAMLASD.NumberOfLinenumbers = ObjSD->NumberOfLinenumbers; + YAMLASD.CheckSum = ObjSD->CheckSum; + YAMLASD.Number = ObjSD->Number; + YAMLASD.Selection = ObjSD->Selection; + + Sym->SectionDefinition = YAMLASD; +} + +static void +dumpCLRTokenDefinition(COFFYAML::Symbol *Sym, + const object::coff_aux_clr_token *ObjCLRToken) { + COFF::AuxiliaryCLRToken YAMLCLRToken; + YAMLCLRToken.AuxType = ObjCLRToken->AuxType; + YAMLCLRToken.SymbolTableIndex = ObjCLRToken->SymbolTableIndex; + + Sym->CLRToken = YAMLCLRToken; +} + void COFFDumper::dumpSymbols(unsigned NumSymbols) { std::vector &Symbols = YAMLObj.Symbols; for (const auto &S : Obj.symbols()) { @@ -90,7 +145,62 @@ void COFFDumper::dumpSymbols(unsigned NumSymbols) { Sym.Header.Value = Symbol->Value; Sym.Header.SectionNumber = Symbol->SectionNumber; Sym.Header.NumberOfAuxSymbols = Symbol->NumberOfAuxSymbols; - Sym.AuxiliaryData = object::yaml::BinaryRef(Obj.getSymbolAuxData(Symbol)); + + if (Symbol->NumberOfAuxSymbols > 0) { + ArrayRef AuxData = Obj.getSymbolAuxData(Symbol); + if (Symbol->isFunctionDefinition()) { + // This symbol represents a function definition. + assert(Symbol->NumberOfAuxSymbols == 1 && + "Expected a single aux symbol to describe this function!"); + + const object::coff_aux_function_definition *ObjFD = + reinterpret_cast( + AuxData.data()); + dumpFunctionDefinition(&Sym, ObjFD); + } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_FUNCTION) { + // This symbol describes function line number information. + assert(Symbol->NumberOfAuxSymbols == 1 && + "Exepected a single aux symbol to describe this section!"); + + const object::coff_aux_bf_and_ef_symbol *ObjBES = + reinterpret_cast( + AuxData.data()); + dumpbfAndEfLineInfo(&Sym, ObjBES); + } else if (Symbol->isWeakExternal()) { + // This symbol represents a weak external definition. + assert(Symbol->NumberOfAuxSymbols == 1 && + "Exepected a single aux symbol to describe this section!"); + + const object::coff_aux_weak_external *ObjWE = + reinterpret_cast( + AuxData.data()); + dumpWeakExternal(&Sym, ObjWE); + } else if (Symbol->isFileRecord()) { + // This symbol represents a file record. + Sym.File = StringRef(reinterpret_cast(AuxData.data()), + Symbol->NumberOfAuxSymbols * COFF::SymbolSize); + } else if (Symbol->isSectionDefinition()) { + // This symbol represents a section definition. + assert(Symbol->NumberOfAuxSymbols == 1 && + "Expected a single aux symbol to describe this section!"); + + const object::coff_aux_section_definition *ObjSD = + reinterpret_cast( + AuxData.data()); + dumpSectionDefinition(&Sym, ObjSD); + } else if (Symbol->isCLRToken()) { + // This symbol represents a CLR token definition. + assert(Symbol->NumberOfAuxSymbols == 1 && + "Expected a single aux symbol to describe this CLR Token"); + + const object::coff_aux_clr_token *ObjCLRToken = + reinterpret_cast( + AuxData.data()); + dumpCLRTokenDefinition(&Sym, ObjCLRToken); + } else { + llvm_unreachable("Unhandled auxiliary symbol!"); + } + } Symbols.push_back(Sym); } } diff --git a/tools/yaml2obj/yaml2coff.cpp b/tools/yaml2obj/yaml2coff.cpp index c757eb64fb..a0ede246bd 100644 --- a/tools/yaml2obj/yaml2coff.cpp +++ b/tools/yaml2obj/yaml2coff.cpp @@ -14,6 +14,7 @@ #include "yaml2obj.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" @@ -153,13 +154,22 @@ static bool layoutCOFF(COFFParser &CP) { for (std::vector::iterator i = CP.Obj.Symbols.begin(), e = CP.Obj.Symbols.end(); i != e; ++i) { - unsigned AuxBytes = i->AuxiliaryData.binary_size(); - if (AuxBytes % COFF::SymbolSize != 0) { - errs() << "AuxiliaryData size not a multiple of symbol size!\n"; - return false; - } - i->Header.NumberOfAuxSymbols = AuxBytes / COFF::SymbolSize; - NumberOfSymbols += 1 + i->Header.NumberOfAuxSymbols; + uint32_t NumberOfAuxSymbols = 0; + if (i->FunctionDefinition) + NumberOfAuxSymbols += 1; + if (i->bfAndefSymbol) + NumberOfAuxSymbols += 1; + if (i->WeakExternal) + NumberOfAuxSymbols += 1; + if (!i->File.empty()) + NumberOfAuxSymbols += + (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize; + if (i->SectionDefinition) + NumberOfAuxSymbols += 1; + if (i->CLRToken) + NumberOfAuxSymbols += 1; + i->Header.NumberOfAuxSymbols = NumberOfAuxSymbols; + NumberOfSymbols += 1 + NumberOfAuxSymbols; } // Store all the allocated start addresses in the header. @@ -194,6 +204,24 @@ binary_le_impl binary_le(value_type V) { return binary_le_impl(V); } +template +struct zeros_impl { + zeros_impl() {} +}; + +template +raw_ostream &operator<<(raw_ostream &OS, const zeros_impl &) { + char Buffer[NumBytes]; + memset(Buffer, 0, sizeof(Buffer)); + OS.write(Buffer, sizeof(Buffer)); + return OS; +} + +template +zeros_impl zeros(const T &) { + return zeros_impl(); +} + bool writeCOFF(COFFParser &CP, raw_ostream &OS) { OS << binary_le(CP.Obj.Header.Machine) << binary_le(CP.Obj.Header.NumberOfSections) @@ -253,7 +281,45 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) { << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass) << binary_le(i->Header.NumberOfAuxSymbols); - i->AuxiliaryData.writeAsBinary(OS); + + if (i->FunctionDefinition) + OS << binary_le(i->FunctionDefinition->TagIndex) + << binary_le(i->FunctionDefinition->TotalSize) + << binary_le(i->FunctionDefinition->PointerToLinenumber) + << binary_le(i->FunctionDefinition->PointerToNextFunction) + << zeros(i->FunctionDefinition->unused); + if (i->bfAndefSymbol) + OS << zeros(i->bfAndefSymbol->unused1) + << binary_le(i->bfAndefSymbol->Linenumber) + << zeros(i->bfAndefSymbol->unused2) + << binary_le(i->bfAndefSymbol->PointerToNextFunction) + << zeros(i->bfAndefSymbol->unused3); + if (i->WeakExternal) + OS << binary_le(i->WeakExternal->TagIndex) + << binary_le(i->WeakExternal->Characteristics) + << zeros(i->WeakExternal->unused); + if (!i->File.empty()) { + uint32_t NumberOfAuxRecords = + (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize; + uint32_t NumberOfAuxBytes = NumberOfAuxRecords * COFF::SymbolSize; + uint32_t NumZeros = NumberOfAuxBytes - i->File.size(); + OS.write(i->File.data(), i->File.size()); + for (uint32_t Padding = 0; Padding < NumZeros; ++Padding) + OS.write(0); + } + if (i->SectionDefinition) + OS << binary_le(i->SectionDefinition->Length) + << binary_le(i->SectionDefinition->NumberOfRelocations) + << binary_le(i->SectionDefinition->NumberOfLinenumbers) + << binary_le(i->SectionDefinition->CheckSum) + << binary_le(i->SectionDefinition->Number) + << binary_le(i->SectionDefinition->Selection) + << zeros(i->SectionDefinition->unused); + if (i->CLRToken) + OS << binary_le(i->CLRToken->AuxType) + << zeros(i->CLRToken->unused1) + << binary_le(i->CLRToken->SymbolTableIndex) + << zeros(i->CLRToken->unused2); } // Output string table. -- cgit v1.2.3