this repo has no description
at fixPythonPipStalling 182 lines 3.8 kB view raw
1#include <mach-o/loader.h> 2#include <mach-o/fat.h> 3#include <iostream> 4#include <stdexcept> 5#include <sstream> 6#include <cstring> 7#include <stdlib.h> 8#include <unistd.h> 9#include <fcntl.h> 10#include <errno.h> 11 12#define CPU_ARCH_ABI64 0x01000000 13 14static void load(const char* path); 15 16int main(int argc, const char** argv) 17{ 18 if (argc != 2) 19 { 20 std::cerr << "Prints the name of the ELF library referenced by given Mach-O library.\n\n" 21 "Usage: print_wrapped_elf <mach-o file>\n"; 22 return 1; 23 } 24 25 try 26 { 27 load(argv[1]); 28 } 29 catch (const std::exception& e) 30 { 31 std::cerr << "When processing " << argv[1] << ": " << e.what() << std::endl; 32 return 1; 33 } 34 return 0; 35} 36 37static void throwErrno(const char* msg) 38{ 39 std::stringstream ss; 40 ss << msg << ": " << strerror(errno); 41 throw std::runtime_error(ss.str()); 42} 43 44template<typename mhdr_type, typename section_type, int seg_cmd, typename segment_type> 45void parseMachO(int fd) 46{ 47 mhdr_type header; 48 uint8_t* cmds; 49 unsigned long fat_offset; 50 51 fat_offset = lseek(fd, 0, SEEK_CUR); 52 53 if (read(fd, &header, sizeof(header)) != sizeof(header)) 54 throwErrno("Cannot read the mach header"); 55 56 cmds = new uint8_t[header.sizeofcmds]; 57 58 if (read(fd, cmds, header.sizeofcmds) != header.sizeofcmds) 59 throwErrno("Cannot read loader commands"); 60 61 for (uint32_t i = 0, p = 0; i < header.ncmds; i++) 62 { 63 load_command* lc; 64 65 lc = (load_command*) &cmds[p]; 66 67 if (lc->cmd == seg_cmd) 68 { 69 segment_type* seg = (segment_type*) lc; 70 71 if (strcmp(seg->segname, "__TEXT") == 0) 72 { 73 section_type* sect = (section_type*) (seg+1); 74 section_type* end = (section_type*) (&cmds[p + lc->cmdsize]); 75 76 while (sect < end) 77 { 78 if (strcmp(sect->sectname, "__elfname") == 0) 79 { 80 char* text; 81 82 if (sect->size > 100) 83 throw std::runtime_error("__TEXT,__elfname section has unusual length"); 84 85 text = new char[sect->size]; 86 87 if (pread(fd, text, sect->size, sect->offset + fat_offset) != sect->size) 88 throwErrno("Cannot read __elfname section"); 89 90 if (text[sect->size-1] != 0) 91 throw std::runtime_error("__TEXT,__elfname section contents don't look like a string"); 92 93 std::cout << text << std::endl; 94 delete [] text; 95 } 96 sect++; 97 } 98 } 99 } 100 101 p += lc->cmdsize; 102 } 103 104 delete [] cmds; 105} 106 107void parseMachO32(int fd) 108{ 109 parseMachO<mach_header, section, LC_SEGMENT, segment_command>(fd); 110} 111 112void parseMachO64(int fd) 113{ 114 parseMachO<mach_header_64, section_64, LC_SEGMENT_64, segment_command_64>(fd); 115} 116 117static void load(const char* path) 118{ 119 int fd; 120 uint32_t magic; 121 122 fd = open(path, O_RDONLY); 123 if (fd == -1) 124 throwErrno("Cannot open the file"); 125 126 if (read(fd, &magic, sizeof(magic)) != sizeof(magic)) 127 throwErrno("Cannot read file header"); 128 129 if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) 130 { 131 lseek(fd, 0, SEEK_SET); 132 parseMachO64(fd); 133 } 134 else if (magic == MH_MAGIC || magic == MH_CIGAM) 135 { 136 lseek(fd, 0, SEEK_SET); 137 parseMachO32(fd); 138 } 139 else if (magic == FAT_MAGIC || magic == FAT_CIGAM) 140 { 141 struct fat_header fhdr; 142 const bool swap = magic == FAT_CIGAM; 143 144#define SWAP32(x) x = __bswap_32(x) 145 146 if (read(fd, &fhdr.nfat_arch, sizeof(fhdr.nfat_arch)) != sizeof(fhdr.nfat_arch)) 147 throwErrno("Cannot read file header"); 148 149 if (swap) 150 SWAP32(fhdr.nfat_arch); 151 152 for (uint32_t i = 0; i < fhdr.nfat_arch; i++) 153 { 154 struct fat_arch arch; 155 156 if (read(fd, &arch, sizeof(arch)) != sizeof(arch)) 157 throwErrno("Cannot read fat_arch header"); 158 159 if (swap) 160 { 161 SWAP32(arch.cputype); 162 SWAP32(arch.cpusubtype); 163 SWAP32(arch.offset); 164 SWAP32(arch.size); 165 SWAP32(arch.align); 166 } 167 168 if (lseek(fd, arch.offset, SEEK_SET) == -1) 169 throwErrno("Cannot seek to selected arch in fat"); 170 171 if (arch.cputype & CPU_ARCH_ABI64) 172 parseMachO64(fd); 173 else 174 parseMachO32(fd); 175 176 break; 177 } 178 } 179 180 ::close(fd); 181} 182