/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
#include <mach-o/reloc.h>
+#include <mach-o/fat.h>
+#include <mach-o/stab.h>
+#include <mach-o/reloc.h>
+#include <mach-o/ppc/reloc.h>
+#include <mach-o/x86_64/reloc.h>
#include <mach/machine.h>
-// suport older versions of mach-o/loader.h
-#ifndef LC_UUID
-#define LC_UUID 0x1b
-struct uuid_command {
- uint32_t cmd; /* LC_UUID */
- uint32_t cmdsize; /* sizeof(struct uuid_command) */
- uint8_t uuid[16]; /* the 128-bit uuid */
-};
-#endif
-
-
#include "FileAbstraction.hpp"
#include "Architectures.hpp"
+// stuff that will eventually go away once newer cctools headers are widespread
+#ifndef LC_LAZY_LOAD_DYLIB
+ #define LC_LAZY_LOAD_DYLIB 0x20
+#endif
+#ifndef S_LAZY_DYLIB_SYMBOL_POINTERS
+ #define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10
+#endif
+#ifndef CPU_SUBTYPE_ARM_V5TEJ
+ #define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7)
+#endif
+#ifndef CPU_SUBTYPE_ARM_XSCALE
+ #define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8)
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7
+ #define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9)
+#endif
+#ifndef N_ARM_THUMB_DEF
+ #define N_ARM_THUMB_DEF 0x0008
+#endif
+enum reloc_type_arm
+{
+ ARM_RELOC_VANILLA, /* generic relocation as discribed above */
+ ARM_RELOC_PAIR, /* the second relocation entry of a pair */
+ ARM_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ ARM_RELOC_LOCAL_SECTDIFF, /* like ARM_RELOC_SECTDIFF, but the symbol
+ referenced was local. */
+ ARM_RELOC_PB_LA_PTR,/* prebound lazy pointer */
+ ARM_RELOC_BR24, /* 24 bit branch displacement (to a word address) */
+ ARM_THUMB_RELOC_BR22, /* 22 bit branch displacement (to a half-word
+ address) */
+};
+
+#ifndef LC_ENCRYPTION_INFO
+ #define LC_ENCRYPTION_INFO 0x21
+ struct encryption_info_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t cryptoff; /* file offset of encrypted range */
+ uint32_t cryptsize; /* file size of encrypted range */
+ uint32_t cryptid; /* which enryption system, 0 means not-encrypted yet */
+ };
+#endif
//
void set_cmdsize(uint32_t value) INLINE { E::set32(segment.fields.cmdsize, value); }
const char* segname() const INLINE { return segment.fields.segname; }
- void set_segname(const char* value) INLINE { memcpy(&segment.fields.segname, value, 16); }
+ void set_segname(const char* value) INLINE { strncpy(segment.fields.segname, value, 16); }
uint64_t vmaddr() const INLINE { return P::getP(segment.fields.vmaddr); }
void set_vmaddr(uint64_t value) INLINE { P::setP(segment.fields.vmaddr, value); }
class macho_section {
public:
const char* sectname() const INLINE { return section.fields.sectname; }
- void set_sectname(const char* value) INLINE { memcpy(§ion.fields.sectname, value, 16); }
+ void set_sectname(const char* value) INLINE { strncpy(section.fields.sectname, value, 16); }
const char* segname() const INLINE { return section.fields.segname; }
- void set_segname(const char* value) INLINE { memcpy(§ion.fields.segname, value, 16); }
+ void set_segname(const char* value) INLINE { strncpy(section.fields.segname, value, 16); }
uint64_t addr() const INLINE { return P::getP(section.fields.addr); }
void set_addr(uint64_t value) INLINE { P::setP(section.fields.addr, value); }
};
+
+
+//
+// mach-o module table entry (for compatibility with old ld/dyld)
+//
+template <typename P> struct macho_dylib_module_content {};
+template <> struct macho_dylib_module_content<Pointer32<BigEndian> > { struct dylib_module fields; };
+template <> struct macho_dylib_module_content<Pointer32<LittleEndian> > { struct dylib_module fields; };
+template <> struct macho_dylib_module_content<Pointer64<BigEndian> > { struct dylib_module_64 fields; };
+template <> struct macho_dylib_module_content<Pointer64<LittleEndian> > { struct dylib_module_64 fields; };
+
+template <typename P>
+class macho_dylib_module {
+public:
+ uint32_t module_name() const INLINE { return E::get32(module.fields.module_name); }
+ void set_module_name(uint32_t value) INLINE { E::set32(module.fields.module_name, value); }
+
+ uint32_t iextdefsym() const INLINE { return E::get32(module.fields.iextdefsym); }
+ void set_iextdefsym(uint32_t value) INLINE { E::set32(module.fields.iextdefsym, value); }
+
+ uint32_t nextdefsym() const INLINE { return E::get32(module.fields.nextdefsym); }
+ void set_nextdefsym(uint32_t value) INLINE { E::set32(module.fields.nextdefsym, value); }
+
+ uint32_t irefsym() const INLINE { return E::get32(module.fields.irefsym); }
+ void set_irefsym(uint32_t value) INLINE { E::set32(module.fields.irefsym, value); }
+
+ uint32_t nrefsym() const INLINE { return E::get32(module.fields.nrefsym); }
+ void set_nrefsym(uint32_t value) INLINE { E::set32(module.fields.nrefsym, value); }
+
+ uint32_t ilocalsym() const INLINE { return E::get32(module.fields.ilocalsym); }
+ void set_ilocalsym(uint32_t value) INLINE { E::set32(module.fields.ilocalsym, value); }
+
+ uint32_t nlocalsym() const INLINE { return E::get32(module.fields.nlocalsym); }
+ void set_nlocalsym(uint32_t value) INLINE { E::set32(module.fields.nlocalsym, value); }
+
+ uint32_t iextrel() const INLINE { return E::get32(module.fields.iextrel); }
+ void set_iextrel(uint32_t value) INLINE { E::set32(module.fields.iextrel, value); }
+
+ uint32_t nextrel() const INLINE { return E::get32(module.fields.nextrel); }
+ void set_nextrel(uint32_t value) INLINE { E::set32(module.fields.nextrel, value); }
+
+ uint16_t iinit() const INLINE { return E::get32(module.fields.iinit_iterm) & 0xFFFF; }
+ uint16_t iterm() const INLINE { return E::get32(module.fields.iinit_iterm) > 16; }
+ void set_iinit_iterm(uint16_t init, uint16_t term) INLINE { E::set32(module.fields.iinit_iterm, (term<<16) | (init &0xFFFF)); }
+
+ uint16_t ninit() const INLINE { return E::get32(module.fields.ninit_nterm) & 0xFFFF; }
+ uint16_t nterm() const INLINE { return E::get32(module.fields.ninit_nterm) > 16; }
+ void set_ninit_nterm(uint16_t init, uint16_t term) INLINE { E::set32(module.fields.ninit_nterm, (term<<16) | (init &0xFFFF)); }
+
+ uint64_t objc_module_info_addr() const INLINE { return P::getP(module.fields.objc_module_info_addr); }
+ void set_objc_module_info_addr(uint64_t value) INLINE { P::setP(module.fields.objc_module_info_addr, value); }
+
+ uint32_t objc_module_info_size() const INLINE { return E::get32(module.fields.objc_module_info_size); }
+ void set_objc_module_info_size(uint32_t value) INLINE { E::set32(module.fields.objc_module_info_size, value); }
+
+
+ typedef typename P::E E;
+private:
+ macho_dylib_module_content<P> module;
+};
+
+
+//
+// mach-o dylib_reference entry
+//
+template <typename P>
+class macho_dylib_reference {
+public:
+ uint32_t isym() const INLINE { return E::getBits(fields, 0, 24); }
+ void set_isym(uint32_t value) INLINE { E::setBits(fields, value, 0, 24); }
+
+ uint8_t flags() const INLINE { return E::getBits(fields, 24, 8); }
+ void set_flags(uint8_t value) INLINE { E::setBits(fields, value, 24, 8); }
+
+ typedef typename P::E E;
+private:
+ uint32_t fields;
+};
+
+
+
+//
+// mach-o two-level hints load command
+//
+template <typename P>
+class macho_dylib_table_of_contents {
+public:
+ uint32_t symbol_index() const INLINE { return E::get32(fields.symbol_index); }
+ void set_symbol_index(uint32_t value) INLINE { E::set32(fields.symbol_index, value); }
+
+ uint32_t module_index() const INLINE { return E::get32(fields.module_index); }
+ void set_module_index(uint32_t value) INLINE { E::set32(fields.module_index, value); }
+
+ typedef typename P::E E;
+private:
+ dylib_table_of_contents fields;
+};
+
+
+
//
// mach-o two-level hints load command
//
};
+//
+// mach-o misc data
+//
+template <typename P>
+class macho_linkedit_data_command {
+public:
+ uint32_t cmd() const INLINE { return E::get32(fields.cmd); }
+ void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); }
+
+ uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); }
+ void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); }
+
+ uint32_t dataoff() const INLINE { return E::get32(fields.dataoff); }
+ void set_dataoff(uint32_t value) INLINE { E::set32(fields.dataoff, value); }
+
+ uint32_t datasize() const INLINE { return E::get32(fields.datasize); }
+ void set_datasize(uint32_t value)INLINE { E::set32(fields.datasize, value); }
+
+
+ typedef typename P::E E;
+private:
+ struct linkedit_data_command fields;
+};
+
+
+//
+// mach-o rpath
+//
+template <typename P>
+class macho_rpath_command {
+public:
+ uint32_t cmd() const INLINE { return E::get32(fields.cmd); }
+ void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); }
+
+ uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); }
+ void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); }
+
+ uint32_t path_offset() const INLINE { return E::get32(fields.path.offset); }
+ void set_path_offset(uint32_t value) INLINE { E::set32(fields.path.offset, value); }
+
+ const char* path() const INLINE { return (const char*)&fields + path_offset(); }
+ void set_path_offset() INLINE { set_path_offset(sizeof(fields)); }
+
+
+ typedef typename P::E E;
+private:
+ struct rpath_command fields;
+};
+
//
void set_r_type(uint8_t x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 4, 4); E::set32(other, temp); }
uint32_t r_address() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 8, 24); }
- void set_r_address(uint32_t x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 8, 24); E::set32(other, temp); }
+ void set_r_address(uint32_t x) { if ( x > 0x00FFFFFF ) throw "scattered reloc r_address too large";
+ uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 8, 24); E::set32(other, temp); }
uint32_t r_value() const INLINE { return E::get32(value); }
void set_r_value(uint32_t x) INLINE { E::set32(value, x); }
uint32_t r_other() const INLINE { return other; }
+ void set_r_length() INLINE { set_r_length((sizeof(typename P::uint_t)==8) ? 3 : 2); }
+
typedef typename P::E E;
private:
uint32_t other;
+//
+// mach-o encyrption info load command
+//
+template <typename P>
+class macho_encryption_info_command {
+public:
+ uint32_t cmd() const INLINE { return E::get32(fields.cmd); }
+ void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); }
+
+ uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); }
+ void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); }
+
+ uint32_t cryptoff() const INLINE { return E::get32(fields.cryptoff); }
+ void set_cryptoff(uint32_t value) INLINE { E::set32(fields.cryptoff, value); }
+
+ uint32_t cryptsize() const INLINE { return E::get32(fields.cryptsize); }
+ void set_cryptsize(uint32_t value) INLINE { E::set32(fields.cryptsize, value); }
+
+ uint32_t cryptid() const INLINE { return E::get32(fields.cryptid); }
+ void set_cryptid(uint32_t value) INLINE { E::set32(fields.cryptid, value); }
+
+ typedef typename P::E E;
+private:
+ encryption_info_command fields;
+};