X-Git-Url: https://git.saurik.com/ldid.git/blobdiff_plain/af4e57ce334307364381c6c5ecc8a584f6516f27..dede61211e9c6d4384a0eda92c9680f19292ef23:/ldid.cpp diff --git a/ldid.cpp b/ldid.cpp index 7e56f14..7dec246 100644 --- a/ldid.cpp +++ b/ldid.cpp @@ -20,17 +20,21 @@ /* }}} */ #include "minimal/stdlib.h" -#include "minimal/string.h" -#include "minimal/mapping.h" - -extern "C" { -#include "sha1.h" -} #include #include #include +#include +#include + +#include +#include + +#include + +#include + struct fat_header { uint32_t magic; uint32_t nfat_arch; @@ -636,12 +640,6 @@ class FatHeader : } }; -FatHeader Map(const char *path, bool ro = false) { - size_t size; - void *base(map(path, 0, _not(size_t), &size, ro)); - return FatHeader(base, size); -} - template class Pointer { private: @@ -717,10 +715,7 @@ struct CodeDirectory { extern "C" uint32_t hash(uint8_t *k, uint32_t length, uint32_t initval); void sha1(uint8_t *hash, uint8_t *data, size_t size) { - SHA1Context context; - SHA1Reset(&context); - SHA1Input(&context, data, size); - SHA1Result(&context, hash); + SHA1(data, size, hash); } struct CodesignAllocation { @@ -728,14 +723,92 @@ struct CodesignAllocation { uint32_t offset_; uint32_t size_; uint32_t alloc_; + uint32_t align_; - CodesignAllocation(FatMachHeader mach_header, size_t offset, size_t size, size_t alloc) : + CodesignAllocation(FatMachHeader mach_header, size_t offset, size_t size, size_t alloc, size_t align) : mach_header_(mach_header), offset_(offset), size_(size), - alloc_(alloc) + alloc_(alloc), + align_(align) + { + } +}; + +class File { + private: + int file_; + + public: + File() : + file_(-1) + { + } + + ~File() { + if (file_ != -1) + _syscall(close(file_)); + } + + void open(const char *path, bool ro) { + _assert(file_ == -1); + _syscall(file_ = ::open(path, ro ? O_RDONLY : O_RDWR)); + } + + int file() const { + return file_; + } +}; + +class Map { + private: + File file_; + void *data_; + size_t size_; + + void clear() { + if (data_ == NULL) + return; + _syscall(munmap(data_, size_)); + data_ = NULL; + size_ = 0; + } + + public: + Map() : + data_(NULL), + size_(0) { } + + Map(const char *path, bool ro) { + open(path, ro); + } + + ~Map() { + clear(); + } + + void open(const char *path, bool ro) { + clear(); + + file_.open(path, ro); + int file(file_.file()); + + struct stat stat; + _syscall(fstat(file, &stat)); + size_ = stat.st_size; + + _syscall(data_ = mmap(NULL, size_, ro ? PROT_READ : PROT_READ | PROT_WRITE, ro ? MAP_PRIVATE : MAP_SHARED, file, 0)); + } + + void *data() const { + return data_; + } + + size_t size() const { + return size_; + } }; int main(int argc, const char *argv[]) { @@ -775,6 +848,7 @@ int main(int argc, const char *argv[]) { bool timeh(false); uint32_t timev(0); + Map xmlm; const void *xmld(NULL); size_t xmls(0); @@ -833,7 +907,9 @@ int main(int argc, const char *argv[]) { flag_S = true; if (argv[argi][2] != '\0') { const char *xml = argv[argi] + 2; - xmld = map(xml, 0, _not(size_t), &xmls, true); + xmlm.open(xml, true); + xmld = xmlm.data(); + xmls = xmlm.size(); } break; @@ -877,20 +953,20 @@ int main(int argc, const char *argv[]) { _foreach (file, files) try { const char *path(file.c_str()); const char *base = strrchr(path, '/'); - char *temp(NULL), *dir; + std::string dir; if (base != NULL) - dir = strndup_(path, base++ - path + 1); - else { - dir = strdup(""); + dir.assign(path, base++ - path + 1); + else base = path; - } const char *name(flag_I ?: base); + char *temp(NULL); if (flag_r) { uint32_t clip(0); { - FatHeader fat_header(Map(path)); + Map mapping(path, false); + FatHeader fat_header(mapping.data(), mapping.size()); _foreach (mach_header, fat_header.GetMachHeaders()) { if (flag_A) { if (mach_header.GetCPUType() != flag_CPUType) @@ -950,7 +1026,8 @@ int main(int argc, const char *argv[]) { } if (flag_S) { - FatHeader source(Map(path)); + Map input(path, true); + FatHeader source(input.data(), input.size()); size_t offset(0); @@ -966,8 +1043,6 @@ int main(int argc, const char *argv[]) { continue; } - mach_header->flags = mach_header.Swap(mach_header.Swap(mach_header->flags) | MH_DYLDLINK); - size_t size(_not(size_t)); { _foreach (load_command, mach_header.GetLoadCommands()) { uint32_t cmd(mach_header.Swap(load_command->cmd)); @@ -1006,17 +1081,23 @@ int main(int argc, const char *argv[]) { size_t normal((size + 0x1000 - 1) / 0x1000); alloc = Align(alloc + (special + normal) * 0x14, 16); - offset = Align(offset, 4096); - allocations.push_back(CodesignAllocation(mach_header, offset, size, alloc)); + auto *fat_arch(mach_header.GetFatArch()); + uint32_t align(fat_arch == NULL ? 0 : source.Swap(fat_arch->align)); + offset = Align(offset, 1 << align); + + allocations.push_back(CodesignAllocation(mach_header, offset, size, alloc, align)); offset += size + alloc; + offset = Align(offset, 16); } } - asprintf(&temp, "%s.%s.cs", dir, base); + asprintf(&temp, "%s.%s.cs", dir.c_str(), base); fclose(fopen(temp, "w+")); - truncate(temp, offset); + _syscall(truncate(temp, offset)); - void *file(map(temp, 0, offset, NULL, false)); + Map output(temp, false); + _assert(output.size() == offset); + void *file(output.data()); memset(file, 0, offset); fat_arch *fat_arch; @@ -1040,7 +1121,7 @@ int main(int argc, const char *argv[]) { fat_arch->cpusubtype = Swap(source->cpusubtype); fat_arch->offset = Swap(allocation.offset_); fat_arch->size = Swap(align + allocation.alloc_); - fat_arch->align = Swap(0xc); + fat_arch->align = Swap(allocation.align_); ++fat_arch; } @@ -1068,20 +1149,30 @@ int main(int argc, const char *argv[]) { signature->dataoff = mach_header.Swap(align); signature->datasize = mach_header.Swap(allocation.alloc_); - _foreach (segment, mach_header.GetSegments("__LINKEDIT")) - segment->filesize = mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff)); - _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) - segment->filesize = mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff)); + _foreach (segment, mach_header.GetSegments("__LINKEDIT")) { + size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff))); + segment->filesize = size; + segment->vmsize = Align(size, 0x1000); + } + + _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) { + size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff))); + segment->filesize = size; + segment->vmsize = Align(size, 0x1000); + } } } if (flag_p) printf("path%zu='%s'\n", filei, file.c_str()); - FatHeader fat_header(Map(temp == NULL ? path : temp, !(flag_R || flag_T || flag_s || flag_S || flag_O || flag_D))); - struct linkedit_data_command *signature(NULL); + Map mapping(temp == NULL ? path : temp, !(flag_R || flag_T || flag_s || flag_S || flag_O || flag_D)); + FatHeader fat_header(mapping.data(), mapping.size()); _foreach (mach_header, fat_header.GetMachHeaders()) { + struct linkedit_data_command *signature(NULL); + struct encryption_info_command *encryption(NULL); + if (flag_A) { if (mach_header.GetCPUType() != flag_CPUType) continue; @@ -1128,6 +1219,8 @@ int main(int argc, const char *argv[]) { load_command->cmd = mach_header.Swap(LC_LOAD_DYLIB); else if (cmd == LC_CODE_SIGNATURE) signature = reinterpret_cast(load_command); + else if (cmd == LC_ENCRYPTION_INFO) + encryption = reinterpret_cast(load_command); else if (cmd == LC_UUID) { volatile struct uuid_command *uuid_command(reinterpret_cast(load_command)); @@ -1157,18 +1250,20 @@ int main(int argc, const char *argv[]) { dylib_command->dylib.timestamp = mach_header.Swap(timed); } - } else if (cmd == LC_ENCRYPTION_INFO) { - volatile struct encryption_info_command *encryption_info_command(reinterpret_cast(load_command)); + } + } - if (flag_D) - encryption_info_command->cryptid = mach_header.Swap(0); + if (flag_d) { + _assert(encryption != NULL); - if (flag_d) { - printf("cryptoff=0x%x\n", mach_header.Swap(encryption_info_command->cryptoff)); - printf("cryptsize=0x%x\n", mach_header.Swap(encryption_info_command->cryptsize)); - printf("cryptid=0x%x\n", mach_header.Swap(encryption_info_command->cryptid)); - } - } + printf("cryptoff=0x%x\n", mach_header.Swap(encryption->cryptoff)); + printf("cryptsize=0x%x\n", mach_header.Swap(encryption->cryptsize)); + printf("cryptid=0x%x\n", mach_header.Swap(encryption->cryptid)); + } + + if (flag_D) { + _assert(encryption != NULL); + encryption->cryptid = mach_header.Swap(0); } if (flag_e) { @@ -1317,7 +1412,7 @@ int main(int argc, const char *argv[]) { size_t size = fat_header.GetSize(); char *copy; - asprintf(©, "%s.%s.cp", dir, base); + asprintf(©, "%s.%s.cp", dir.c_str(), base); FILE *file = fopen(copy, "w+"); size_t writ = fwrite(top, 1, size, file); _assert(writ == size); @@ -1338,7 +1433,6 @@ int main(int argc, const char *argv[]) { free(temp); } - free(dir); ++filei; } catch (const char *) { ++filee;