llvm.org GIT mirror llvm / 7a578c9
[WebAssembly] Add llvm-objdump support for wasm file format This is the first part of an effort to add wasm binary support across all llvm tools. Patch by Sam Clegg Differential Revision: https://reviews.llvm.org/D26172 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288251 91177308-0d34-0410-b5e6-96231b3b80d8 Derek Schuff 3 years ago
17 changed file(s) with 546 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
5858 ID_MachO64L, // MachO 64-bit, little endian
5959 ID_MachO64B, // MachO 64-bit, big endian
6060
61 ID_Wasm,
62
6163 ID_EndObjects
6264 };
6365
113115 bool isCOFF() const {
114116 return TypeID == ID_COFF;
115117 }
118
119 bool isWasm() const { return TypeID == ID_Wasm; }
116120
117121 bool isCOFFImportFile() const {
118122 return TypeID == ID_COFFImportFile;
2828 class ObjectFile;
2929 class COFFObjectFile;
3030 class MachOObjectFile;
31 class WasmObjectFile;
3132
3233 class SymbolRef;
3334 class symbol_iterator;
303304 uint32_t UniversalCputype = 0,
304305 uint32_t UniversalIndex = 0);
305306
307 static Expected>
308 createWasmObjectFile(MemoryBufferRef Object);
306309 };
307310
308311 // Inline function definitions.
0 //===- WasmObjectFile.h - Wasm object file implementation -------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares the WasmObjectFile class, which implements the ObjectFile
10 // interface for Wasm files.
11 //
12 // See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md
13 //
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_OBJECT_WASM_H
17 #define LLVM_OBJECT_WASM_H
18
19 #include "llvm/Object/ObjectFile.h"
20 #include "llvm/Support/Wasm.h"
21
22 namespace llvm {
23 namespace object {
24
25 class WasmObjectFile : public ObjectFile {
26 public:
27 WasmObjectFile(MemoryBufferRef Object, Error &Err);
28 const wasm::WasmObjectHeader &getHeader() const;
29 const wasm::WasmSection *getWasmSection(const SectionRef &Section) const;
30 static bool classof(const Binary *v) { return v->isWasm(); }
31
32 protected:
33 void moveSymbolNext(DataRefImpl &Symb) const override;
34
35 std::error_code printSymbolName(raw_ostream &OS,
36 DataRefImpl Symb) const override;
37
38 uint32_t getSymbolFlags(DataRefImpl Symb) const override;
39
40 basic_symbol_iterator symbol_begin() const override;
41
42 basic_symbol_iterator symbol_end() const override;
43 Expected getSymbolName(DataRefImpl Symb) const override;
44
45 Expected getSymbolAddress(DataRefImpl Symb) const override;
46 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
47 uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
48 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
49 Expected getSymbolType(DataRefImpl Symb) const override;
50 Expected getSymbolSection(DataRefImpl Symb) const override;
51
52 // Overrides from SectionRef.
53 void moveSectionNext(DataRefImpl &Sec) const override;
54 std::error_code getSectionName(DataRefImpl Sec,
55 StringRef &Res) const override;
56 uint64_t getSectionAddress(DataRefImpl Sec) const override;
57 uint64_t getSectionSize(DataRefImpl Sec) const override;
58 std::error_code getSectionContents(DataRefImpl Sec,
59 StringRef &Res) const override;
60 uint64_t getSectionAlignment(DataRefImpl Sec) const override;
61 bool isSectionCompressed(DataRefImpl Sec) const override;
62 bool isSectionText(DataRefImpl Sec) const override;
63 bool isSectionData(DataRefImpl Sec) const override;
64 bool isSectionBSS(DataRefImpl Sec) const override;
65 bool isSectionVirtual(DataRefImpl Sec) const override;
66 bool isSectionBitcode(DataRefImpl Sec) const override;
67 relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
68 relocation_iterator section_rel_end(DataRefImpl Sec) const override;
69 section_iterator getRelocatedSection(DataRefImpl Sec) const override;
70
71 // Overrides from RelocationRef.
72 void moveRelocationNext(DataRefImpl &Rel) const override;
73 uint64_t getRelocationOffset(DataRefImpl Rel) const override;
74 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
75 uint64_t getRelocationType(DataRefImpl Rel) const override;
76 void getRelocationTypeName(DataRefImpl Rel,
77 SmallVectorImpl &Result) const override;
78
79 section_iterator section_begin() const override;
80 section_iterator section_end() const override;
81 uint8_t getBytesInAddress() const override;
82 StringRef getFileFormatName() const override;
83 unsigned getArch() const override;
84 SubtargetFeatures getFeatures() const override;
85 bool isRelocatableObject() const override;
86
87 private:
88 const uint8_t *getPtr(size_t Offset) const;
89 Error parseUserSection(wasm::WasmSection &Sec, const uint8_t *Ptr,
90 size_t Length);
91
92 wasm::WasmObjectHeader Header;
93 std::vector Sections;
94 };
95 }
96 }
97
98 #endif
261261 coff_object, ///< COFF object file
262262 coff_import_library, ///< COFF import library
263263 pecoff_executable, ///< PECOFF executable file
264 windows_resource ///< Windows compiled resource file (.rc)
264 windows_resource, ///< Windows compiled resource file (.rc)
265 wasm_object ///< WebAssembly Object file
265266 };
266267
267268 bool is_object() const {
0 //===- Wasm.h - Wasm object file format -------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines manifest constants for the wasm object file format.
10 // See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_SUPPORT_WASM_H
15 #define LLVM_SUPPORT_WASM_H
16
17 #include "llvm/ADT/ArrayRef.h"
18
19 namespace llvm {
20 namespace wasm {
21
22 // Object file magic string.
23 const char WasmMagic[] = {'\0', 'a', 's', 'm'};
24 // Wasm binary format version
25 const uint32_t WasmVersion = 0xd;
26
27 struct WasmObjectHeader {
28 StringRef Magic;
29 uint32_t Version;
30 };
31
32 struct WasmSection {
33 uint32_t Type; // Section type (See below)
34 uint32_t Offset; // Offset with in the file
35 StringRef Name; // Section name (User-defined sections only)
36 ArrayRef Content; // Section content
37 };
38
39 enum : unsigned {
40 WASM_SEC_USER = 0, // User-defined section
41 WASM_SEC_TYPE = 1, // Function signature declarations
42 WASM_SEC_IMPORT = 2, // Import declarations
43 WASM_SEC_FUNCTION = 3, // Function declarations
44 WASM_SEC_TABLE = 4, // Indirect function table and other tables
45 WASM_SEC_MEMORY = 5, // Memory attributes
46 WASM_SEC_GLOBAL = 6, // Global declarations
47 WASM_SEC_EXPORT = 7, // Exports
48 WASM_SEC_START = 8, // Start function declaration
49 WASM_SEC_ELEM = 9, // Elements section
50 WASM_SEC_CODE = 10, // Function bodies (code)
51 WASM_SEC_DATA = 11 // Data segments
52 };
53
54 } // end namespace wasm
55 } // end namespace llvm
56
57 #endif
6262 case sys::fs::file_magic::coff_import_library:
6363 case sys::fs::file_magic::pecoff_executable:
6464 case sys::fs::file_magic::bitcode:
65 case sys::fs::file_magic::wasm_object:
6566 return ObjectFile::createSymbolicFile(Buffer, Type, Context);
6667 case sys::fs::file_magic::macho_universal_binary:
6768 return MachOUniversalBinary::create(Buffer);
1414 RecordStreamer.cpp
1515 SymbolicFile.cpp
1616 SymbolSize.cpp
17 WasmObjectFile.cpp
1718
1819 ADDITIONAL_HEADER_DIRS
1920 ${LLVM_MAIN_INCLUDE_DIR}/llvm/Object
1010 //
1111 //===----------------------------------------------------------------------===//
1212
13 #include "llvm/Object/ObjectFile.h"
1314 #include "llvm/Object/COFF.h"
1415 #include "llvm/Object/MachO.h"
15 #include "llvm/Object/ObjectFile.h"
16 #include "llvm/Object/Wasm.h"
1617 #include "llvm/Support/ErrorHandling.h"
1718 #include "llvm/Support/FileSystem.h"
1819 #include "llvm/Support/MemoryBuffer.h"
104105 case sys::fs::file_magic::coff_import_library:
105106 case sys::fs::file_magic::pecoff_executable:
106107 return errorOrToExpected(createCOFFObjectFile(Object));
108 case sys::fs::file_magic::wasm_object:
109 return createWasmObjectFile(Object);
107110 }
108111 llvm_unreachable("Unexpected Object File Type");
109112 }
5757 case sys::fs::file_magic::macho_dsym_companion:
5858 case sys::fs::file_magic::macho_kext_bundle:
5959 case sys::fs::file_magic::pecoff_executable:
60 case sys::fs::file_magic::wasm_object:
6061 return ObjectFile::createObjectFile(Object, Type);
6162 case sys::fs::file_magic::coff_import_library:
6263 return std::unique_ptr(new COFFImportFile(Object));
0 //===- WasmObjectFile.cpp - Wasm object file implementation -----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Object/Wasm.h"
10 #include "llvm/Support/Endian.h"
11 #include "llvm/Support/LEB128.h"
12
13 #include
14
15 namespace llvm {
16 namespace object {
17
18 Expected>
19 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
20 Error Err = Error::success();
21 auto ObjectFile = llvm::make_unique(Buffer, Err);
22 if (Err)
23 return std::move(Err);
24
25 return std::move(ObjectFile);
26 }
27
28 namespace {
29
30 uint32_t readUint32(const uint8_t *&Ptr) {
31 uint32_t Result = support::endian::read32le(Ptr);
32 Ptr += sizeof(Result);
33 return Result;
34 }
35
36 uint64_t readULEB128(const uint8_t *&Ptr) {
37 unsigned Count;
38 uint64_t Result = decodeULEB128(Ptr, &Count);
39 Ptr += Count;
40 return Result;
41 }
42
43 StringRef readString(const uint8_t *&Ptr) {
44 uint32_t StringLen = readULEB128(Ptr);
45 StringRef Return = StringRef(reinterpret_cast(Ptr), StringLen);
46 Ptr += StringLen;
47 return Return;
48 }
49
50 Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr,
51 const uint8_t *Start) {
52 // TODO(sbc): Avoid reading past EOF in the case of malformed files.
53 Section.Offset = Ptr - Start;
54 Section.Type = readULEB128(Ptr);
55 uint32_t Size = readULEB128(Ptr);
56 if (Size == 0)
57 return make_error("Zero length section",
58 object_error::parse_failed);
59 Section.Content = ArrayRef(Ptr, Size);
60 Ptr += Size;
61 return Error::success();
62 }
63 }
64
65 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
66 : ObjectFile(Binary::ID_Wasm, Buffer) {
67 ErrorAsOutParameter ErrAsOutParam(&Err);
68 Header.Magic = getData().substr(0, 4);
69 if (Header.Magic != StringRef("\0asm", 4)) {
70 Err = make_error("Bad magic number",
71 object_error::parse_failed);
72 return;
73 }
74 const uint8_t *Ptr = getPtr(4);
75 Header.Version = readUint32(Ptr);
76 if (Header.Version != wasm::WasmVersion) {
77 Err = make_error("Bad version number",
78 object_error::parse_failed);
79 return;
80 }
81
82 const uint8_t *Eof = getPtr(getData().size());
83 wasm::WasmSection Sec;
84 while (Ptr < Eof) {
85 if ((Err = readSection(Sec, Ptr, getPtr(0))))
86 return;
87 if (Sec.Type == wasm::WASM_SEC_USER) {
88 if ((Err = parseUserSection(Sec, Sec.Content.data(), Sec.Content.size())))
89 return;
90 }
91 Sections.push_back(Sec);
92 }
93 }
94
95 Error WasmObjectFile::parseUserSection(wasm::WasmSection &Sec,
96 const uint8_t *Ptr, size_t Length) {
97 Sec.Name = readString(Ptr);
98 return Error::success();
99 }
100
101 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
102 return reinterpret_cast(getData().substr(Offset, 1).data());
103 }
104
105 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
106 return Header;
107 }
108
109 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
110 llvm_unreachable("not yet implemented");
111 }
112
113 std::error_code WasmObjectFile::printSymbolName(raw_ostream &OS,
114 DataRefImpl Symb) const {
115 llvm_unreachable("not yet implemented");
116 return object_error::invalid_symbol_index;
117 }
118
119 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
120 llvm_unreachable("not yet implemented");
121 return 0;
122 }
123
124 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
125 return BasicSymbolRef(DataRefImpl(), this);
126 }
127
128 basic_symbol_iterator WasmObjectFile::symbol_end() const {
129 return BasicSymbolRef(DataRefImpl(), this);
130 }
131
132 Expected WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
133 llvm_unreachable("not yet implemented");
134 return errorCodeToError(object_error::invalid_symbol_index);
135 }
136
137 Expected WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
138 llvm_unreachable("not yet implemented");
139 return errorCodeToError(object_error::invalid_symbol_index);
140 }
141
142 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
143 llvm_unreachable("not yet implemented");
144 return 0;
145 }
146
147 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
148 llvm_unreachable("not yet implemented");
149 return 0;
150 }
151
152 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
153 llvm_unreachable("not yet implemented");
154 return 0;
155 }
156
157 Expected
158 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
159 llvm_unreachable("not yet implemented");
160 return errorCodeToError(object_error::invalid_symbol_index);
161 }
162
163 Expected
164 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
165 llvm_unreachable("not yet implemented");
166 return errorCodeToError(object_error::invalid_symbol_index);
167 }
168
169 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
170
171 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
172 StringRef &Res) const {
173 const wasm::WasmSection &S = Sections[Sec.d.a];
174 #define ECase(X) \
175 case wasm::WASM_SEC_##X: \
176 Res = #X; \
177 break
178 switch (S.Type) {
179 ECase(TYPE);
180 ECase(IMPORT);
181 ECase(FUNCTION);
182 ECase(TABLE);
183 ECase(MEMORY);
184 ECase(GLOBAL);
185 ECase(EXPORT);
186 ECase(START);
187 ECase(ELEM);
188 ECase(CODE);
189 ECase(DATA);
190 case wasm::WASM_SEC_USER:
191 Res = S.Name;
192 break;
193 default:
194 return object_error::invalid_section_index;
195 }
196 #undef ECase
197 return std::error_code();
198 }
199
200 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
201
202 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
203 const wasm::WasmSection &S = Sections[Sec.d.a];
204 return S.Content.size();
205 }
206
207 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
208 StringRef &Res) const {
209 const wasm::WasmSection &S = Sections[Sec.d.a];
210 // This will never fail since wasm sections can never be empty (user-sections
211 // must have a name and non-user sections each have a defined structure).
212 Res = StringRef(reinterpret_cast(S.Content.data()),
213 S.Content.size());
214 return std::error_code();
215 }
216
217 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
218 return 1;
219 }
220
221 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
222 return false;
223 }
224
225 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
226 const wasm::WasmSection &S = Sections[Sec.d.a];
227 return S.Type == wasm::WASM_SEC_CODE;
228 }
229
230 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
231 const wasm::WasmSection &S = Sections[Sec.d.a];
232 return S.Type == wasm::WASM_SEC_DATA;
233 }
234
235 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
236
237 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
238
239 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
240
241 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Sec) const {
242 llvm_unreachable("not yet implemented");
243 RelocationRef Rel;
244 return relocation_iterator(Rel);
245 }
246
247 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Sec) const {
248 llvm_unreachable("not yet implemented");
249 RelocationRef Rel;
250 return relocation_iterator(Rel);
251 }
252
253 section_iterator WasmObjectFile::getRelocatedSection(DataRefImpl Sec) const {
254 llvm_unreachable("not yet implemented");
255 SectionRef Ref;
256 return section_iterator(Ref);
257 }
258
259 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
260 llvm_unreachable("not yet implemented");
261 }
262
263 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Rel) const {
264 llvm_unreachable("not yet implemented");
265 return 0;
266 }
267
268 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
269 llvm_unreachable("not yet implemented");
270 SymbolRef Ref;
271 return symbol_iterator(Ref);
272 }
273
274 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Rel) const {
275 llvm_unreachable("not yet implemented");
276 return 0;
277 }
278
279 void WasmObjectFile::getRelocationTypeName(
280 DataRefImpl Rel, SmallVectorImpl &Result) const {
281 llvm_unreachable("not yet implemented");
282 }
283
284 section_iterator WasmObjectFile::section_begin() const {
285 DataRefImpl Ref;
286 Ref.d.a = 0;
287 return section_iterator(SectionRef(Ref, this));
288 }
289
290 section_iterator WasmObjectFile::section_end() const {
291 DataRefImpl Ref;
292 Ref.d.a = Sections.size();
293 return section_iterator(SectionRef(Ref, this));
294 }
295
296 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
297
298 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
299
300 unsigned WasmObjectFile::getArch() const { return Triple::wasm32; }
301
302 SubtargetFeatures WasmObjectFile::getFeatures() const {
303 return SubtargetFeatures();
304 }
305
306 bool WasmObjectFile::isRelocatableObject() const { return false; }
307
308 const wasm::WasmSection *
309 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
310 return &Sections[Section.getRawDataRefImpl().d.a];
311 }
312
313 } // end namespace object
314 } // end namespace llvm
10091009 // 0x0000 = COFF unknown machine type
10101010 if (Magic[1] == 0)
10111011 return file_magic::coff_object;
1012 if (startswith(Magic, "\0asm"))
1013 return file_magic::wasm_object;
10121014 break;
10131015 }
10141016 case 0xDE: // 0x0B17C0DE = BC wraper
0 # RUN: llvm-objdump -h %p/Inputs/test.wasm | FileCheck %s
1
2 # CHECK: Sections:
3 # CHECK: Idx Name Size Address Type
4 # CHECK: 0 TYPE 0000000f 0000000000000000
5 # CHECK: 1 IMPORT 0000000b 0000000000000000
6 # CHECK: 2 FUNCTION 00000003 0000000000000000
7 # CHECK: 3 TABLE 00000005 0000000000000000
8 # CHECK: 4 EXPORT 0000000e 0000000000000000
9 # CHECK: 5 ELEM 00000007 0000000000000000
10 # CHECK: 6 CODE 0000002a 0000000000000000 TEXT
11 # CHECK: 7 name 0000002c 0000000000000000
12
13 # RUN: llvm-objdump -p %p/Inputs/test.wasm | FileCheck %s -check-prefix CHECK-HEADER
14
15 # CHECK-HEADER: Program Header:
16 # CHECK-HEADER: Version: 0xd
17
18 # RUN: llvm-objdump -s --section=CODE %p/Inputs/test.wasm | FileCheck %s -check-prefix CHECK-SECTIONS
19
20 # CHECK-SECTIONS: Contents of section CODE:
21 # CHECK-SECTIONS: 0000 02070043 0000803f 0b200201 7d017c10 ...C...?. ..}.|.
22 # CHECK-SECTIONS: 0010 001a4100 10011a41 00410111 00001a20 ..A....A.A.....
23 # CHECK-SECTIONS: 0020 011a4300 00000021 020b ..C....!..
1818 COFFDump.cpp
1919 ELFDump.cpp
2020 MachODump.cpp
21 WasmDump.cpp
2122 )
2223
2324 if(HAVE_LIBXAR)
0 //===-- WasmDump.cpp - wasm-specific dumper ---------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// \brief This file implements the wasm-specific dumper for llvm-objdump.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm-objdump.h"
15 #include "llvm/Object/Wasm.h"
16
17 using namespace llvm;
18 using namespace object;
19
20 void llvm::printWasmFileHeader(const object::ObjectFile *Obj) {
21 const WasmObjectFile *File = dyn_cast(Obj);
22
23 outs() << "Program Header:\n";
24 outs() << "Version: 0x";
25 outs().write_hex(File->getHeader().Version);
26 outs() << "\n";
27 }
19091909 return printELFFileHeader(o);
19101910 if (o->isCOFF())
19111911 return printCOFFFileHeader(o);
1912 if (o->isWasm())
1913 return printWasmFileHeader(o);
19121914 if (o->isMachO()) {
19131915 printMachOFileHeader(o);
19141916 if (!onlyFirst)
7878 void printCOFFSymbolTable(const object::COFFObjectFile *o);
7979 void printMachOFileHeader(const object::ObjectFile *o);
8080 void printMachOLoadCommands(const object::ObjectFile *o);
81 void printWasmFileHeader(const object::ObjectFile *o);
8182 void printExportsTrie(const object::ObjectFile *o);
8283 void printRebaseTable(const object::ObjectFile *o);
8384 void printBindTable(const object::ObjectFile *o);