llvm-dwarfdump: support dumping UUIDs of Mach-O binaries.

This is a feature supported by Darwin dwarfdump. UUIDs are used to
associate executables with their .dSYM bundles.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313165 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Adrian Prantl 2017-09-13 18:22:59 +00:00
parent 51aca1f185
commit 7ff141c202
10 changed files with 464 additions and 14 deletions

View File

@ -116,21 +116,23 @@ struct DILineInfoSpecifier {
enum DIDumpTypeCounter {
DIDT_ID_Null = 0,
#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
DIDT_ID##ENUM_NAME,
DIDT_ID_##ENUM_NAME,
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
DIDT_ID_Count,
DIDT_ID_UUID,
DIDT_ID_Count
};
static_assert(DIDT_ID_Count <= 64, "section types overflow storage");
static_assert(DIDT_ID_Count <= 64, "section types overflow storage");
/// Selects which debug sections get dumped.
enum DIDumpType : uint64_t {
DIDT_Null,
DIDT_All = ~0ULL,
#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
DIDT_##ENUM_NAME = 1 << (DIDT_ID##ENUM_NAME - 1),
DIDT_##ENUM_NAME = 1 << (DIDT_ID_##ENUM_NAME - 1),
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
DIDT_UUID = 1 << (DIDT_ID_UUID - 1),
};
/// Container for dump options that control which debug information will be

View File

@ -266,7 +266,7 @@ template <> struct ScalarTraits<char_16> {
// This trait is used for UUIDs. It reads and writes them matching otool's
// formatting style.
using uuid_t = uint8_t[16];
using uuid_t = raw_ostream::uuid_t;
template <> struct ScalarTraits<uuid_t> {
static void output(const uuid_t &Val, void *, raw_ostream &Out);

View File

@ -213,6 +213,10 @@ public:
/// Output \p N in hexadecimal, without any prefix or padding.
raw_ostream &write_hex(unsigned long long N);
/// Output a formatted UUID with dash separators.
using uuid_t = uint8_t[16];
raw_ostream &write_uuid(const uuid_t UUID);
/// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't
/// satisfy std::isprint into an escape sequence.
raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false);

View File

@ -80,6 +80,27 @@ static void dumpAccelSection(raw_ostream &OS, StringRef Name,
Accel.dump(OS);
}
/// Dump the UUID load command.
static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {
auto *MachO = dyn_cast<MachOObjectFile>(&Obj);
if (!MachO)
return;
for (auto LC : MachO->load_commands()) {
raw_ostream::uuid_t UUID;
if (LC.C.cmd == MachO::LC_UUID) {
if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) {
OS << "error: UUID load command is too short.\n";
return;
}
OS << "UUID: ";
memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));
OS.write_uuid(UUID);
OS << ' ' << MachO->getFileFormatName();
OS << ' ' << MachO->getFileName() << '\n';
}
}
}
static void
dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName,
const DWARFObject &Obj,
@ -203,6 +224,13 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
uint64_t DumpType = DumpOpts.DumpType;
bool DumpEH = DumpOpts.DumpEH;
const auto *ObjFile = DObj->getFile();
if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All)
outs() << ObjFile->getFileName() << ":\tfile format "
<< ObjFile->getFileFormatName() << "\n\n";
if (DumpType & DIDT_UUID)
dumpUUID(OS, *ObjFile);
if (DumpType & DIDT_DebugAbbrev) {
OS << ".debug_abbrev contents:\n";
getDebugAbbrev()->dump(OS);

View File

@ -55,11 +55,7 @@ StringRef ScalarTraits<char_16>::input(StringRef Scalar, void *, char_16 &Val) {
bool ScalarTraits<char_16>::mustQuote(StringRef S) { return needsQuotes(S); }
void ScalarTraits<uuid_t>::output(const uuid_t &Val, void *, raw_ostream &Out) {
for (int Idx = 0; Idx < 16; ++Idx) {
Out << format("%02" PRIX32, Val[Idx]);
if (Idx == 3 || Idx == 5 || Idx == 7 || Idx == 9)
Out << "-";
}
Out.write_uuid(Val);
}
StringRef ScalarTraits<uuid_t>::input(StringRef Scalar, void *, uuid_t &Val) {

View File

@ -139,6 +139,16 @@ raw_ostream &raw_ostream::write_hex(unsigned long long N) {
return *this;
}
raw_ostream &raw_ostream::write_uuid(const uuid_t UUID) {
for (int Idx = 0; Idx < 16; ++Idx) {
*this << format("%02" PRIX32, UUID[Idx]);
if (Idx == 3 || Idx == 5 || Idx == 7 || Idx == 9)
*this << "-";
}
return *this;
}
raw_ostream &raw_ostream::write_escaped(StringRef Str,
bool UseHexEscapes) {
for (unsigned char c : Str) {

View File

@ -0,0 +1 @@
config.suffixes = ['.test', '.ll', '.s', '.yaml']

View File

@ -0,0 +1,203 @@
# RUN: yaml2obj %s | llvm-dwarfdump -u - | FileCheck %s
# RUN: yaml2obj %s | llvm-dwarfdump --uuid - | FileCheck %s
# CHECK: UUID: E5874E6F-946F-317B-B348-56FAEE59D8D1 Mach-O 64-bit x86-64 <stdin>
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x01000007
cpusubtype: 0x80000003
filetype: 0x00000002
ncmds: 14
sizeofcmds: 728
flags: 0x00200085
reserved: 0x00000000
LoadCommands:
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __PAGEZERO
vmaddr: 0
vmsize: 4294967296
fileoff: 0
filesize: 0
maxprot: 0
initprot: 0
nsects: 0
flags: 0
- cmd: LC_SEGMENT_64
cmdsize: 232
segname: __TEXT
vmaddr: 4294967296
vmsize: 4096
fileoff: 0
filesize: 4096
maxprot: 7
initprot: 5
nsects: 2
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x0000000100000FB0
size: 8
offset: 0x00000FB0
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __unwind_info
segname: __TEXT
addr: 0x0000000100000FB8
size: 72
offset: 0x00000FB8
align: 2
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __LINKEDIT
vmaddr: 4294971392
vmsize: 4096
fileoff: 4096
filesize: 152
maxprot: 7
initprot: 1
nsects: 0
flags: 0
- cmd: LC_DYLD_INFO_ONLY
cmdsize: 48
rebase_off: 0
rebase_size: 0
bind_off: 0
bind_size: 0
weak_bind_off: 0
weak_bind_size: 0
lazy_bind_off: 0
lazy_bind_size: 0
export_off: 4096
export_size: 48
- cmd: LC_SYMTAB
cmdsize: 24
symoff: 4152
nsyms: 3
stroff: 4200
strsize: 48
- cmd: LC_DYSYMTAB
cmdsize: 80
ilocalsym: 0
nlocalsym: 0
iextdefsym: 0
nextdefsym: 2
iundefsym: 2
nundefsym: 1
tocoff: 0
ntoc: 0
modtaboff: 0
nmodtab: 0
extrefsymoff: 0
nextrefsyms: 0
indirectsymoff: 0
nindirectsyms: 0
extreloff: 0
nextrel: 0
locreloff: 0
nlocrel: 0
- cmd: LC_LOAD_DYLINKER
cmdsize: 32
name: 12
PayloadString: /usr/lib/dyld
ZeroPadBytes: 7
- cmd: LC_UUID
cmdsize: 24
uuid: E5874E6F-946F-317B-B348-56FAEE59D8D1
- cmd: LC_VERSION_MIN_MACOSX
cmdsize: 16
version: 658688
sdk: 658688
- cmd: LC_SOURCE_VERSION
cmdsize: 16
version: 0
- cmd: LC_MAIN
cmdsize: 24
entryoff: 4016
stacksize: 0
- cmd: LC_LOAD_DYLIB
cmdsize: 56
dylib:
name: 24
timestamp: 2
current_version: 81985536
compatibility_version: 65536
PayloadString: /usr/lib/libSystem.B.dylib
ZeroPadBytes: 6
- cmd: LC_FUNCTION_STARTS
cmdsize: 16
dataoff: 4144
datasize: 8
- cmd: LC_DATA_IN_CODE
cmdsize: 16
dataoff: 4152
datasize: 0
LinkEditData:
ExportTrie:
TerminalSize: 0
NodeOffset: 0
Name: ''
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
Children:
- TerminalSize: 0
NodeOffset: 5
Name: _
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
Children:
- TerminalSize: 2
NodeOffset: 33
Name: _mh_execute_header
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
- TerminalSize: 3
NodeOffset: 37
Name: main
Flags: 0x0000000000000000
Address: 0x0000000000000FB0
Other: 0x0000000000000000
ImportName: ''
NameList:
- n_strx: 2
n_type: 0x0F
n_sect: 1
n_desc: 16
n_value: 4294967296
- n_strx: 22
n_type: 0x0F
n_sect: 1
n_desc: 0
n_value: 4294971312
- n_strx: 28
n_type: 0x01
n_sect: 0
n_desc: 256
n_value: 0
StringTable:
- ' '
- __mh_execute_header
- _main
- dyld_stub_binder
- ''
- ''
- ''
...

View File

@ -0,0 +1,201 @@
# RUN: yaml2obj %s | llvm-dwarfdump --uuid - | FileCheck %s
# CHECK: UUID: 229E6146-A7AB-3BA0-8B17-DD5125D3AFEF Mach-O 32-bit i386 <stdin>
--- !mach-o
FileHeader:
magic: 0xFEEDFACE
cputype: 0x00000007
cpusubtype: 0x00000003
filetype: 0x00000002
ncmds: 14
sizeofcmds: 648
flags: 0x01200085
LoadCommands:
- cmd: LC_SEGMENT
cmdsize: 56
segname: __PAGEZERO
vmaddr: 0
vmsize: 4096
fileoff: 0
filesize: 0
maxprot: 0
initprot: 0
nsects: 0
flags: 0
- cmd: LC_SEGMENT
cmdsize: 192
segname: __TEXT
vmaddr: 4096
vmsize: 4096
fileoff: 0
filesize: 4096
maxprot: 7
initprot: 5
nsects: 2
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x0000000000001FB1
size: 7
offset: 0x00000FB1
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __unwind_info
segname: __TEXT
addr: 0x0000000000001FB8
size: 72
offset: 0x00000FB8
align: 2
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- cmd: LC_SEGMENT
cmdsize: 56
segname: __LINKEDIT
vmaddr: 8192
vmsize: 4096
fileoff: 4096
filesize: 132
maxprot: 7
initprot: 1
nsects: 0
flags: 0
- cmd: LC_DYLD_INFO_ONLY
cmdsize: 48
rebase_off: 0
rebase_size: 0
bind_off: 0
bind_size: 0
weak_bind_off: 0
weak_bind_size: 0
lazy_bind_off: 0
lazy_bind_size: 0
export_off: 4096
export_size: 44
- cmd: LC_SYMTAB
cmdsize: 24
symoff: 4144
nsyms: 3
stroff: 4180
strsize: 48
- cmd: LC_DYSYMTAB
cmdsize: 80
ilocalsym: 0
nlocalsym: 0
iextdefsym: 0
nextdefsym: 2
iundefsym: 2
nundefsym: 1
tocoff: 0
ntoc: 0
modtaboff: 0
nmodtab: 0
extrefsymoff: 0
nextrefsyms: 0
indirectsymoff: 0
nindirectsyms: 0
extreloff: 0
nextrel: 0
locreloff: 0
nlocrel: 0
- cmd: LC_LOAD_DYLINKER
cmdsize: 28
name: 12
PayloadString: /usr/lib/dyld
ZeroPadBytes: 3
- cmd: LC_UUID
cmdsize: 24
uuid: 229E6146-A7AB-3BA0-8B17-DD5125D3AFEF
- cmd: LC_VERSION_MIN_MACOSX
cmdsize: 16
version: 658688
sdk: 658688
- cmd: LC_SOURCE_VERSION
cmdsize: 16
version: 0
- cmd: LC_MAIN
cmdsize: 24
entryoff: 4017
stacksize: 0
- cmd: LC_LOAD_DYLIB
cmdsize: 52
dylib:
name: 24
timestamp: 2
current_version: 81985536
compatibility_version: 65536
PayloadString: /usr/lib/libSystem.B.dylib
ZeroPadBytes: 2
- cmd: LC_FUNCTION_STARTS
cmdsize: 16
dataoff: 4140
datasize: 4
- cmd: LC_DATA_IN_CODE
cmdsize: 16
dataoff: 4144
datasize: 0
LinkEditData:
ExportTrie:
TerminalSize: 0
NodeOffset: 0
Name: ''
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
Children:
- TerminalSize: 0
NodeOffset: 5
Name: _
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
Children:
- TerminalSize: 2
NodeOffset: 33
Name: _mh_execute_header
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
- TerminalSize: 3
NodeOffset: 37
Name: main
Flags: 0x0000000000000000
Address: 0x0000000000000FB1
Other: 0x0000000000000000
ImportName: ''
NameList:
- n_strx: 2
n_type: 0x0F
n_sect: 1
n_desc: 16
n_value: 4096
- n_strx: 22
n_type: 0x0F
n_sect: 1
n_desc: 0
n_value: 8113
- n_strx: 28
n_type: 0x01
n_sect: 0
n_desc: 256
n_value: 0
StringTable:
- ' '
- __mh_execute_header
- _main
- dyld_stub_binder
- ''
- ''
- ''
...

View File

@ -60,6 +60,9 @@ static uint64_t DumpType = DIDT_Null;
cat(SectionCategory));
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
static opt<bool> DumpUUID("uuid", desc("Show the UUID for each architecture"),
cat(DwarfDumpCategory));
static alias DumpUUIDAlias("u", desc("Alias for -uuid"), aliasopt(DumpUUID));
static opt<bool>
SummarizeTypes("summarize-types",
@ -94,10 +97,10 @@ static void DumpObjectFile(ObjectFile &Obj, Twine Filename) {
std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(Obj);
logAllUnhandledErrors(DICtx->loadRegisterInfo(Obj), errs(),
Filename.str() + ": ");
outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName()
<< "\n\n";
// The UUID dump already contains all the same information.
if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All)
outs() << Filename << ":\tfile format " << Obj.getFileFormatName()
<< "\n\n";
// Dump the complete DWARF structure.
DICtx->dump(outs(), GetDumpOpts());
@ -225,6 +228,8 @@ int main(int argc, char **argv) {
DumpType |= DIDT_##ENUM_NAME;
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
if (DumpUUID)
DumpType |= DIDT_UUID;
if (DumpAll)
DumpType = DIDT_All;
if (DumpType == DIDT_Null) {