-/* JocStrap - Java/Objective-C Bootstrap
- * Copyright (C) 2007 Jay Freeman (saurik)
+/* ldid - (Mach-O) Link-Loader Identity Editor
+ * Copyright (C) 2007-2010 Jay Freeman (saurik)
*/
/*
#define MH_MAGIC 0xfeedface
#define MH_CIGAM 0xcefaedfe
+#define MH_MAGIC_64 0xfeedfacf
+#define MH_CIGAM_64 0xcffaedfe
+
#define MH_DYLDLINK 0x4
#define MH_EXECUTE 0x2
uint32_t cmdsize;
} _packed;
-#define LC_REQ_DYLD 0x80000000
+#define LC_REQ_DYLD uint32_t(0x80000000)
-#define LC_SEGMENT 0x01
-#define LC_LOAD_DYLIB 0x0c
-#define LC_ID_DYLIB 0x0d
-#define LC_UUID 0x1b
-#define LC_CODE_SIGNATURE 0x1d
-#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD)
+#define LC_SEGMENT uint32_t(0x01)
+#define LC_LOAD_DYLIB uint32_t(0x0c)
+#define LC_ID_DYLIB uint32_t(0x0d)
+#define LC_UUID uint32_t(0x1b)
+#define LC_CODE_SIGNATURE uint32_t(0x1d)
+#define LC_REEXPORT_DYLIB uint32_t(0x1f | LC_REQ_DYLD)
struct dylib {
uint32_t name;
return Swap_(static_cast<uint32_t>(value));
}
+bool little_(true);
+
uint16_t Swap(uint16_t value) {
- return true ? Swap_(value) : value;
+ return little_ ? Swap_(value) : value;
}
uint32_t Swap(uint32_t value) {
- return true ? Swap_(value) : value;
+ return little_ ? Swap_(value) : value;
}
int16_t Swap(int16_t value) {
private:
void *base_;
size_t size_;
- mach_header *mach_header_;
+
+ struct mach_header *mach_header_;
+ struct load_command *load_command_;
+
bool swapped_;
+ bool bits64_;
public:
uint16_t Swap(uint16_t value) const {
}
found:
- if (Swap(mach_header_->magic) == MH_CIGAM)
- swapped_ = !swapped_;
- else _assert(Swap(mach_header_->magic) == MH_MAGIC);
+ switch (Swap(mach_header_->magic)) {
+ case MH_CIGAM:
+ swapped_ = !swapped_;
+ case MH_MAGIC:
+ bits64_ = false;
+ break;
+
+ case MH_CIGAM_64:
+ swapped_ = !swapped_;
+ case MH_MAGIC_64:
+ bits64_ = true;
+ break;
+
+ default:
+ _assert(false);
+ }
+
+ void *post = mach_header_ + 1;
+ if (bits64_)
+ post = (uint32_t *) post + 1;
+ load_command_ = (struct load_command *) post;
_assert(
Swap(mach_header_->filetype) == MH_EXECUTE ||
return base_;
}
- size_t GetSize() {
+ size_t GetSize() const {
return size_;
}
+ uint32_t GetCPUType() const {
+ return Swap(mach_header_->cputype);
+ }
+
+ uint16_t GetCPUSubtype() const {
+ return Swap(mach_header_->cpusubtype) & 0xff;
+ }
+
std::vector<struct load_command *> GetLoadCommands() {
std::vector<struct load_command *> load_commands;
- struct load_command *load_command = reinterpret_cast<struct load_command *>(mach_header_ + 1);
+ struct load_command *load_command = load_command_;
for (uint32_t cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) {
load_commands.push_back(load_command);
load_command = (struct load_command *) ((uint8_t *) load_command + Swap(load_command->cmdsize));
}
};
-#define CSMAGIC_CODEDIRECTORY 0xfade0c02
-#define CSMAGIC_EMBEDDED_SIGNATURE 0xfade0cc0
-#define CSMAGIC_ENTITLEMENTS 0xfade7171
+#define CSMAGIC_CODEDIRECTORY uint32_t(0xfade0c02)
+#define CSMAGIC_EMBEDDED_SIGNATURE uint32_t(0xfade0cc0)
+#define CSMAGIC_ENTITLEMENTS uint32_t(0xfade7171)
-#define CSSLOT_CODEDIRECTORY 0
-#define CSSLOT_REQUIREMENTS 2
-#define CSSLOT_ENTITLEMENTS 5
+#define CSSLOT_CODEDIRECTORY uint32_t(0)
+#define CSSLOT_REQUIREMENTS uint32_t(2)
+#define CSSLOT_ENTITLEMENTS uint32_t(5)
struct BlobIndex {
uint32_t type;
}
int main(int argc, const char *argv[]) {
+ union {
+ uint16_t word;
+ uint8_t byte[2];
+ } endian = {1};
+
+ little_ = endian.byte[0];
+
bool flag_R(false);
bool flag_t(false);
bool flag_p(false);
size_t size = _not(size_t);
const char *arch; {
Framework framework(path);
- framework->flags |= MH_DYLDLINK;
+ framework->flags = framework.Swap(framework.Swap(framework->flags) | MH_DYLDLINK);
_foreach (load_command, framework.GetLoadCommands()) {
uint32_t cmd(framework.Swap((*load_command)->cmd));
if (size == _not(size_t))
size = framework.GetSize();
- switch (framework->cputype) {
- case 12: switch (framework->cpusubtype) {
+ switch (framework.GetCPUType()) {
+ case 7: switch (framework.GetCPUSubtype()) {
+ case 3: arch = "i386"; break;
+ default: arch = NULL; break;
+ } break;
+
+ case 12: switch (framework.GetCPUSubtype()) {
case 0: arch = "arm"; break;
case 6: arch = "armv6"; break;
+ case 9: arch = "armv7"; break;
+ default: arch = NULL; break;
+ } break;
+
+ case 18: switch (framework.GetCPUSubtype()) {
+ case 10: arch = "ppc7400"; break;
+ default: arch = NULL; break;
+ } break;
+
+ case 16777223: switch (framework.GetCPUSubtype()) {
+ case 3: arch = "x86_64"; break;
+ default: arch = NULL; break;
+ } break;
+
+ case 16777234: switch (framework.GetCPUSubtype()) {
+ case 0: arch = "ppc64"; break;
default: arch = NULL; break;
} break;
if (woffset != _not(uintptr_t)) {
Pointer<uint32_t> wvalue(framework.GetPointer<uint32_t>(woffset));
if (wvalue == NULL)
- printf("(null) %p\n", woffset);
+ printf("(null) %p\n", reinterpret_cast<void *>(woffset));
else
printf("0x%.08x\n", *wvalue);
}
offset += sizeof(struct CodeDirectory);
directory->blob.magic = Swap(CSMAGIC_CODEDIRECTORY);
- directory->version = Swap(0x00020001);
- directory->flags = Swap(0);
+ directory->version = Swap(uint32_t(0x00020001));
+ directory->flags = Swap(uint32_t(0));
directory->codeLimit = Swap(data);
directory->hashSize = 0x14;
directory->hashType = 0x01;
directory->spare1 = 0x00;
directory->pageSize = 0x0c;
- directory->spare2 = Swap(0);
+ directory->spare2 = Swap(uint32_t(0));
directory->identOffset = Swap(offset - begin);
strcpy(reinterpret_cast<char *>(blob + offset), base);