]> git.saurik.com Git - apple/ld64.git/blob - src/ObjDump.cpp
ld64-21.tar.gz
[apple/ld64.git] / src / ObjDump.cpp
1 /*
2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <sys/mman.h>
26 #include <fcntl.h>
27 #include <fcntl.h>
28 #include <mach-o/loader.h>
29 #include <mach-o/fat.h>
30 #include <mach-o/stab.h>
31
32
33 #include "ObjectFile.h"
34 #include "ObjectFileMachO-all.h"
35
36 __attribute__((noreturn))
37 void throwf(const char* format, ...)
38 {
39 va_list list;
40 char* p;
41 va_start(list, format);
42 vasprintf(&p, format, list);
43 va_end(list);
44
45 const char* t = p;
46 throw t;
47 }
48
49 static void dumpStabs(std::vector<ObjectFile::StabsInfo>* stabs)
50 {
51 // debug info
52 const int stabCount = stabs->size();
53 printf("stabs: (%u)\n", stabCount);
54 for (int i=0; i < stabCount; ++i) {
55 ObjectFile::StabsInfo& stab = (*stabs)[i];
56 const char* code = "?????";
57 switch (stab.type) {
58 case N_GSYM:
59 code = " GSYM";
60 break;
61 case N_FNAME:
62 code = "FNAME";
63 break;
64 case N_FUN:
65 code = " FUN";
66 break;
67 case N_STSYM:
68 code = "STSYM";
69 break;
70 case N_LCSYM:
71 code = "LCSYM";
72 break;
73 case N_BNSYM:
74 code = "BNSYM";
75 break;
76 case N_OPT:
77 code = " OPT";
78 break;
79 case N_RSYM:
80 code = " RSYM";
81 break;
82 case N_SLINE:
83 code = "SLINE";
84 break;
85 case N_ENSYM:
86 code = "ENSYM";
87 break;
88 case N_SSYM:
89 code = " SSYM";
90 break;
91 case N_SO:
92 code = " SO";
93 break;
94 case N_LSYM:
95 code = " LSYM";
96 break;
97 case N_BINCL:
98 code = "BINCL";
99 break;
100 case N_SOL:
101 code = " SOL";
102 break;
103 case N_PARAMS:
104 code = "PARMS";
105 break;
106 case N_VERSION:
107 code = " VERS";
108 break;
109 case N_OLEVEL:
110 code = "OLEVL";
111 break;
112 case N_PSYM:
113 code = " PSYM";
114 break;
115 case N_EINCL:
116 code = "EINCL";
117 break;
118 case N_ENTRY:
119 code = "ENTRY";
120 break;
121 case N_LBRAC:
122 code = "LBRAC";
123 break;
124 case N_EXCL:
125 code = " EXCL";
126 break;
127 case N_RBRAC:
128 code = "RBRAC";
129 break;
130 case N_BCOMM:
131 code = "BCOMM";
132 break;
133 case N_ECOMM:
134 code = "ECOMM";
135 break;
136 case N_LENG:
137 code = "LENG";
138 break;
139 }
140 printf(" %08X %02X %04X %s %s\n", (uint32_t)stab.atomOffset, stab.other, stab.desc, code, stab.string);
141 }
142 }
143
144
145 static void dumpAtom(ObjectFile::Atom* atom)
146 {
147 //printf("atom: %p\n", atom);
148
149 // name
150 printf("name: %s\n", atom->getDisplayName());
151
152 // scope
153 switch ( atom->getScope() ) {
154 case ObjectFile::Atom::scopeTranslationUnit:
155 printf("scope: translation unit\n");
156 break;
157 case ObjectFile::Atom::scopeLinkageUnit:
158 printf("scope: linkage unit\n");
159 break;
160 case ObjectFile::Atom::scopeGlobal:
161 printf("scope: global\n");
162 break;
163 default:
164 printf("scope: unknown\n");
165 }
166
167 // segment and section
168 printf("section: %s,%s\n", atom->getSegment().getName(), atom->getSectionName());
169
170 // attributes
171 printf("attrs: ");
172 if ( atom->isWeakDefinition() )
173 printf("weak ");
174 if ( atom->isCoalesableByName() )
175 printf("coalesce-by-name ");
176 if ( atom->isCoalesableByValue() )
177 printf("coalesce-by-value ");
178 if ( atom->dontDeadStrip() )
179 printf("dont-dead-strip ");
180 if ( atom->isZeroFill() )
181 printf("zero-fill ");
182 printf("\n");
183
184 // size
185 printf("size: 0x%012llX\n", atom->getSize());
186
187 // alignment
188 printf("align: %d\n", atom->getAlignment());
189
190 // content
191 uint64_t size = atom->getSize();
192 if ( size < 4096 ) {
193 uint8_t content[size];
194 atom->copyRawContent(content);
195 printf("content: ");
196 if ( strcmp(atom->getSectionName(), "__cstring") == 0 ) {
197 printf("\"%s\"", content);
198 }
199 else {
200 for (unsigned int i=0; i < size; ++i)
201 printf("%02X ", content[i]);
202 }
203 }
204 printf("\n");
205
206 // references
207 std::vector<ObjectFile::Reference*>& references = atom->getReferences();
208 const int refCount = references.size();
209 printf("references: (%u)\n", refCount);
210 for (int i=0; i < refCount; ++i) {
211 ObjectFile::Reference* ref = references[i];
212 printf(" %s\n", ref->getDescription());
213 }
214
215 // debug info
216 std::vector<ObjectFile::StabsInfo>* stabs = atom->getStabsDebugInfo();
217 if ( stabs != NULL )
218 dumpStabs(stabs);
219 }
220
221
222 static void dumpFile(ObjectFile::Reader* reader)
223 {
224 #if 0
225 // debug info
226 std::vector<ObjectFile::StabsInfo>* stabs = reader->getStabsDebugInfo();
227 if ( stabs != NULL )
228 dumpStabs(stabs);
229 #endif
230 // atom content
231 std::vector<ObjectFile::Atom*> atoms = reader->getAtoms();
232 const int atomCount = atoms.size();
233 for(int i=0; i < atomCount; ++i) {
234 dumpAtom(atoms[i]);
235 printf("\n");
236 }
237 }
238
239
240 static ObjectFile::Reader* createReader(const char* path, const ObjectFile::ReaderOptions& options)
241 {
242 struct stat stat_buf;
243
244 int fd = ::open(path, O_RDONLY, 0);
245 if ( fd == -1 )
246 throw "cannot open file";
247 ::fstat(fd, &stat_buf);
248 char* p = (char*)::mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE, fd, 0);
249 ::close(fd);
250 const mach_header* mh = (mach_header*)p;
251 if ( mh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
252 const struct fat_header* fh = (struct fat_header*)p;
253 const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header));
254 for (unsigned long i=0; i < fh->nfat_arch; ++i) {
255 if ( archs[i].cputype == CPU_TYPE_POWERPC64 ) {
256 p = p + archs[i].offset;
257 mh = (struct mach_header*)p;
258 }
259 }
260 }
261 if ( mh->magic == MH_MAGIC ) {
262 if ( mh->filetype == MH_OBJECT ) {
263 switch ( mh->cputype ) {
264 case CPU_TYPE_I386:
265 return i386::ObjectFileMachO::MakeReader((class i386::macho_header*)mh, path, options);
266 case CPU_TYPE_POWERPC:
267 return ppc::ObjectFileMachO::MakeReader((class ppc::macho_header*)mh, path, options);
268 case CPU_TYPE_POWERPC64:
269 return ppc64::ObjectFileMachO::MakeReader((class ppc64::macho_header*)mh, path, options);
270 default:
271 throw "unknown mach-o cpu type";
272 }
273 }
274 if ( mh->filetype == MH_DYLIB )
275 return ppc::ObjectFileDylibMachO::MakeReader((class ppc::macho_header*)mh, path, options);
276 throw "unknown mach-o file type";
277 }
278 else if ( mh->magic == MH_MAGIC_64 ) {
279 if ( mh->filetype == MH_OBJECT )
280 return ppc64::ObjectFileMachO::MakeReader((class ppc64::macho_header*)mh, path, options);
281 if ( mh->filetype == MH_DYLIB )
282 return ppc64::ObjectFileDylibMachO::MakeReader((class ppc64::macho_header*)mh, path, options);
283 throw "unknown mach-o file type";
284 }
285 else if ( mh->magic == OSSwapInt32(MH_MAGIC) ) {
286 if ( mh->filetype == OSSwapInt32(MH_OBJECT) ) {
287 switch ( OSSwapInt32(mh->cputype) ) {
288 case CPU_TYPE_I386:
289 return i386::ObjectFileMachO::MakeReader((class i386::macho_header*)mh, path, options);
290 case CPU_TYPE_POWERPC:
291 return ppc::ObjectFileMachO::MakeReader((class ppc::macho_header*)mh, path, options);
292 case CPU_TYPE_POWERPC64:
293 return ppc64::ObjectFileMachO::MakeReader((class ppc64::macho_header*)mh, path, options);
294 default:
295 throw "unknown mach-o cpu type";
296 }
297 }
298 if ( mh->filetype == OSSwapInt32(MH_DYLIB) )
299 return ppc::ObjectFileDylibMachO::MakeReader((class ppc::macho_header*)mh, path, options);
300 throw "unknown mach-o file type";
301 }
302 else if ( mh->magic == OSSwapInt32(MH_MAGIC_64) ) {
303 if ( mh->filetype == OSSwapInt32(MH_OBJECT) )
304 return ppc64::ObjectFileMachO::MakeReader((class ppc64::macho_header*)mh, path, options);
305 if ( mh->filetype == OSSwapInt32(MH_DYLIB) )
306 return ppc64::ObjectFileDylibMachO::MakeReader((class ppc64::macho_header*)mh, path, options);
307 throw "unknown mach-o file type";
308 }
309 throw "unknown file type";
310 }
311
312
313 int main(int argc, const char* argv[])
314 {
315 ObjectFile::ReaderOptions options;
316 //const char* path = argv[1];
317 //ObjectFile::Reader* reader = ObjectFile::Reader::createReader(path);
318 try {
319 ObjectFile::Reader* reader = createReader("/tmp/gcov-1.o", options);
320
321 dumpFile(reader);
322 }
323 catch (const char* msg) {
324 fprintf(stderr, "ObjDump failed: %s\n", msg);
325 }
326
327 return 0;
328 }
329
330
331