Apply patch from Daniel Schürmann: https://sourceforge.net/p/boomerang/bugs/78/
[boomerang.git] / boomerang / loader / MachOBinaryFile.cpp
blob3fdb403b4e8f084b0905f4bd7132cce5ecb1a343
1 /*
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
8 * WARRANTIES.
12 /* File: MachOBinaryFile.cc
13 * $Revision$
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)
25 #endif
27 #include "BinaryFile.h"
28 #include "MachOBinaryFile.h"
29 #include <iostream>
30 #include <sstream>
31 #include <cassert>
32 #include <cstdlib>
33 #include <cstring>
34 #include <cstdarg> // For va_list for MinGW at least
36 #include "nlist.h"
37 #include "macho-apple.h"
39 #ifndef HOST_OSX
40 #include "objc/objc-class.h"
41 #include "objc/objc-runtime.h"
42 #else
43 #include <objc/objc-class.h>
44 #include <objc/objc-runtime.h>
45 #endif
47 //#define DEBUG_MACHO_LOADER
48 //#define DEBUG_MACHO_LOADER_OBJC
50 MachOBinaryFile::MachOBinaryFile() : m_pFileName(0)
52 machine = MACHINE_PPC;
53 swap_bytes = false;
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;
69 return false;
72 void MachOBinaryFile::Close()
74 UnLoad();
77 std::list<SectionInfo*>& MachOBinaryFile::GetEntryPoints(
78 const char* pEntry)
80 fprintf(stderr,"really don't know how to implement GetEntryPoints\n");
81 exit(0);
82 static std::list<SectionInfo*> l;
83 return l;
86 ADDRESS MachOBinaryFile::GetEntryPoint()
88 return entrypoint;
91 ADDRESS MachOBinaryFile::GetMainEntryPoint()
93 ADDRESS aMain = GetAddressByName ("main", true);
94 if (aMain != NO_ADDRESS)
95 return aMain;
96 aMain = GetAddressByName ("_main", true);
97 if (aMain != NO_ADDRESS)
98 return aMain;
100 return 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)
107 m_pFileName = 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);
120 #endif
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);
135 #endif
137 if (cputype == 0x7) // i386
138 imgoffs = offset;
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))
148 fclose(fp);
149 fprintf(stderr,"error loading file %s, bad Mach-O magic\n", sName);
150 return false;
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;
159 else
160 machine = MACHINE_PPC;
162 sections.clear();
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;
167 char *strtbl = NULL;
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))
182 case LC_SEGMENT:
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));
189 #endif
190 for (unsigned n = 0; n < BMMH(seg.nsects); n++)
192 struct section sect;
193 fread(&sect, 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));
197 #endif
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));
203 #endif
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);
228 break;
229 case LC_SYMTAB:
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++)
239 struct nlist sym;
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));
244 #endif
246 #ifdef DEBUG_MACHO_LOADER
247 fprintf(stdout, "symtab contains %i symbols\n", BMMH(syms.nsyms));
248 #endif
250 break;
251 case LC_DYSYMTAB:
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));
260 #endif
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));
270 #endif
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");
280 #endif
282 break;
283 default:
284 #ifdef DEBUG_MACHO_LOADER
285 fprintf(stderr, "not handled load command %x\n", BMMH(cmd.cmd));
286 #endif
287 // yep, there's lots of em
288 break;
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);
308 if (!base)
310 fclose(fp);
311 fprintf(stderr,"Cannot allocate memory for copy of image\n");
312 return false;
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);
342 #endif
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);
355 #endif
356 char *name = strtbl + BMMH(symbols[symbol].n_un.n_strx);
357 if (*name == '_') // we want printf not _printf
358 name++;
359 m_SymA[addr] = name;
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);
375 #endif
376 if (*name == '_') // we want main not _main
377 name++;
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");
387 #endif
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));
395 #endif
396 ObjcModule *m = &modules[name];
397 m->name = 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);
404 #endif
405 ObjcClass *cl = &m->classes[name];
406 cl->name = 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));
415 #endif
416 ObjcIvar *iv = &cl->ivars[name];
417 iv->name = name;
418 iv->type = types;
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));
430 #endif
431 ObjcMethod *me = &cl->methods[name];
432 me->name = name;
433 me->types = types;
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();
445 fclose(fp);
446 return true;
449 // Clean up and unload the binary image
450 void MachOBinaryFile::UnLoad()
453 bool MachOBinaryFile::PostLoad(void* handle)
455 return false;
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())
462 return 0;
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
470 // Use linear search
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)
476 return it->first;
477 it++;
479 return NO_ADDRESS;
482 void MachOBinaryFile::AddSymbol(ADDRESS uNative, const char *pName)
484 m_SymA[uNative] = pName;
487 bool MachOBinaryFile::DisplayDetails(const char* fileName, FILE* f
488 /* = stdout */)
490 return false;
493 int MachOBinaryFile::machORead2(short* ps) const
495 unsigned char* p = (unsigned char*)ps;
496 int n;
497 if (machine == MACHINE_PPC)
498 n = (int)(p[1] + (p[0] << 8));
499 else
500 n = (int)(p[0] + (p[1] << 8));
501 return n;
504 int MachOBinaryFile::machORead4(int* pi) const
506 short* p = (short*)pi;
507 int n1 = machORead2(p);
508 int n2 = machORead2(p+1);
509 int n;
510 if (machine == MACHINE_PPC)
511 n = (int) (n2 | (n1 << 16));
512 else
513 n = (int) (n1 | (n2 << 16));
514 return n;
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);
527 else return 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);
539 else return x;
542 unsigned int MachOBinaryFile::BMMH(unsigned long x)
544 if (swap_bytes) return _BMMH(x);
545 else return x;
548 unsigned int MachOBinaryFile::BMMH(long int & x)
550 if (swap_bytes) return _BMMH(x);
551 else return x;
554 signed int MachOBinaryFile::BMMH(signed int x)
556 if (swap_bytes) return _BMMH(x);
557 else return x;
560 unsigned int MachOBinaryFile::BMMH(unsigned int x)
562 if (swap_bytes) return _BMMH(x);
563 else return x;
566 unsigned short MachOBinaryFile::BMMHW(unsigned short x)
568 if (swap_bytes) return _BMMHW(x);
569 else return 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"))
593 return true;
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"))
608 return true;
611 return BinaryFile::isCFStringConstant(uEntry);
614 // Read 2 bytes from given native address
615 int MachOBinaryFile::readNative1(ADDRESS nat)
617 PSectionInfo si = GetSectionInfoByAddr(nat);
618 if (si == 0)
619 si = GetSectionInfo(0);
620 ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
621 return *(char*)host;
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);
631 return n;
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);
641 return n;
644 // Read 8 bytes from given native address
645 QWord MachOBinaryFile::readNative8(ADDRESS nat)
647 int raw[2];
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);
652 #else
653 // Source and host are same endianness
654 raw[0] = readNative4(nat);
655 raw[1] = readNative4(nat+4);
656 #endif
657 return *(QWord*)raw;
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)
672 int raw[2];
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);
677 #else
678 // Source and host are same endianness
679 raw[0] = readNative4(nat);
680 raw[1] = readNative4(nat+4);
681 #endif
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
698 return machine;
701 bool MachOBinaryFile::isLibrary() const
703 return false;
706 ADDRESS MachOBinaryFile::getImageBase()
708 return loaded_addr;
711 size_t MachOBinaryFile::getImageSize()
713 return loaded_size;
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
733 extern "C"
735 #ifdef _WIN32
736 __declspec(dllexport)
737 #endif
738 BinaryFile* construct()
740 return new MachOBinaryFile;