From 7f0edadcaf45b0fb545e6edfd4d026bb6fa7c5e5 Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Tue, 10 Nov 2015 00:31:08 +0000 Subject: [PATCH] =?utf8?q?Fix=20llvm-nm(1)=20printing=20of=20llvm-bitcode?= =?utf8?q?=20files=20for=20-format=20darwin=20to=20match=20darwin=E2=80=99?= =?utf8?q?s=20nm(1).=20Also=20a=20small=20fix=20to=20match=20printing=20of?= =?utf8?q?=20Mach-O=20objects=20with=20-format=20posix.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252567 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/SymbolicFile.h | 1 + lib/Object/IRObjectFile.cpp | 6 + test/tools/llvm-nm/X86/IRobj.test | 11 ++ .../llvm-nm/X86/Inputs/test.IRobj-x86_64 | Bin 0 -> 1168 bytes test/tools/llvm-nm/X86/posixMachO.test | 7 + tools/llvm-nm/llvm-nm.cpp | 158 +++++++++++++----- 6 files changed, 138 insertions(+), 45 deletions(-) create mode 100644 test/tools/llvm-nm/X86/IRobj.test create mode 100644 test/tools/llvm-nm/X86/Inputs/test.IRobj-x86_64 create mode 100644 test/tools/llvm-nm/X86/posixMachO.test diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 6b10ceb263a..0c5b38111a9 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -101,6 +101,7 @@ public: // (e.g. section symbols) SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary SF_Hidden = 1U << 9, // Symbol has hidden visibility + SF_Const = 1U << 10, // Symbol value is constant }; BasicSymbolRef() : OwningObject(nullptr) { } diff --git a/lib/Object/IRObjectFile.cpp b/lib/Object/IRObjectFile.cpp index 9f5132e9062..dcd385a1780 100644 --- a/lib/Object/IRObjectFile.cpp +++ b/lib/Object/IRObjectFile.cpp @@ -219,6 +219,12 @@ uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { uint32_t Res = BasicSymbolRef::SF_None; if (GV->isDeclarationForLinker()) Res |= BasicSymbolRef::SF_Undefined; + else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage()) + Res |= BasicSymbolRef::SF_Hidden; + if (const GlobalVariable *GVar = dyn_cast(GV)) { + if (GVar->isConstant()) + Res |= BasicSymbolRef::SF_Const; + } if (GV->hasPrivateLinkage()) Res |= BasicSymbolRef::SF_FormatSpecific; if (!GV->hasLocalLinkage()) diff --git a/test/tools/llvm-nm/X86/IRobj.test b/test/tools/llvm-nm/X86/IRobj.test new file mode 100644 index 00000000000..e6fa517d00e --- /dev/null +++ b/test/tools/llvm-nm/X86/IRobj.test @@ -0,0 +1,11 @@ +# RUN: llvm-nm -format darwin %p/Inputs/test.IRobj-x86_64 | FileCheck %s + +# CHECK: ---------------- (LTO,RODATA) external _global_const +# CHECK: ---------------- (LTO,DATA) external _global_data +# CHECK: ---------------- (LTO,CODE) external _global_func +# CHECK: ---------------- (LTO,RODATA) private external _hidden_const +# CHECK: ---------------- (LTO,DATA) private external _hidden_data +# CHECK: ---------------- (LTO,CODE) private external _hidden_func +# CHECK: ---------------- (LTO,RODATA) non-external _static_const +# CHECK: ---------------- (LTO,DATA) non-external _static_data +# CHECK: ---------------- (LTO,CODE) non-external _static_func diff --git a/test/tools/llvm-nm/X86/Inputs/test.IRobj-x86_64 b/test/tools/llvm-nm/X86/Inputs/test.IRobj-x86_64 new file mode 100644 index 0000000000000000000000000000000000000000..8bfa857fa7d163f3b74daa2df6e179e34a5c44e0 GIT binary patch literal 1168 zcmZuxPfR0K82_d-%$x0>=|G!M+?jEPqQQj2SP09yAp*tNO<04*7;jDql6qJ&w4}7` z9;VQBYN)2H9Ehh*vIhpm4e%TR;98Twf!BI)Lz&>_WQDp;bD^tuiLCpD zE~ZbUHs*BhHOJIl*Ho4Z`Nx>Rb!TXLAmS{@!M(S1cb^;|KozEYZl}02v44&s;mrWR z4Ln|63_gB}jVOSJA=iXzRP30Z)}&aC@&{3|YIMn;3EHq6I z-f(Do8YW*Z@lY0yOwU0{s6|EmRm=2X(uafq2?iy%jW{qXDPvSKG|fn3cHJ0_8Cnr7 zLrvxzSSKNMGGaN(|9m0-2opv5hi&25^z4~pt;E~Bs(3K@e3h_BeFv><8=7M4|39cx z3}|{fZK0O2#WdPNIU_z(0@rcw>>T>m06vlcSnP-TnM>0A9m>~#FN?beS+n5pnaSl{ z+3XBAl%OI#@HI~a>Ur2IR%i#)VJ2({@QvKI$ZL1T#^%NTfgEysdUPQberUu?^Arrjk7JCBp=a%!Ux>HrX zCzAJ3f&IP3sw!Fpr0Vnoi*2{qU+Z)dkk+E{lPI7MfR0IQTk)PuuOCvaL4Q(3w_@l@1jPr@O3`=;M`ZK&V*X)9=l9zDf}a@Ag~zh@^HVxXr%+;h$=w0( zZyful&JMe$#Bxda!Q>Z|u8VE!muuvBB|M%d$7`uPuIXD0N=I~l+gJBEx0NdaI6ou_`ybNb Sn7=p)JJ_PqfB5$MzxFqnH)G=f literal 0 HcmV?d00001 diff --git a/test/tools/llvm-nm/X86/posixMachO.test b/test/tools/llvm-nm/X86/posixMachO.test new file mode 100644 index 00000000000..a0d114237ce --- /dev/null +++ b/test/tools/llvm-nm/X86/posixMachO.test @@ -0,0 +1,7 @@ +# RUN: llvm-nm -P %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s + +# CHECK: EH_frame0 s 104 0 +# CHECK: L_.str s 59 0 +# CHECK: _main T 0 0 +# CHECK: _main.eh S 128 0 +# CHECK: _printf U 0 0 diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 770731fea9f..4144d538c1a 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" @@ -207,8 +208,14 @@ static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) { } static char isSymbolList64Bit(SymbolicFile &Obj) { - if (isa(Obj)) - return false; + if (isa(Obj)) { + IRObjectFile *IRobj = dyn_cast(&Obj); + Module &M = IRobj->getModule(); + if (M.getTargetTriple().empty()) + return false; + Triple T(M.getTargetTriple()); + return T.isArch64Bit(); + } if (isa(Obj)) return false; if (MachOObjectFile *MachO = dyn_cast(&Obj)) @@ -220,54 +227,81 @@ static StringRef CurrentFilename; typedef std::vector SymbolListT; static SymbolListT SymbolList; +static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I); + // darwinPrintSymbol() is used to print a symbol from a Mach-O file when the // the OutputFormat is darwin or we are printing Mach-O symbols in hex. For // the darwin format it produces the same output as darwin's nm(1) -m output // and when printing Mach-O symbols in hex it produces the same output as // darwin's nm(1) -x format. -static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, - char *SymbolAddrStr, const char *printBlanks) { +static void darwinPrintSymbol(SymbolicFile &Obj, SymbolListT::iterator I, + char *SymbolAddrStr, const char *printBlanks, + const char *printDashes, const char *printFormat) { MachO::mach_header H; MachO::mach_header_64 H_64; uint32_t Filetype, Flags; MachO::nlist_64 STE_64; MachO::nlist STE; - uint8_t NType; - uint8_t NSect; - uint16_t NDesc; - uint32_t NStrx; - uint64_t NValue; - DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); - if (MachO->is64Bit()) { - H_64 = MachO->MachOObjectFile::getHeader64(); - Filetype = H_64.filetype; - Flags = H_64.flags; - STE_64 = MachO->getSymbol64TableEntry(SymDRI); - NType = STE_64.n_type; - NSect = STE_64.n_sect; - NDesc = STE_64.n_desc; - NStrx = STE_64.n_strx; - NValue = STE_64.n_value; + uint8_t NType = 0; + uint8_t NSect = 0; + uint16_t NDesc = 0; + uint32_t NStrx = 0; + uint64_t NValue = 0; + MachOObjectFile *MachO = dyn_cast(&Obj); + if (Obj.isIR()) { + uint32_t SymFlags = I->Sym.getFlags(); + if (SymFlags & SymbolRef::SF_Global) + NType |= MachO::N_EXT; + if (SymFlags & SymbolRef::SF_Hidden) + NType |= MachO::N_PEXT; + if (SymFlags & SymbolRef::SF_Undefined) + NType |= MachO::N_EXT | MachO::N_UNDF; + else { + // Here we have a symbol definition. So to fake out a section name we + // use 1, 2 and 3 for section numbers. See below where they are used to + // print out fake section names. + NType |= MachO::N_SECT; + if(SymFlags & SymbolRef::SF_Const) + NSect = 3; + else { + IRObjectFile *IRobj = dyn_cast(&Obj); + char c = getSymbolNMTypeChar(*IRobj, I->Sym); + if (c == 't') + NSect = 1; + else + NSect = 2; + } + } + if (SymFlags & SymbolRef::SF_Weak) + NDesc |= MachO::N_WEAK_DEF; } else { - H = MachO->MachOObjectFile::getHeader(); - Filetype = H.filetype; - Flags = H.flags; - STE = MachO->getSymbolTableEntry(SymDRI); - NType = STE.n_type; - NSect = STE.n_sect; - NDesc = STE.n_desc; - NStrx = STE.n_strx; - NValue = STE.n_value; + DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); + if (MachO->is64Bit()) { + H_64 = MachO->MachOObjectFile::getHeader64(); + Filetype = H_64.filetype; + Flags = H_64.flags; + STE_64 = MachO->getSymbol64TableEntry(SymDRI); + NType = STE_64.n_type; + NSect = STE_64.n_sect; + NDesc = STE_64.n_desc; + NStrx = STE_64.n_strx; + NValue = STE_64.n_value; + } else { + H = MachO->MachOObjectFile::getHeader(); + Filetype = H.filetype; + Flags = H.flags; + STE = MachO->getSymbolTableEntry(SymDRI); + NType = STE.n_type; + NSect = STE.n_sect; + NDesc = STE.n_desc; + NStrx = STE.n_strx; + NValue = STE.n_value; + } } // If we are printing Mach-O symbols in hex do that and return. if (FormatMachOasHex) { char Str[18] = ""; - const char *printFormat; - if (MachO->is64Bit()) - printFormat = "%016" PRIx64; - else - printFormat = "%08" PRIx64; format(printFormat, NValue).print(Str, sizeof(Str)); outs() << Str << ' '; format("%02x", NType).print(Str, sizeof(Str)); @@ -285,6 +319,8 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, if (PrintAddress) { if ((NType & MachO::N_TYPE) == MachO::N_INDR) strcpy(SymbolAddrStr, printBlanks); + if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE) + strcpy(SymbolAddrStr, printDashes); outs() << SymbolAddrStr << ' '; } @@ -319,6 +355,19 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, outs() << "(indirect) "; break; case MachO::N_SECT: { + if (Obj.isIR()) { + // For llvm bitcode files print out a fake section name using the values + // use 1, 2 and 3 for section numbers as set above. + if (NSect == 1) + outs() << "(LTO,CODE) "; + else if (NSect == 2) + outs() << "(LTO,DATA) "; + else if (NSect == 3) + outs() << "(LTO,RODATA) "; + else + outs() << "(?,?) "; + break; + } section_iterator Sec = *MachO->getSymbolSection(I->Sym.getRawDataRefImpl()); DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; @@ -378,7 +427,8 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, if ((NType & MachO::N_TYPE) == MachO::N_INDR) { outs() << I->Name << " (for "; StringRef IndirectName; - if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName)) + if (!MachO || + MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName)) outs() << "?)"; else outs() << IndirectName << ")"; @@ -396,7 +446,8 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, outs() << " (dynamically looked up)"; else { StringRef LibraryName; - if (MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName)) + if (!MachO || + MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName)) outs() << " (from bad library ordinal " << LibraryOrdinal << ")"; else outs() << " (from " << LibraryName << ")"; @@ -516,12 +567,14 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, } } - const char *printBlanks, *printFormat; + const char *printBlanks, *printDashes, *printFormat; if (isSymbolList64Bit(Obj)) { printBlanks = " "; + printDashes = "----------------"; printFormat = "%016" PRIx64; } else { printBlanks = " "; + printDashes = "--------"; printFormat = "%08" PRIx64; } @@ -545,7 +598,8 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, outs() << ArchiveName << ":"; outs() << CurrentFilename << ": "; } - if (JustSymbolName || (UndefinedOnly && isa(Obj))) { + if ((JustSymbolName || (UndefinedOnly && isa(Obj) && + OutputFormat != darwin)) && OutputFormat != posix) { outs() << I->Name << "\n"; continue; } @@ -558,9 +612,13 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, if (OutputFormat == sysv) strcpy(SymbolSizeStr, printBlanks); - if (I->TypeChar != 'U') - format(printFormat, I->Address) + if (I->TypeChar != 'U') { + if (Obj.isIR()) + strcpy(SymbolAddrStr, printDashes); + else + format(printFormat, I->Address) .print(SymbolAddrStr, sizeof(SymbolAddrStr)); + } format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); // If OutputFormat is darwin or we are printing Mach-O symbols in hex and @@ -569,11 +627,15 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, // printing Mach-O symbols in hex and not a Mach-O object fall back to // OutputFormat bsd (see below). MachOObjectFile *MachO = dyn_cast(&Obj); - if ((OutputFormat == darwin || FormatMachOasHex) && MachO) { - darwinPrintSymbol(MachO, I, SymbolAddrStr, printBlanks); + if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) { + darwinPrintSymbol(Obj, I, SymbolAddrStr, printBlanks, printDashes, + printFormat); } else if (OutputFormat == posix) { - outs() << I->Name << " " << I->TypeChar << " " << SymbolAddrStr - << SymbolSizeStr << "\n"; + outs() << I->Name << " " << I->TypeChar << " "; + if (MachO) + outs() << I->Address << " " << "0" /* SymbolSizeStr */ << "\n"; + else + outs() << SymbolAddrStr << SymbolSizeStr << "\n"; } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) { if (PrintAddress) outs() << SymbolAddrStr << ' '; @@ -771,8 +833,14 @@ static char getNMTypeChar(SymbolicFile &Obj, basic_symbol_iterator I) { char Ret = '?'; if (Symflags & object::SymbolRef::SF_Absolute) Ret = 'a'; - else if (IRObjectFile *IR = dyn_cast(&Obj)) + else if (IRObjectFile *IR = dyn_cast(&Obj)) { Ret = getSymbolNMTypeChar(*IR, I); + Triple Host(sys::getDefaultTargetTriple()); + if (Ret == 'd' && Host.isOSDarwin()) { + if(Symflags & SymbolRef::SF_Const) + Ret = 's'; + } + } else if (COFFObjectFile *COFF = dyn_cast(&Obj)) Ret = getSymbolNMTypeChar(*COFF, I); else if (MachOObjectFile *MachO = dyn_cast(&Obj)) -- 2.40.0