diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h index 9492284ea93d37..47926ab3ae401a 100644 --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -411,13 +411,13 @@ class XCOFFCsectAuxRef { return Entry64->AuxType; } -private: uint8_t getSymbolAlignmentAndType() const { return GETVALUE(SymbolAlignmentAndType); } #undef GETVALUE +private: const XCOFFCsectAuxEnt32 *Entry32 = nullptr; const XCOFFCsectAuxEnt64 *Entry64 = nullptr; }; diff --git a/llvm/lib/ObjectYAML/XCOFFYAML.cpp b/llvm/lib/ObjectYAML/XCOFFYAML.cpp index 44ef33501b65e4..b71a7b8b6cb44a 100644 --- a/llvm/lib/ObjectYAML/XCOFFYAML.cpp +++ b/llvm/lib/ObjectYAML/XCOFFYAML.cpp @@ -282,45 +282,57 @@ static void auxSymMapping(IO &IO, XCOFFYAML::SectAuxEntForStat &AuxSym) { void MappingTraits>::mapping( IO &IO, std::unique_ptr &AuxSym) { - assert(!IO.outputting() && "We don't dump aux symbols currently."); + + auto ResetAuxSym = [&](auto *AuxEnt) { + if (!IO.outputting()) + AuxSym.reset(AuxEnt); + }; + const bool Is64 = static_cast(IO.getContext())->Header.Magic == (llvm::yaml::Hex16)XCOFF::XCOFF64; + XCOFFYAML::AuxSymbolType AuxType; + if (IO.outputting()) + AuxType = AuxSym.get()->Type; IO.mapRequired("Type", AuxType); switch (AuxType) { case XCOFFYAML::AUX_EXCEPT: - if (!Is64) + if (!Is64) { IO.setError("an auxiliary symbol of type AUX_EXCEPT cannot be defined in " "XCOFF32"); - AuxSym.reset(new XCOFFYAML::ExcpetionAuxEnt()); + return; + } + ResetAuxSym(new XCOFFYAML::ExcpetionAuxEnt()); auxSymMapping(IO, *cast(AuxSym.get())); break; case XCOFFYAML::AUX_FCN: - AuxSym.reset(new XCOFFYAML::FunctionAuxEnt()); + ResetAuxSym(new XCOFFYAML::FunctionAuxEnt()); auxSymMapping(IO, *cast(AuxSym.get()), Is64); break; case XCOFFYAML::AUX_SYM: - AuxSym.reset(new XCOFFYAML::BlockAuxEnt()); + ResetAuxSym(new XCOFFYAML::BlockAuxEnt()); auxSymMapping(IO, *cast(AuxSym.get()), Is64); break; case XCOFFYAML::AUX_FILE: - AuxSym.reset(new XCOFFYAML::FileAuxEnt()); + ResetAuxSym(new XCOFFYAML::FileAuxEnt()); auxSymMapping(IO, *cast(AuxSym.get())); break; case XCOFFYAML::AUX_CSECT: - AuxSym.reset(new XCOFFYAML::CsectAuxEnt()); + ResetAuxSym(new XCOFFYAML::CsectAuxEnt()); auxSymMapping(IO, *cast(AuxSym.get()), Is64); break; case XCOFFYAML::AUX_SECT: - AuxSym.reset(new XCOFFYAML::SectAuxEntForDWARF()); + ResetAuxSym(new XCOFFYAML::SectAuxEntForDWARF()); auxSymMapping(IO, *cast(AuxSym.get())); break; case XCOFFYAML::AUX_STAT: - if (Is64) + if (Is64) { IO.setError( "an auxiliary symbol of type AUX_STAT cannot be defined in XCOFF64"); - AuxSym.reset(new XCOFFYAML::SectAuxEntForStat()); + return; + } + ResetAuxSym(new XCOFFYAML::SectAuxEntForStat()); auxSymMapping(IO, *cast(AuxSym.get())); break; } @@ -334,8 +346,7 @@ void MappingTraits::mapping(IO &IO, XCOFFYAML::Symbol &S) { IO.mapOptional("Type", S.Type); IO.mapOptional("StorageClass", S.StorageClass); IO.mapOptional("NumberOfAuxEntries", S.NumberOfAuxEntries); - if (!IO.outputting()) - IO.mapOptional("AuxEntries", S.AuxEntries); + IO.mapOptional("AuxEntries", S.AuxEntries); } void MappingTraits::mapping(IO &IO, XCOFFYAML::StringTable &Str) { diff --git a/llvm/test/tools/obj2yaml/XCOFF/aix.yaml b/llvm/test/tools/obj2yaml/XCOFF/aix.yaml index cd1e88dec11d29..fbd5fa0629d10b 100644 --- a/llvm/test/tools/obj2yaml/XCOFF/aix.yaml +++ b/llvm/test/tools/obj2yaml/XCOFF/aix.yaml @@ -52,12 +52,30 @@ # CHECK32-NEXT: Type: 0x0 # CHECK32-NEXT: StorageClass: C_EXT # CHECK32-NEXT: NumberOfAuxEntries: 1 +# CHECK32-NEXT: AuxEntries: +# CHECK32-NEXT: - Type: AUX_CSECT +# CHECK32-NEXT: ParameterHashIndex: 0 +# CHECK32-NEXT: TypeChkSectNum: 0 +# CHECK32-NEXT: SymbolAlignmentAndType: 0 +# CHECK32-NEXT: StorageMappingClass: XMC_PR +# CHECK32-NEXT: SectionOrLength: 0 +# CHECK32-NEXT: StabInfoIndex: 0 +# CHECK32-NEXT: StabSectNum: 0 # CHECK32-NEXT: - Name: .data # CHECK32-NEXT: Value: 0x70 # CHECK32-NEXT: Section: .data # CHECK32-NEXT: Type: 0x0 # CHECK32-NEXT: StorageClass: C_HIDEXT # CHECK32-NEXT: NumberOfAuxEntries: 1 +# CHECK32-NEXT: AuxEntries: +# CHECK32-NEXT: - Type: AUX_CSECT +# CHECK32-NEXT: ParameterHashIndex: 0 +# CHECK32-NEXT: TypeChkSectNum: 0 +# CHECK32-NEXT: SymbolAlignmentAndType: 0 +# CHECK32-NEXT: StorageMappingClass: XMC_PR +# CHECK32-NEXT: SectionOrLength: 0 +# CHECK32-NEXT: StabInfoIndex: 0 +# CHECK32-NEXT: StabSectNum: 0 # CHECK64: --- !XCOFF # CHECK64-NEXT: FileHeader: @@ -106,12 +124,28 @@ # CHECK64-NEXT: Type: 0x0 # CHECK64-NEXT: StorageClass: C_EXT # CHECK64-NEXT: NumberOfAuxEntries: 1 +# CHECK64-NEXT: AuxEntries: +# CHECK64-NEXT: - Type: AUX_CSECT +# CHECK64-NEXT: ParameterHashIndex: 0 +# CHECK64-NEXT: TypeChkSectNum: 0 +# CHECK64-NEXT: SymbolAlignmentAndType: 0 +# CHECK64-NEXT: StorageMappingClass: XMC_PR +# CHECK64-NEXT: SectionOrLengthLo: 0 +# CHECK64-NEXT: SectionOrLengthHi: 0 # CHECK64-NEXT: - Name: .data # CHECK64-NEXT: Value: 0x70 # CHECK64-NEXT: Section: .data # CHECK64-NEXT: Type: 0x0 # CHECK64-NEXT: StorageClass: C_HIDEXT # CHECK64-NEXT: NumberOfAuxEntries: 1 +# CHECK64-NEXT: AuxEntries: +# CHECK64-NEXT: - Type: AUX_CSECT +# CHECK64-NEXT: ParameterHashIndex: 0 +# CHECK64-NEXT: TypeChkSectNum: 0 +# CHECK64-NEXT: SymbolAlignmentAndType: 0 +# CHECK64-NEXT: StorageMappingClass: XMC_PR +# CHECK64-NEXT: SectionOrLengthLo: 0 +# CHECK64-NEXT: SectionOrLengthHi: 0 --- !XCOFF FileHeader: @@ -140,9 +174,13 @@ Symbols: Type: 0x0 StorageClass: C_EXT NumberOfAuxEntries: 1 + AuxEntries: + - Type: AUX_CSECT - Name: .data Value: 0x70 Section: .data Type: 0x0 StorageClass: C_HIDEXT NumberOfAuxEntries: 1 + AuxEntries: + - Type: AUX_CSECT diff --git a/llvm/test/tools/obj2yaml/XCOFF/aux-symbols.yaml b/llvm/test/tools/obj2yaml/XCOFF/aux-symbols.yaml new file mode 100644 index 00000000000000..7f93b8dae0ca9b --- /dev/null +++ b/llvm/test/tools/obj2yaml/XCOFF/aux-symbols.yaml @@ -0,0 +1,322 @@ +## Check that obj2yaml can parse auxiliary symbols for XCOFF object file correctly. + +## 32-bit +# RUN: yaml2obj %s --docnum=1 -o %t32 +# RUN: obj2yaml %t32 | FileCheck %s --check-prefix=CHECK32 + +# CHECK32: --- !XCOFF +# CHECK32-NEXT: FileHeader: +# CHECK32-NEXT: MagicNumber: 0x1DF +# CHECK32-NEXT: NumberOfSections: 0 +# CHECK32-NEXT: CreationTime: 0 +# CHECK32-NEXT: OffsetToSymbolTable: 0x14 +# CHECK32-NEXT: EntriesInSymbolTable: 13 +# CHECK32-NEXT: AuxiliaryHeaderSize: 0 +# CHECK32-NEXT: Flags: 0x0 +# CHECK32-NEXT: Symbols: +# CHECK32-NEXT: - Name: '' +# CHECK32-NEXT: Value: 0x0 +# CHECK32-NEXT: Section: N_UNDEF +# CHECK32-NEXT: Type: 0x0 +# CHECK32-NEXT: StorageClass: C_FILE +# CHECK32-NEXT: NumberOfAuxEntries: 1 +# CHECK32-NEXT: AuxEntries: +# CHECK32-NEXT: - Type: AUX_FILE +# CHECK32-NEXT: FileNameOrString: FileName +# CHECK32-NEXT: FileStringType: XFT_CD +# CHECK32-NEXT: - Name: '' +# CHECK32-NEXT: Value: 0x0 +# CHECK32-NEXT: Section: N_UNDEF +# CHECK32-NEXT: Type: 0x0 +# CHECK32-NEXT: StorageClass: C_HIDEXT +# CHECK32-NEXT: NumberOfAuxEntries: 1 +# CHECK32-NEXT: AuxEntries: +# CHECK32-NEXT: - Type: AUX_CSECT +# CHECK32-NEXT: ParameterHashIndex: 1 +# CHECK32-NEXT: TypeChkSectNum: 2 +# CHECK32-NEXT: SymbolAlignmentAndType: 41 +# CHECK32-NEXT: StorageMappingClass: XMC_PR +# CHECK32-NEXT: SectionOrLength: 3 +# CHECK32-NEXT: StabInfoIndex: 4 +# CHECK32-NEXT: StabSectNum: 5 +# CHECK32-NEXT: - Name: '' +# CHECK32-NEXT: Value: 0x0 +# CHECK32-NEXT: Section: N_UNDEF +# CHECK32-NEXT: Type: 0x0 +# CHECK32-NEXT: StorageClass: C_EXT +# CHECK32-NEXT: NumberOfAuxEntries: 2 +# CHECK32-NEXT: AuxEntries: +# CHECK32-NEXT: - Type: AUX_FCN +# CHECK32-NEXT: OffsetToExceptionTbl: 1 +# CHECK32-NEXT: SizeOfFunction: 2 +# CHECK32-NEXT: SymIdxOfNextBeyond: 3 +# CHECK32-NEXT: PtrToLineNum: 4 +# CHECK32-NEXT: - Type: AUX_CSECT +# CHECK32-NEXT: ParameterHashIndex: 1 +# CHECK32-NEXT: TypeChkSectNum: 2 +# CHECK32-NEXT: SymbolAlignmentAndType: 17 +# CHECK32-NEXT: StorageMappingClass: XMC_PR +# CHECK32-NEXT: SectionOrLength: 4 +# CHECK32-NEXT: StabInfoIndex: 5 +# CHECK32-NEXT: StabSectNum: 6 +# CHECK32-NEXT: - Name: '' +# CHECK32-NEXT: Value: 0x0 +# CHECK32-NEXT: Section: N_UNDEF +# CHECK32-NEXT: Type: 0x0 +# CHECK32-NEXT: StorageClass: C_DWARF +# CHECK32-NEXT: NumberOfAuxEntries: 1 +# CHECK32-NEXT: AuxEntries: +# CHECK32-NEXT: - Type: AUX_SECT +# CHECK32-NEXT: LengthOfSectionPortion: 44 +# CHECK32-NEXT: NumberOfRelocEnt: 1 +# CHECK32-NEXT: - Name: '' +# CHECK32-NEXT: Value: 0x0 +# CHECK32-NEXT: Section: N_UNDEF +# CHECK32-NEXT: Type: 0x0 +# CHECK32-NEXT: StorageClass: C_STAT +# CHECK32-NEXT: NumberOfAuxEntries: 1 +# CHECK32-NEXT: AuxEntries: +# CHECK32-NEXT: - Type: AUX_STAT +# CHECK32-NEXT: SectionLength: 1 +# CHECK32-NEXT: NumberOfRelocEnt: 2 +# CHECK32-NEXT: NumberOfLineNum: 3 +# CHECK32-NEXT: - Name: '' +# CHECK32-NEXT: Value: 0x0 +# CHECK32-NEXT: Section: N_UNDEF +# CHECK32-NEXT: Type: 0x0 +# CHECK32-NEXT: StorageClass: C_BLOCK +# CHECK32-NEXT: NumberOfAuxEntries: 1 +# CHECK32-NEXT: AuxEntries: +# CHECK32-NEXT: - Type: AUX_SYM +# CHECK32-NEXT: LineNumHi: 1 +# CHECK32-NEXT: LineNumLo: 2 + +--- !XCOFF +FileHeader: + MagicNumber: 0x01DF +Symbols: + - StorageClass: C_FILE + AuxEntries: + - Type: AUX_FILE + FileNameOrString: FileName + FileStringType: XFT_CD + - StorageClass: C_HIDEXT + AuxEntries: + - Type: AUX_CSECT + ParameterHashIndex: 1 + TypeChkSectNum: 2 + SymbolAlignmentAndType: 41 + SectionOrLength: 3 + StabInfoIndex: 4 + StabSectNum: 5 + - StorageClass: C_EXT + AuxEntries: + - Type: AUX_FCN + OffsetToExceptionTbl: 1 + SizeOfFunction: 2 + SymIdxOfNextBeyond: 3 + PtrToLineNum: 4 + - Type: AUX_CSECT + ParameterHashIndex: 1 + TypeChkSectNum: 2 + SymbolAlignmentAndType: 17 + SectionOrLength: 4 + StabInfoIndex: 5 + StabSectNum: 6 + - StorageClass: C_DWARF + AuxEntries: + - Type: AUX_SECT + LengthOfSectionPortion: 44 + NumberOfRelocEnt: 1 + - StorageClass: C_STAT + AuxEntries: + - Type: AUX_STAT + SectionLength: 1 + NumberOfRelocEnt: 2 + NumberOfLineNum: 3 + - StorageClass: C_BLOCK + AuxEntries: + - Type: AUX_SYM + LineNumHi: 1 + LineNumLo: 2 + +## 64-bit +# RUN: yaml2obj %s --docnum=2 -o %t64 +# RUN: obj2yaml %t64 | FileCheck %s --check-prefix=CHECK64 + +# CHECK64: --- !XCOFF +# CHECK64-NEXT: FileHeader: +# CHECK64-NEXT: MagicNumber: 0x1F7 +# CHECK64-NEXT: NumberOfSections: 0 +# CHECK64-NEXT: CreationTime: 0 +# CHECK64-NEXT: OffsetToSymbolTable: 0x18 +# CHECK64-NEXT: EntriesInSymbolTable: 12 +# CHECK64-NEXT: AuxiliaryHeaderSize: 0 +# CHECK64-NEXT: Flags: 0x0 +# CHECK64-NEXT: Symbols: +# CHECK64-NEXT: - Name: '' +# CHECK64-NEXT: Value: 0x0 +# CHECK64-NEXT: Section: N_UNDEF +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: StorageClass: C_FILE +# CHECK64-NEXT: NumberOfAuxEntries: 1 +# CHECK64-NEXT: AuxEntries: +# CHECK64-NEXT: - Type: AUX_FILE +# CHECK64-NEXT: FileNameOrString: FileName +# CHECK64-NEXT: FileStringType: XFT_CD +# CHECK64-NEXT: - Name: '' +# CHECK64-NEXT: Value: 0x0 +# CHECK64-NEXT: Section: N_UNDEF +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: StorageClass: C_HIDEXT +# CHECK64-NEXT: NumberOfAuxEntries: 1 +# CHECK64-NEXT: AuxEntries: +# CHECK64-NEXT: - Type: AUX_CSECT +# CHECK64-NEXT: ParameterHashIndex: 1 +# CHECK64-NEXT: TypeChkSectNum: 2 +# CHECK64-NEXT: SymbolAlignmentAndType: 41 +# CHECK64-NEXT: StorageMappingClass: XMC_PR +# CHECK64-NEXT: SectionOrLengthLo: 3 +# CHECK64-NEXT: SectionOrLengthHi: 4 +# CHECK64-NEXT: - Name: '' +# CHECK64-NEXT: Value: 0x0 +# CHECK64-NEXT: Section: N_UNDEF +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: StorageClass: C_EXT +# CHECK64-NEXT: NumberOfAuxEntries: 3 +# CHECK64-NEXT: AuxEntries: +# CHECK64-NEXT: - Type: AUX_FCN +# CHECK64-NEXT: SizeOfFunction: 3 +# CHECK64-NEXT: SymIdxOfNextBeyond: 2 +# CHECK64-NEXT: PtrToLineNum: 1 +# CHECK64-NEXT: - Type: AUX_EXCEPT +# CHECK64-NEXT: OffsetToExceptionTbl: 1 +# CHECK64-NEXT: SizeOfFunction: 2 +# CHECK64-NEXT: SymIdxOfNextBeyond: 3 +# CHECK64-NEXT: - Type: AUX_CSECT +# CHECK64-NEXT: ParameterHashIndex: 1 +# CHECK64-NEXT: TypeChkSectNum: 2 +# CHECK64-NEXT: SymbolAlignmentAndType: 17 +# CHECK64-NEXT: StorageMappingClass: XMC_PR +# CHECK64-NEXT: SectionOrLengthLo: 3 +# CHECK64-NEXT: SectionOrLengthHi: 4 +# CHECK64-NEXT: - Name: '' +# CHECK64-NEXT: Value: 0x0 +# CHECK64-NEXT: Section: N_UNDEF +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: StorageClass: C_DWARF +# CHECK64-NEXT: NumberOfAuxEntries: 1 +# CHECK64-NEXT: AuxEntries: +# CHECK64-NEXT: - Type: AUX_SECT +# CHECK64-NEXT: LengthOfSectionPortion: 44 +# CHECK64-NEXT: NumberOfRelocEnt: 1 +# CHECK64-NEXT: - Name: '' +# CHECK64-NEXT: Value: 0x0 +# CHECK64-NEXT: Section: N_UNDEF +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: StorageClass: C_BLOCK +# CHECK64-NEXT: NumberOfAuxEntries: 1 +# CHECK64-NEXT: AuxEntries: +# CHECK64-NEXT: - Type: AUX_SYM +# CHECK64-NEXT: LineNum: 1 + +--- !XCOFF +FileHeader: + MagicNumber: 0x1F7 +Symbols: + - StorageClass: C_FILE + AuxEntries: + - Type: AUX_FILE + FileNameOrString: FileName + FileStringType: XFT_CD + - StorageClass: C_HIDEXT + AuxEntries: + - Type: AUX_CSECT + ParameterHashIndex: 1 + TypeChkSectNum: 2 + SymbolAlignmentAndType: 41 + SectionOrLengthLo: 3 + SectionOrLengthHi: 4 + - StorageClass: C_EXT + AuxEntries: + - Type: AUX_FCN + SizeOfFunction: 3 + SymIdxOfNextBeyond: 2 + PtrToLineNum: 1 + - Type: AUX_EXCEPT + OffsetToExceptionTbl: 1 + SizeOfFunction: 2 + SymIdxOfNextBeyond: 3 + - Type: AUX_CSECT + ParameterHashIndex: 1 + TypeChkSectNum: 2 + SymbolAlignmentAndType: 17 + SectionOrLengthLo: 3 + SectionOrLengthHi: 4 + - StorageClass: C_DWARF + AuxEntries: + - Type: AUX_SECT + LengthOfSectionPortion: 44 + NumberOfRelocEnt: 1 + - StorageClass: C_BLOCK + AuxEntries: + - Type: AUX_SYM + LineNum: 1 + +## Check that error messages are reported appropriately. + +# RUN: yaml2obj %s --docnum=3 -o - | not obj2yaml 2>&1 | FileCheck %s --check-prefix=ERROR1 +# ERROR1: failed to parse symbol "SYM_STAT" with index of 1: expected 1 aux symbol for C_STAT, while got 2 + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Symbols: + - Name: SYM + - Name: SYM_STAT + StorageClass: C_STAT + NumberOfAuxEntries: 2 + AuxEntries: + - Type: AUX_STAT + - Type: AUX_STAT + +# RUN: yaml2obj %s --docnum=4 -o - | not obj2yaml 2>&1 | FileCheck %s --check-prefix=ERROR2 +# ERROR2: failed to parse symbol "SYM_BLOCK" with index of 0: expected 1 aux symbol for C_BLOCK or C_FCN, while got 2 + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Symbols: + - Name: SYM_BLOCK + StorageClass: C_BLOCK + NumberOfAuxEntries: 2 + AuxEntries: + - Type: AUX_SYM + - Type: AUX_SYM + +# RUN: yaml2obj %s --docnum=5 -o - | not obj2yaml 2>&1 | FileCheck %s --check-prefix=ERROR3 +# ERROR3: failed to parse symbol "SYM_DWARF" with index of 0: expected 1 aux symbol for C_DWARF, while got 2 + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Symbols: + - Name: SYM_DWARF + StorageClass: C_DWARF + NumberOfAuxEntries: 2 + AuxEntries: + - Type: AUX_SECT + - Type: AUX_SECT + +# RUN: yaml2obj %s --docnum=6 -o - | not obj2yaml 2>&1 | FileCheck %s --check-prefix=ERROR4 +# ERROR4: failed to parse symbol "SYM_EXT" with index of 0: invalid auxiliary symbol type: 252 + +--- !XCOFF +FileHeader: + MagicNumber: 0x1F7 +Symbols: + - Name: SYM_EXT + StorageClass: C_EXT + AuxEntries: + - Type: AUX_FILE + - Type: AUX_CSECT diff --git a/llvm/tools/obj2yaml/xcoff2yaml.cpp b/llvm/tools/obj2yaml/xcoff2yaml.cpp index 882c410496012a..f7c2bae7479895 100644 --- a/llvm/tools/obj2yaml/xcoff2yaml.cpp +++ b/llvm/tools/obj2yaml/xcoff2yaml.cpp @@ -25,10 +25,30 @@ class XCOFFDumper { template Error dumpSections(ArrayRef Sections); + // Dump auxiliary symbols. + Error dumpFileAuxSym(XCOFFYAML::Symbol &Sym, + const XCOFFSymbolRef &SymbolEntRef); + Error dumpStatAuxSym(XCOFFYAML::Symbol &Sym, + const XCOFFSymbolRef &SymbolEntRef); + Error dumpBlockAuxSym(XCOFFYAML::Symbol &Sym, + const XCOFFSymbolRef &SymbolEntRef); + Error dumpDwarfAuxSym(XCOFFYAML::Symbol &Sym, + const XCOFFSymbolRef &SymbolEntRef); + Error dumpAuxSyms(XCOFFYAML::Symbol &Sym, const XCOFFSymbolRef &SymbolEntRef); + void dumpFuncAuxSym(XCOFFYAML::Symbol &Sym, const uintptr_t AuxAddress); + void dumpExpAuxSym(XCOFFYAML::Symbol &Sym, const uintptr_t AuxAddress); + void dumpCscetAuxSym(XCOFFYAML::Symbol &Sym, + const object::XCOFFCsectAuxRef &AuxEntPtr); + public: XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {} Error dump(); XCOFFYAML::Object &getYAMLObj() { return YAMLObj; } + + template const T *getAuxEntPtr(uintptr_t AuxAddress) { + Obj.checkSymbolEntryPointer(AuxAddress); + return reinterpret_cast(AuxAddress); + } }; } // namespace @@ -106,6 +126,210 @@ Error XCOFFDumper::dumpSections(ArrayRef Sections) { return Error::success(); } +Error XCOFFDumper::dumpFileAuxSym(XCOFFYAML::Symbol &Sym, + const XCOFFSymbolRef &SymbolEntRef) { + for (uint8_t I = 1; I <= Sym.NumberOfAuxEntries; ++I) { + uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( + SymbolEntRef.getEntryAddress(), I); + const XCOFFFileAuxEnt *FileAuxEntPtr = + getAuxEntPtr(AuxAddress); + auto FileNameOrError = Obj.getCFileName(FileAuxEntPtr); + if (!FileNameOrError) + return FileNameOrError.takeError(); + + XCOFFYAML::FileAuxEnt FileAuxSym; + FileAuxSym.FileNameOrString = FileNameOrError.get(); + FileAuxSym.FileStringType = FileAuxEntPtr->Type; + Sym.AuxEntries.push_back( + std::make_unique(FileAuxSym)); + } + return Error::success(); +} + +Error XCOFFDumper::dumpStatAuxSym(XCOFFYAML::Symbol &Sym, + const XCOFFSymbolRef &SymbolEntRef) { + if (Sym.NumberOfAuxEntries != 1) { + uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress()); + return createError("failed to parse symbol \"" + Sym.SymbolName + + "\" with index of " + Twine(SymbolIndex) + + ": expected 1 aux symbol for C_STAT, while got " + + Twine(static_cast(*Sym.NumberOfAuxEntries))); + } + + const XCOFFSectAuxEntForStat *AuxEntPtr = + getAuxEntPtr( + XCOFFObjectFile::getAdvancedSymbolEntryAddress( + SymbolEntRef.getEntryAddress(), 1)); + XCOFFYAML::SectAuxEntForStat StatAuxSym; + StatAuxSym.SectionLength = AuxEntPtr->SectionLength; + StatAuxSym.NumberOfLineNum = AuxEntPtr->NumberOfLineNum; + StatAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt; + Sym.AuxEntries.push_back( + std::make_unique(StatAuxSym)); + return Error::success(); +} + +void XCOFFDumper::dumpFuncAuxSym(XCOFFYAML::Symbol &Sym, + const uintptr_t AuxAddress) { + XCOFFYAML::FunctionAuxEnt FunAuxSym; + + if (Obj.is64Bit()) { + const XCOFFFunctionAuxEnt64 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + FunAuxSym.PtrToLineNum = AuxEntPtr->PtrToLineNum; + FunAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction; + FunAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond; + } else { + const XCOFFFunctionAuxEnt32 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + FunAuxSym.OffsetToExceptionTbl = AuxEntPtr->OffsetToExceptionTbl; + FunAuxSym.PtrToLineNum = AuxEntPtr->PtrToLineNum; + FunAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction; + FunAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond; + } + + Sym.AuxEntries.push_back( + std::make_unique(FunAuxSym)); +} + +void XCOFFDumper::dumpExpAuxSym(XCOFFYAML::Symbol &Sym, + const uintptr_t AuxAddress) { + const XCOFFExceptionAuxEnt *AuxEntPtr = + getAuxEntPtr(AuxAddress); + XCOFFYAML::ExcpetionAuxEnt ExceptAuxSym; + ExceptAuxSym.OffsetToExceptionTbl = AuxEntPtr->OffsetToExceptionTbl; + ExceptAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction; + ExceptAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond; + Sym.AuxEntries.push_back( + std::make_unique(ExceptAuxSym)); +} + +void XCOFFDumper::dumpCscetAuxSym(XCOFFYAML::Symbol &Sym, + const object::XCOFFCsectAuxRef &AuxEntPtr) { + XCOFFYAML::CsectAuxEnt CsectAuxSym; + CsectAuxSym.ParameterHashIndex = AuxEntPtr.getParameterHashIndex(); + CsectAuxSym.TypeChkSectNum = AuxEntPtr.getTypeChkSectNum(); + CsectAuxSym.SymbolAlignmentAndType = AuxEntPtr.getSymbolAlignmentAndType(); + CsectAuxSym.StorageMappingClass = AuxEntPtr.getStorageMappingClass(); + + if (Obj.is64Bit()) { + CsectAuxSym.SectionOrLengthLo = + static_cast(AuxEntPtr.getSectionOrLength64()); + CsectAuxSym.SectionOrLengthHi = + static_cast(AuxEntPtr.getSectionOrLength64() >> 32); + } else { + CsectAuxSym.SectionOrLength = AuxEntPtr.getSectionOrLength32(); + CsectAuxSym.StabInfoIndex = AuxEntPtr.getStabInfoIndex32(); + CsectAuxSym.StabSectNum = AuxEntPtr.getStabSectNum32(); + } + + Sym.AuxEntries.push_back( + std::make_unique(CsectAuxSym)); +} + +Error XCOFFDumper::dumpAuxSyms(XCOFFYAML::Symbol &Sym, + const XCOFFSymbolRef &SymbolEntRef) { + auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef(); + if (!ErrOrCsectAuxRef) + return ErrOrCsectAuxRef.takeError(); + XCOFFCsectAuxRef CsectAuxRef = ErrOrCsectAuxRef.get(); + + for (uint8_t I = 1; I <= Sym.NumberOfAuxEntries; ++I) { + + if (I == Sym.NumberOfAuxEntries && !Obj.is64Bit()) { + dumpCscetAuxSym(Sym, CsectAuxRef); + return Error::success(); + } + + uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( + SymbolEntRef.getEntryAddress(), I); + + if (Obj.is64Bit()) { + XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress); + if (Type == XCOFF::SymbolAuxType::AUX_CSECT) + dumpCscetAuxSym(Sym, CsectAuxRef); + else if (Type == XCOFF::SymbolAuxType::AUX_FCN) + dumpFuncAuxSym(Sym, AuxAddress); + else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) + dumpExpAuxSym(Sym, AuxAddress); + else { + uint32_t SymbolIndex = + Obj.getSymbolIndex(SymbolEntRef.getEntryAddress()); + return createError("failed to parse symbol \"" + Sym.SymbolName + + "\" with index of " + Twine(SymbolIndex) + + ": invalid auxiliary symbol type: " + + Twine(static_cast(Type))); + } + + } else + dumpFuncAuxSym(Sym, AuxAddress); + } + + return Error::success(); +} + +Error XCOFFDumper::dumpBlockAuxSym(XCOFFYAML::Symbol &Sym, + const XCOFFSymbolRef &SymbolEntRef) { + if (Sym.NumberOfAuxEntries != 1) { + uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress()); + return createError( + "failed to parse symbol \"" + Sym.SymbolName + "\" with index of " + + Twine(SymbolIndex) + + ": expected 1 aux symbol for C_BLOCK or C_FCN, while got " + + Twine(static_cast(*Sym.NumberOfAuxEntries))); + } + + uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( + SymbolEntRef.getEntryAddress(), 1); + XCOFFYAML::BlockAuxEnt BlockAuxSym; + + if (Obj.is64Bit()) { + const XCOFFBlockAuxEnt64 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + BlockAuxSym.LineNum = AuxEntPtr->LineNum; + } else { + const XCOFFBlockAuxEnt32 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + BlockAuxSym.LineNumLo = AuxEntPtr->LineNumLo; + BlockAuxSym.LineNumHi = AuxEntPtr->LineNumHi; + } + + Sym.AuxEntries.push_back( + std::make_unique(BlockAuxSym)); + return Error::success(); +} + +Error XCOFFDumper::dumpDwarfAuxSym(XCOFFYAML::Symbol &Sym, + const XCOFFSymbolRef &SymbolEntRef) { + if (Sym.NumberOfAuxEntries != 1) { + uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress()); + return createError("failed to parse symbol \"" + Sym.SymbolName + + "\" with index of " + Twine(SymbolIndex) + + ": expected 1 aux symbol for C_DWARF, while got " + + Twine(static_cast(*Sym.NumberOfAuxEntries))); + } + + uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( + SymbolEntRef.getEntryAddress(), 1); + XCOFFYAML::SectAuxEntForDWARF DwarfAuxSym; + + if (Obj.is64Bit()) { + const XCOFFSectAuxEntForDWARF64 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + DwarfAuxSym.LengthOfSectionPortion = AuxEntPtr->LengthOfSectionPortion; + DwarfAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt; + } else { + const XCOFFSectAuxEntForDWARF32 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + DwarfAuxSym.LengthOfSectionPortion = AuxEntPtr->LengthOfSectionPortion; + DwarfAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt; + } + + Sym.AuxEntries.push_back( + std::make_unique(DwarfAuxSym)); + return Error::success(); +} + Error XCOFFDumper::dumpSymbols() { std::vector &Symbols = YAMLObj.Symbols; @@ -133,6 +357,36 @@ Error XCOFFDumper::dumpSymbols() { Sym.StorageClass = SymbolEntRef.getStorageClass(); Sym.NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries(); + if (Sym.NumberOfAuxEntries) { + switch (Sym.StorageClass) { + case XCOFF::C_FILE: + if (Error E = dumpFileAuxSym(Sym, SymbolEntRef)) + return E; + break; + case XCOFF::C_STAT: + if (Error E = dumpStatAuxSym(Sym, SymbolEntRef)) + return E; + break; + case XCOFF::C_EXT: + case XCOFF::C_WEAKEXT: + case XCOFF::C_HIDEXT: + if (Error E = dumpAuxSyms(Sym, SymbolEntRef)) + return E; + break; + case XCOFF::C_BLOCK: + case XCOFF::C_FCN: + if (Error E = dumpBlockAuxSym(Sym, SymbolEntRef)) + return E; + break; + case XCOFF::C_DWARF: + if (Error E = dumpDwarfAuxSym(Sym, SymbolEntRef)) + return E; + break; + default: + break; + } + } + Symbols.push_back(std::move(Sym)); }