From 90516c5a7be5457813313d89ecf8ae9d3c0d1708 Mon Sep 17 00:00:00 2001 From: Jude Taylor Date: Tue, 16 Aug 2016 12:45:55 -0700 Subject: [PATCH] switch to mmap strategy --- .../resolve-system-dependencies.cc | 149 ++++++++---------- 1 file changed, 68 insertions(+), 81 deletions(-) diff --git a/src/resolve-system-dependencies/resolve-system-dependencies.cc b/src/resolve-system-dependencies/resolve-system-dependencies.cc index 4b2f55f09..216be1210 100644 --- a/src/resolve-system-dependencies/resolve-system-dependencies.cc +++ b/src/resolve-system-dependencies/resolve-system-dependencies.cc @@ -6,9 +6,13 @@ #include #include #include +#include +#include #include #include +#define DO_SWAP(x, y) ((x) ? OSSwapInt32(y) : (y)) + using namespace nix; static auto cacheDir = Path{}; @@ -31,76 +35,59 @@ void writeCacheFile(const Path & file, std::set & deps) { fp.close(); } -std::string findDylibName(FILE *obj_file, struct load_command cmd) { - fpos_t pos; - fgetpos(obj_file, &pos); - struct dylib_command dylc; - dylc.cmd = cmd.cmd; - dylc.cmdsize = cmd.cmdsize; - fread(&dylc.dylib, sizeof(struct dylib), 1, obj_file); +std::string findDylibName(bool should_swap, ptrdiff_t dylib_command_start) { + struct dylib_command *dylc = (struct dylib_command*)dylib_command_start; - char *dylib_name = (char*)calloc(cmd.cmdsize, sizeof(char)); - fseek(obj_file, - // offset is calculated from the beginning of the load command, which is two - // uint32_t's backwards - dylc.dylib.name.offset - (sizeof(uint32_t) * 2) + pos, - SEEK_SET); - fread(dylib_name, sizeof(char), cmd.cmdsize, obj_file); - fseek(obj_file, pos, SEEK_SET); - return std::string(dylib_name); -} - -bool seekMach64Blob(FILE *obj_file, enum NXByteOrder end) { - struct fat_header head; - fread(&head, sizeof(struct fat_header), 1, obj_file); - swap_fat_header(&head, end); - for(uint32_t narches = 0; narches < head.nfat_arch; narches++) { - struct fat_arch arch; - fread(&arch, sizeof(struct fat_arch), 1, obj_file); - swap_fat_arch(&arch, 1, end); - if(arch.cputype == CPU_TYPE_X86_64) { - fseek(obj_file, arch.offset, SEEK_SET); - return true; - } - } - return false; + return std::string((char*)(dylib_command_start + DO_SWAP(should_swap, dylc->dylib.name.offset))); } std::set runResolver(const Path & filename) { - FILE *obj_file = fopen(filename.c_str(), "rb"); - uint32_t magic; - fread(&magic, sizeof(uint32_t), 1, obj_file); - fseek(obj_file, 0, SEEK_SET); - enum NXByteOrder endianness; - if(magic == 0xBEBAFECA) { - endianness = NX_BigEndian; - if(!seekMach64Blob(obj_file, endianness)) { - std::cerr << "Could not find any mach64 blobs in file " << filename << ", continuing..." << std::endl; + int fd = open(filename.c_str(), O_RDONLY); + struct stat s; + fstat(fd, &s); + void *obj = mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0); + + ptrdiff_t mach64_offset = 0; + + uint32_t magic = ((struct mach_header_64*)obj)->magic; + if(magic == FAT_CIGAM || magic == FAT_MAGIC) { + bool should_swap = magic == FAT_CIGAM; + uint32_t narches = DO_SWAP(should_swap, ((struct fat_header*)obj)->nfat_arch); + + for(uint32_t iter = 0; iter < narches; iter++) { + ptrdiff_t header_offset = (ptrdiff_t)obj + sizeof(struct fat_header); + struct fat_arch* arch = (struct fat_arch*)header_offset; + if(DO_SWAP(should_swap, arch->cputype) == CPU_TYPE_X86_64) { + mach64_offset = (ptrdiff_t)DO_SWAP(should_swap, arch->offset); + break; + } + } + if (mach64_offset == 0) { + printMsg(lvlError, format("Could not find any mach64 blobs in file ‘%1%’, continuing...") % filename); return std::set(); } + } else if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) { + mach64_offset = 0; } - struct mach_header_64 header; - fread(&header, sizeof(struct mach_header_64), 1, obj_file); - if(!(header.magic == MH_MAGIC_64 || header.magic == MH_CIGAM_64)) { - std::cerr << "Not a mach-o object file: " << filename << std::endl; - return std::set(); - } + + struct mach_header_64 *m_header = (struct mach_header_64 *)((ptrdiff_t)obj + mach64_offset); + + bool should_swap = magic == MH_CIGAM_64; + ptrdiff_t cmd_offset = (ptrdiff_t)m_header + sizeof(struct mach_header_64); + std::set libs; - for(uint32_t i = 0; i < header.ncmds; i++) { - struct load_command cmd; - fread(&cmd.cmd, sizeof(cmd.cmd), 1, obj_file); - fread(&cmd.cmdsize, sizeof(cmd.cmdsize), 1, obj_file); - switch(cmd.cmd) { - case LC_LOAD_DYLIB: + for(uint32_t i = 0; i < DO_SWAP(should_swap, m_header->ncmds); i++) { + struct load_command *cmd = (struct load_command*)cmd_offset; + switch(DO_SWAP(should_swap, cmd->cmd)) { case LC_LOAD_UPWARD_DYLIB: + case LC_LOAD_DYLIB: case LC_REEXPORT_DYLIB: - libs.insert(findDylibName(obj_file, cmd)); + libs.insert(findDylibName(should_swap, cmd_offset)); break; } - fseek(obj_file, cmd.cmdsize - (sizeof(uint32_t) * 2), SEEK_CUR); + cmd_offset += DO_SWAP(should_swap, cmd->cmdsize); } - fclose(obj_file); - libs.erase(filename); + return libs; } @@ -165,40 +152,40 @@ std::set getPath(const Path & path) { int main(int argc, char ** argv) { return handleExceptions(argv[0], [&]() { - initNix(); + initNix(); - struct utsname _uname; + struct utsname _uname; - uname(&_uname); + uname(&_uname); - auto cacheParentDir = (format("%1%/dependency-maps") % settings.nixStateDir).str(); + auto cacheParentDir = (format("%1%/dependency-maps") % settings.nixStateDir).str(); - cacheDir = (format("%1%/%2%-%3%-%4%") - % cacheParentDir - % _uname.machine - % _uname.sysname - % _uname.release).str(); + cacheDir = (format("%1%/%2%-%3%-%4%") + % cacheParentDir + % _uname.machine + % _uname.sysname + % _uname.release).str(); - mkdir(cacheParentDir.c_str(), 0755); - mkdir(cacheDir.c_str(), 0755); + mkdir(cacheParentDir.c_str(), 0755); + mkdir(cacheDir.c_str(), 0755); - auto store = openStore(); + auto store = openStore(); - auto drv = store->derivationFromPath(Path(argv[1])); - Strings impurePaths = tokenizeString(get(drv.env, "__impureHostDeps")); + auto drv = store->derivationFromPath(Path(argv[1])); + Strings impurePaths = tokenizeString(get(drv.env, "__impureHostDeps")); - std::set all_paths; + std::set all_paths; - for (auto & path : impurePaths) { - for(auto & p : getPath(path)) { - all_paths.insert(p); - } + for (auto & path : impurePaths) { + for(auto & p : getPath(path)) { + all_paths.insert(p); } + } - std::cout << "extra-chroot-dirs" << std::endl; - for(auto & path : all_paths) { - std::cout << path << std::endl; - } - std::cout << std::endl; + std::cout << "extra-chroot-dirs" << std::endl; + for(auto & path : all_paths) { + std::cout << path << std::endl; + } + std::cout << std::endl; }); }