Fix llvm-nm(1) printing of llvm-bitcode files for -format darwin to match darwin’s nm(1).

Also a small fix to match printing of Mach-O objects with -format posix.

llvm-svn: 252567
This commit is contained in:
Kevin Enderby 2015-11-10 00:31:08 +00:00
parent ffa143ce81
commit dc0dbe1f69
6 changed files with 138 additions and 45 deletions

View File

@ -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) { }

View File

@ -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<GlobalVariable>(GV)) {
if (GVar->isConstant())
Res |= BasicSymbolRef::SF_Const;
}
if (GV->hasPrivateLinkage())
Res |= BasicSymbolRef::SF_FormatSpecific;
if (!GV->hasLocalLinkage())

View File

@ -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

Binary file not shown.

View File

@ -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

View File

@ -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<IRObjectFile>(Obj))
return false;
if (isa<IRObjectFile>(Obj)) {
IRObjectFile *IRobj = dyn_cast<IRObjectFile>(&Obj);
Module &M = IRobj->getModule();
if (M.getTargetTriple().empty())
return false;
Triple T(M.getTargetTriple());
return T.isArch64Bit();
}
if (isa<COFFObjectFile>(Obj))
return false;
if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
@ -220,54 +227,81 @@ static StringRef CurrentFilename;
typedef std::vector<NMSymbol> 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<MachOObjectFile>(&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<IRObjectFile>(&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<MachOObjectFile>(Obj))) {
if ((JustSymbolName || (UndefinedOnly && isa<MachOObjectFile>(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<MachOObjectFile>(&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<IRObjectFile>(&Obj))
else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&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<COFFObjectFile>(&Obj))
Ret = getSymbolNMTypeChar(*COFF, I);
else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))