this repo has no description
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