source: trunk/Cocoa/F-Script Anywhere/Source/libMatch.c@ 7

Last change on this file since 7 was 7, checked in by Nicholas Riley, 20 years ago

F-Script Anywhere 1.1.2a1

File size: 35.1 KB
Line 
1/*
2 * libMatch.c
3 * F-Script Anywhere
4 *
5 * Created by Nicholas Riley on Fri Feb 01 2002.
6 * Copyright (c) 2001 Nicholas Riley. All rights reserved.
7 *
8 */
9
10/*
11 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
12 *
13 * @APPLE_LICENSE_HEADER_START@
14 *
15 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
16 * Reserved. This file contains Original Code and/or Modifications of
17 * Original Code as defined in and that are subject to the Apple Public
18 * Source License Version 1.1 (the "License"). You may not use this file
19 * except in compliance with the License. Please obtain a copy of the
20 * License at http://www.apple.com/publicsource and read it before using
21 * this file.
22 *
23 * The Original Code and all software distributed under the License are
24 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
25 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
26 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
28 * License for the specific language governing rights and limitations
29 * under the License.
30 *
31 * @APPLE_LICENSE_HEADER_END@
32 */
33
34// Yes, this file is a gigantic hack of otool code. It still took me several hours
35// of work to get to this point, though, and all to get around one of Apple's bugs.
36// Cleanup very much appreciated.
37
38#include "libMatch.h"
39#include <stdlib.h>
40#include <string.h>
41#include <mach-o/loader.h>
42#include "stuff/bytesex.h"
43#include "stuff/ofile.h"
44
45typedef char BOOL;
46
47#define YES (BOOL)1
48#define NO (BOOL)0
49
50
51char *progname = "libMatch"; // used by libstuff for errors
52
53#define error printf
54#define printf NOOP
55
56void NOOP(char *fmt, ...) {
57
58}
59
60BOOL ofile_matches_lib(struct mach_header *mh,
61 struct load_command *load_commands,
62 enum byte_sex load_commands_byte_sex,
63 enum bool just_id,
64 const char **libList);
65
66
67// derived from main.c processor() in otool
68
69static
70BOOL
71processor(
72 struct ofile *ofile,
73 char *arch_name,
74 const char *libs[])
75 {
76 char *addr;
77 unsigned long size, magic;
78 struct mach_header mh;
79 struct load_command *load_commands;
80 unsigned long nsorted_symbols;
81 struct nlist *allocated_symbols, *sorted_symbols;
82 unsigned long *indirect_symbols, *allocated_indirect_symbols,
83 nindirect_symbols;
84 struct dylib_module *allocated_mods;
85 struct dylib_table_of_contents *allocated_tocs;
86 struct dylib_reference *allocated_refs;
87 struct twolevel_hint *hints, *allocated_hints;
88 unsigned long nhints;
89 BOOL result;
90 sorted_symbols = NULL;
91 nsorted_symbols = 0;
92 indirect_symbols = NULL;
93 nindirect_symbols = 0;
94 hints = NULL;
95 nhints = 0;
96 /*
97 * These may or may not be allocated. If allocated they will not be
98 * NULL and then free'ed before returning.
99 */
100 load_commands = NULL;
101 allocated_symbols = NULL;
102 sorted_symbols = NULL;
103 allocated_indirect_symbols = NULL;
104 allocated_tocs = NULL;
105 allocated_mods = NULL;
106 allocated_refs = NULL;
107 allocated_hints = NULL;
108 /*
109 * Print header for the object name if in an archive or an architecture
110 * name is passed in.
111 */
112 if(TRUE){ // XXX needed?
113 printf("%s", ofile->file_name);
114 if(ofile->member_ar_hdr != NULL){
115 printf("(%.*s)", (int)ofile->member_name_size,
116 ofile->member_name);
117 }
118 if(arch_name != NULL)
119 printf(" (architecture %s):", arch_name);
120 else
121 printf(":");
122 /*
123 * If the mach_header pointer is NULL the file is not an object
124 * file. Truncated object file (where the file size is less
125 * than sizeof(struct mach_header)) also does not have it's
126 * mach_header set. So deal with both cases here and then
127 * return as the rest of this routine deals only with things
128 * in object files.
129 */
130 if(ofile->mh == NULL){
131 if(ofile->file_type == OFILE_FAT){
132 /*
133 * This routine is not called on fat files where the
134 * offset is past end of file. An error message is
135 * printed in ofile_specific_arch() in ofile.c.
136 */
137 if(ofile->arch_type == OFILE_ARCHIVE){
138 addr = ofile->member_addr;
139 size = ofile->member_size;
140 }
141 else{
142 addr = ofile->file_addr +
143 ofile->fat_archs[ofile->narch].offset;
144 size = ofile->fat_archs[ofile->narch].size;
145 }
146 if(addr + size > ofile->file_addr + ofile->file_size)
147 size = (ofile->file_addr + ofile->file_size) - addr;
148 }
149 else if(ofile->file_type == OFILE_ARCHIVE){
150 addr = ofile->member_addr;
151 size = ofile->member_size;
152 }
153 else{ /* ofile->file_type == OFILE_UNKNOWN */
154 addr = ofile->file_addr;
155 size = ofile->file_size;
156 }
157 if(size > sizeof(long)){
158 memcpy(&magic, addr, sizeof(unsigned long));
159 if(magic == MH_MAGIC || magic == SWAP_LONG(MH_MAGIC)){
160 printf(" is a truncated object file\n");
161 memset(&mh, '\0', sizeof(struct mach_header));
162 if(size > sizeof(struct mach_header))
163 size = sizeof(struct mach_header);
164 memcpy(&mh, addr, size);
165 if(magic == SWAP_LONG(MH_MAGIC))
166 swap_mach_header(&mh, get_host_byte_sex());
167 return FALSE;
168 }
169 }
170 printf(" is not an object file\n");
171 return FALSE;
172 }
173 }
174 if(ofile->mh != NULL){
175 if((int)(ofile->mh) % sizeof(unsigned long)){
176 if(TRUE) // XXX remove?
177 printf("(object file offset is not a multiple of sizeof("
178 "unsigned long))");
179 memcpy(&mh, ofile->mh, sizeof(struct mach_header));
180 if(mh.magic == SWAP_LONG(MH_MAGIC))
181 swap_mach_header(&mh, get_host_byte_sex());
182 ofile->mh = &mh;
183 }
184 else if(ofile->mh->magic == SWAP_LONG(MH_MAGIC)){
185 mh = *(ofile->mh);
186 swap_mach_header(&mh, get_host_byte_sex());
187 ofile->mh = &mh;
188 }
189 }
190 printf("\n");
191 /*
192 * If this is not an object file then just return.
193 */
194 if(ofile->mh == NULL)
195 return NO;
196 /*
197 * Calculate the true number of bytes of the of the object file that
198 * is in memory (in case this file is truncated).
199 */
200 addr = ofile->object_addr;
201 size = ofile->object_size;
202 if(addr + size > ofile->file_addr + ofile->file_size)
203 size = (ofile->file_addr + ofile->file_size) - addr;
204 /*
205 * Load commands.
206 */
207 if(ofile->mh->sizeofcmds + sizeof(struct mach_header) > size){
208 load_commands = malloc(ofile->mh->sizeofcmds);
209 memset(load_commands, '\0', ofile->mh->sizeofcmds);
210 memcpy(load_commands, ofile->load_commands,
211 size - sizeof(struct mach_header));
212 ofile->load_commands = load_commands;
213 }
214 result = ofile_matches_lib(ofile->mh, ofile->load_commands,
215 ofile->object_byte_sex, FALSE, libs);
216 if(load_commands != NULL)
217 free(load_commands);
218 if(allocated_symbols != NULL)
219 free(allocated_symbols);
220 if(sorted_symbols != NULL)
221 free(sorted_symbols);
222 if(allocated_indirect_symbols != NULL)
223 free(allocated_indirect_symbols);
224 if(allocated_hints != NULL)
225 free(allocated_hints);
226 if(allocated_tocs != NULL)
227 free(allocated_tocs);
228 if(allocated_mods != NULL)
229 free(allocated_mods);
230 if(allocated_refs != NULL)
231 free(allocated_refs);
232 return result;
233}
234
235// derived from ofile.c ofile_process() in otool
236
237BOOL appContainsLibMatching(const char *appPath, const char *libs[])
238{
239 const char *name = appPath;
240 struct arch_flag *arch_flags = NULL;
241 unsigned long narch_flags = 0;
242 enum bool all_archs = FALSE;
243 enum bool process_non_objects = FALSE; // TRUE?
244 enum bool dylib_flat = TRUE;
245 char *member_name, *arch_name;
246 unsigned long i;
247 struct ofile ofile;
248 enum bool flag, hostflag, arch_found, family;
249 struct arch_flag host_arch_flag;
250 const struct arch_flag *family_arch_flag;
251 /*
252 * If use_member_syntax is TRUE look for a name of the form
253 * "archive(member)" which is to mean a member in that archive (the
254 * member name must be at least one character long to be recognized as
255 * this form).
256 */
257 member_name = NULL;
258 /*
259 if(use_member_syntax == TRUE){
260 len = strlen(name);
261 if(len >= 4 && name[len-1] == ')'){
262 p = strrchr(name, '(');
263 if(p != NULL && p != name){
264 member_name = p+1;
265 *p = '\0';
266 name[len-1] = '\0';
267 }
268 }
269 }
270 */
271#ifdef OTOOL
272 otool_first_ofile_map = TRUE;
273#endif /* OTOOL */
274 if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE)
275 return NO;
276#ifdef OTOOL
277 otool_first_ofile_map = FALSE;
278#endif /* OTOOL */
279 if(ofile.file_type == OFILE_FAT){
280 /*
281 * This is a fat file so see if a list of architecture is
282 * specified and process only those.
283 */
284 if(all_archs == FALSE && narch_flags != 0){
285 family = FALSE;
286 if(narch_flags == 1){
287 family_arch_flag =
288 get_arch_family_from_cputype(arch_flags[0].cputype);
289 if(family_arch_flag != NULL)
290 family = (enum bool)(family_arch_flag->cpusubtype ==
291 arch_flags[0].cpusubtype);
292 }
293 for(i = 0; i < narch_flags; i++){
294 (void)ofile_first_arch(&ofile);
295 arch_found = FALSE;
296 if(narch_flags != 1)
297 arch_name = ofile.arch_flag.name;
298 else
299 arch_name = NULL;
300 do{
301 if(ofile.arch_flag.cputype ==
302 arch_flags[i].cputype &&
303 (ofile.arch_flag.cpusubtype ==
304 arch_flags[i].cpusubtype || family == TRUE)){
305 arch_found = TRUE;
306 if(ofile.arch_type == OFILE_ARCHIVE){
307 if(member_name != NULL){
308 if(ofile_specific_member(member_name,
309 &ofile) == TRUE)
310 processor(&ofile, arch_name, libs);
311 }
312 else{
313 /* loop through archive */
314#ifdef OTOOL
315 printf("Archive : %s", ofile.file_name);
316 if(arch_name != NULL)
317 printf(" (architecture %s)",
318 arch_name);
319 printf("\n");
320#endif /* OTOOL */
321 if(ofile_first_member(&ofile) == TRUE){
322 flag = FALSE;
323 do{
324 if(process_non_objects == TRUE ||
325 ofile.member_type ==
326 OFILE_Mach_O){
327 processor(&ofile, arch_name,
328 libs);
329 flag = TRUE;
330 }
331 }while(ofile_next_member(&ofile) ==
332 TRUE);
333 if(flag == FALSE){
334 error("for architecture: %s "
335 "archive: %s contains no "
336 "members that are object "
337 "files", ofile.arch_flag.name,
338 ofile.file_name);
339 }
340 }
341 else{
342 error("for architecture: %s archive: "
343 "%s contains no members",
344 ofile.arch_flag.name,
345 ofile.file_name);
346 }
347 }
348 }
349 else if(process_non_objects == TRUE ||
350 ofile.arch_type == OFILE_Mach_O){
351 if(ofile.arch_type == OFILE_Mach_O &&
352 ofile.mh->filetype == MH_DYLIB){
353 if(dylib_flat == TRUE){
354 processor(&ofile, arch_name, libs);
355 }
356 else{
357 if(member_name != NULL){
358 if(ofile_specific_module(
359 member_name, &ofile) == TRUE)
360 processor(&ofile, arch_name,
361 libs);
362 }
363 else{
364 /*loop through the dynamic library*/
365 if(ofile_first_module(&ofile)){
366 do{
367 processor(&ofile, arch_name,
368 libs);
369 }while(ofile_next_module(
370 &ofile));
371 }
372 else{
373 error("for architecture: %s "
374 "dynamic library: %s "
375 "contains no modules",
376 ofile.arch_flag.name,
377 ofile.file_name);
378 }
379 }
380 }
381 }
382 else{
383 if(member_name != NULL)
384 error("for architecture: %s file: %s "
385 "is not an archive and thus does "
386 "not contain member: %s",
387 ofile.arch_flag.name,
388 ofile.file_name,
389 member_name);
390 else
391 processor(&ofile, arch_name, libs);
392 }
393 }
394 else if(ofile.arch_type == OFILE_UNKNOWN){
395 error("for architecture: %s file: %s is "
396 "not an object file",
397 ofile.arch_flag.name,ofile.file_name);
398 }
399 break;
400 }
401 }while(ofile_next_arch(&ofile) == TRUE);
402 if(arch_found == FALSE)
403 error("file: %s does not contain architecture: %s",
404 ofile.file_name, arch_flags[i].name);
405 }
406 return NO;
407 }
408 /*
409 * This is a fat file and no architectures has been specified
410 * so if it contains the host architecture process only that
411 * architecture but if not process all architectures
412 * specified.
413 */
414 if(all_archs == FALSE){
415 (void)get_arch_from_host(&host_arch_flag, NULL);
416 hostflag = FALSE;
417 family = FALSE;
418 family_arch_flag =
419 get_arch_family_from_cputype(host_arch_flag.cputype);
420 if(family_arch_flag != NULL)
421 family = (enum bool)(family_arch_flag->cpusubtype ==
422 host_arch_flag.cpusubtype);
423 ofile_unmap(&ofile);
424 if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE)
425 return NO;
426 (void)ofile_first_arch(&ofile);
427 do{
428 if(ofile.arch_flag.cputype ==
429 host_arch_flag.cputype &&
430 (ofile.arch_flag.cpusubtype ==
431 host_arch_flag.cpusubtype || family == TRUE)){
432 hostflag = TRUE;
433 if(ofile.arch_type == OFILE_ARCHIVE){
434 if(member_name != NULL){
435 if(ofile_specific_member(member_name,
436 &ofile) == TRUE)
437 processor(&ofile, NULL, libs);
438 }
439 else{
440 /* loop through archive */
441#ifdef OTOOL
442 printf("Archive : %s\n", ofile.file_name);
443#endif /* OTOOL */
444 if(ofile_first_member(&ofile) == TRUE){
445 flag = FALSE;
446 do{
447 if(process_non_objects == TRUE ||
448 ofile.member_type == OFILE_Mach_O){
449 processor(&ofile, NULL, libs);
450 flag = TRUE;
451 }
452 }while(ofile_next_member(&ofile) ==
453 TRUE);
454 if(flag == FALSE){
455 error("archive: %s contains no "
456 "members that are object "
457 "files", ofile.file_name);
458 }
459 }
460 else{
461 error("archive: %s contains no "
462 "members", ofile.file_name);
463 }
464 }
465 }
466 else if(process_non_objects == TRUE ||
467 ofile.arch_type == OFILE_Mach_O){
468 if(ofile.arch_type == OFILE_Mach_O &&
469 ofile.mh->filetype == MH_DYLIB){
470 if(dylib_flat == TRUE){
471 processor(&ofile, NULL, libs);
472 }
473 else{
474 if(member_name != NULL){
475 if(ofile_specific_module(member_name,
476 &ofile) == TRUE)
477 processor(&ofile, NULL, libs);
478 }
479 else{
480 /* loop through the dynamic library */
481 if(ofile_first_module(&ofile) == TRUE){
482 do{
483 processor(&ofile, NULL, libs);
484 }while(ofile_next_module(&ofile));
485 }
486 else{
487 error("for architecture: %s dynamic"
488 " library: %s contains no "
489 "modules",
490 ofile.arch_flag.name,
491 ofile.file_name);
492 }
493 }
494 }
495 }
496 else{
497 if(member_name != NULL)
498 error("for architecture: %s file: %s is "
499 "not an archive and thus does not "
500 "contain member: %s",
501 ofile.arch_flag.name, ofile.file_name,
502 member_name);
503 else
504 processor(&ofile, NULL, libs);
505 }
506 }
507 else if(ofile.arch_type == OFILE_UNKNOWN){
508 error("file: %s is not an object file",
509 ofile.file_name);
510 }
511 }
512 }while(hostflag == FALSE && ofile_next_arch(&ofile) == TRUE);
513 if(hostflag == TRUE)
514 return NO;
515 }
516 /*
517 * Either all architectures have been specified or none have
518 * been specified and it does not contain the host architecture
519 * so do all the architectures in the fat file
520 */
521 ofile_unmap(&ofile);
522 if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE)
523 return NO;
524 (void)ofile_first_arch(&ofile);
525 do{
526 if(ofile.arch_type == OFILE_ARCHIVE){
527 if(member_name != NULL){
528 if(ofile_specific_member(member_name, &ofile) == TRUE)
529 processor(&ofile, ofile.arch_flag.name, libs);
530 }
531 else{
532 /* loop through archive */
533#ifdef OTOOL
534 printf("Archive : %s (architecture %s)\n",
535 ofile.file_name, ofile.arch_flag.name);
536#endif /* OTOOL */
537 if(ofile_first_member(&ofile) == TRUE){
538 flag = FALSE;
539 do{
540 if(process_non_objects == TRUE ||
541 ofile.member_type == OFILE_Mach_O){
542 processor(&ofile, ofile.arch_flag.name,
543 libs);
544 flag = TRUE;
545 }
546 }while(ofile_next_member(&ofile) == TRUE);
547 if(flag == FALSE){
548 error("for architecture: %s archive: %s "
549 "contains no members that are object "
550 "files", ofile.arch_flag.name,
551 ofile.file_name);
552 }
553 }
554 else{
555 error("for architecture: %s archive: %s "
556 "contains no members",
557 ofile.arch_flag.name, ofile.file_name);
558 }
559 }
560 }
561 else if(process_non_objects == TRUE ||
562 ofile.arch_type == OFILE_Mach_O){
563 if(ofile.arch_type == OFILE_Mach_O &&
564 ofile.mh->filetype == MH_DYLIB){
565 if(dylib_flat == TRUE){
566 processor(&ofile, ofile.arch_flag.name, libs);
567 }
568 else{
569 if(member_name != NULL){
570 if(ofile_specific_module(member_name, &ofile)
571 == TRUE)
572 processor(&ofile, ofile.arch_flag.name,
573 libs);
574 }
575 else{
576 /* loop through the dynamic library */
577 if(ofile_first_module(&ofile) == TRUE){
578 do{
579 processor(&ofile, ofile.arch_flag.name,
580 libs);
581 }while(ofile_next_module(&ofile) == TRUE);
582 }
583 else{
584 error("for architecture: %s dynamic library"
585 ": %s contains no modules",
586 ofile.arch_flag.name,ofile.file_name);
587 }
588 }
589 }
590 }
591 else{
592 if(member_name != NULL)
593 error("for architecture: %s file: %s is not an "
594 "archive and thus does not contain member: "
595 "%s", ofile.arch_flag.name, ofile.file_name,
596 member_name);
597 else
598 processor(&ofile, ofile.arch_flag.name, libs);
599 }
600 }
601 else if(ofile.arch_type == OFILE_UNKNOWN){
602 error("for architecture: %s file: %s is not an "
603 "object file", ofile.arch_flag.name,
604 ofile.file_name);
605 }
606 }while(ofile_next_arch(&ofile) == TRUE);
607 }
608 else if(ofile.file_type == OFILE_ARCHIVE){
609 if(narch_flags != 0){
610 arch_found = FALSE;
611 for(i = 0; i < narch_flags; i++){
612 family = FALSE;
613 if(narch_flags == 1){
614 family_arch_flag =
615 get_arch_family_from_cputype(arch_flags[0].cputype);
616 if(family_arch_flag != NULL)
617 family = (enum bool)(family_arch_flag->cpusubtype ==
618 arch_flags[0].cpusubtype);
619 }
620 if(ofile.archive_cputype == arch_flags[i].cputype &&
621 (ofile.archive_cpusubtype == arch_flags[i].cpusubtype ||
622 family == TRUE)){
623 arch_found = TRUE;
624 }
625 else{
626 error("file: %s does not contain architecture: %s",
627 ofile.file_name, arch_flags[i].name);
628 }
629 }
630 if(arch_found == FALSE)
631 return NO;
632 }
633 if(member_name != NULL){
634 if(ofile_specific_member(member_name, &ofile) == TRUE)
635 processor(&ofile, NULL, libs);
636 }
637 else{
638 /* loop through archive */
639#ifdef OTOOL
640 printf("Archive : %s\n", ofile.file_name);
641#endif /* OTOOL */
642 if(ofile_first_member(&ofile) == TRUE){
643 flag = FALSE;
644 do{
645 if(process_non_objects == TRUE ||
646 ofile.member_type == OFILE_Mach_O){
647 processor(&ofile, NULL, libs);
648 flag = TRUE;
649 }
650 }while(ofile_next_member(&ofile) == TRUE);
651 if(flag == FALSE){
652 error("archive: %s contains no members that are "
653 "object files", ofile.file_name);
654 }
655 }
656 else{
657 error("archive: %s contains no members",
658 ofile.file_name);
659 }
660 }
661 }
662 else if(ofile.file_type == OFILE_Mach_O){
663 if(narch_flags != 0){
664 arch_found = FALSE;
665 for(i = 0; i < narch_flags; i++){
666 family = FALSE;
667 if(narch_flags == 1){
668 family_arch_flag =
669 get_arch_family_from_cputype(arch_flags[0].cputype);
670 if(family_arch_flag != NULL)
671 family = (enum bool)(family_arch_flag->cpusubtype ==
672 arch_flags[0].cpusubtype);
673 }
674#ifdef OTOOL
675 if(ofile.mh->magic == SWAP_LONG(MH_MAGIC)){
676 if(SWAP_LONG(ofile.mh->cputype) ==
677 arch_flags[i].cputype &&
678 (SWAP_LONG(ofile.mh->cpusubtype) ==
679 arch_flags[i].cpusubtype ||
680 family == TRUE)){
681 arch_found = TRUE;
682 }
683 }
684 else
685#endif /* OTOOL */
686 if(ofile.mh->cputype == arch_flags[i].cputype &&
687 (ofile.mh->cpusubtype == arch_flags[i].cpusubtype ||
688 family == TRUE)){
689 arch_found = TRUE;
690 }
691 else{
692 error("file: %s does not contain architecture: %s",
693 ofile.file_name, arch_flags[i].name);
694 }
695 }
696 if(arch_found == FALSE)
697 return NO;
698 }
699 if(ofile.mh->filetype == MH_DYLIB){
700 if(dylib_flat == TRUE){
701 processor(&ofile, NULL, libs);
702 }
703 else{
704 if(member_name != NULL){
705 if(ofile_specific_module(member_name, &ofile) == TRUE)
706 processor(&ofile, NULL, libs);
707 }
708 else{
709 /* loop through the dynamic library */
710 if(ofile_first_module(&ofile) == TRUE){
711 do{
712 processor(&ofile, NULL, libs);
713 }while(ofile_next_module(&ofile) == TRUE);
714 }
715 else{
716 error("dynamic library: %s contains no modules",
717 ofile.file_name);
718 }
719 }
720 }
721 }
722 else{
723 if(member_name != NULL)
724 error("file: %s is not an archive and thus does not contain"
725 " member: %s", ofile.file_name, member_name);
726 else
727 return processor(&ofile, NULL, libs);
728 }
729 }
730 else{
731 if(process_non_objects == TRUE)
732 processor(&ofile, NULL, libs);
733 else if(member_name != NULL)
734 error("file: %s(%s) is not an object file", name,
735 member_name);
736 else
737 error("file: %s is not an object file", name);
738 }
739 return NO;
740}
741
742// derived from ofile_print.c print_libraries() in otool
743
744BOOL ofile_matches_lib(struct mach_header *mh,
745 struct load_command *load_commands,
746 enum byte_sex load_commands_byte_sex,
747 enum bool just_id,
748 const char **libs)
749{
750 enum byte_sex host_byte_sex;
751 enum bool swapped;
752 unsigned long i, left, size;
753 struct load_command *lc, l;
754 struct fvmlib_command fl;
755 struct dylib_command dl;
756 char *p;
757
758 host_byte_sex = get_host_byte_sex();
759 swapped = host_byte_sex != load_commands_byte_sex;
760 lc = load_commands;
761 for(i = 0 ; i < mh->ncmds; i++){
762 memcpy((char *)&l, (char *)lc, sizeof(struct load_command));
763 if(swapped)
764 swap_load_command(&l, host_byte_sex);
765 if(l.cmdsize % sizeof(long) != 0)
766 printf("load command %lu size not a multiple of sizeof(long)\n",
767 i);
768 if((char *)lc + l.cmdsize > (char *)load_commands + mh->sizeofcmds)
769 printf("load command %lu extends past end of load commands\n",
770 i);
771 left = mh->sizeofcmds - ((char *)lc - (char *)load_commands);
772 switch(l.cmd){
773 case LC_IDFVMLIB:
774 case LC_LOADFVMLIB:
775 if(just_id == TRUE)
776 break;
777 memset((char *)&fl, '\0', sizeof(struct fvmlib_command));
778 size = left < sizeof(struct fvmlib_command) ?
779 left : sizeof(struct fvmlib_command);
780 memcpy((char *)&fl, (char *)lc, size);
781 if(swapped)
782 swap_fvmlib_command(&fl, host_byte_sex);
783 if(fl.fvmlib.name.offset < fl.cmdsize){
784 p = (char *)lc + fl.fvmlib.name.offset;
785 printf("\t%s (minor version %lu)\n", p,
786 fl.fvmlib.minor_version);
787 }
788 else{
789 printf("\tBad offset (%lu) for name of %s command %lu\n",
790 fl.fvmlib.name.offset, l.cmd == LC_IDFVMLIB ?
791 "LC_IDFVMLIB" : "LC_LOADFVMLIB" , i);
792 }
793 break;
794 case LC_LOAD_DYLIB:
795 case LC_LOAD_WEAK_DYLIB:
796 if(just_id == TRUE)
797 break;
798 case LC_ID_DYLIB:
799 memset((char *)&dl, '\0', sizeof(struct dylib_command));
800 size = left < sizeof(struct dylib_command) ?
801 left : sizeof(struct dylib_command);
802 memcpy((char *)&dl, (char *)lc, size);
803 if(swapped)
804 swap_dylib_command(&dl, host_byte_sex);
805 if(dl.dylib.name.offset < dl.cmdsize) {
806 p = (char *)lc + dl.dylib.name.offset;
807 if(just_id == TRUE)
808 printf("%s\n", p);
809 else
810 printf("\t%s (compatibility version %lu.%lu.%lu, "
811 "current version %lu.%lu.%lu)\n", p,
812 dl.dylib.compatibility_version >> 16,
813 (dl.dylib.compatibility_version >> 8) & 0xff,
814 dl.dylib.compatibility_version & 0xff,
815 dl.dylib.current_version >> 16,
816 (dl.dylib.current_version >> 8) & 0xff,
817 dl.dylib.current_version & 0xff);
818 {
819 const char **libName;
820 for (libName = libs ; *libName != NULL ; libName++) {
821 if (strstr(p, *libName) != NULL) return YES;
822 }
823 }
824 }
825 else{
826 printf("\tBad offset (%lu) for name of %s command %lu\n",
827 dl.dylib.name.offset, l.cmd == LC_ID_DYLIB ?
828 "LC_ID_DYLIB" :
829 (l.cmd == LC_LOAD_DYLIB ? "LC_LOAD_DYLIB" :
830 "LC_LOAD_WEAK_DYLIB") , i);
831 }
832 break;
833 }
834 if(l.cmdsize == 0){
835 printf("load command %lu size zero (can't advance to other "
836 "load commands)\n", i);
837 return NO;
838 }
839 lc = (struct load_command *)((char *)lc + l.cmdsize);
840 if((char *)lc > (char *)load_commands + mh->sizeofcmds)
841 return NO;
842 }
843 if((char *)load_commands + mh->sizeofcmds != (char *)lc)
844 printf("Inconsistent mh_sizeofcmds\n");
845 return NO;
846}
Note: See TracBrowser for help on using the repository browser.