Blob


1 /*-
2 * Copyright (c) 2006 Matthias Schmidt <xhr @ giessen.ccc.de>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
27 /* $Id: util.c,v 1.20 2006/09/02 01:29:51 matthias Exp $ */
29 #include "dermob.h"
30 #include "mach.h"
31 #include "defs.h"
32 #include "list.h"
34 #define swap_bo(i) \
35 (((i & 0xFF000000) >> 24) | \
36 ((i & 0x00FF0000) >> 8) | \
37 ((i & 0x0000FF00) << 8) | \
38 ((i & 0x000000FF) << 24))
40 int
41 display_fat_header(struct list *lst, char *buffer, int *roffset)
42 {
43 struct fat_header *fh;
44 struct fat_arch *fa;
45 int offset = 0, i, narch;
47 fh = malloc(sizeof(*fh));
49 if (analyse_fat_header(buffer, &offset, fh) < 0) {
50 free(fh);
51 return(-1);
52 }
54 list_insert_node(lst, fh, 0x1);
56 narch = swapi(fh->nfat_arch);
57 for (i = 0; i < narch; i++) {
58 fa = malloc(sizeof(*fa));
59 analyse_fat_arch(buffer, &offset, fa);
61 list_insert_node(lst, fa, 0x2);
63 if (swapi(fa->size) > size) {
64 printf("Malformed universal binary. Size for one " \
65 "Architecture is larger than the complete binary.\n");
66 exit(1);
67 }
69 if (cpu == swapi(fa->cputype))
70 *roffset = swapi(fa->offset);
71 }
73 return(narch);
74 }
76 int
77 display_mo_header(struct list *lst, char *buffer, int *offset, int *ncmds)
78 {
79 struct mach_header *mh;
81 mh = malloc(sizeof(*mh));
82 if (analyse_mo_header(buffer, offset, mh) < 0) {
83 free(mh);
84 return(-1);
85 }
87 *ncmds = swapi(mh->ncmds);
89 list_insert_node(lst, mh, 0x3);
91 return(1);
92 }
94 void
95 display_load_commands(struct list *lst, char *buffer, int *offset, int ncmds)
96 {
97 struct load_command *ld;
98 struct section *sec;
99 int i, nofx = 0, val = 0, j, offset_old;
101 for (i = 0; i < ncmds; i++) {
102 ld = malloc(sizeof(*ld));
103 analyse_load_command(buffer, offset, ld);
104 list_insert_node(lst, ld, 0x4);
105 offset_old = *offset;
106 val = examine_segmet(buffer, offset, swapi(ld->cmd), swapi(ld->cmdsize), &nofx);
107 if (nofx > 0) {
108 for (j = 0; j < nofx; j++) {
109 sec = malloc(sizeof(*sec));
110 // Skip the segment header
111 if (j == 0) *offset += val;
112 examine_section(buffer, offset, sec);
113 if ((strcmp(sec->segname, "__TEXT") == 0) &&
114 (strcmp(sec->sectname, "__text") == 0)) {
115 text_addr = swapi(sec->addr);
116 text_size = swapi(sec->size);
117 text_offset = swapi(sec->offset);
119 if ((strcmp(sec->segname, "__TEXT") == 0) &&
120 (strcmp(sec->sectname, "__cstring") == 0)) {
121 cs_addr = swapi(sec->addr);
122 cs_size = swapi(sec->size);
123 cs_offset = swapi(sec->offset);
125 if ((strcmp(sec->segname, "__DATA") == 0) &&
126 (strcmp(sec->sectname, "__data") == 0)) {
127 data_addr = swapi(sec->addr);
128 data_size = swapi(sec->size);
129 data_offset = swapi(sec->offset);
131 list_insert_node(lst, sec, 0x5);
133 nofx = 0;
135 /* XXX Have to fix this
137 * Currently val is the length of the segment. We need val to
138 * skip the segment header, if the segment contains sections.
140 * Would be better to adjust offset in examine_segment for all
141 * possible segments (not currently implemented!)
142 */
143 else
144 *offset += swapi(ld->cmdsize);
146 //if (*offset == offset_old)
147 // *offset += swapi(ld->cmdsize);
151 void
152 print_lc_towlevel_hints(struct twolevel_hints_command *two)
154 mprintf(" Offset: %d\n", swapi(two->offset));
155 mprintf(" No of 2level hints: %d\n", swapi(two->nhints));
158 void
159 print_lc_dysymtab(struct dysymtab_command *dsym)
161 mprintf(" ilocalsym: %d\n", swapi(dsym->ilocalsym));
162 mprintf(" nlocalsym: %d\n", swapi(dsym->nlocalsym));
163 mprintf(" iextdefsym: %d\n", swapi(dsym->iextdefsym));
164 mprintf(" nextdefsym: %d\n", swapi(dsym->nextdefsym));
165 mprintf(" iundefsym: %d\n", swapi(dsym->iundefsym));
166 mprintf(" nundefsym: %d\n", swapi(dsym->nundefsym));
167 mprintf(" tocoff: %d\n", swapi(dsym->tocoff));
168 mprintf(" ntoc: %d\n", swapi(dsym->ntoc));
169 mprintf(" modtaboff: %d\n", swapi(dsym->modtaboff));
170 mprintf(" nmodtab: %d\n", swapi(dsym->nmodtab));
171 mprintf(" extrefsymoff: %d\n", swapi(dsym->extrefsymoff));
172 mprintf(" nextrefsyms: %d\n", swapi(dsym->nextrefsyms));
173 mprintf(" indirectsymoff: %d\n", swapi(dsym->indirectsymoff));
174 mprintf(" nindirectsyms: %d\n", swapi(dsym->nindirectsyms));
175 mprintf(" extreloff: %d\n", swapi(dsym->extreloff));
176 mprintf(" nextrel: %d\n", swapi(dsym->nextrel));
177 mprintf(" locreloff: %d\n", swapi(dsym->locreloff));
178 mprintf(" nlocrel: %d\n", swapi(dsym->nlocrel));
181 void
182 print_lc_load_dylib(struct dylib_command *dly)
184 time_t timev;
186 if (dyn_display < 1) {
187 //mprintf(" Name: %s\n", ptr+swapi(dly->dylib.name.offset));
188 timev = swapi(dly->dylib.timestamp);
189 mprintf(" Timestamp: %s", ctime(&timev));
190 mprintf(" Current version: 0x%x\n", swapi(dly->dylib.current_version));
191 mprintf(" Compat version: 0x%x\n", swapi(dly->dylib.compatibility_version));
192 } else {
193 trigger = 0;
194 //mprintf(" + %s\n", ptr+swapi(dly->dylib.name.offset));
195 trigger = 1;
199 void
200 print_lc_symtab(struct symtab_command *symc)
202 mprintf(" Symbol table offset: %d bytes\n", swapi(symc->symoff));
203 mprintf(" Symbol table entries: %d\n", swapi(symc->nsyms));
204 mprintf(" String table offset: %d bytes\n", swapi(symc->stroff));
205 mprintf(" String table size: %d bytes\n", swapi(symc->strsize));
208 void
209 print_lc_segment(struct segment_command *sc)
211 mprintf(" Name: %s\n", sc->segname);
212 mprintf(" VM addr: 0x%.08x\n", swapi(sc->vmaddr));
213 mprintf(" VM size: 0x%.08x\n", swapi(sc->vmsize));
214 mprintf(" VM size: 0x%.08x\n", swapi(sc->vmsize));
215 mprintf(" File offset: 0x%.08x\n", swapi(sc->fileoff));
216 mprintf(" File size: %d bytes\n", swapi(sc->filesize));
217 mprintf(" Max prot: 0x%.08x\n", swapi(sc->maxprot));
218 mprintf(" Init prot: 0x%.08x\n", swapi(sc->initprot));
219 mprintf(" No of sects: %d\n", swapi(sc->nsects));
220 mprintf(" Flags: 0x%.08x\n", swapi(sc->flags));
223 void
224 print_section(struct section *sec)
226 mprintf(" Sectname: %s\n", sec->sectname);
227 mprintf(" VM addr: 0x%.08x\n", swapi(sec->addr));
228 mprintf(" VM size: %d bytes\n", swapi(sec->size));
229 mprintf(" Offset: %d\n", swapi(sec->offset));
230 mprintf("\n");
233 void
234 print_load_command(struct load_command *ld)
236 mprintf(" Command: ");
237 display_cmd_name(swapi(ld->cmd));
238 mprintf(" Command size: %d bytes\n", swapi(ld->cmdsize));
241 void
242 print_mo_header(struct mach_header *mh)
244 mprintf("Magic: 0x%x\n", swapi(mh->magic));
245 mprintf(" CPU Type: ");
246 display_cpu_arch(swapi(mh->cputype));
247 mprintf("\n");
248 mprintf(" Subtype: %d\n", swapi(mh->cpusubtype));
249 mprintf(" Filetype: 0x%x\n", swapi(mh->filetype));
250 mprintf(" No load cmds: %d cmds\n", swapi(mh->ncmds));
251 mprintf(" Size of cmds: %d bytes\n", swapi(mh->sizeofcmds));
252 mprintf(" Flags: 0x%.08x\n", swapi(mh->flags));
253 mprintf("\n");
256 void
257 print_fat_header(struct fat_header *fh)
259 mprintf("Magic: 0x%x\n", swapi(fh->magic));
262 void
263 print_fat_arch(struct fat_arch *fa)
265 /* The fat header is always stored in big-endian byte order, so we have
266 * to swap the bo, if we work on a little-endian machine.
267 */
268 if (bo_a == LE) {
269 mprintf(" CPU Type: (%x) ", swap_bo(fa->cputype));
270 display_cpu_arch(swap_bo(fa->cputype));
271 mprintf("\n");
272 mprintf(" Subtype: %d\n", swap_bo(fa->cpusubtype));
273 mprintf(" Offest: %d\n", swap_bo(fa->offset));
274 mprintf(" Size: %d\n", swap_bo(fa->size));
275 mprintf(" Align: %d\n", swap_bo(fa->align));
276 } else {
277 mprintf(" CPU Type: (%x) ", swapi(fa->cputype));
278 display_cpu_arch(swapi(fa->cputype));
279 mprintf("\n");
280 mprintf(" Subtype: %d\n", swapi(fa->cpusubtype));
281 mprintf(" Offest: %d\n", swapi(fa->offset));
282 mprintf(" Size: %d\n", swapi(fa->size));
283 mprintf(" Align: %d\n", swapi(fa->align));
286 mprintf("\n");
289 void
290 display_cmd_name(int cmd)
292 switch(cmd) {
293 case LC_SEGMENT:
294 mprintf("LC_SEGMENT\n"); break;
295 case LC_SYMTAB:
296 mprintf("LC_SYMTAB\n"); break;
297 case LC_LOAD_DYLIB:
298 mprintf("LC_LOAD_DYLIB\n"); break;
299 case LC_LOAD_DYLINKER:
300 mprintf("LC_LOAD_DYLINKER\n"); break;
301 case LC_DYSYMTAB:
302 mprintf("LC_DYSYMTAB\n"); break;
303 case LC_UNIXTHREAD:
304 mprintf("LC_UNIXTHREAD\n"); break;
305 case LC_TWOLEVEL_HINTS:
306 mprintf("LC_TWOLEVEL_HINTS\n"); break;
307 default:
308 mprintf("\n"); break;
312 void
313 display_cpu_arch(int cputype)
315 switch (cputype) {
316 case CPU_TYPE_MC680x0:
317 mprintf("MC680x0"); break;
318 case CPU_TYPE_I386:
319 mprintf("x86_32"); break;
320 case CPU_TYPE_X86_64:
321 mprintf("x86_64"); break;
322 case CPU_TYPE_POWERPC:
323 mprintf("PowerPC"); break;
324 case CPU_TYPE_HPPA:
325 mprintf("HPPA"); break;
326 case CPU_TYPE_SPARC:
327 mprintf("Sparc"); break;
328 default:
329 mprintf("\n"); break;
333 void
334 mprintf(const char *fmt, ...)
336 va_list ap;
338 if (trigger == 1)
339 return;
341 va_start(ap, fmt);
342 vfprintf(stdout, fmt, ap);
343 va_end(ap);
346 int
347 get_cpu_information()
349 #ifndef __linux__
350 char buf[50];
351 int mib[2];
352 size_t len;
354 mib[0] = CTL_HW;
355 mib[1] = HW_MACHINE;
356 len = sizeof(buf);
357 if (sysctl(mib, 2, &buf, &len, NULL, 0) < 0)
358 errx(1, "Cannot determine local CPU type");
360 if (strncmp(buf, "i386", 4) == 0)
361 return(CPU_TYPE_X86);
362 else if (strncmp(buf, "Power Macintosh", 15) == 0)
363 return(CPU_TYPE_POWERPC);
364 #else /* __linux__ */
365 #if defined __x86_64__
366 return(CPU_TYPE_X86);
367 #elif defined __i386__
368 return(CPU_TYPE_I386);
369 #else
370 # error "Cannot determine local CPU type"
371 #endif
372 #endif /* __linux__ */
373 return(-1);
376 int
377 get_bo_information()
379 #ifndef __linux__
380 int mib[2], bo;
381 size_t len;
383 mib[0] = CTL_HW;
384 mib[1] = HW_BYTEORDER;
385 len = sizeof(bo);
386 if (sysctl(mib, 2, &bo, &len, NULL, 0) < 0)
387 errx(1, "Cannot determine local byte order");
389 if (bo == 1234)
390 return(LE);
391 else if (bo == 4321)
392 return(BE);
393 #else /* __linux__ */
394 #if defined(__BIG_ENDIAN)
395 return(BE);
396 #elif defined(__LITTLE_ENDIAN)
397 return(LE);
398 #else
399 # error "Cannot determine local byte order"
400 #endif /* byte order */
401 #endif /* __linux__ */
403 return(-1);
406 unsigned int
407 swapi(unsigned int i)
409 unsigned int ret = i;
411 if (bo_a == LE && bo_b == BE) {
412 ret = swap_bo(i);
413 } else if(bo_a == BE && bo_b == LE) {
414 ret = swap_bo(i);
417 return(ret);