/* }}} */
#include "minimal/stdlib.h"
-#include "minimal/string.h"
-#include "minimal/mapping.h"
-
-extern "C" {
-#include "sha1.h"
-}
#include <cstring>
#include <string>
#include <vector>
+#include <dlfcn.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <openssl/sha.h>
+
+#include <plist/plist.h>
+
struct fat_header {
uint32_t magic;
uint32_t nfat_arch;
}
};
-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 <typename Target_>
class Pointer {
private:
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 {
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[]) {
bool timeh(false);
uint32_t timev(0);
+ Map xmlm;
const void *xmld(NULL);
size_t xmls(0);
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;
_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)
}
if (flag_S) {
- FatHeader source(Map(path));
+ Map input(path, true);
+ FatHeader source(input.data(), input.size());
size_t offset(0);
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));
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;
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;
}
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;
load_command->cmd = mach_header.Swap(LC_LOAD_DYLIB);
else if (cmd == LC_CODE_SIGNATURE)
signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
+ else if (cmd == LC_ENCRYPTION_INFO)
+ encryption = reinterpret_cast<struct encryption_info_command *>(load_command);
else if (cmd == LC_UUID) {
volatile struct uuid_command *uuid_command(reinterpret_cast<struct uuid_command *>(load_command));
dylib_command->dylib.timestamp = mach_header.Swap(timed);
}
- } else if (cmd == LC_ENCRYPTION_INFO) {
- volatile struct encryption_info_command *encryption_info_command(reinterpret_cast<struct encryption_info_command *>(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) {
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);
free(temp);
}
- free(dir);
++filei;
} catch (const char *) {
++filee;