diff --git a/llvm/test/tools/llvm-nm/XCOFF/Inputs/test_xlclang.o b/llvm/test/tools/llvm-nm/XCOFF/Inputs/test_xlclang.o new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@&1 | FileCheck %s -DFILE=%t.o --check-prefix=NM + +# NM: {{.*}}llvm-nm{{(\.exe)?}}: warning: [[FILE]]: for symbol with index 0: the section index (4) is invalid +# NM-NEXT: 00000000 ? .text + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Sections: + - Name: .text +Symbols: + - Name: .text + Value: 0x0 + SectionIndex: 4 + Type: 0x0 + StorageClass: C_STAT + NumberOfAuxEntries: 1 diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -31,6 +31,7 @@ #include "llvm/Object/TapiFile.h" #include "llvm/Object/TapiUniversal.h" #include "llvm/Object/Wasm.h" +#include "llvm/Object/XCOFFObjectFile.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" @@ -127,6 +128,20 @@ static StringRef ToolName; +static void warn(Error Err, Twine Path, Twine Context = Twine()) { + assert(Err); + + // Flush the standard output so that the warning isn't interleaved with other + // output if stdout and stderr are writing to the same place. + outs().flush(); + + handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) { + WithColor::warning(errs(), ToolName) + << Path << ": " << (Context.str().empty() ? "" : Context + ": ") + << EI.message() << "\n"; + }); +} + static void error(Twine Message, Twine Path = Twine()) { HadError = true; WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n"; @@ -246,6 +261,9 @@ return Triple(IRObj->getTargetTriple()).isArch64Bit(); if (isa(Obj) || isa(Obj)) return false; + if (XCOFFObjectFile *XCOFFObj = dyn_cast(&Obj)) + return XCOFFObj->is64Bit(); + if (isa(Obj)) return false; if (TapiFile *Tapi = dyn_cast(&Obj)) @@ -903,6 +921,43 @@ return '?'; } +static char getSymbolNMTypeChar(XCOFFObjectFile &Obj, symbol_iterator I) { + Expected TypeOrErr = I->getType(); + if (!TypeOrErr) { + + warn(TypeOrErr.takeError(), Obj.getFileName(), + "for symbol with index " + + Twine(Obj.getSymbolIndex(I->getRawDataRefImpl().p))); + return '?'; + } + + uint32_t SymType = *TypeOrErr; + + if (SymType == SymbolRef::ST_Debug) + return 'N'; + + if (SymType == SymbolRef::ST_File) + return 'f'; + + // If the I->getSection() call would return an error, the earlier I->getType() + // call will already have returned the same error first. + section_iterator SecIter = cantFail(I->getSection()); + + if (SecIter == Obj.section_end()) + return '?'; + + if (SecIter->isText()) + return 't'; + + if (SecIter->isData()) + return 'd'; + + if (SecIter->isBSS()) + return 'b'; + + return '?'; +} + static char getSymbolNMTypeChar(COFFImportFile &Obj) { switch (Obj.getCOFFImportHeader()->getType()) { case COFF::IMPORT_CODE: @@ -1051,6 +1106,8 @@ Ret = getSymbolNMTypeChar(*IR, I); else if (COFFObjectFile *COFF = dyn_cast(&Obj)) Ret = getSymbolNMTypeChar(*COFF, I); + else if (XCOFFObjectFile *XCOFF = dyn_cast(&Obj)) + Ret = getSymbolNMTypeChar(*XCOFF, I); else if (COFFImportFile *COFFImport = dyn_cast(&Obj)) Ret = getSymbolNMTypeChar(*COFFImport); else if (MachOObjectFile *MachO = dyn_cast(&Obj))