llvm.org GIT mirror llvm / 894e54f
[llvm-readobj] Allow --hex-dump/--string-dump to dump multiple sections 1) `-x foo` currently dumps one `foo`. This change makes it dump all `foo`. 2) `-x foo -x foo` currently dumps `foo` twice. This change makes it dump `foo` once. In addition, if foo has section index 9, `-x foo -x 9` dumps `foo` once. 3) Give a warning instead of an error if `foo` does not exist. The new behaviors match GNU readelf. Also, print a new line as a separator between two section dumps. GNU readelf uses two lines, but one seems good enough. Reviewed By: grimar, jhenderson Differential Revision: https://reviews.llvm.org/D63475 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363683 91177308-0d34-0410-b5e6-96231b3b80d8 Fangrui Song 2 months ago
11 changed file(s) with 223 addition(s) and 166 deletion(s). Raw diff Collapse all Expand all
3131
3232 # CONTENTS: Hex dump of section '.first':
3333 # CONTENTS-NEXT: 0x00000000 01234567
34 # CONTENTS-EMPTY:
3435 # CONTENTS-NEXT: Hex dump of section '.second':
3536 # CONTENTS-NEXT: 0x00000000 23456789
3637
3636
3737 # CONTENTS: Hex dump of section '.first':
3838 # CONTENTS-NEXT: 0x00000000 01234567
39 # CONTENTS-EMPTY:
3940 # CONTENTS-NEXT: Hex dump of section '.second':
4041 # CONTENTS-NEXT: 0x00000000 23456789
4142
0 # REQUIRES: x86-registered-target
1
2 # RUN: llvm-mc -filetype=obj -triple x86_64 %s -o %t.o
3 # RUN: llvm-readobj -x .a -x .b %t.o | FileCheck %s
4 # RUN: llvm-readelf -x .a -x .b %t.o | FileCheck %s
5
6 # CHECK: Hex dump of section '.a':
7 # CHECK-NEXT: 0x00000000 00
8 # CHECK-EMPTY:
9 # CHECK-NEXT: Hex dump of section '.b':
10 # CHECK-NEXT: 0x00000000 01
11 # CHECK-EMPTY:
12 # CHECK-NEXT: Hex dump of section '.a':
13 # CHECK-NEXT: 0x00000000 02
14
15 .section .a,"a",@progbits,unique,0
16 .byte 0
17 .section .b,"a",@progbits
18 .byte 1
19 .section .a,"a",@progbits,unique,1
20 .byte 2
0 ## Test that the -x alias can be used flexibly. Create a baseline and ensure
1 ## all other combinations are identical.
2 # RUN: llvm-readelf --file-header --hex-dump=.text \
3 # RUN: %p/Inputs/trivial.obj.elf-x86-64 > %t.hexdump.out
4 # RUN: llvm-readelf -h --hex-dump .text %p/Inputs/trivial.obj.elf-x86-64 > %t.hexdump.1
5 # RUN: llvm-readelf -h -x .text %p/Inputs/trivial.obj.elf-x86-64 > %t.hexdump.2
6 # RUN: llvm-readelf -h -x=.text %p/Inputs/trivial.obj.elf-x86-64 > %t.hexdump.3
7 # RUN: llvm-readelf -h -x.text %p/Inputs/trivial.obj.elf-x86-64 > %t.hexdump.4
8 # RUN: llvm-readelf -hx .text %p/Inputs/trivial.obj.elf-x86-64 > %t.hexdump.5
9 # RUN: llvm-readelf -hx=.text %p/Inputs/trivial.obj.elf-x86-64 > %t.hexdump.6
10 # RUN: llvm-readelf -hx.text %p/Inputs/trivial.obj.elf-x86-64 > %t.hexdump.7
11
12 # RUN: cmp %t.hexdump.out %t.hexdump.1
13 # RUN: cmp %t.hexdump.out %t.hexdump.2
14 # RUN: cmp %t.hexdump.out %t.hexdump.3
15 # RUN: cmp %t.hexdump.out %t.hexdump.4
16 # RUN: cmp %t.hexdump.out %t.hexdump.5
17 # RUN: cmp %t.hexdump.out %t.hexdump.6
18 # RUN: cmp %t.hexdump.out %t.hexdump.7
19
20 # RUN: llvm-readelf -S %p/Inputs/trivial.obj.elf-x86-64 | FileCheck %s --check-prefix=ELF-SEC
21
22 ## Both 9 and .strtab refer to .strtab. Test we dump the section only once.
23 # RUN: llvm-readobj -x 9 -x 9 -x .strtab -x .strtab %p/Inputs/trivial.obj.elf-x86-64 2>&1 | \
24 # RUN: FileCheck %s --check-prefix=ELF
25 # RUN: llvm-readobj -x 9 -x .strtab -x 10 -x not_exist \
26 # RUN: %p/Inputs/trivial.obj.elf-x86-64 2>&1 | FileCheck %s --check-prefixes=ELF-WARN,ELF
27
28 # ELF-SEC: [ 9] .strtab
29
30 # ELF-WARN: warning: could not find section 'not_exist'
31 # ELF-WARN: warning: could not find section 10
32 # ELF: Hex dump of section '.strtab':
33 # ELF-NEXT: 0x00000000 00747269 7669616c 2e6c6c00 6d61696e .trivial.ll.main
34 # ELF-NEXT: 0x00000010 002e4c2e 73747200 70757473 00536f6d ..L.str.puts.Som
35 # ELF-NEXT: 0x00000020 654f7468 65724675 6e637469 6f6e005f eOtherFunction._
36 # ELF-NEXT: 0x00000030 474c4f42 414c5f4f 46465345 545f5441 GLOBAL_OFFSET_TA
37 # ELF-NEXT: 0x00000040 424c455f 00 BLE_.
38 # ELF-NOT: {{.}}
39
40 ## Below we test -x can be used for other binary formats.
41
42 # RUN: llvm-readobj -x 1 %p/Inputs/trivial.obj.coff-x86-64 \
43 # RUN: | FileCheck %s --check-prefix COFF
44
45 # COFF: 0x00000000 4883ec28 488d0d00 000000e8 00000000 H..(H...........
46 # COFF: 0x00000010 e8000000 0031c048 83c428c3 .....1.H..(.
47
48 # RUN: llvm-readobj -x 1 %p/Inputs/trivial.obj.macho-x86-64 \
49 # RUN: | FileCheck %s --check-prefix MACHO
50
51 # MACHO: 0x00000000 50488d3d 00000000 e8000000 00e80000 PH.=............
52 # MACHO: 0x00000010 000031c0 5ac3 ..1.Z.
53
54 # RUN: llvm-readobj -x 1 %p/Inputs/trivial.obj.wasm \
55 # RUN: | FileCheck %s --check-prefix WASM
56
57 # WASM: 0x00000000 04600001 7f60017f 017f6000 0060017f .`...`....`..`..
58 # WASM: 0x00000010 00 .
+0
-32
test/tools/llvm-readobj/hexdump.test less more
None // Check dumping of the hexadecimal bytes of a section.
1 RUN: llvm-readobj -x .text %p/../../Object/Inputs/hello-world.elf-x86-64 | FileCheck %s
2
3 CHECK: Hex dump of section '.text':
4 CHECK-NEXT: {{^}}0x00400460
5
6 // Test that the -x alias can be used flexibly. Create a baseline and ensure
7 // all other combinations are identical.
8 RUN: llvm-readelf --file-header --hex-dump=.text \
9 RUN: %p/../../Object/Inputs/hello-world.elf-x86-64 > %t.hexdump.out
10 RUN: llvm-readelf -h --hex-dump .text \
11 RUN: %p/../../Object/Inputs/hello-world.elf-x86-64 > %t.hexdump.1
12 RUN: llvm-readelf -h -x .text \
13 RUN: %p/../../Object/Inputs/hello-world.elf-x86-64 > %t.hexdump.2
14 RUN: llvm-readelf -h -x=.text \
15 RUN: %p/../../Object/Inputs/hello-world.elf-x86-64 > %t.hexdump.3
16 RUN: llvm-readelf -h -x.text \
17 RUN: %p/../../Object/Inputs/hello-world.elf-x86-64 > %t.hexdump.4
18 RUN: llvm-readelf -hx .text \
19 RUN: %p/../../Object/Inputs/hello-world.elf-x86-64 > %t.hexdump.5
20 RUN: llvm-readelf -hx=.text \
21 RUN: %p/../../Object/Inputs/hello-world.elf-x86-64 > %t.hexdump.6
22 RUN: llvm-readelf -hx.text \
23 RUN: %p/../../Object/Inputs/hello-world.elf-x86-64 > %t.hexdump.7
24
25 RUN: cmp %t.hexdump.out %t.hexdump.1
26 RUN: cmp %t.hexdump.out %t.hexdump.2
27 RUN: cmp %t.hexdump.out %t.hexdump.3
28 RUN: cmp %t.hexdump.out %t.hexdump.4
29 RUN: cmp %t.hexdump.out %t.hexdump.5
30 RUN: cmp %t.hexdump.out %t.hexdump.6
31 RUN: cmp %t.hexdump.out %t.hexdump.7
+0
-26
test/tools/llvm-readobj/print-hex.test less more
None RUN: llvm-readobj -x .strtab %p/Inputs/trivial.obj.elf-x86-64 \
1 RUN: | FileCheck %s --check-prefix ELF
2
3 ELF: 0x00000000 00747269 7669616c 2e6c6c00 6d61696e .trivial.ll.main
4 ELF: 0x00000010 002e4c2e 73747200 70757473 00536f6d ..L.str.puts.Som
5 ELF: 0x00000020 654f7468 65724675 6e637469 6f6e005f eOtherFunction._
6 ELF: 0x00000030 474c4f42 414c5f4f 46465345 545f5441 GLOBAL_OFFSET_TA
7 ELF: 0x00000040 424c455f 00 BLE_.
8
9 RUN: llvm-readobj -x 1 %p/Inputs/trivial.obj.coff-x86-64 \
10 RUN: | FileCheck %s --check-prefix COFF
11
12 COFF: 0x00000000 4883ec28 488d0d00 000000e8 00000000 H..(H...........
13 COFF: 0x00000010 e8000000 0031c048 83c428c3 .....1.H..(.
14
15 RUN: llvm-readobj -x 1 %p/Inputs/trivial.obj.macho-x86-64 \
16 RUN: | FileCheck %s --check-prefix MACHO
17
18 MACHO: 0x00000000 50488d3d 00000000 e8000000 00e80000 PH.=............
19 MACHO: 0x00000010 000031c0 5ac3 ..1.Z.
20
21 RUN: llvm-readobj -x 1 %p/Inputs/trivial.obj.wasm \
22 RUN: | FileCheck %s --check-prefix WASM
23
24 WASM: 0x00000000 04600001 7f60017f 017f6000 0060017f .`...`....`..`..
25 WASM: 0x00000010 00 .
0 # REQUIRES: x86-registered-target
1
2 # RUN: llvm-mc -filetype=obj -triple x86_64 %s -o %t.o
3 # RUN: llvm-readobj -p .a -p .b %t.o | FileCheck %s
4 # RUN: llvm-readelf -p .a -p .b %t.o | FileCheck %s
5
6 # CHECK: String dump of section '.a':
7 # CHECK-NEXT: [ 0] 0
8 # CHECK-EMPTY:
9 # CHECK-NEXT: String dump of section '.b':
10 # CHECK-NEXT: [ 0] 1
11 # CHECK-EMPTY:
12 # CHECK-NEXT: String dump of section '.a':
13 # CHECK-NEXT: [ 0] 2
14
15 .section .a,"a",@progbits,unique,0
16 .asciz "0"
17 .section .b,"a",@progbits
18 .asciz "1"
19 .section .a,"a",@progbits,unique,1
20 .asciz "2"
88 # flag (-p), with different prefix modes (-p .foo, -p=.foo, -p.foo), and with
99 # the value being a index section number instead of a section name.
1010 # RUN: llvm-readobj -p=.strings -p=.not_null_terminated %t > %t.readobj.1
11 # RUN: llvm-readobj -p.strings -p.not_null_terminated %t > %t.readobj.2
11 # RUN: llvm-readobj -p.strings -p.strings -p.not_null_terminated %t > %t.readobj.2
1212 # RUN: llvm-readobj --string-dump=1 --string-dump=2 %t > %t.readobj.3
13 # RUN: llvm-readobj -p1 -p2 %t > %t.readobj.4
13 # RUN: llvm-readobj -p1 -p1 -p2 %t > %t.readobj.4
1414 # RUN: llvm-readobj -p=1 -p=2 %t > %t.readobj.5
1515
1616 # RUN: cmp %t.readobj.out %t.readobj.1
4444 # CHECK-NEXT: [ 5] are
4545 # CHECK-NEXT: [ 9] some
4646 # CHECK-NEXT: [ e] strings
47 # CHECK-EMPTY:
4748 # CHECK-NEXT: String dump of section '.not_null_terminated':
4849 # CHECK-NEXT: [ 0] no
4950 # CHECK-NEXT: [ 3] null{{$}}
5051 # CHECK-NOT: {{.}}
5152
52 # RUN: not llvm-readobj --string-dump=does_not_exist %t 2>&1 | FileCheck %s --check-prefix=ERR1
53 # RUN: not llvm-readobj --string-dump=42 %t 2>&1 | FileCheck %s --check-prefix=ERR2
53 # RUN: llvm-readobj --string-dump=does_not_exist %t 2>&1 | FileCheck %s --check-prefix=WARN1
54 # RUN: llvm-readobj --string-dump=42 %t 2>&1 | FileCheck %s --check-prefix=WARN2
5455
55 # RUN: not llvm-readelf --string-dump=does_not_exist %t 2>&1 | FileCheck %s --check-prefix=ERR1
56 # RUN: not llvm-readelf --string-dump=42 %t 2>&1 | FileCheck %s --check-prefix=ERR2
56 # RUN: llvm-readelf --string-dump=does_not_exist %t 2>&1 | FileCheck %s --check-prefix=WARN1
57 # RUN: llvm-readelf --string-dump=42 %t 2>&1 | FileCheck %s --check-prefix=WARN2
5758
58 # ERR1: error: could not find section 'does_not_exist'
59 # ERR2: error: could not find section '42'
59 # WARN1: warning: could not find section 'does_not_exist'
60 # WARN2: warning: could not find section 42
6061
6162 --- !ELF
6263 FileHeader:
1818 #include "llvm/Support/FormatVariadic.h"
1919 #include "llvm/Support/ScopedPrinter.h"
2020 #include "llvm/Support/raw_ostream.h"
21 #include
2122
2223 namespace llvm {
2324
3132 W << (isPrint(Start[i]) ? static_cast(Start[i]) : '.');
3233 }
3334
34 static Expected
35 getSecNameOrIndexAsSecRef(const object::ObjectFile *Obj, StringRef SecName) {
36 char *StrPtr;
37 long SectionIndex = strtol(SecName.data(), &StrPtr, 10);
38 long SecIndex;
39 if (Obj->isELF())
40 SecIndex = 0;
41 else
42 SecIndex = 1;
35 static std::vector
36 getSectionRefsByNameOrIndex(const object::ObjectFile *Obj,
37 ArrayRef Sections) {
38 std::vector Ret;
39 std::map SecNames;
40 std::map SecIndices;
41 unsigned SecIndex;
42 for (StringRef Section : Sections) {
43 if (!Section.getAsInteger(0, SecIndex))
44 SecIndices.emplace(SecIndex, false);
45 else
46 SecNames.emplace(Section, false);
47 }
48
49 SecIndex = Obj->isELF() ? 0 : 1;
4350 for (object::SectionRef SecRef : Obj->sections()) {
44 if (*StrPtr) {
45 StringRef SectionName;
46
47 if (std::error_code E = SecRef.getName(SectionName))
48 return errorCodeToError(E);
49
50 if (SectionName == SecName)
51 return SecRef;
52 } else if (SecIndex == SectionIndex)
53 return SecRef;
54
51 StringRef SecName;
52 error(SecRef.getName(SecName));
53 auto NameIt = SecNames.find(SecName);
54 if (NameIt != SecNames.end())
55 NameIt->second = true;
56 auto IndexIt = SecIndices.find(SecIndex);
57 if (IndexIt != SecIndices.end())
58 IndexIt->second = true;
59 if (NameIt != SecNames.end() || IndexIt != SecIndices.end())
60 Ret.push_back(SecRef);
5561 SecIndex++;
5662 }
57 return make_error(
58 formatv("could not find section '{0}'", SecName),
59 object::object_error::parse_failed);
63
64 for (const std::pair &S : SecNames)
65 if (!S.second)
66 reportWarning(formatv("could not find section '{0}'", S.first).str());
67 for (std::pair S : SecIndices)
68 if (!S.second)
69 reportWarning(formatv("could not find section {0}", S.first).str());
70
71 return Ret;
6072 }
6173
62 void ObjDumper::printSectionAsString(const object::ObjectFile *Obj,
63 StringRef SecName) {
64 Expected SectionRefOrError =
65 getSecNameOrIndexAsSecRef(Obj, SecName);
66 if (!SectionRefOrError)
67 error(std::move(SectionRefOrError));
68 object::SectionRef Section = *SectionRefOrError;
69 StringRef SectionName;
74 void ObjDumper::printSectionsAsString(const object::ObjectFile *Obj,
75 ArrayRef Sections) {
76 bool First = true;
77 for (object::SectionRef Section :
78 getSectionRefsByNameOrIndex(Obj, Sections)) {
79 StringRef SectionName;
80 error(Section.getName(SectionName));
81 if (!First)
82 W.startLine() << '\n';
83 First = false;
84 W.startLine() << "String dump of section '" << SectionName << "':\n";
7085
71 if (std::error_code E = Section.getName(SectionName))
72 error(E);
73 W.startLine() << "String dump of section '" << SectionName << "':\n";
86 StringRef SectionContent = unwrapOrError(Section.getContents());
7487
75 StringRef SectionContent = unwrapOrError(Section.getContents());
88 const uint8_t *SecContent = SectionContent.bytes_begin();
89 const uint8_t *CurrentWord = SecContent;
90 const uint8_t *SecEnd = SectionContent.bytes_end();
7691
77 const uint8_t *SecContent = SectionContent.bytes_begin();
78 const uint8_t *CurrentWord = SecContent;
79 const uint8_t *SecEnd = SectionContent.bytes_end();
80
81 while (CurrentWord <= SecEnd) {
82 size_t WordSize = strnlen(reinterpret_cast(CurrentWord),
83 SecEnd - CurrentWord);
84 if (!WordSize) {
85 CurrentWord++;
86 continue;
92 while (CurrentWord <= SecEnd) {
93 size_t WordSize = strnlen(reinterpret_cast(CurrentWord),
94 SecEnd - CurrentWord);
95 if (!WordSize) {
96 CurrentWord++;
97 continue;
98 }
99 W.startLine() << format("[%6tx] ", CurrentWord - SecContent);
100 printAsPrintable(W.startLine(), CurrentWord, WordSize);
101 W.startLine() << '\n';
102 CurrentWord += WordSize + 1;
87103 }
88 W.startLine() << format("[%6tx] ", CurrentWord - SecContent);
89 printAsPrintable(W.startLine(), CurrentWord, WordSize);
90 W.startLine() << '\n';
91 CurrentWord += WordSize + 1;
92104 }
93105 }
94106
95 void ObjDumper::printSectionAsHex(const object::ObjectFile *Obj,
96 StringRef SecName) {
97 Expected SectionRefOrError =
98 getSecNameOrIndexAsSecRef(Obj, SecName);
99 if (!SectionRefOrError)
100 error(std::move(SectionRefOrError));
101 object::SectionRef Section = *SectionRefOrError;
102 StringRef SectionName;
107 void ObjDumper::printSectionsAsHex(const object::ObjectFile *Obj,
108 ArrayRef Sections) {
109 bool First = true;
110 for (object::SectionRef Section :
111 getSectionRefsByNameOrIndex(Obj, Sections)) {
112 StringRef SectionName;
113 error(Section.getName(SectionName));
114 if (!First)
115 W.startLine() << '\n';
116 First = false;
117 W.startLine() << "Hex dump of section '" << SectionName << "':\n";
103118
104 if (std::error_code E = Section.getName(SectionName))
105 error(E);
106 W.startLine() << "Hex dump of section '" << SectionName << "':\n";
119 StringRef SectionContent = unwrapOrError(Section.getContents());
120 const uint8_t *SecContent = SectionContent.bytes_begin();
121 const uint8_t *SecEnd = SecContent + SectionContent.size();
107122
108 StringRef SectionContent = unwrapOrError(Section.getContents());
109 const uint8_t *SecContent = SectionContent.bytes_begin();
110 const uint8_t *SecEnd = SecContent + SectionContent.size();
123 for (const uint8_t *SecPtr = SecContent; SecPtr < SecEnd; SecPtr += 16) {
124 const uint8_t *TmpSecPtr = SecPtr;
125 uint8_t i;
126 uint8_t k;
111127
112 for (const uint8_t *SecPtr = SecContent; SecPtr < SecEnd; SecPtr += 16) {
113 const uint8_t *TmpSecPtr = SecPtr;
114 uint8_t i;
115 uint8_t k;
128 W.startLine() << format_hex(Section.getAddress() + (SecPtr - SecContent),
129 10);
130 W.startLine() << ' ';
131 for (i = 0; TmpSecPtr < SecEnd && i < 4; ++i) {
132 for (k = 0; TmpSecPtr < SecEnd && k < 4; k++, TmpSecPtr++) {
133 uint8_t Val = *(reinterpret_cast(TmpSecPtr));
134 W.startLine() << format_hex_no_prefix(Val, 2);
135 }
136 W.startLine() << ' ';
137 }
116138
117 W.startLine() << format_hex(Section.getAddress() + (SecPtr - SecContent),
118 10);
119 W.startLine() << ' ';
120 for (i = 0; TmpSecPtr < SecEnd && i < 4; ++i) {
121 for (k = 0; TmpSecPtr < SecEnd && k < 4; k++, TmpSecPtr++) {
122 uint8_t Val = *(reinterpret_cast(TmpSecPtr));
123 W.startLine() << format_hex_no_prefix(Val, 2);
124 }
125 W.startLine() << ' ';
139 // We need to print the correct amount of spaces to match the format.
140 // We are adding the (4 - i) last rows that are 8 characters each.
141 // Then, the (4 - i) spaces that are in between the rows.
142 // Least, if we cut in a middle of a row, we add the remaining characters,
143 // which is (8 - (k * 2)).
144 if (i < 4)
145 W.startLine() << format("%*c", (4 - i) * 8 + (4 - i) + (8 - (k * 2)),
146 ' ');
147
148 TmpSecPtr = SecPtr;
149 for (i = 0; TmpSecPtr + i < SecEnd && i < 16; ++i)
150 W.startLine() << (isPrint(TmpSecPtr[i])
151 ? static_cast(TmpSecPtr[i])
152 : '.');
153
154 W.startLine() << '\n';
126155 }
127
128 // We need to print the correct amount of spaces to match the format.
129 // We are adding the (4 - i) last rows that are 8 characters each.
130 // Then, the (4 - i) spaces that are in between the rows.
131 // Least, if we cut in a middle of a row, we add the remaining characters,
132 // which is (8 - (k * 2)).
133 if (i < 4)
134 W.startLine() << format("%*c", (4 - i) * 8 + (4 - i) + (8 - (k * 2)),
135 ' ');
136
137 TmpSecPtr = SecPtr;
138 for (i = 0; TmpSecPtr + i < SecEnd && i < 16; ++i)
139 W.startLine() << (isPrint(TmpSecPtr[i]) ? static_cast(TmpSecPtr[i])
140 : '.');
141
142 W.startLine() << '\n';
143156 }
144157 }
145158
103103
104104 virtual void printStackMap() const = 0;
105105
106 void printSectionAsString(const object::ObjectFile *Obj, StringRef SecName);
107 void printSectionAsHex(const object::ObjectFile *Obj, StringRef SecName);
106 void printSectionsAsString(const object::ObjectFile *Obj,
107 ArrayRef Sections);
108 void printSectionsAsHex(const object::ObjectFile *Obj,
109 ArrayRef Sections);
108110
109111 protected:
110112 ScopedPrinter &W;
494494 if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE)
495495 Dumper->printProgramHeaders(opts::ProgramHeaders, opts::SectionMapping);
496496 if (!opts::StringDump.empty())
497 llvm::for_each(opts::StringDump, [&Dumper, Obj](StringRef SectionName) {
498 Dumper->printSectionAsString(Obj, SectionName);
499 });
497 Dumper->printSectionsAsString(Obj, opts::StringDump);
500498 if (!opts::HexDump.empty())
501 llvm::for_each(opts::HexDump, [&Dumper, Obj](StringRef SectionName) {
502 Dumper->printSectionAsHex(Obj, SectionName);
503 });
499 Dumper->printSectionsAsHex(Obj, opts::HexDump);
504500 if (opts::HashTable)
505501 Dumper->printHashTable();
506502 if (opts::GnuHashTable)