This commit is contained in:
2021-02-18 10:42:34 +07:00
parent 26c40f9a4c
commit 852129aec7
36 changed files with 6333 additions and 0 deletions

102
data/dyldcache/binary.c Normal file
View File

@ -0,0 +1,102 @@
#include "binary.h"
#include "../mach-o/headers/loader.h"
#include "headers/dyld_cache_format.h"
#define downcast(val, typ) ({ typeof(val) v = (val); typ t = (typ) v; if(t != v) die("out of range %s", #val); t; })
void b_prange_load_dyldcache(struct binary *binary, prange_t pr, const char *name) {
#define _arg name
binary->valid = true;
binary->pointer_size = 4;
binary->dyld = calloc(1, sizeof(*binary->dyld));
binary->valid_range = pr;
if(pr.size < sizeof(*binary->dyld->hdr)) {
die("truncated (no room for dyld cache header)");
}
binary->dyld->hdr = pr.start;
if(memcmp(binary->dyld->hdr->magic, "dyld_", 5)) {
die("not a dyld cache");
}
char *thing = binary->dyld->hdr->magic + sizeof(binary->dyld->hdr->magic) - 7;
if(!memcmp(thing, " armv7", 7)) {
binary->cputype = CPU_TYPE_ARM;
binary->cpusubtype = CPU_SUBTYPE_ARM_V7;
} else if(!memcmp(thing, " armv6", 7)) {
binary->cputype = CPU_TYPE_ARM;
binary->cpusubtype = CPU_SUBTYPE_ARM_V6;
} else {
die("unknown processor in magic: %.6s", thing);
}
if(binary->dyld->hdr->mappingCount > 1000) {
die("insane mapping count: %u", binary->dyld->hdr->mappingCount);
}
binary->nsegments = binary->dyld->hdr->mappingCount;
binary->segments = malloc(sizeof(*binary->segments) * binary->nsegments);
struct shared_file_mapping_np *mappings = rangeconv_off((range_t) {binary, binary->dyld->hdr->mappingOffset, binary->dyld->hdr->mappingCount * sizeof(struct shared_file_mapping_np)}, MUST_FIND).start;
for(uint32_t i = 0; i < binary->dyld->hdr->mappingCount; i++) {
struct data_segment *seg = &binary->segments[i];
seg->vm_range.binary = seg->file_range.binary = binary;
seg->native_segment = &mappings[i];
seg->vm_range.start = downcast(mappings[i].sfm_address, addr_t);
seg->file_range.start = downcast(mappings[i].sfm_file_offset, addr_t);
seg->file_range.size = seg->vm_range.size = downcast(mappings[i].sfm_size, size_t);
}
for(unsigned int i = 0; i < binary->dyld->nmappings; i++) {
struct shared_file_mapping_np *mapping = &binary->dyld->mappings[i];
if(mapping->sfm_file_offset >= pr.size || mapping->sfm_size > pr.size - mapping->sfm_file_offset) {
die("truncated (no room for dyld cache mapping %d)", i);
}
}
#undef _arg
}
void b_dyldcache_load_macho(const struct binary *binary, const char *filename, struct binary *out) {
if(binary == out) {
die("uck");
}
if(binary->dyld->hdr->imagesCount > 1000) {
die("insane images count");
}
struct dyld_cache_image_info *info = rangeconv_off((range_t) {binary, binary->dyld->hdr->imagesOffset, binary->dyld->hdr->imagesCount * sizeof(*info)}, MUST_FIND).start;
for(unsigned int i = 0; i < binary->dyld->hdr->imagesCount; i++) {
char *name = rangeconv_off((range_t) {binary, info[i].pathFileOffset, 128}, MUST_FIND).start;
if(strncmp(name, filename, 128)) {
continue;
}
// we found it
b_prange_load_macho(out, binary->valid_range,range_to_off_range((range_t) {binary, (uint32_t) info[i].address, 0}, MUST_FIND).start, filename);
// look for reexports (maybe blowing the stack)
int count = 0;
CMD_ITERATE(b_mach_hdr(out), cmd) {
if(cmd->cmd == LC_REEXPORT_DYLIB) count++;
}
if(count > 0 && count < 1000) {
out->nreexports = (unsigned int) count;
struct binary *p = out->reexports = malloc(out->nreexports * sizeof(struct binary));
CMD_ITERATE(b_mach_hdr(out), cmd) {
if(cmd->cmd == LC_REEXPORT_DYLIB) {
const char *name = convert_lc_str(cmd, ((struct dylib_command *) cmd)->dylib.name.offset);
b_dyldcache_load_macho(binary, name, p);
p++;
}
}
}
return;
}
die("couldn't find %s in dyld cache", filename);
}
void b_load_dyldcache(struct binary *binary, const char *filename) {
return b_prange_load_dyldcache(binary, load_file(filename, true, NULL), filename);
}

20
data/dyldcache/binary.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include "../binary.h"
#include "../mach-o/binary.h"
struct dyldcache_binary {
struct dyld_cache_header *hdr;
struct shared_file_mapping_np *mappings;
uint32_t nmappings;
struct shared_file_mapping_np *last_sfm;
};
__BEGIN_DECLS
void b_prange_load_dyldcache(struct binary *binary, prange_t range, const char *name);
void b_dyldcache_load_macho(const struct binary *binary, const char *filename, struct binary *out);
void b_load_dyldcache(struct binary *binary, const char *filename);
__END_DECLS

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2006-2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
struct shared_file_mapping_np {
uint64_t sfm_address;
uint64_t sfm_size;
uint64_t sfm_file_offset;
int sfm_max_prot;
int sfm_init_prot;
};
// v1 apparently has some extra gunk at the end, oh well
struct dyld_cache_header
{
char magic[16]; // e.g. "dyld_v0 ppc"
uint32_t mappingOffset; // file offset to first shared_file_mapping_np
uint32_t mappingCount; // number of shared_file_mapping_np entries
uint32_t imagesOffset; // file offset to first dyld_cache_image_info
uint32_t imagesCount; // number of dyld_cache_image_info entries
uint64_t dyldBaseAddress; // base address of dyld when cache was built
};
struct dyld_cache_image_info
{
uint64_t address;
uint64_t modTime;
uint64_t inode;
uint32_t pathFileOffset;
uint32_t pad;
};