Index: include/llvm/ADT/StringExtras.h =================================================================== --- include/llvm/ADT/StringExtras.h +++ include/llvm/ADT/StringExtras.h @@ -137,6 +137,9 @@ return std::string(BufPtr, std::end(Buffer)); } +/// Convert an unsigned value into a human readable size (988, 1.23K, 2.34G). +std::string toHumanReadableSize(uint64_t X); + /// Convert buffer \p Input to its hexadecimal representation. /// The returned string is double the size of \p Input. inline std::string toHex(StringRef Input, bool LowerCase = false) { Index: lib/Support/StringExtras.cpp =================================================================== --- lib/Support/StringExtras.cpp +++ lib/Support/StringExtras.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -89,3 +90,24 @@ for (const char C : String) Out << toLower(C); } + +std::string llvm::toHumanReadableSize(uint64_t USize) { + std::string Result; + llvm::raw_string_ostream OS(Result); + if (USize < 1024) + OS << USize; + else { + float FSize = (float)USize; + int I = 0; + // UINT64_MAX values converted to human readable form can only go up to + // exabytes, so "Units" below stops at 'E'. + const char Units[] = {' ', 'K', 'M', 'G', 'T', 'P', 'E'}; + while (FSize >= 1024.0) { + FSize /= 1024.0; + I++; + } + OS << format("%.2f", FSize) << Units[I]; + } + OS.flush(); + return Result; +} Index: test/tools/llvm-dwarfdump/analyze-dwarf-section-sizes.test =================================================================== --- test/tools/llvm-dwarfdump/analyze-dwarf-section-sizes.test +++ test/tools/llvm-dwarfdump/analyze-dwarf-section-sizes.test @@ -0,0 +1,909 @@ +# RUN: yaml2obj %s > %t.o && llvm-dwarfdump --analyze %t.o 2>&1 | FileCheck %s -check-prefix=CHECKTEXT +# RUN: yaml2obj %s > %t.o && llvm-dwarfdump --analyze --json %t.o 2>&1 | FileCheck %s -check-prefix=CHECKJSON +# CHECKTEXT: File: +# CHECKTEXT: Size: 9765 (9.54K) +# CHECKTEXT: DWARF section sizes: +# CHECKTEXT: SIZE % DWARF % FILE SECTION NAME +# CHECKTEXT: ------- ------- ------- ------------------------------------- +# CHECKTEXT: 372 23.65% 3.81% __debug_info +# CHECKTEXT: 207 13.16% 2.12% __debug_line +# CHECKTEXT: 182 11.57% 1.86% __debug_str +# CHECKTEXT: 171 10.87% 1.75% __apple_types +# CHECKTEXT: 165 10.49% 1.69% __debug_abbrev +# CHECKTEXT: 116 7.37% 1.19% __apple_names +# CHECKTEXT: 96 6.10% 0.98% __debug_aranges +# CHECKTEXT: 83 5.28% 0.85% __debug_pubnames +# CHECKTEXT: 81 5.15% 0.83% __debug_pubtypes +# CHECKTEXT: 64 4.07% 0.66% __apple_namespac +# CHECKTEXT: 36 2.29% 0.37% __apple_objc +# CHECKTEXT: ======= ======= ======= ===================================== +# CHECKTEXT: 1.54K 100.00% 16.11% Total DWARF Size +# CHECKJSON: { +# CHECKJSON: "path": +# CHECKJSON: analyze-dwarf-section-sizes.test.tmp.o", +# CHECKJSON: "sections": +# CHECKJSON: [ +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__debug_info", +# CHECKJSON: "size": +# CHECKJSON: 372 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__debug_line", +# CHECKJSON: "size": +# CHECKJSON: 207 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__debug_str", +# CHECKJSON: "size": +# CHECKJSON: 182 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__apple_types", +# CHECKJSON: "size": +# CHECKJSON: 171 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__debug_abbrev", +# CHECKJSON: "size": +# CHECKJSON: 165 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__apple_names", +# CHECKJSON: "size": +# CHECKJSON: 116 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__debug_aranges", +# CHECKJSON: "size": +# CHECKJSON: 96 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__debug_pubnames", +# CHECKJSON: "size": +# CHECKJSON: 83 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__debug_pubtypes", +# CHECKJSON: "size": +# CHECKJSON: 81 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__apple_namespac", +# CHECKJSON: "size": +# CHECKJSON: 64 +# CHECKJSON: }, +# CHECKJSON: { +# CHECKJSON: "name": +# CHECKJSON: "__apple_objc", +# CHECKJSON: "size": +# CHECKJSON: 36 +# CHECKJSON: } +# CHECKJSON: ], +# CHECKJSON: "size": +# CHECKJSON: 9765 +# CHECKJSON: } + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x0000000A + ncmds: 6 + sizeofcmds: 1456 + flags: 0x00000000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_UUID + cmdsize: 24 + uuid: E0E3F792-CB03-3B36-945A-96195077AA9C + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 4096 + nsyms: 3 + stroff: 4144 + strsize: 53 + - 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: 312 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 4096 + fileoff: 0 + filesize: 0 + maxprot: 7 + initprot: 5 + nsects: 3 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000100000F20 + size: 116 + offset: 0x00000000 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __const + segname: __TEXT + addr: 0x0000000100000FA0 + size: 16 + offset: 0x00000000 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __unwind_info + segname: __TEXT + addr: 0x0000000100000FB0 + size: 72 + offset: 0x00000000 + 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: 101 + maxprot: 7 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 952 + segname: __DWARF + vmaddr: 4294975488 + vmsize: 4096 + fileoff: 8192 + filesize: 1573 + maxprot: 7 + initprot: 3 + nsects: 11 + flags: 0 + Sections: + - sectname: __debug_line + segname: __DWARF + addr: 0x0000000100002000 + size: 207 + offset: 0x00002000 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_pubnames + segname: __DWARF + addr: 0x00000001000020CF + size: 83 + offset: 0x000020CF + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_pubtypes + segname: __DWARF + addr: 0x0000000100002122 + size: 81 + offset: 0x00002122 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_aranges + segname: __DWARF + addr: 0x0000000100002173 + size: 96 + offset: 0x00002173 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_info + segname: __DWARF + addr: 0x00000001000021D3 + size: 372 + offset: 0x000021D3 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x0000000100002347 + size: 165 + offset: 0x00002347 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_str + segname: __DWARF + addr: 0x00000001000023EC + size: 182 + offset: 0x000023EC + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_names + segname: __DWARF + addr: 0x00000001000024A2 + size: 116 + offset: 0x000024A2 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_namespac + segname: __DWARF + addr: 0x0000000100002516 + size: 64 + offset: 0x00002516 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_types + segname: __DWARF + addr: 0x0000000100002556 + size: 171 + offset: 0x00002556 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_objc + segname: __DWARF + addr: 0x0000000100002601 + size: 36 + offset: 0x00002601 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 +LinkEditData: + NameList: + - n_strx: 2 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 4294971264 + - n_strx: 27 + n_type: 0x0F + n_sect: 1 + n_desc: 16 + n_value: 4294967296 + - n_strx: 47 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 4294971168 + StringTable: + - '' + - '' + - __Z5sumXYN6shapes5PointE + - __mh_execute_header + - _main +DWARF: + debug_str: + - '' + - 'Apple LLVM version 10.0.0 (clang-1000.11.45.5)' + - '../src/main.cpp' + - '/tmp/test/build' + - main + - argc + - argv + - pt + - sum + - int + - char + - shapes + - Point + - x + - y + - ptr + - foo + - '../src2/foo.cpp' + - _Z5sumXYN6shapes5PointE + - sumXY + debug_abbrev: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_producer + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Attribute: DW_AT_comp_dir + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Code: 0x00000002 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Attribute: DW_AT_frame_base + Form: DW_FORM_exprloc + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + - Code: 0x00000003 + Tag: DW_TAG_formal_parameter + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_location + Form: DW_FORM_exprloc + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Code: 0x00000004 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_location + Form: DW_FORM_exprloc + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Code: 0x00000005 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_encoding + Form: DW_FORM_data1 + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x00000006 + Tag: DW_TAG_pointer_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Code: 0x00000007 + Tag: DW_TAG_const_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Code: 0x00000008 + Tag: DW_TAG_namespace + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Code: 0x00000009 + Tag: DW_TAG_structure_type + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_calling_convention + Form: DW_FORM_data1 + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Code: 0x0000000A + Tag: DW_TAG_member + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_data_member_location + Form: DW_FORM_data1 + - Code: 0x0000000B + Tag: DW_TAG_structure_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_declaration + Form: DW_FORM_flag_present + - Code: 0x0000000C + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Attribute: DW_AT_frame_base + Form: DW_FORM_exprloc + - Attribute: DW_AT_linkage_name + Form: DW_FORM_strp + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + debug_aranges: + - Length: + TotalLength: 44 + Version: 2 + CuOffset: 0 + AddrSize: 8 + SegSize: 0 + Descriptors: + - Address: 0x0000000100000F20 + Length: 86 + - Length: + TotalLength: 44 + Version: 2 + CuOffset: 216 + AddrSize: 8 + SegSize: 0 + Descriptors: + - Address: 0x0000000100000F80 + Length: 20 + debug_pubnames: + Length: + TotalLength: 23 + Version: 2 + UnitOffset: 0 + UnitSize: 216 + Entries: + - DieOffset: 0x0000002A + Name: main + debug_pubtypes: + Length: + TotalLength: 41 + Version: 2 + UnitOffset: 0 + UnitSize: 216 + Entries: + - DieOffset: 0x0000007C + Name: int + - DieOffset: 0x00000092 + Name: char + - DieOffset: 0x0000009E + Name: Point + debug_info: + - Length: + TotalLength: 212 + Version: 4 + AbbrOffset: 0 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x0000000000000001 + - Value: 0x0000000000000004 + - Value: 0x0000000000000030 + - Value: 0x0000000000000000 + - Value: 0x0000000000000040 + - Value: 0x0000000100000F20 + - Value: 0x0000000000000056 + - AbbrCode: 0x00000002 + Values: + - Value: 0x0000000100000F20 + - Value: 0x0000000000000056 + - Value: 0x0000000000000001 + BlockData: + - 0x56 + - Value: 0x0000000000000050 + - Value: 0x0000000000000001 + - Value: 0x0000000000000007 + - Value: 0x000000000000007C + - Value: 0x0000000000000001 + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000002 + BlockData: + - 0x91 + - 0x78 + - Value: 0x0000000000000055 + - Value: 0x0000000000000001 + - Value: 0x0000000000000007 + - Value: 0x000000000000007C + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000002 + BlockData: + - 0x91 + - 0x70 + - Value: 0x000000000000005A + - Value: 0x0000000000000001 + - Value: 0x0000000000000007 + - Value: 0x0000000000000083 + - AbbrCode: 0x00000004 + Values: + - Value: 0x0000000000000002 + BlockData: + - 0x91 + - 0x60 + - Value: 0x000000000000005F + - Value: 0x0000000000000001 + - Value: 0x0000000000000008 + - Value: 0x000000000000009E + - AbbrCode: 0x00000004 + Values: + - Value: 0x0000000000000002 + BlockData: + - 0x91 + - 0x5C + - Value: 0x0000000000000062 + - Value: 0x0000000000000001 + - Value: 0x0000000000000009 + - Value: 0x000000000000007C + - AbbrCode: 0x00000000 + Values: + - AbbrCode: 0x00000005 + Values: + - Value: 0x0000000000000066 + - Value: 0x0000000000000005 + - Value: 0x0000000000000004 + - AbbrCode: 0x00000006 + Values: + - Value: 0x0000000000000088 + - AbbrCode: 0x00000006 + Values: + - Value: 0x000000000000008D + - AbbrCode: 0x00000007 + Values: + - Value: 0x0000000000000092 + - AbbrCode: 0x00000005 + Values: + - Value: 0x000000000000006A + - Value: 0x0000000000000006 + - Value: 0x0000000000000001 + - AbbrCode: 0x00000008 + Values: + - Value: 0x000000000000006F + - AbbrCode: 0x00000009 + Values: + - Value: 0x0000000000000005 + - Value: 0x0000000000000076 + - Value: 0x0000000000000010 + - Value: 0x0000000000000002 + - Value: 0x0000000000000005 + - AbbrCode: 0x0000000A + Values: + - Value: 0x000000000000007C + - Value: 0x000000000000007C + - Value: 0x0000000000000002 + - Value: 0x0000000000000006 + - Value: 0x0000000000000000 + - AbbrCode: 0x0000000A + Values: + - Value: 0x000000000000007E + - Value: 0x000000000000007C + - Value: 0x0000000000000002 + - Value: 0x0000000000000006 + - Value: 0x0000000000000004 + - AbbrCode: 0x0000000A + Values: + - Value: 0x0000000000000080 + - Value: 0x00000000000000D2 + - Value: 0x0000000000000002 + - Value: 0x0000000000000007 + - Value: 0x0000000000000008 + - AbbrCode: 0x00000000 + Values: + - AbbrCode: 0x0000000B + Values: + - Value: 0x0000000000000084 + - Value: 0x0000000000000001 + - AbbrCode: 0x00000000 + Values: + - AbbrCode: 0x00000006 + Values: + - Value: 0x00000000000000CC + - AbbrCode: 0x00000000 + Values: + - Length: + TotalLength: 152 + Version: 4 + AbbrOffset: 0 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x0000000000000001 + - Value: 0x0000000000000004 + - Value: 0x0000000000000088 + - Value: 0x000000000000006C + - Value: 0x0000000000000040 + - Value: 0x0000000100000F80 + - Value: 0x0000000000000014 + - AbbrCode: 0x0000000C + Values: + - Value: 0x0000000100000F80 + - Value: 0x0000000000000014 + - Value: 0x0000000000000001 + BlockData: + - 0x56 + - Value: 0x0000000000000098 + - Value: 0x00000000000000B0 + - Value: 0x0000000000000001 + - Value: 0x0000000000000003 + - Value: 0x000000000000012E + - Value: 0x0000000000000001 + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000002 + BlockData: + - 0x91 + - 0x70 + - Value: 0x000000000000005F + - Value: 0x0000000000000001 + - Value: 0x0000000000000003 + - Value: 0x000000000000013A + - AbbrCode: 0x00000000 + Values: + - AbbrCode: 0x00000005 + Values: + - Value: 0x0000000000000066 + - Value: 0x0000000000000005 + - Value: 0x0000000000000004 + - AbbrCode: 0x00000008 + Values: + - Value: 0x000000000000006F + - AbbrCode: 0x00000009 + Values: + - Value: 0x0000000000000005 + - Value: 0x0000000000000076 + - Value: 0x0000000000000010 + - Value: 0x0000000000000002 + - Value: 0x0000000000000005 + - AbbrCode: 0x0000000A + Values: + - Value: 0x000000000000007C + - Value: 0x000000000000012E + - Value: 0x0000000000000002 + - Value: 0x0000000000000006 + - Value: 0x0000000000000000 + - AbbrCode: 0x0000000A + Values: + - Value: 0x000000000000007E + - Value: 0x000000000000012E + - Value: 0x0000000000000002 + - Value: 0x0000000000000006 + - Value: 0x0000000000000004 + - AbbrCode: 0x0000000A + Values: + - Value: 0x0000000000000080 + - Value: 0x000000000000016E + - Value: 0x0000000000000002 + - Value: 0x0000000000000007 + - Value: 0x0000000000000008 + - AbbrCode: 0x00000000 + Values: + - AbbrCode: 0x0000000B + Values: + - Value: 0x0000000000000084 + - Value: 0x0000000000000001 + - AbbrCode: 0x00000000 + Values: + - AbbrCode: 0x00000006 + Values: + - Value: 0x0000000000000168 + - AbbrCode: 0x00000000 + Values: + debug_line: + - Length: + TotalLength: 104 + Version: 2 + PrologueLength: 61 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - '../src' + - '../include' + Files: + - Name: main.cpp + DirIdx: 1 + ModTime: 0 + Length: 0 + - Name: shapes.h + DirIdx: 2 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4294971168 + - Opcode: 0x18 + Data: 4294971168 + - Opcode: DW_LNS_set_column + Data: 17 + - Opcode: DW_LNS_set_prologue_end + Data: 17 + - Opcode: DW_LNS_const_add_pc + Data: 17 + - Opcode: 0x59 + Data: 17 + - Opcode: DW_LNS_set_column + Data: 19 + - Opcode: DW_LNS_const_add_pc + Data: 19 + - Opcode: 0x59 + Data: 19 + - Opcode: DW_LNS_set_column + Data: 13 + - Opcode: DW_LNS_negate_stmt + Data: 13 + - Opcode: 0xF2 + Data: 13 + - Opcode: DW_LNS_set_column + Data: 7 + - Opcode: 0xE4 + Data: 7 + - Opcode: DW_LNS_set_column + Data: 3 + - Opcode: DW_LNS_negate_stmt + Data: 3 + - Opcode: 0x3D + Data: 3 + - Opcode: DW_LNS_advance_pc + Data: 8 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 8 + - Length: + TotalLength: 95 + Version: 2 + PrologueLength: 61 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - '../src2' + - '../include' + Files: + - Name: foo.cpp + DirIdx: 1 + ModTime: 0 + Length: 0 + - Name: shapes.h + DirIdx: 2 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4294971264 + - Opcode: 0x14 + Data: 4294971264 + - Opcode: DW_LNS_set_column + Data: 13 + - Opcode: DW_LNS_set_prologue_end + Data: 13 + - Opcode: 0xBB + Data: 13 + - Opcode: DW_LNS_set_column + Data: 15 + - Opcode: DW_LNS_negate_stmt + Data: 15 + - Opcode: 0x3C + Data: 15 + - Opcode: DW_LNS_set_column + Data: 3 + - Opcode: 0x3C + Data: 3 + - Opcode: DW_LNS_advance_pc + Data: 2 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 2 +... Index: tools/llvm-dwarfdump/Analyze.cpp =================================================================== --- tools/llvm-dwarfdump/Analyze.cpp +++ tools/llvm-dwarfdump/Analyze.cpp @@ -0,0 +1,140 @@ +//===-- Analyze.cpp -------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/JSON.h" +#include + +using namespace llvm; +using namespace dwarf; +using namespace object; + +extern cl::opt EnableJSON; + +static bool isDwarfSectionName(StringRef Name) { + return Name.startswith(".debug") || Name.startswith("__debug") || + Name.startswith(".apple") || Name.startswith("__apple"); +} + +namespace { +// A helper class to print out percentages with 2 digits past the decimal with +// optional width. +struct Percent { + uint64_t Value; ///< Value to use when displaying percentage. + uint64_t Total; ///< Total count to use when calculating percentage. + uint32_t Width; ///< Display width in characters. + float percentage() const { + if (Value == 0 || Total == 0) + return 0.0f; + return ((float)Value/(float)Total) * 100.0f; + } + Percent(uint64_t V, uint64_t T, uint32_t W): Value(V), Total(T), Width(W) {} +}; +// A helper class to dump human readable file sizes (988, 1.23K, 2.34G). +struct ReadableFileSize { + uint64_t Size; ///< Byte size to display as human readable value. + uint64_t Total; ///< Display percentage if non zero. + uint32_t Width; ///< Display width in characters. + ReadableFileSize(uint64_t S, uint64_t T, uint32_t W) : + Size(S), Total(T), Width(W) {}; +}; +// A helper class to display float values with 2 digits past the decimal with +// optional widths for tabular display. +struct Float { + float Value; ///< Float value to display. + uint32_t Width; ///< Total width in bytes to use when printing float. + Float(float V, uint32_t W) : Value(V), Width(W) {} +}; + +raw_ostream &operator<<(raw_ostream &OS, const Float &F) { + char FormatStr[32]; + const uint32_t Width = F.Width < 2 ? 2 : F.Width; + snprintf(FormatStr, sizeof(FormatStr), "%%%u.2f", Width); + OS << format(FormatStr, F.Value); + return OS; +} + +raw_ostream &operator<<(raw_ostream &OS, const Percent &PV) { + const uint32_t FloatWidth = PV.Width ? PV.Width-1 : 0; + OS << Float{PV.percentage(), FloatWidth} << '%'; + return OS; +} + +raw_ostream &operator<<(raw_ostream &OS, const ReadableFileSize &RFS) { + OS << right_justify(toHumanReadableSize(RFS.Size), RFS.Width); + if (RFS.Total > 0) + OS << ' ' << Percent(RFS.Size, RFS.Total, RFS.Width); + return OS; +} + +} // anonymous namespace + + +bool analyzeObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename, + raw_ostream &OS) { + const size_t FileSize = Obj.getData().size(); + + json::Object JSON; + if (EnableJSON) { + JSON.try_emplace("path", Filename.str()); + JSON.try_emplace("size", static_cast(FileSize)); + } else { + OS << "File: \"" << Filename << "\"\n" << "Size: " << FileSize; + if (FileSize > 1024) + OS << " (" << ReadableFileSize(FileSize, 0, 0) << ")"; + OS << '\n'; + } + + // Calculate the total size of all DWARF sections. + uint64_t TotalDwarfSize = 0; + std::map > SizeToSection; + StringRef Name; + for (const auto &Sect: Obj.sections()) { + Sect.getName(Name); + const auto SectSize = Sect.getSize(); + if (isDwarfSectionName(Name)) { + TotalDwarfSize += SectSize; + SizeToSection[SectSize] = Sect; + } + } + + // Report all DWARF section sizes relative to total DWARF size and total + // file size. + if (EnableJSON) { + json::Array SectionsArray; + for (const auto &Pair: SizeToSection) { + SectionRef Sect = Pair.second; + Sect.getName(Name); + const auto SectSize = Sect.getSize(); + json::Object SectObj; + SectObj.try_emplace("name", Name); + SectObj.try_emplace("size", static_cast(SectSize)); + SectionsArray.emplace_back(std::move(SectObj)); + } + JSON.try_emplace("sections", std::move(SectionsArray)); + OS << formatv("{0:2}", json::Value(std::move(JSON))) << "\n"; + } else { + OS << "DWARF section sizes:\n"; + OS << "SIZE % DWARF % FILE SECTION NAME\n"; + OS << "------- ------- ------- -------------------------------------\n"; + for (const auto &Pair: SizeToSection) { + SectionRef Sect = Pair.second; + Sect.getName(Name); + const auto SectSize = Sect.getSize(); + OS << ReadableFileSize(SectSize, TotalDwarfSize, 7) << ' ' + << Percent(SectSize, FileSize, 7) << ' ' << Name << '\n'; + } + OS << "======= ======= ======= =====================================\n"; + OS << ReadableFileSize(TotalDwarfSize, TotalDwarfSize, 7) << ' ' + << Percent(TotalDwarfSize, FileSize, 7) << " Total DWARF Size\n\n"; + } + return true; +} Index: tools/llvm-dwarfdump/CMakeLists.txt =================================================================== --- tools/llvm-dwarfdump/CMakeLists.txt +++ tools/llvm-dwarfdump/CMakeLists.txt @@ -8,6 +8,7 @@ ) add_llvm_tool(llvm-dwarfdump + Analyze.cpp Statistics.cpp llvm-dwarfdump.cpp ) Index: tools/llvm-dwarfdump/llvm-dwarfdump.cpp =================================================================== --- tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -93,11 +93,12 @@ using namespace cl; OptionCategory DwarfDumpCategory("Specific Options"); +OptionCategory AnalyzeCategory("Analyze Options"); static opt Help("h", desc("Alias for -help"), Hidden, cat(DwarfDumpCategory)); static list InputFilenames(Positional, desc(""), - ZeroOrMore, cat(DwarfDumpCategory)); + ZeroOrMore, cat(DwarfDumpCategory), cat(AnalyzeCategory)); cl::OptionCategory SectionCategory("Section-specific Dump Options", "These control which sections are dumped. " @@ -207,6 +208,10 @@ Statistics("statistics", cl::desc("Emit JSON-formatted debug info quality metrics."), cat(DwarfDumpCategory)); +static cl::opt + Analyze("analyze", + cl::desc("Analyze the DWARF and report detailed information."), + cl::cat(AnalyzeCategory)); static opt Verify("verify", desc("Verify the DWARF debug info."), cat(DwarfDumpCategory)); static opt Quiet("quiet", desc("Use with -verify to not emit to STDOUT."), @@ -220,6 +225,13 @@ static alias VerboseAlias("v", desc("Alias for -verbose."), aliasopt(Verbose), cat(DwarfDumpCategory)); } // namespace + +// Options that need to be accesses from other source files go here. +cl::opt + EnableJSON("json", + cl::desc("Output the analyze information in JSON format."), + cl::cat(AnalyzeCategory)); + /// @} //===----------------------------------------------------------------------===// @@ -404,6 +416,9 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename, raw_ostream &OS); +bool analyzeObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename, + raw_ostream &OS); + static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename, raw_ostream &OS) { logAllUnhandledErrors(DICtx.loadRegisterInfo(Obj), errs(), @@ -560,7 +575,7 @@ llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); - HideUnrelatedOptions({&DwarfDumpCategory, &SectionCategory, &ColorCategory}); + HideUnrelatedOptions({&DwarfDumpCategory, &AnalyzeCategory, &SectionCategory, &ColorCategory}); cl::ParseCommandLineOptions( argc, argv, "pretty-print DWARF debug information in object files" @@ -636,12 +651,15 @@ return handleFile(Object, verifyObjectFile, OS); })) exit(1); - } else if (Statistics) + } else if (Statistics) { for (auto Object : Objects) handleFile(Object, collectStatsForObjectFile, OS); - else + } else if (Analyze) { + for (auto Object : Objects) + handleFile(Object, analyzeObjectFile, OS); + } else { for (auto Object : Objects) handleFile(Object, dumpObjectFile, OS); - + } return EXIT_SUCCESS; } Index: unittests/ADT/StringExtrasTest.cpp =================================================================== --- unittests/ADT/StringExtrasTest.cpp +++ unittests/ADT/StringExtrasTest.cpp @@ -119,3 +119,21 @@ printHTMLEscaped("ABCdef123&<>\"'", OS); EXPECT_EQ("ABCdef123&<>"'", OS.str()); } + +TEST(StringExtrasTest, toHumanReadableSize) { + EXPECT_EQ("0", toHumanReadableSize(0)); + EXPECT_EQ("1023", toHumanReadableSize(1023)); + uint64_t Value = 1024; + EXPECT_EQ("1.00K", toHumanReadableSize(Value)); + Value*=1024; + EXPECT_EQ("1.00M", toHumanReadableSize(Value)); + Value*=1024; + EXPECT_EQ("1.00G", toHumanReadableSize(Value)); + Value*=1024; + EXPECT_EQ("1.00T", toHumanReadableSize(Value)); + Value*=1024; + EXPECT_EQ("1.00P", toHumanReadableSize(Value)); + Value*=1024; + EXPECT_EQ("1.00E", toHumanReadableSize(Value)); + EXPECT_EQ("16.00E", toHumanReadableSize(UINT64_MAX)); +}