diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h index 4d5783ddceae..67afe35ae90e 100644 --- a/llvm/include/llvm/Object/COFF.h +++ b/llvm/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/llvm/include/llvm/Object/COFFYAML.h b/llvm/include/llvm/Object/COFFYAML.h index 3fa3ec6c124b..b5f9cccf85d4 100644 --- a/llvm/include/llvm/Object/COFFYAML.h +++ b/llvm/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<COFF::AuxiliaryFunctionDefinition> FunctionDefinition; + Optional<COFF::AuxiliarybfAndefSymbol> bfAndefSymbol; + Optional<COFF::AuxiliaryWeakExternal> WeakExternal; + StringRef File; + Optional<COFF::AuxiliarySectionDefinition> SectionDefinition; + Optional<COFF::AuxiliaryCLRToken> CLRToken; StringRef Name; Symbol(); }; @@ -75,6 +85,21 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Relocation) namespace llvm { namespace yaml { +template <> +struct ScalarEnumerationTraits<COFFYAML::WeakExternalCharacteristics> { + static void enumeration(IO &IO, COFFYAML::WeakExternalCharacteristics &Value); +}; + +template <> +struct ScalarEnumerationTraits<COFFYAML::AuxSymbolType> { + static void enumeration(IO &IO, COFFYAML::AuxSymbolType &Value); +}; + +template <> +struct ScalarEnumerationTraits<COFFYAML::COMDATType> { + static void enumeration(IO &IO, COFFYAML::COMDATType &Value); +}; + template <> struct ScalarEnumerationTraits<COFF::MachineTypes> { static void enumeration(IO &IO, COFF::MachineTypes &Value); @@ -120,6 +145,26 @@ struct MappingTraits<COFF::header> { static void mapping(IO &IO, COFF::header &H); }; +template <> struct MappingTraits<COFF::AuxiliaryFunctionDefinition> { + static void mapping(IO &IO, COFF::AuxiliaryFunctionDefinition &AFD); +}; + +template <> struct MappingTraits<COFF::AuxiliarybfAndefSymbol> { + static void mapping(IO &IO, COFF::AuxiliarybfAndefSymbol &AAS); +}; + +template <> struct MappingTraits<COFF::AuxiliaryWeakExternal> { + static void mapping(IO &IO, COFF::AuxiliaryWeakExternal &AWE); +}; + +template <> struct MappingTraits<COFF::AuxiliarySectionDefinition> { + static void mapping(IO &IO, COFF::AuxiliarySectionDefinition &ASD); +}; + +template <> struct MappingTraits<COFF::AuxiliaryCLRToken> { + static void mapping(IO &IO, COFF::AuxiliaryCLRToken &ACT); +}; + template <> struct MappingTraits<COFFYAML::Symbol> { static void mapping(IO &IO, COFFYAML::Symbol &S); diff --git a/llvm/include/llvm/Support/COFF.h b/llvm/include/llvm/Support/COFF.h index 558625330911..dca7fc6ee898 100644 --- a/llvm/include/llvm/Support/COFF.h +++ b/llvm/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/llvm/include/llvm/Support/YAMLTraits.h b/llvm/include/llvm/Support/YAMLTraits.h index e704bf17fe17..ea217c39fca2 100644 --- a/llvm/include/llvm/Support/YAMLTraits.h +++ b/llvm/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 <typename T> + void mapOptional(const char* Key, Optional<T> &Val) { + processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false); + } + template <typename T> typename std::enable_if<!has_SequenceTraits<T>::value,void>::type mapOptional(const char* Key, T& Val) { @@ -432,6 +438,26 @@ public: } private: + template <typename T> + void processKeyWithDefault(const char *Key, Optional<T> &Val, + const Optional<T> &DefaultValue, bool Required) { + assert(DefaultValue.hasValue() == false && + "Optional<T> 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 <typename T> void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue, bool Required) { diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index 039bc4ef48b9..8036ab181273 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/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/llvm/lib/Object/COFFYAML.cpp b/llvm/lib/Object/COFFYAML.cpp index 2a0c07a391aa..94b72ffcbf3f 100644 --- a/llvm/lib/Object/COFFYAML.cpp +++ b/llvm/lib/Object/COFFYAML.cpp @@ -23,6 +23,31 @@ Object::Object() { memset(&Header, 0, sizeof(COFF::header)); } } namespace yaml { +void ScalarEnumerationTraits<COFFYAML::COMDATType>::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<COFFYAML::WeakExternalCharacteristics>::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<COFFYAML::AuxSymbolType>::enumeration( + IO &IO, COFFYAML::AuxSymbolType &Value) { + ECase(IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF); +} + void ScalarEnumerationTraits<COFF::MachineTypes>::enumeration( IO &IO, COFF::MachineTypes &Value) { ECase(IMAGE_FILE_MACHINE_UNKNOWN); @@ -187,6 +212,24 @@ void ScalarBitSetTraits<COFF::SectionCharacteristics>::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<COFF::header>::mapping(IO &IO, COFF::header &H) { IO.mapOptional("Characteristics", NC->Characteristics); } +void MappingTraits<COFF::AuxiliaryFunctionDefinition>::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<COFF::AuxiliarybfAndefSymbol>::mapping( + IO &IO, COFF::AuxiliarybfAndefSymbol &AAS) { + IO.mapRequired("Linenumber", AAS.Linenumber); + IO.mapRequired("PointerToNextFunction", AAS.PointerToNextFunction); +} + +void MappingTraits<COFF::AuxiliaryWeakExternal>::mapping( + IO &IO, COFF::AuxiliaryWeakExternal &AWE) { + MappingNormalization<NWeakExternalCharacteristics, uint32_t> NWEC( + IO, AWE.Characteristics); + IO.mapRequired("TagIndex", AWE.TagIndex); + IO.mapRequired("Characteristics", NWEC->Characteristics); +} + +void MappingTraits<COFF::AuxiliarySectionDefinition>::mapping( + IO &IO, COFF::AuxiliarySectionDefinition &ASD) { + MappingNormalization<NSectionSelectionType, uint8_t> 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<COFF::AuxiliaryCLRToken>::mapping( + IO &IO, COFF::AuxiliaryCLRToken &ACT) { + MappingNormalization<NAuxTokenType, uint8_t> NATT(IO, ACT.AuxType); + IO.mapRequired("AuxType", NATT->AuxType); + IO.mapRequired("SymbolTableIndex", ACT.SymbolTableIndex); +} + void MappingTraits<COFFYAML::Symbol>::mapping(IO &IO, COFFYAML::Symbol &S) { MappingNormalization<NStorageClass, uint8_t> NS(IO, S.Header.StorageClass); @@ -256,9 +350,12 @@ void MappingTraits<COFFYAML::Symbol>::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<COFFYAML::Section>::mapping(IO &IO, COFFYAML::Section &Sec) { diff --git a/llvm/test/Object/Inputs/COFF/i386.yaml b/llvm/test/Object/Inputs/COFF/i386.yaml index 1badad8d5915..7873df0a7e25 100644 --- a/llvm/test/Object/Inputs/COFF/i386.yaml +++ b/llvm/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/llvm/test/Object/Inputs/COFF/x86-64.yaml b/llvm/test/Object/Inputs/COFF/x86-64.yaml index b775ae9cdfbd..1dc2b10cf410 100644 --- a/llvm/test/Object/Inputs/COFF/x86-64.yaml +++ b/llvm/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/llvm/test/Object/obj2yaml.test b/llvm/test/Object/obj2yaml.test index 49541336c682..d96275fe2cc1 100644 --- a/llvm/test/Object/obj2yaml.test +++ b/llvm/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/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index 100a1f20a118..22e019a8a527 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/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/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 3f871471bca4..f5328a959e91 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/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<coff_aux_section_definition>(i, asd))) return; diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index d2275f0aab8f..cd40da7d6cc2 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/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/llvm/tools/obj2yaml/coff2yaml.cpp b/llvm/tools/obj2yaml/coff2yaml.cpp index 6cf79aeabc7d..b003029407ca 100644 --- a/llvm/tools/obj2yaml/coff2yaml.cpp +++ b/llvm/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<COFFYAML::Symbol> &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<uint8_t> 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<const object::coff_aux_function_definition *>( + 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<const object::coff_aux_bf_and_ef_symbol *>( + 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<const object::coff_aux_weak_external *>( + AuxData.data()); + dumpWeakExternal(&Sym, ObjWE); + } else if (Symbol->isFileRecord()) { + // This symbol represents a file record. + Sym.File = StringRef(reinterpret_cast<const char *>(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<const object::coff_aux_section_definition *>( + 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<const object::coff_aux_clr_token *>( + AuxData.data()); + dumpCLRTokenDefinition(&Sym, ObjCLRToken); + } else { + llvm_unreachable("Unhandled auxiliary symbol!"); + } + } Symbols.push_back(Sym); } } diff --git a/llvm/tools/yaml2obj/yaml2coff.cpp b/llvm/tools/yaml2obj/yaml2coff.cpp index c757eb64fb72..a0ede246bd68 100644 --- a/llvm/tools/yaml2obj/yaml2coff.cpp +++ b/llvm/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<COFFYAML::Symbol>::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<value_type> binary_le(value_type V) { return binary_le_impl<value_type>(V); } +template <size_t NumBytes> +struct zeros_impl { + zeros_impl() {} +}; + +template <size_t NumBytes> +raw_ostream &operator<<(raw_ostream &OS, const zeros_impl<NumBytes> &) { + char Buffer[NumBytes]; + memset(Buffer, 0, sizeof(Buffer)); + OS.write(Buffer, sizeof(Buffer)); + return OS; +} + +template <typename T> +zeros_impl<sizeof(T)> zeros(const T &) { + return zeros_impl<sizeof(T)>(); +} + 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.