mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
Add "-format darwin" to llvm-nm to be like darwin's nm(1) -m output.
This is a first step in seeing if it is possible to make llvm-nm produce the same output as darwin's nm(1). Darwin's default format is bsd but its -m output prints the longer Mach-O specific details. For now I added the "-format darwin" to do this (whos name may need to change in the future). As there are other Mach-O specific flags to nm(1) which I'm hoping to add some how in the future. But I wanted to see if I could get the correct output for -m flag using llvm-nm and the libObject interfaces. I got this working but would love to hear what others think about this approach to getting object/format specific details printed with llvm-nm. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210285 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
542fdf5fba
commit
ecbc72405e
@ -61,6 +61,10 @@ public:
|
||||
|
||||
void moveSymbolNext(DataRefImpl &Symb) const override;
|
||||
error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override;
|
||||
|
||||
// MachO specific.
|
||||
error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const;
|
||||
|
||||
error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override;
|
||||
error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const override;
|
||||
error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override;
|
||||
@ -105,6 +109,9 @@ public:
|
||||
LibraryRef &Res) const override;
|
||||
error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const override;
|
||||
|
||||
// MachO specific.
|
||||
error_code getLibraryShortNameByIndex(unsigned Index, StringRef &Res);
|
||||
|
||||
// TODO: Would be useful to have an iterator based version
|
||||
// of the load command interface too.
|
||||
|
||||
@ -198,6 +205,9 @@ public:
|
||||
bool is64Bit() const;
|
||||
void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
|
||||
|
||||
static StringRef guessLibraryShortName(StringRef Name, bool &isFramework,
|
||||
StringRef &Suffix);
|
||||
|
||||
static Triple::ArchType getArch(uint32_t CPUType);
|
||||
|
||||
static bool classof(const Binary *v) {
|
||||
@ -207,6 +217,10 @@ public:
|
||||
private:
|
||||
typedef SmallVector<const char*, 1> SectionList;
|
||||
SectionList Sections;
|
||||
typedef SmallVector<const char*, 1> LibraryList;
|
||||
LibraryList Libraries;
|
||||
typedef SmallVector<StringRef, 1> LibraryShortName;
|
||||
LibraryShortName LibrariesShortNames;
|
||||
const char *SymtabLoadCmd;
|
||||
const char *DysymtabLoadCmd;
|
||||
const char *DataInCodeLoadCmd;
|
||||
|
@ -86,8 +86,8 @@ public:
|
||||
SF_Weak = 1U << 2, // Weak symbol
|
||||
SF_Absolute = 1U << 3, // Absolute symbol
|
||||
SF_Common = 1U << 4, // Symbol has common linkage
|
||||
SF_Indirect = 1U << 5,
|
||||
SF_FormatSpecific = 1U << 5 // Specific to the object file format
|
||||
SF_Indirect = 1U << 5, // Symbol is an alias to another symbol
|
||||
SF_FormatSpecific = 1U << 6 // Specific to the object file format
|
||||
// (e.g. section symbols)
|
||||
};
|
||||
|
||||
|
@ -360,11 +360,28 @@ namespace llvm {
|
||||
enum {
|
||||
// Constant masks for the "n_desc" field in llvm::MachO::nlist and
|
||||
// llvm::MachO::nlist_64
|
||||
// The low 3 bits are the for the REFERENCE_TYPE.
|
||||
REFERENCE_TYPE = 0x7,
|
||||
REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0,
|
||||
REFERENCE_FLAG_UNDEFINED_LAZY = 1,
|
||||
REFERENCE_FLAG_DEFINED = 2,
|
||||
REFERENCE_FLAG_PRIVATE_DEFINED = 3,
|
||||
REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4,
|
||||
REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5,
|
||||
// Flag bits (some overlap with the library ordinal bits).
|
||||
N_ARM_THUMB_DEF = 0x0008u,
|
||||
REFERENCED_DYNAMICALLY = 0x0010u,
|
||||
N_NO_DEAD_STRIP = 0x0020u,
|
||||
N_WEAK_REF = 0x0040u,
|
||||
N_WEAK_DEF = 0x0080u,
|
||||
N_SYMBOL_RESOLVER = 0x0100u
|
||||
N_SYMBOL_RESOLVER = 0x0100u,
|
||||
N_ALT_ENTRY = 0x0200u,
|
||||
// For undefined symbols coming from libraries, see GET_LIBRARY_ORDINAL()
|
||||
// as these are in the top 8 bits.
|
||||
SELF_LIBRARY_ORDINAL = 0x0,
|
||||
MAX_LIBRARY_ORDINAL = 0xfd,
|
||||
DYNAMIC_LOOKUP_ORDINAL = 0xfe,
|
||||
EXECUTABLE_ORDINAL = 0xff
|
||||
};
|
||||
|
||||
enum StabType {
|
||||
|
@ -222,6 +222,16 @@ void SwapStruct(MachO::version_min_command&C) {
|
||||
SwapValue(C.reserved);
|
||||
}
|
||||
|
||||
template<>
|
||||
void SwapStruct(MachO::dylib_command&C) {
|
||||
SwapValue(C.cmd);
|
||||
SwapValue(C.cmdsize);
|
||||
SwapValue(C.dylib.name);
|
||||
SwapValue(C.dylib.timestamp);
|
||||
SwapValue(C.dylib.current_version);
|
||||
SwapValue(C.dylib.compatibility_version);
|
||||
}
|
||||
|
||||
template<>
|
||||
void SwapStruct(MachO::data_in_code_entry &C) {
|
||||
SwapValue(C.offset);
|
||||
@ -443,6 +453,12 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian,
|
||||
const char *Sec = getSectionPtr(this, Load, J);
|
||||
Sections.push_back(Sec);
|
||||
}
|
||||
} else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
|
||||
Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
|
||||
Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
|
||||
Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
|
||||
Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
|
||||
Libraries.push_back(Load.Ptr);
|
||||
}
|
||||
|
||||
if (I == LoadCommandCount - 1)
|
||||
@ -468,6 +484,30 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
|
||||
return object_error::success;
|
||||
}
|
||||
|
||||
// getIndirectName() returns the name of the alias'ed symbol who's string table
|
||||
// index is in the n_value field.
|
||||
error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
|
||||
StringRef &Res) const {
|
||||
StringRef StringTable = getStringTableData();
|
||||
uint64_t NValue;
|
||||
if (is64Bit()) {
|
||||
MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
|
||||
NValue = Entry.n_value;
|
||||
if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
|
||||
return object_error::parse_failed;
|
||||
} else {
|
||||
MachO::nlist Entry = getSymbolTableEntry(Symb);
|
||||
NValue = Entry.n_value;
|
||||
if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
|
||||
return object_error::parse_failed;
|
||||
}
|
||||
if (NValue >= StringTable.size())
|
||||
return object_error::parse_failed;
|
||||
const char *Start = &StringTable.data()[NValue];
|
||||
Res = StringRef(Start);
|
||||
return object_error::success;
|
||||
}
|
||||
|
||||
error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
|
||||
uint64_t &Res) const {
|
||||
if (is64Bit()) {
|
||||
@ -1180,6 +1220,189 @@ error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
|
||||
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
|
||||
}
|
||||
|
||||
//
|
||||
// guessLibraryShortName() is passed a name of a dynamic library and returns a
|
||||
// guess on what the short name is. Then name is returned as a substring of the
|
||||
// StringRef Name passed in. The name of the dynamic library is recognized as
|
||||
// a framework if it has one of the two following forms:
|
||||
// Foo.framework/Versions/A/Foo
|
||||
// Foo.framework/Foo
|
||||
// Where A and Foo can be any string. And may contain a trailing suffix
|
||||
// starting with an underbar. If the Name is recognized as a framework then
|
||||
// isFramework is set to true else it is set to false. If the Name has a
|
||||
// suffix then Suffix is set to the substring in Name that contains the suffix
|
||||
// else it is set to a NULL StringRef.
|
||||
//
|
||||
// The Name of the dynamic library is recognized as a library name if it has
|
||||
// one of the two following forms:
|
||||
// libFoo.A.dylib
|
||||
// libFoo.dylib
|
||||
// The library may have a suffix trailing the name Foo of the form:
|
||||
// libFoo_profile.A.dylib
|
||||
// libFoo_profile.dylib
|
||||
//
|
||||
// The Name of the dynamic library is also recognized as a library name if it
|
||||
// has the following form:
|
||||
// Foo.qtx
|
||||
//
|
||||
// If the Name of the dynamic library is none of the forms above then a NULL
|
||||
// StringRef is returned.
|
||||
//
|
||||
StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
|
||||
bool &isFramework,
|
||||
StringRef &Suffix) {
|
||||
StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
|
||||
size_t a, b, c, d, Idx;
|
||||
|
||||
isFramework = false;
|
||||
Suffix = StringRef();
|
||||
|
||||
// Pull off the last component and make Foo point to it
|
||||
a = Name.rfind('/');
|
||||
if (a == Name.npos || a == 0)
|
||||
goto guess_library;
|
||||
Foo = Name.slice(a+1, Name.npos);
|
||||
|
||||
// Look for a suffix starting with a '_'
|
||||
Idx = Foo.rfind('_');
|
||||
if (Idx != Foo.npos && Foo.size() >= 2) {
|
||||
Suffix = Foo.slice(Idx, Foo.npos);
|
||||
Foo = Foo.slice(0, Idx);
|
||||
}
|
||||
|
||||
// First look for the form Foo.framework/Foo
|
||||
b = Name.rfind('/', a);
|
||||
if (b == Name.npos)
|
||||
Idx = 0;
|
||||
else
|
||||
Idx = b+1;
|
||||
F = Name.slice(Idx, Idx + Foo.size());
|
||||
DotFramework = Name.slice(Idx + Foo.size(),
|
||||
Idx + Foo.size() + sizeof(".framework/")-1);
|
||||
if (F == Foo && DotFramework == ".framework/") {
|
||||
isFramework = true;
|
||||
return Foo;
|
||||
}
|
||||
|
||||
// Next look for the form Foo.framework/Versions/A/Foo
|
||||
if (b == Name.npos)
|
||||
goto guess_library;
|
||||
c = Name.rfind('/', b);
|
||||
if (c == Name.npos || c == 0)
|
||||
goto guess_library;
|
||||
V = Name.slice(c+1, Name.npos);
|
||||
if (!V.startswith("Versions/"))
|
||||
goto guess_library;
|
||||
d = Name.rfind('/', c);
|
||||
if (d == Name.npos)
|
||||
Idx = 0;
|
||||
else
|
||||
Idx = d+1;
|
||||
F = Name.slice(Idx, Idx + Foo.size());
|
||||
DotFramework = Name.slice(Idx + Foo.size(),
|
||||
Idx + Foo.size() + sizeof(".framework/")-1);
|
||||
if (F == Foo && DotFramework == ".framework/") {
|
||||
isFramework = true;
|
||||
return Foo;
|
||||
}
|
||||
|
||||
guess_library:
|
||||
// pull off the suffix after the "." and make a point to it
|
||||
a = Name.rfind('.');
|
||||
if (a == Name.npos || a == 0)
|
||||
return StringRef();
|
||||
Dylib = Name.slice(a, Name.npos);
|
||||
if (Dylib != ".dylib")
|
||||
goto guess_qtx;
|
||||
|
||||
// First pull off the version letter for the form Foo.A.dylib if any.
|
||||
if (a >= 3) {
|
||||
Dot = Name.slice(a-2, a-1);
|
||||
if (Dot == ".")
|
||||
a = a - 2;
|
||||
}
|
||||
|
||||
b = Name.rfind('/', a);
|
||||
if (b == Name.npos)
|
||||
b = 0;
|
||||
else
|
||||
b = b+1;
|
||||
// ignore any suffix after an underbar like Foo_profile.A.dylib
|
||||
Idx = Name.find('_', b);
|
||||
if (Idx != Name.npos && Idx != b) {
|
||||
Lib = Name.slice(b, Idx);
|
||||
Suffix = Name.slice(Idx, a);
|
||||
}
|
||||
else
|
||||
Lib = Name.slice(b, a);
|
||||
// There are incorrect library names of the form:
|
||||
// libATS.A_profile.dylib so check for these.
|
||||
if (Lib.size() >= 3) {
|
||||
Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
|
||||
if (Dot == ".")
|
||||
Lib = Lib.slice(0, Lib.size()-2);
|
||||
}
|
||||
return Lib;
|
||||
|
||||
guess_qtx:
|
||||
Qtx = Name.slice(a, Name.npos);
|
||||
if (Qtx != ".qtx")
|
||||
return StringRef();
|
||||
b = Name.rfind('/', a);
|
||||
if (b == Name.npos)
|
||||
Lib = Name.slice(0, a);
|
||||
else
|
||||
Lib = Name.slice(b+1, a);
|
||||
// There are library names of the form: QT.A.qtx so check for these.
|
||||
if (Lib.size() >= 3) {
|
||||
Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
|
||||
if (Dot == ".")
|
||||
Lib = Lib.slice(0, Lib.size()-2);
|
||||
}
|
||||
return Lib;
|
||||
}
|
||||
|
||||
// getLibraryShortNameByIndex() is used to get the short name of the library
|
||||
// for an undefined symbol in a linked Mach-O binary that was linked with the
|
||||
// normal two-level namespace default (that is MH_TWOLEVEL in the header).
|
||||
// It is passed the index (0 - based) of the library as translated from
|
||||
// GET_LIBRARY_ORDINAL (1 - based).
|
||||
error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
|
||||
StringRef &Res) {
|
||||
if (Index >= Libraries.size())
|
||||
return object_error::parse_failed;
|
||||
|
||||
MachO::dylib_command D =
|
||||
getStruct<MachO::dylib_command>(this, Libraries[Index]);
|
||||
if (D.dylib.name >= D.cmdsize)
|
||||
return object_error::parse_failed;
|
||||
|
||||
// If the cache of LibrariesShortNames is not built up do that first for
|
||||
// all the Libraries.
|
||||
if (LibrariesShortNames.size() == 0) {
|
||||
for (unsigned i = 0; i < Libraries.size(); i++) {
|
||||
MachO::dylib_command D =
|
||||
getStruct<MachO::dylib_command>(this, Libraries[i]);
|
||||
if (D.dylib.name >= D.cmdsize) {
|
||||
LibrariesShortNames.push_back(StringRef());
|
||||
continue;
|
||||
}
|
||||
char *P = (char *)(Libraries[i]) + D.dylib.name;
|
||||
StringRef Name = StringRef(P);
|
||||
StringRef Suffix;
|
||||
bool isFramework;
|
||||
StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
|
||||
if (shortName == StringRef())
|
||||
LibrariesShortNames.push_back(Name);
|
||||
else
|
||||
LibrariesShortNames.push_back(shortName);
|
||||
}
|
||||
}
|
||||
|
||||
Res = LibrariesShortNames[Index];
|
||||
return object_error::success;
|
||||
}
|
||||
|
||||
basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
|
||||
return getSymbolByIndex(0);
|
||||
}
|
||||
|
BIN
test/Object/Inputs/darwin-m-test1.mach0-armv7
Normal file
BIN
test/Object/Inputs/darwin-m-test1.mach0-armv7
Normal file
Binary file not shown.
BIN
test/Object/Inputs/darwin-m-test2.macho-i386
Normal file
BIN
test/Object/Inputs/darwin-m-test2.macho-i386
Normal file
Binary file not shown.
BIN
test/Object/Inputs/darwin-m-test3.macho-x86-64
Executable file
BIN
test/Object/Inputs/darwin-m-test3.macho-x86-64
Executable file
Binary file not shown.
53
test/Object/nm-darwin-m.test
Normal file
53
test/Object/nm-darwin-m.test
Normal file
@ -0,0 +1,53 @@
|
||||
RUN: llvm-nm -format darwin %p/Inputs/darwin-m-test1.mach0-armv7 \
|
||||
RUN: | FileCheck %s -check-prefix test1
|
||||
RUN: llvm-nm -format darwin %p/Inputs/darwin-m-test2.macho-i386 \
|
||||
RUN: | FileCheck %s -check-prefix test2
|
||||
RUN: llvm-nm -format darwin %p/Inputs/darwin-m-test3.macho-x86-64 \
|
||||
RUN: | FileCheck %s -check-prefix test3
|
||||
|
||||
# This is testing that the various bits in the n_desc feild are correct
|
||||
test1: 00000001 (absolute) non-external _a
|
||||
test1: 00000008 (common) (alignment 2^2) external _c
|
||||
test1: 0000000a (__DATA,__data) non-external [no dead strip] _d
|
||||
test1: 00000004 (__TEXT,__text) non-external [alt entry] _e
|
||||
test1: 00000000 (__TEXT,__text) non-external [symbol resolver] _r
|
||||
test1: 00000008 (__TEXT,__text) non-external [Thumb] _t
|
||||
|
||||
# This is testing that an N_INDR symbol gets its alias name, the "(for ...)"
|
||||
test2: (undefined) external __i
|
||||
test2: (indirect) external _i (for __i)
|
||||
|
||||
# This is testing is using darwin-m-test3.macho-x86-64 that is linked with
|
||||
# dylibs that have the follow set of -install_names:
|
||||
# Foo.framework/Foo
|
||||
# /System/Library/Frameworks/FooPath.framework/FooPath
|
||||
# FooSuffix.framework/FooSuffix_debug
|
||||
# /System/Library/Frameworks/FooPathSuffix.framework/FooPathSuffix_profile
|
||||
# FooVers.framework/Versions/A/FooVers
|
||||
# /System/Library/Frameworks/FooPathVers.framework/Versions/B/FooPathVers
|
||||
# libx.dylib
|
||||
# libxSuffix_profile.dylib
|
||||
# /usr/local/lib/libxPathSuffix_debug.dylib
|
||||
# libATS.A_profile.dylib
|
||||
# /usr/lib/libPathATS.A_profile.dylib
|
||||
# QT.A.qtx
|
||||
# /lib/QTPath.qtx
|
||||
# /usr/lib/libSystem.B.dylib
|
||||
# to test that MachOObjectFile::guessLibraryShortName() is correctly parsing
|
||||
# them into their short names.
|
||||
test3: 0000000100000000 (__TEXT,__text) [referenced dynamically] external __mh_execute_header
|
||||
test3: (undefined) external _atsPathVersSuffix (from libPathATS)
|
||||
test3: (undefined) external _atsVersSuffix (from libATS)
|
||||
test3: (undefined) external _foo (from Foo)
|
||||
test3: (undefined) external _fooPath (from FooPath)
|
||||
test3: (undefined) external _fooPathSuffix (from FooPathSuffix)
|
||||
test3: (undefined) external _fooPathVers (from FooPathVers)
|
||||
test3: (undefined) external _fooSuffix (from FooSuffix)
|
||||
test3: (undefined) external _fooVers (from FooVers)
|
||||
test3: 0000000100000e60 (__TEXT,__text) external _main
|
||||
test3: (undefined) external _qt (from QT)
|
||||
test3: (undefined) external _qtPath (from QTPath)
|
||||
test3: (undefined) external _x (from libx)
|
||||
test3: (undefined) external _xPathSuffix (from libxPathSuffix)
|
||||
test3: (undefined) external _xSuffix (from libxSuffix)
|
||||
test3: (undefined) external dyld_stub_binder (from libSystem)
|
@ -47,11 +47,12 @@ using namespace llvm;
|
||||
using namespace object;
|
||||
|
||||
namespace {
|
||||
enum OutputFormatTy { bsd, sysv, posix };
|
||||
enum OutputFormatTy { bsd, sysv, posix, darwin };
|
||||
cl::opt<OutputFormatTy> OutputFormat(
|
||||
"format", cl::desc("Specify output format"),
|
||||
cl::values(clEnumVal(bsd, "BSD format"), clEnumVal(sysv, "System V format"),
|
||||
clEnumVal(posix, "POSIX.2 format"), clEnumValEnd),
|
||||
clEnumVal(posix, "POSIX.2 format"),
|
||||
clEnumVal(darwin, "Darwin -m format"), clEnumValEnd),
|
||||
cl::init(bsd));
|
||||
cl::alias OutputFormat2("f", cl::desc("Alias for --format"),
|
||||
cl::aliasopt(OutputFormat));
|
||||
@ -145,6 +146,7 @@ struct NMSymbol {
|
||||
uint64_t Size;
|
||||
char TypeChar;
|
||||
StringRef Name;
|
||||
DataRefImpl Symb;
|
||||
};
|
||||
}
|
||||
|
||||
@ -204,6 +206,169 @@ static StringRef CurrentFilename;
|
||||
typedef std::vector<NMSymbol> SymbolListT;
|
||||
static SymbolListT SymbolList;
|
||||
|
||||
// darwinPrintSymbol() is used to print a symbol from a Mach-O file when the
|
||||
// the OutputFormat is darwin. It produces the same output as darwin's nm(1) -m
|
||||
// output.
|
||||
static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
|
||||
char *SymbolAddrStr, const char *printBlanks) {
|
||||
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;
|
||||
uint16_t NDesc;
|
||||
uint64_t NValue;
|
||||
if (MachO->is64Bit()) {
|
||||
H_64 = MachO->MachOObjectFile::getHeader64();
|
||||
Filetype = H_64.filetype;
|
||||
Flags = H_64.flags;
|
||||
STE_64 = MachO->getSymbol64TableEntry(I->Symb);
|
||||
NType = STE_64.n_type;
|
||||
NDesc = STE_64.n_desc;
|
||||
NValue = STE_64.n_value;
|
||||
} else {
|
||||
H = MachO->MachOObjectFile::getHeader();
|
||||
Filetype = H.filetype;
|
||||
Flags = H.flags;
|
||||
STE = MachO->getSymbolTableEntry(I->Symb);
|
||||
NType = STE.n_type;
|
||||
NDesc = STE.n_desc;
|
||||
NValue = STE.n_value;
|
||||
}
|
||||
|
||||
if (PrintAddress) {
|
||||
if ((NType & MachO::N_TYPE) == MachO::N_INDR)
|
||||
strcpy(SymbolAddrStr, printBlanks);
|
||||
outs() << SymbolAddrStr << ' ';
|
||||
}
|
||||
|
||||
switch (NType & MachO::N_TYPE) {
|
||||
case MachO::N_UNDF:
|
||||
if (NValue != 0) {
|
||||
outs() << "(common) ";
|
||||
if (MachO::GET_COMM_ALIGN(NDesc) != 0)
|
||||
outs() << "(alignment 2^" <<
|
||||
(int)MachO::GET_COMM_ALIGN(NDesc) << ") ";
|
||||
} else {
|
||||
if ((NType & MachO::N_TYPE) == MachO::N_PBUD)
|
||||
outs() << "(prebound ";
|
||||
else
|
||||
outs() << "(";
|
||||
if ((NDesc & MachO::REFERENCE_TYPE) ==
|
||||
MachO::REFERENCE_FLAG_UNDEFINED_LAZY)
|
||||
outs() << "undefined [lazy bound]) ";
|
||||
else if ((NDesc & MachO::REFERENCE_TYPE) ==
|
||||
MachO::REFERENCE_FLAG_UNDEFINED_LAZY)
|
||||
outs() << "undefined [private lazy bound]) ";
|
||||
else if ((NDesc & MachO::REFERENCE_TYPE) ==
|
||||
MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)
|
||||
outs() << "undefined [private]) ";
|
||||
else
|
||||
outs() << "undefined) ";
|
||||
}
|
||||
break;
|
||||
case MachO::N_ABS:
|
||||
outs() << "(absolute) ";
|
||||
break;
|
||||
case MachO::N_INDR:
|
||||
outs() << "(indirect) ";
|
||||
break;
|
||||
case MachO::N_SECT: {
|
||||
section_iterator Sec = MachO->section_end();
|
||||
MachO->getSymbolSection(I->Symb, Sec);
|
||||
DataRefImpl Ref = Sec->getRawDataRefImpl();
|
||||
StringRef SectionName;
|
||||
MachO->getSectionName(Ref, SectionName);
|
||||
StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref);
|
||||
outs() << "(" << SegmentName << "," << SectionName << ") ";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
outs() << "(?) ";
|
||||
break;
|
||||
}
|
||||
|
||||
if (NType & MachO::N_EXT) {
|
||||
if (NDesc & MachO::REFERENCED_DYNAMICALLY)
|
||||
outs() << "[referenced dynamically] ";
|
||||
if (NType & MachO::N_PEXT) {
|
||||
if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF)
|
||||
outs() << "weak private external ";
|
||||
else
|
||||
outs() << "private external ";
|
||||
} else {
|
||||
if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF ||
|
||||
(NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF){
|
||||
if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) ==
|
||||
(MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
|
||||
outs() << "weak external automatically hidden ";
|
||||
else
|
||||
outs() << "weak external ";
|
||||
}
|
||||
else
|
||||
outs() << "external ";
|
||||
}
|
||||
} else {
|
||||
if (NType & MachO::N_PEXT)
|
||||
outs() << "non-external (was a private external) ";
|
||||
else
|
||||
outs() << "non-external ";
|
||||
}
|
||||
|
||||
if (Filetype == MachO::MH_OBJECT &&
|
||||
(NDesc & MachO::N_NO_DEAD_STRIP) == MachO::N_NO_DEAD_STRIP)
|
||||
outs() << "[no dead strip] ";
|
||||
|
||||
if (Filetype == MachO::MH_OBJECT &&
|
||||
((NType & MachO::N_TYPE) != MachO::N_UNDF) &&
|
||||
(NDesc & MachO::N_SYMBOL_RESOLVER) == MachO::N_SYMBOL_RESOLVER)
|
||||
outs() << "[symbol resolver] ";
|
||||
|
||||
if (Filetype == MachO::MH_OBJECT &&
|
||||
((NType & MachO::N_TYPE) != MachO::N_UNDF) &&
|
||||
(NDesc & MachO::N_ALT_ENTRY) == MachO::N_ALT_ENTRY)
|
||||
outs() << "[alt entry] ";
|
||||
|
||||
if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF)
|
||||
outs() << "[Thumb] ";
|
||||
|
||||
if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
|
||||
outs() << I->Name << " (for ";
|
||||
StringRef IndirectName;
|
||||
if (MachO->getIndirectName(I->Symb, IndirectName))
|
||||
outs() << "?)";
|
||||
else
|
||||
outs() << IndirectName << ")";
|
||||
}
|
||||
else
|
||||
outs() << I->Name;
|
||||
|
||||
if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
|
||||
(((NType & MachO::N_TYPE) == MachO::N_UNDF &&
|
||||
NValue == 0) ||
|
||||
(NType & MachO::N_TYPE) == MachO::N_PBUD)) {
|
||||
uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
|
||||
if (LibraryOrdinal != 0) {
|
||||
if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL)
|
||||
outs() << " (from executable)";
|
||||
else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL)
|
||||
outs() << " (dynamically looked up)";
|
||||
else {
|
||||
StringRef LibraryName;
|
||||
if (MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1,
|
||||
LibraryName))
|
||||
outs() << " (from bad library ordinal " <<
|
||||
LibraryOrdinal << ")";
|
||||
else
|
||||
outs() << " (from " << LibraryName << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outs() << "\n";
|
||||
}
|
||||
|
||||
static void sortAndPrintSymbolList(SymbolicFile *Obj) {
|
||||
if (!NoSort) {
|
||||
if (NumericSort)
|
||||
@ -256,10 +421,16 @@ static void sortAndPrintSymbolList(SymbolicFile *Obj) {
|
||||
if (I->Size != UnknownAddressOrSize)
|
||||
format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
|
||||
|
||||
if (OutputFormat == posix) {
|
||||
// If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
|
||||
// nm(1) -m output, else if OutputFormat is darwin and not a Mach-O object
|
||||
// fall back to OutputFormat bsd (see below).
|
||||
MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
|
||||
if (OutputFormat == darwin && MachO) {
|
||||
darwinPrintSymbol(MachO, I, SymbolAddrStr, printBlanks);
|
||||
} else if (OutputFormat == posix) {
|
||||
outs() << I->Name << " " << I->TypeChar << " " << SymbolAddrStr
|
||||
<< SymbolSizeStr << "\n";
|
||||
} else if (OutputFormat == bsd) {
|
||||
} else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) {
|
||||
if (PrintAddress)
|
||||
outs() << SymbolAddrStr << ' ';
|
||||
if (PrintSize) {
|
||||
@ -529,6 +700,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile *Obj) {
|
||||
if (error(I->printName(OS)))
|
||||
break;
|
||||
OS << '\0';
|
||||
S.Symb = I->getRawDataRefImpl();
|
||||
SymbolList.push_back(S);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user