From: Adrian Prantl Date: Wed, 13 Sep 2017 18:22:59 +0000 (+0000) Subject: llvm-dwarfdump: support dumping UUIDs of Mach-O binaries. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7ff141c2023c29c40f9e328b122632fec41a6db9;p=llvm 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 --- diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 516491864e5..2d62d8c4cb8 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -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 diff --git a/include/llvm/ObjectYAML/MachOYAML.h b/include/llvm/ObjectYAML/MachOYAML.h index 305497b6aa6..b84c093cd4e 100644 --- a/include/llvm/ObjectYAML/MachOYAML.h +++ b/include/llvm/ObjectYAML/MachOYAML.h @@ -266,7 +266,7 @@ template <> struct ScalarTraits { // 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 { static void output(const uuid_t &Val, void *, raw_ostream &Out); diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index f5db87b0607..565833c95b7 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -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); diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index e9b3c0c132e..02c91d2464c 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -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(&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); diff --git a/lib/ObjectYAML/MachOYAML.cpp b/lib/ObjectYAML/MachOYAML.cpp index ab452a7bf6e..85079f2605f 100644 --- a/lib/ObjectYAML/MachOYAML.cpp +++ b/lib/ObjectYAML/MachOYAML.cpp @@ -55,11 +55,7 @@ StringRef ScalarTraits::input(StringRef Scalar, void *, char_16 &Val) { bool ScalarTraits::mustQuote(StringRef S) { return needsQuotes(S); } void ScalarTraits::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::input(StringRef Scalar, void *, uuid_t &Val) { diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index 6a0f08690e7..c66457ca066 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -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) { diff --git a/test/tools/llvm-dwarfdump/lit.local.cfg b/test/tools/llvm-dwarfdump/lit.local.cfg new file mode 100644 index 00000000000..ec8ad451d2d --- /dev/null +++ b/test/tools/llvm-dwarfdump/lit.local.cfg @@ -0,0 +1 @@ +config.suffixes = ['.test', '.ll', '.s', '.yaml'] diff --git a/test/tools/llvm-dwarfdump/uuid.yaml b/test/tools/llvm-dwarfdump/uuid.yaml new file mode 100644 index 00000000000..a1e82649576 --- /dev/null +++ b/test/tools/llvm-dwarfdump/uuid.yaml @@ -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 +--- !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 + - '' + - '' + - '' +... diff --git a/test/tools/llvm-dwarfdump/uuid32.yaml b/test/tools/llvm-dwarfdump/uuid32.yaml new file mode 100644 index 00000000000..ae367b26f24 --- /dev/null +++ b/test/tools/llvm-dwarfdump/uuid32.yaml @@ -0,0 +1,201 @@ +# RUN: yaml2obj %s | llvm-dwarfdump --uuid - | FileCheck %s +# CHECK: UUID: 229E6146-A7AB-3BA0-8B17-DD5125D3AFEF Mach-O 32-bit i386 +--- !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 + - '' + - '' + - '' +... diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 39d207b8d58..8508982ab39 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -60,6 +60,9 @@ static uint64_t DumpType = DIDT_Null; cat(SectionCategory)); #include "llvm/BinaryFormat/Dwarf.def" #undef HANDLE_DWARF_SECTION +static opt DumpUUID("uuid", desc("Show the UUID for each architecture"), + cat(DwarfDumpCategory)); +static alias DumpUUIDAlias("u", desc("Alias for -uuid"), aliasopt(DumpUUID)); static opt SummarizeTypes("summarize-types", @@ -94,10 +97,10 @@ static void DumpObjectFile(ObjectFile &Obj, Twine Filename) { std::unique_ptr 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) {