2 * Copyright (C) 2000, The University of Queensland
3 * Copyright (C) 2001, Sun Microsystems, Inc
4 * Copyright (C) 2002, Trent Waddington
6 * See the file "LICENSE.TERMS" for information on usage and
7 * redistribution of this file, and for a DISCLAIMER OF ALL
12 /* File: MachOBinaryFile.cc
14 * Desc: This file contains the implementation of the class MachOBinaryFile.
17 /* MachO binary file format.
18 * This file implements the class MachOBinaryFile, derived from class
19 * BinaryFile. See MachOBinaryFile.h and BinaryFile.h for details.
20 * 13 Jan 05 - Trent: Created.
23 #if defined(_MSC_VER) && _MSC_VER <= 1200
24 #pragma warning(disable:4786)
27 #include "BinaryFile.h"
28 #include "MachOBinaryFile.h"
34 #include <cstdarg> // For va_list for MinGW at least
37 #include "macho-apple.h"
40 #include "objc/objc-class.h"
41 #include "objc/objc-runtime.h"
43 #include <objc/objc-class.h>
44 #include <objc/objc-runtime.h>
47 //#define DEBUG_MACHO_LOADER
48 //#define DEBUG_MACHO_LOADER_OBJC
50 MachOBinaryFile::MachOBinaryFile() : m_pFileName(0)
52 machine
= MACHINE_PPC
;
56 MachOBinaryFile::~MachOBinaryFile()
58 for (int i
=0; i
< m_iNumSections
; i
++)
60 if (m_pSections
[i
].pSectionName
)
61 delete [] m_pSections
[i
].pSectionName
;
63 if (m_pSections
) delete [] m_pSections
;
66 bool MachOBinaryFile::Open(const char* sName
)
68 //return Load(sName) != 0;
72 void MachOBinaryFile::Close()
77 std::list
<SectionInfo
*>& MachOBinaryFile::GetEntryPoints(
80 fprintf(stderr
,"really don't know how to implement GetEntryPoints\n");
82 static std::list
<SectionInfo
*> l
;
86 ADDRESS
MachOBinaryFile::GetEntryPoint()
91 ADDRESS
MachOBinaryFile::GetMainEntryPoint()
93 ADDRESS aMain
= GetAddressByName ("main", true);
94 if (aMain
!= NO_ADDRESS
)
96 aMain
= GetAddressByName ("_main", true);
97 if (aMain
!= NO_ADDRESS
)
103 #define BE4(x) ((magic[(x)] << 24) | (magic[(x)+1] << 16) | (magic[(x)+2] << 8) | (magic[(x)+3]))
105 bool MachOBinaryFile::RealLoad(const char* sName
)
108 FILE *fp
= fopen(sName
,"rb");
110 unsigned int imgoffs
= 0;
112 unsigned char magic
[12*4];
113 fread(magic
, sizeof(magic
), 1, fp
);
115 if (magic
[0] == 0xca && magic
[1] == 0xfe && magic
[2] == 0xba && magic
[3] == 0xbe)
117 int nimages
= BE4(4);
118 #ifdef DEBUG_MACHO_LOADER
119 printf("binary is universal with %d images\n", nimages
);
121 for (int i
= 0; i
< nimages
; i
++)
123 int fbh
= 8 + i
* 5*4;
124 unsigned int cputype
= BE4(fbh
);
125 unsigned int cpusubtype
= BE4(fbh
+4);
126 unsigned int offset
= BE4(fbh
+8);
127 unsigned int size
= BE4(fbh
+12);
128 unsigned int pad
= BE4(fbh
+16);
129 #ifdef DEBUG_MACHO_LOADER
130 printf("cputype: %08x\n", cputype
);
131 printf("cpusubtype: %08x\n", cpusubtype
);
132 printf("offset: %08x\n", offset
);
133 printf("size: %08x\n", size
);
134 printf("pad: %08x\n", pad
);
137 if (cputype
== 0x7) // i386
142 fseek(fp
, imgoffs
, SEEK_SET
);
143 header
= new struct mach_header
;
144 fread(header
, sizeof(*header
), 1, fp
);
146 if ((header
->magic
!= MH_MAGIC
) && (_BMMH(header
->magic
) != MH_MAGIC
))
149 fprintf(stderr
,"error loading file %s, bad Mach-O magic\n", sName
);
153 // check for swapped bytes
154 swap_bytes
= (_BMMH(header
->magic
) == MH_MAGIC
);
156 // Determine CPU type
157 if (BMMH(header
->cputype
) == 0x07)
158 machine
= MACHINE_PENTIUM
;
160 machine
= MACHINE_PPC
;
163 std::vector
<struct segment_command
> segments
;
164 std::vector
<struct nlist
> symbols
;
165 unsigned startlocal
, nlocal
, startdef
, ndef
, startundef
, nundef
;
166 std::vector
<struct section
> stubs_sects
;
168 unsigned *indirectsymtbl
= NULL
;
169 ADDRESS objc_symbols
= NO_ADDRESS
, objc_modules
= NO_ADDRESS
, objc_strings
= NO_ADDRESS
, objc_refs
= NO_ADDRESS
;
170 unsigned objc_modules_size
= 0;
172 fseek(fp
, imgoffs
+ sizeof(*header
), SEEK_SET
);
173 for (unsigned i
= 0; i
< BMMH(header
->ncmds
); i
++)
175 struct load_command cmd
;
176 long pos
= ftell(fp
);
177 fread(&cmd
, 1, sizeof(struct load_command
), fp
);
179 fseek(fp
, pos
, SEEK_SET
);
180 switch (BMMH(cmd
.cmd
))
184 struct segment_command seg
;
185 fread(&seg
, 1, sizeof(seg
), fp
);
186 segments
.push_back(seg
);
187 #ifdef DEBUG_MACHO_LOADER
188 fprintf(stdout
, "seg addr %x size %i fileoff %x filesize %i flags %x\n", BMMH(seg
.vmaddr
), BMMH(seg
.vmsize
), BMMH(seg
.fileoff
), BMMH(seg
.filesize
), BMMH(seg
.flags
));
190 for (unsigned n
= 0; n
< BMMH(seg
.nsects
); n
++)
193 fread(§
, 1, sizeof(sect
), fp
);
194 sections
.push_back(sect
);
195 #ifdef DEBUG_MACHO_LOADER
196 fprintf(stdout
, " sectname %s segname %s addr %x size %i flags %x\n", sect
.sectname
, sect
.segname
, BMMH(sect
.addr
), BMMH(sect
.size
), BMMH(sect
.flags
));
198 if ((BMMH(sect
.flags
) & SECTION_TYPE
) == S_SYMBOL_STUBS
)
200 stubs_sects
.push_back(sect
);
201 #ifdef DEBUG_MACHO_LOADER
202 fprintf(stdout
, " symbol stubs section, start index %i, stub size %i\n", BMMH(sect
.reserved1
), BMMH(sect
.reserved2
));
205 if (!strcmp(sect
.sectname
, SECT_OBJC_SYMBOLS
))
207 assert(objc_symbols
== NO_ADDRESS
);
208 objc_symbols
= BMMH(sect
.addr
);
210 if (!strcmp(sect
.sectname
, SECT_OBJC_MODULES
))
212 assert(objc_modules
== NO_ADDRESS
);
213 objc_modules
= BMMH(sect
.addr
);
214 objc_modules_size
= BMMH(sect
.size
);
216 if (!strcmp(sect
.sectname
, SECT_OBJC_STRINGS
))
218 assert(objc_strings
== NO_ADDRESS
);
219 objc_strings
= BMMH(sect
.addr
);
221 if (!strcmp(sect
.sectname
, SECT_OBJC_REFS
))
223 assert(objc_refs
== NO_ADDRESS
);
224 objc_refs
= BMMH(sect
.addr
);
231 struct symtab_command syms
;
232 fread(&syms
, 1, sizeof(syms
), fp
);
233 fseek(fp
, imgoffs
+ BMMH(syms
.stroff
), SEEK_SET
);
234 strtbl
= new char[BMMH(syms
.strsize
)];
235 fread(strtbl
, 1, BMMH(syms
.strsize
), fp
);
236 fseek(fp
, imgoffs
+ BMMH(syms
.symoff
), SEEK_SET
);
237 for (unsigned n
= 0; n
< BMMH(syms
.nsyms
); n
++)
240 fread(&sym
, 1, sizeof(sym
), fp
);
241 symbols
.push_back(sym
);
242 #ifdef DEBUG_MACHO_LOADER
243 //fprintf(stdout, "got sym %s flags %x value %x\n", strtbl + BMMH(sym.n_un.n_strx), sym.n_type, BMMH(sym.n_value));
246 #ifdef DEBUG_MACHO_LOADER
247 fprintf(stdout
, "symtab contains %i symbols\n", BMMH(syms
.nsyms
));
253 struct dysymtab_command syms
;
254 fread(&syms
, 1, sizeof(syms
), fp
);
255 #ifdef DEBUG_MACHO_LOADER
256 fprintf(stdout
, "dysymtab local %i %i defext %i %i undef %i %i\n",
257 BMMH(syms
.ilocalsym
), BMMH(syms
.nlocalsym
),
258 BMMH(syms
.iextdefsym
), BMMH(syms
.nextdefsym
),
259 BMMH(syms
.iundefsym
), BMMH(syms
.nundefsym
));
261 startlocal
= BMMH(syms
.ilocalsym
);
262 nlocal
= BMMH(syms
.nlocalsym
);
263 startdef
= BMMH(syms
.iextdefsym
);
264 ndef
= BMMH(syms
.nextdefsym
);
265 startundef
= BMMH(syms
.iundefsym
);
266 nundef
= BMMH(syms
.nundefsym
);
268 #ifdef DEBUG_MACHO_LOADER
269 fprintf(stdout
, "dysymtab has %i indirect symbols: ", BMMH(syms
.nindirectsyms
));
271 indirectsymtbl
= new unsigned[BMMH(syms
.nindirectsyms
)];
272 fseek(fp
, imgoffs
+ BMMH(syms
.indirectsymoff
), SEEK_SET
);
273 fread(indirectsymtbl
, 1, BMMH(syms
.nindirectsyms
)*sizeof(unsigned), fp
);
274 #ifdef DEBUG_MACHO_LOADER
275 for (unsigned j
= 0; j
< BMMH(syms
.nindirectsyms
); j
++)
277 fprintf(stdout
, "%i ", BMMH(indirectsymtbl
[j
]));
279 fprintf(stdout
, "\n");
284 #ifdef DEBUG_MACHO_LOADER
285 fprintf(stderr
, "not handled load command %x\n", BMMH(cmd
.cmd
));
287 // yep, there's lots of em
291 fseek(fp
, pos
+ BMMH(cmd
.cmdsize
), SEEK_SET
);
294 struct segment_command
*lowest
= &segments
[0], *highest
= &segments
[0];
295 for (unsigned i
= 1; i
< segments
.size(); i
++)
297 if (BMMH(segments
[i
].vmaddr
) < BMMH(lowest
->vmaddr
))
298 lowest
= &segments
[i
];
299 if (BMMH(segments
[i
].vmaddr
) > BMMH(highest
->vmaddr
))
300 highest
= &segments
[i
];
303 loaded_addr
= BMMH(lowest
->vmaddr
);
304 loaded_size
= BMMH(highest
->vmaddr
) - BMMH(lowest
->vmaddr
) + BMMH(highest
->vmsize
);
306 base
= (char *)malloc(loaded_size
);
311 fprintf(stderr
,"Cannot allocate memory for copy of image\n");
315 m_iNumSections
= segments
.size();
316 m_pSections
= new SectionInfo
[m_iNumSections
];
318 for (unsigned i
= 0; i
< segments
.size(); i
++)
320 fseek(fp
, imgoffs
+ BMMH(segments
[i
].fileoff
), SEEK_SET
);
321 ADDRESS a
= BMMH(segments
[i
].vmaddr
);
322 unsigned sz
= BMMH(segments
[i
].vmsize
);
323 unsigned fsz
= BMMH(segments
[i
].filesize
);
324 memset(base
+ a
- loaded_addr
, 0, sz
);
325 fread(base
+ a
- loaded_addr
, 1, fsz
, fp
);
327 m_pSections
[i
].pSectionName
= new char[17];
328 strncpy(m_pSections
[i
].pSectionName
, segments
[i
].segname
, 16);
329 m_pSections
[i
].pSectionName
[16] = 0;
330 m_pSections
[i
].uNativeAddr
= BMMH(segments
[i
].vmaddr
);
331 m_pSections
[i
].uHostAddr
= (ADDRESS
)base
+ BMMH(segments
[i
].vmaddr
) - loaded_addr
;
332 m_pSections
[i
].uSectionSize
= BMMH(segments
[i
].vmsize
);
334 unsigned long l
= BMMH(segments
[i
].initprot
);
335 m_pSections
[i
].bBss
= false; // TODO
336 m_pSections
[i
].bCode
= l
&VM_PROT_EXECUTE
?1:0;
337 m_pSections
[i
].bData
= l
&VM_PROT_READ
?1:0;
338 m_pSections
[i
].bReadOnly
= (l
&VM_PROT_WRITE
)?0:1;
340 #ifdef DEBUG_MACHO_LOADER
341 fprintf(stderr
, "loaded segment %x %i in mem %i in file code=%i data=%i readonly=%i\n", a
, sz
, fsz
, m_pSections
[i
].bCode
, m_pSections
[i
].bData
, m_pSections
[i
].bReadOnly
);
345 // process stubs_sects
346 for (unsigned j
= 0; j
< stubs_sects
.size(); j
++)
348 for (unsigned i
= 0; i
< BMMH(stubs_sects
[j
].size
) / BMMH(stubs_sects
[j
].reserved2
); i
++)
350 unsigned startidx
= BMMH(stubs_sects
[j
].reserved1
);
351 unsigned symbol
= BMMH(indirectsymtbl
[startidx
+ i
]);
352 ADDRESS addr
= BMMH(stubs_sects
[j
].addr
) + i
* BMMH(stubs_sects
[j
].reserved2
);
353 #ifdef DEBUG_MACHO_LOADER
354 fprintf(stdout
, "stub for %s at %x\n", strtbl
+ BMMH(symbols
[symbol
].n_un
.n_strx
), addr
);
356 char *name
= strtbl
+ BMMH(symbols
[symbol
].n_un
.n_strx
);
357 if (*name
== '_') // we want printf not _printf
360 dlprocs
[addr
] = name
;
364 // process the remaining symbols
365 for (unsigned i
= 0; i
< symbols
.size(); i
++)
367 char *name
= strtbl
+ BMMH(symbols
[i
].n_un
.n_strx
);
368 if (BMMH(symbols
[i
].n_un
.n_strx
) != 0 && BMMH(symbols
[i
].n_value
) != 0 && *name
!= 0)
371 #ifdef DEBUG_MACHO_LOADER
372 fprintf(stdout
, "symbol %s at %x type %x\n", name
,
373 BMMH(symbols
[i
].n_value
),
374 BMMH(symbols
[i
].n_type
) & N_TYPE
);
376 if (*name
== '_') // we want main not _main
378 m_SymA
[BMMH(symbols
[i
].n_value
)] = name
;
382 // process objective-c section
383 if (objc_modules
!= NO_ADDRESS
)
385 #ifdef DEBUG_MACHO_LOADER_OBJC
386 fprintf(stdout
, "processing objective-c section\n");
388 for (unsigned i
= 0; i
< objc_modules_size
; )
390 struct objc_module
*module
= (struct objc_module
*)((ADDRESS
)base
+ objc_modules
- loaded_addr
+ i
);
391 char *name
= (char *)((ADDRESS
)base
+ BMMH(module
->name
) - loaded_addr
);
392 Symtab symtab
= (Symtab
)((ADDRESS
)base
+ BMMH(module
->symtab
) - loaded_addr
);
393 #ifdef DEBUG_MACHO_LOADER_OBJC
394 fprintf(stdout
, "module %s (%i classes)\n", name
, BMMHW(symtab
->cls_def_cnt
));
396 ObjcModule
*m
= &modules
[name
];
398 for (unsigned j
= 0; j
< BMMHW(symtab
->cls_def_cnt
); j
++)
400 struct objc_class
*def
= (struct objc_class
*)((ADDRESS
)base
+ BMMH(symtab
->defs
[j
]) - loaded_addr
);
401 char *name
= (char *)((ADDRESS
)base
+ BMMH(def
->name
) - loaded_addr
);
402 #ifdef DEBUG_MACHO_LOADER_OBJC
403 fprintf(stdout
, " class %s\n", name
);
405 ObjcClass
*cl
= &m
->classes
[name
];
407 struct objc_ivar_list
*ivars
= (struct objc_ivar_list
*)((ADDRESS
)base
+ BMMH(def
->ivars
) - loaded_addr
);
408 for (unsigned k
= 0; k
< static_cast<unsigned int>(BMMH(ivars
->ivar_count
)); k
++)
410 struct objc_ivar
*ivar
= &ivars
->ivar_list
[k
];
411 char *name
= (char*)((ADDRESS
)base
+ BMMH(ivar
->ivar_name
) - loaded_addr
);
412 char *types
= (char*)((ADDRESS
)base
+ BMMH(ivar
->ivar_type
) - loaded_addr
);
413 #ifdef DEBUG_MACHO_LOADER_OBJC
414 fprintf(stdout
, " ivar %s %s %x\n", name
, types
, BMMH(ivar
->ivar_offset
));
416 ObjcIvar
*iv
= &cl
->ivars
[name
];
419 iv
->offset
= BMMH(ivar
->ivar_offset
);
421 // this is weird, why is it defined as a ** in the struct but used as a * in otool?
422 struct objc_method_list
*methods
= (struct objc_method_list
*)((ADDRESS
)base
+ BMMH(def
->methodLists
) - loaded_addr
);
423 for (unsigned k
= 0; k
< static_cast<unsigned int>(BMMH(methods
->method_count
)); k
++)
425 struct objc_method
*method
= &methods
->method_list
[k
];
426 char *name
= (char*)((ADDRESS
)base
+ BMMH(method
->method_name
) - loaded_addr
);
427 char *types
= (char*)((ADDRESS
)base
+ BMMH(method
->method_types
) - loaded_addr
);
428 #ifdef DEBUG_MACHO_LOADER_OBJC
429 fprintf(stdout
, " method %s %s %x\n", name
, types
, BMMH((void*)method
->method_imp
));
431 ObjcMethod
*me
= &cl
->methods
[name
];
434 me
->addr
= BMMH((void*)method
->method_imp
);
437 i
+= BMMH(module
->size
);
441 // Give the entry point a symbol
442 // ADDRESS entry = GetMainEntryPoint();
443 entrypoint
= GetMainEntryPoint();
449 // Clean up and unload the binary image
450 void MachOBinaryFile::UnLoad()
453 bool MachOBinaryFile::PostLoad(void* handle
)
458 const char* MachOBinaryFile::SymbolByAddress(ADDRESS dwAddr
)
460 std::map
<ADDRESS
, std::string
>::iterator it
= m_SymA
.find(dwAddr
);
461 if (it
== m_SymA
.end())
463 return (char*) it
->second
.c_str();
466 ADDRESS
MachOBinaryFile::GetAddressByName(const char* pName
,
467 bool bNoTypeOK
/* = false */)
469 // This is "looking up the wrong way" and hopefully is uncommon
471 std::map
<ADDRESS
, std::string
>::iterator it
= m_SymA
.begin();
472 while (it
!= m_SymA
.end())
474 // std::cerr << "Symbol: " << it->second.c_str() << " at 0x" << std::hex << it->first << "\n";
475 if (strcmp(it
->second
.c_str(), pName
) == 0)
482 void MachOBinaryFile::AddSymbol(ADDRESS uNative
, const char *pName
)
484 m_SymA
[uNative
] = pName
;
487 bool MachOBinaryFile::DisplayDetails(const char* fileName
, FILE* f
493 int MachOBinaryFile::machORead2(short* ps
) const
495 unsigned char* p
= (unsigned char*)ps
;
497 if (machine
== MACHINE_PPC
)
498 n
= (int)(p
[1] + (p
[0] << 8));
500 n
= (int)(p
[0] + (p
[1] << 8));
504 int MachOBinaryFile::machORead4(int* pi
) const
506 short* p
= (short*)pi
;
507 int n1
= machORead2(p
);
508 int n2
= machORead2(p
+1);
510 if (machine
== MACHINE_PPC
)
511 n
= (int) (n2
| (n1
<< 16));
513 n
= (int) (n1
| (n2
<< 16));
518 void *MachOBinaryFile::BMMH(void *x)
520 if (swap_bytes) return _BMMH(x); else return x;
524 char *MachOBinaryFile::BMMH(char *x
)
526 if (swap_bytes
) return (char *)_BMMH(x
);
530 unsigned int MachOBinaryFile::BMMH(void * x
)
532 if (swap_bytes
) return (unsigned int)_BMMH(x
);
533 else return (unsigned int)x
;
536 const char *MachOBinaryFile::BMMH(const char *x
)
538 if (swap_bytes
) return (const char *)_BMMH(x
);
542 unsigned int MachOBinaryFile::BMMH(unsigned long x
)
544 if (swap_bytes
) return _BMMH(x
);
548 unsigned int MachOBinaryFile::BMMH(long int & x
)
550 if (swap_bytes
) return _BMMH(x
);
554 signed int MachOBinaryFile::BMMH(signed int x
)
556 if (swap_bytes
) return _BMMH(x
);
560 unsigned int MachOBinaryFile::BMMH(unsigned int x
)
562 if (swap_bytes
) return _BMMH(x
);
566 unsigned short MachOBinaryFile::BMMHW(unsigned short x
)
568 if (swap_bytes
) return _BMMHW(x
);
572 bool MachOBinaryFile::isReadOnly(ADDRESS uEntry
)
574 for (size_t i
= 0; i
< sections
.size(); i
++)
575 if (uEntry
>= BMMH(sections
[i
].addr
) &&
576 uEntry
< BMMH(sections
[i
].addr
) + BMMH(sections
[i
].size
))
578 return (BMMH(sections
[i
].flags
) & VM_PROT_WRITE
) ? 0 : 1;
580 return BinaryFile::isReadOnly(uEntry
);
583 // constant.. hmm, seems __cstring is writable, what's with that?
584 bool MachOBinaryFile::isStringConstant(ADDRESS uEntry
)
586 for (size_t i
= 0; i
< sections
.size(); i
++)
588 if (uEntry
>= BMMH(sections
[i
].addr
) &&
589 uEntry
< BMMH(sections
[i
].addr
) + BMMH(sections
[i
].size
))
591 //printf("%08x is in %s\n", uEntry, sections[i].sectname);
592 if (!strcmp(sections
[i
].sectname
, "__cstring"))
596 return BinaryFile::isStringConstant(uEntry
);
599 bool MachOBinaryFile::isCFStringConstant(ADDRESS uEntry
)
601 for (size_t i
= 0; i
< sections
.size(); i
++)
603 if (uEntry
>= BMMH(sections
[i
].addr
) &&
604 uEntry
< BMMH(sections
[i
].addr
) + BMMH(sections
[i
].size
))
606 //printf("%08x is in %s\n", uEntry, sections[i].sectname);
607 if (!strcmp(sections
[i
].sectname
, "__cfstring"))
611 return BinaryFile::isCFStringConstant(uEntry
);
614 // Read 2 bytes from given native address
615 int MachOBinaryFile::readNative1(ADDRESS nat
)
617 PSectionInfo si
= GetSectionInfoByAddr(nat
);
619 si
= GetSectionInfo(0);
620 ADDRESS host
= si
->uHostAddr
- si
->uNativeAddr
+ nat
;
624 // Read 2 bytes from given native address
625 int MachOBinaryFile::readNative2(ADDRESS nat
)
627 PSectionInfo si
= GetSectionInfoByAddr(nat
);
628 if (si
== 0) return 0;
629 ADDRESS host
= si
->uHostAddr
- si
->uNativeAddr
+ nat
;
630 int n
= machORead2((short*)host
);
634 // Read 4 bytes from given native address
635 int MachOBinaryFile::readNative4(ADDRESS nat
)
637 PSectionInfo si
= GetSectionInfoByAddr(nat
);
638 if (si
== 0) return 0;
639 ADDRESS host
= si
->uHostAddr
- si
->uNativeAddr
+ nat
;
640 int n
= machORead4((int*)host
);
644 // Read 8 bytes from given native address
645 QWord
MachOBinaryFile::readNative8(ADDRESS nat
)
648 #ifdef WORDS_BIGENDIAN // This tests the host machine
649 // Source and host are different endianness
650 raw
[1] = readNative4(nat
);
651 raw
[0] = readNative4(nat
+4);
653 // Source and host are same endianness
654 raw
[0] = readNative4(nat
);
655 raw
[1] = readNative4(nat
+4);
660 // Read 4 bytes as a float
661 float MachOBinaryFile::readNativeFloat4(ADDRESS nat
)
663 int raw
= readNative4(nat
);
664 // Ugh! gcc says that reinterpreting from int to float is invalid!!
665 //return reinterpret_cast<float>(raw); // Note: cast, not convert!!
666 return *(float*)&raw
; // Note: cast, not convert
669 // Read 8 bytes as a float
670 double MachOBinaryFile::readNativeFloat8(ADDRESS nat
)
673 #ifdef WORDS_BIGENDIAN // This tests the host machine
674 // Source and host are different endianness
675 raw
[1] = readNative4(nat
);
676 raw
[0] = readNative4(nat
+4);
678 // Source and host are same endianness
679 raw
[0] = readNative4(nat
);
680 raw
[1] = readNative4(nat
+4);
682 //return reinterpret_cast<double>(*raw); // Note: cast, not convert!!
683 return *(double*)raw
;
686 const char *MachOBinaryFile::GetDynamicProcName(ADDRESS uNative
)
688 return dlprocs
[uNative
].c_str();
691 LOAD_FMT
MachOBinaryFile::GetFormat() const
693 return LOADFMT_MACHO
;
696 MACHINE
MachOBinaryFile::GetMachine() const
701 bool MachOBinaryFile::isLibrary() const
706 ADDRESS
MachOBinaryFile::getImageBase()
711 size_t MachOBinaryFile::getImageSize()
716 std::list
<const char *> MachOBinaryFile::getDependencyList()
718 return std::list
<const char *>(); /* FIXME */
721 ptrdiff_t MachOBinaryFile::getDelta()
723 // Stupid function anyway: delta depends on section
724 // This should work for the header only
725 // return (DWord)base - LMMH(m_pPEHeader->Imagebase);
726 return base
- loaded_addr
;
729 // This function is called via dlopen/dlsym; it returns a new BinaryFile
730 // derived concrete object. After this object is returned, the virtual function
731 // call mechanism will call the rest of the code in this library
732 // It needs to be C linkage so that it its name is not mangled
736 __declspec(dllexport
)
738 BinaryFile
* construct()
740 return new MachOBinaryFile
;