1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
25 #include <sys/types.h>
30 #include <mach-o/loader.h>
31 #include <mach-o/fat.h>
32 #include <mach-o/stab.h>
34 #include "MachOReaderRelocatable.hpp"
36 static bool sDumpContent
= true;
37 static bool sDumpStabs
= false;
38 static bool sSort
= true;
39 static cpu_type_t sPreferredArch
= CPU_TYPE_POWERPC64
;
42 __attribute__((noreturn
))
43 void throwf(const char* format
, ...)
47 va_start(list
, format
);
48 vasprintf(&p
, format
, list
);
55 static void dumpStabs(std::vector
<ObjectFile::Reader::Stab
>* stabs
)
58 printf("stabs: (%lu)\n", stabs
->size());
59 for (std::vector
<ObjectFile::Reader::Stab
>::iterator it
= stabs
->begin(); it
!= stabs
->end(); ++it
) {
60 ObjectFile::Reader::Stab
& stab
= *it
;
61 const char* code
= "?????";
148 printf(" [atom=%20s] %02X %04X %s %s\n", ((stab
.atom
!= NULL
) ? stab
.atom
->getDisplayName() : ""), stab
.other
, stab
.desc
, code
, stab
.string
);
153 static void dumpAtom(ObjectFile::Atom
* atom
)
155 //printf("atom: %p\n", atom);
158 printf("name: %s\n", atom
->getDisplayName());
161 switch ( atom
->getScope() ) {
162 case ObjectFile::Atom::scopeTranslationUnit
:
163 printf("scope: translation unit\n");
165 case ObjectFile::Atom::scopeLinkageUnit
:
166 printf("scope: linkage unit\n");
168 case ObjectFile::Atom::scopeGlobal
:
169 printf("scope: global\n");
172 printf("scope: unknown\n");
176 switch ( atom
->getDefinitionKind() ) {
177 case ObjectFile::Atom::kRegularDefinition
:
178 printf("kind: regular\n");
180 case ObjectFile::Atom::kWeakDefinition
:
181 printf("kind: weak\n");
183 case ObjectFile::Atom::kTentativeDefinition
:
184 printf("kind: tentative\n");
186 case ObjectFile::Atom::kExternalDefinition
:
187 printf("kind: import\n");
189 case ObjectFile::Atom::kExternalWeakDefinition
:
190 printf("kind: weak import\n");
193 printf("scope: unknown\n");
196 // segment and section
197 printf("section: %s,%s\n", atom
->getSegment().getName(), atom
->getSectionName());
201 if ( atom
->dontDeadStrip() )
202 printf("dont-dead-strip ");
203 if ( atom
->isZeroFill() )
204 printf("zero-fill ");
208 printf("size: 0x%012llX\n", atom
->getSize());
211 printf("align: %d\n", atom
->getAlignment());
214 if ( sDumpContent
) {
215 uint64_t size
= atom
->getSize();
217 uint8_t content
[size
];
218 atom
->copyRawContent(content
);
220 if ( strcmp(atom
->getSectionName(), "__cstring") == 0 ) {
221 printf("\"%s\"", content
);
224 for (unsigned int i
=0; i
< size
; ++i
)
225 printf("%02X ", content
[i
]);
232 std::vector
<ObjectFile::Reference
*>& references
= atom
->getReferences();
233 const int refCount
= references
.size();
234 printf("references: (%u)\n", refCount
);
235 for (int i
=0; i
< refCount
; ++i
) {
236 ObjectFile::Reference
* ref
= references
[i
];
237 printf(" %s\n", ref
->getDescription());
241 std::vector
<ObjectFile::LineInfo
>* lineInfo
= atom
->getLineInfo();
242 if ( (lineInfo
!= NULL
) && (lineInfo
->size() > 0) ) {
243 printf("line info: (%lu)\n", lineInfo
->size());
244 for (std::vector
<ObjectFile::LineInfo
>::iterator it
= lineInfo
->begin(); it
!= lineInfo
->end(); ++it
) {
245 printf(" offset 0x%04X, line %d, file %s\n", it
->atomOffset
, it
->lineNumber
, it
->fileName
);
253 bool operator()(ObjectFile::Atom
* left
, ObjectFile::Atom
* right
)
255 return (strcmp(left
->getDisplayName(), right
->getDisplayName()) < 0);
260 static void dumpFile(ObjectFile::Reader
* reader
)
263 if ( sDumpStabs
&& (reader
->getDebugInfoKind() == ObjectFile::Reader::kDebugInfoStabs
) ) {
264 std::vector
<ObjectFile::Reader::Stab
>* stabs
= reader
->getStabs();
270 std::vector
<ObjectFile::Atom
*> atoms
= reader
->getAtoms();
272 // make copy of vector and sort (so output is canonical)
273 std::vector
<ObjectFile::Atom
*> sortedAtoms(atoms
);
275 std::sort(sortedAtoms
.begin(), sortedAtoms
.end(), AtomSorter());
277 for(std::vector
<ObjectFile::Atom
*>::iterator it
=sortedAtoms
.begin(); it
!= sortedAtoms
.end(); ++it
) {
284 static ObjectFile::Reader
* createReader(const char* path
, const ObjectFile::ReaderOptions
& options
)
286 struct stat stat_buf
;
288 int fd
= ::open(path
, O_RDONLY
, 0);
290 throwf("cannot open file: %s", path
);
291 ::fstat(fd
, &stat_buf
);
292 uint8_t* p
= (uint8_t*)::mmap(NULL
, stat_buf
.st_size
, PROT_READ
, MAP_FILE
| MAP_PRIVATE
, fd
, 0);
294 const mach_header
* mh
= (mach_header
*)p
;
295 if ( mh
->magic
== OSSwapBigToHostInt32(FAT_MAGIC
) ) {
296 const struct fat_header
* fh
= (struct fat_header
*)p
;
297 const struct fat_arch
* archs
= (struct fat_arch
*)(p
+ sizeof(struct fat_header
));
298 for (unsigned long i
=0; i
< OSSwapBigToHostInt32(fh
->nfat_arch
); ++i
) {
299 fprintf(stderr
, "archs[i].cputype = %X\n", archs
[i
].cputype
);
300 if ( OSSwapBigToHostInt32(archs
[i
].cputype
) == (uint32_t)sPreferredArch
) {
301 p
= p
+ OSSwapBigToHostInt32(archs
[i
].offset
);
302 mh
= (struct mach_header
*)p
;
306 if ( mach_o::relocatable::Reader
<x86
>::validFile(p
) )
307 return mach_o::relocatable::Reader
<x86
>::make(p
, path
, 0, options
);
308 else if ( mach_o::relocatable::Reader
<ppc
>::validFile(p
) )
309 return mach_o::relocatable::Reader
<ppc
>::make(p
, path
, 0, options
);
310 else if ( mach_o::relocatable::Reader
<ppc64
>::validFile(p
) )
311 return mach_o::relocatable::Reader
<ppc64
>::make(p
, path
, 0, options
);
312 else if ( mach_o::relocatable::Reader
<x86_64
>::validFile(p
) )
313 return mach_o::relocatable::Reader
<x86_64
>::make(p
, path
, 0, options
);
314 throwf("not a mach-o object file: %s", path
);
318 int main(int argc
, const char* argv
[])
320 ObjectFile::ReaderOptions options
;
322 for(int i
=1; i
< argc
; ++i
) {
323 const char* arg
= argv
[i
];
324 if ( arg
[0] == '-' ) {
325 if ( strcmp(arg
, "-no_content") == 0 ) {
326 sDumpContent
= false;
328 else if ( strcmp(arg
, "-stabs") == 0 ) {
331 else if ( strcmp(arg
, "-no_sort") == 0 ) {
334 else if ( strcmp(arg
, "-arch") == 0 ) {
335 const char* arch
= argv
[++i
];
336 if ( strcmp(arch
, "ppc64") == 0 )
337 sPreferredArch
= CPU_TYPE_POWERPC64
;
338 else if ( strcmp(arch
, "ppc") == 0 )
339 sPreferredArch
= CPU_TYPE_POWERPC
;
340 else if ( strcmp(arch
, "i386") == 0 )
341 sPreferredArch
= CPU_TYPE_I386
;
342 else if ( strcmp(arch
, "x86_64") == 0 )
343 sPreferredArch
= CPU_TYPE_X86_64
;
345 throwf("unknown architecture %s", arch
);
348 throwf("unknown option: %s\n", arg
);
352 ObjectFile::Reader
* reader
= createReader(arg
, options
);
357 catch (const char* msg
) {
358 fprintf(stderr
, "ObjDump failed: %s\n", msg
);