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

Last change on this file since 450 was 217, checked in by rchin, 14 years ago
  • Updated to new mach_inject with support for x86
  • Updated nib files to 10.2+ format so that future updates to the f-script framework won't break fsa
  • Adjusted some code to work with the new x86 mach_inject (sends an additional argument)
  • Updates code to work with newer defines in cctools
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.