/* * create() takes the file name of a dynamic library (dylib) and creates a * gmon.out file (gmon_out). It checks to see the dylib file is correct and * creates the gmon.out file proportional to the size of the (__TEXT,__text) * section of the dynamic library. */ static void create( char *dylib, char *gmon_out) { struct arch_flag host_arch_flag; struct ofile ofile; unsigned long i, j, size; struct load_command *lc; struct segment_command *sg; struct section *s, *text_section; kern_return_t r; struct phdr *phdr; char *pcsample_buffer; int fd; /* * Open and map in the dylib file and check it for correctness. */ if(get_arch_from_host(&host_arch_flag, NULL) == 0) fatal("can't determine the host architecture"); if(ofile_map(dylib, &host_arch_flag, NULL, &ofile, FALSE) == FALSE) exit(EXIT_FAILURE); if(ofile.mh == NULL || (ofile.mh->filetype != MH_DYLIB && ofile.mh->filetype != MH_DYLINKER)) fatal("file: %s is not a Mach-O dynamic shared library file", dylib); /* * Get the text section for dynamic library. */ text_section = NULL; lc = ofile.load_commands; for(i = 0; i < ofile.mh->ncmds && text_section == NULL; i++){ if(lc->cmd == LC_SEGMENT){ sg = (struct segment_command *)lc; s = (struct section *) ((char *)sg + sizeof(struct segment_command)); for(j = 0; j < sg->nsects; j++){ if(strcmp(s->sectname, SECT_TEXT) == 0 && strcmp(s->segname, SEG_TEXT) == 0){ text_section = s; break; } s++; } } lc = (struct load_command *)((char *)lc + lc->cmdsize); } if(text_section == NULL) fatal("file: %s does not have a (" SEG_TEXT "," SECT_TEXT ") section", dylib); /* * Create a pcsample buffer for the text section. */ size = text_section->size / HASHFRACTION + sizeof(struct phdr); size = round(size, sizeof(unsigned short)); r = vm_allocate(mach_task_self(), (vm_address_t *)&pcsample_buffer, (vm_size_t)size, TRUE); if(r != KERN_SUCCESS) mach_fatal(r, "can't vm_allocate pcsample buffer of size: %lu", size); /* * Create and write the pcsample file. See comments in gmon.h for the * values of the profile header (struct phdr). */ phdr = (struct phdr *)pcsample_buffer; phdr->lpc = (char *)(text_section->addr); phdr->hpc = (char *)(text_section->addr + text_section->size); phdr->ncnt = (int)size; if((fd = open(gmon_out, O_WRONLY | O_CREAT | O_TRUNC, 0777)) == -1) system_fatal("can't create gmon.out file: %s", gmon_out); if(write(fd, pcsample_buffer, size) != (int)size) system_fatal("can't write gmon.out file: %s", gmon_out); if(close(fd) == -1) system_fatal("can't close gmon.out file: %s", gmon_out); }
int main( int argc, char **argv, char **envp) { const char *LIB = "../libexec/as/"; const char *LOCALLIB = "../local/libexec/as/"; const char *AS = "/as"; const char *LLVM_MC = "llvm-mc"; int i, j; uint32_t count, verbose, run_llvm_mc; char *p, c, *arch_name, *as, *as_local; char **llvm_mc_argv; char *prefix, buf[MAXPATHLEN], resolved_name[PATH_MAX]; unsigned long bufsize; struct arch_flag arch_flag; const struct arch_flag *arch_flags, *family_arch_flag; enum bool oflag_specified; progname = argv[0]; arch_name = NULL; verbose = 0; run_llvm_mc = 0; oflag_specified = FALSE; /* * Construct the prefix to the assembler driver. */ bufsize = MAXPATHLEN; p = buf; i = _NSGetExecutablePath(p, &bufsize); if(i == -1){ p = allocate(bufsize); _NSGetExecutablePath(p, &bufsize); } prefix = realpath(p, resolved_name); if(realpath == NULL) system_fatal("realpath(3) for %s failed", p); p = rindex(prefix, '/'); if(p != NULL) p[1] = '\0'; /* * Process the assembler flags exactly like the assembler would (except * let the assembler complain about multiple flags, bad combinations of * flags, unknown single letter flags and the like). The main thing * here is to parse out the "-arch <arch_flag>" and to do so the * multiple argument and multiple character flags need to be known how * to be stepped over correctly. */ for(i = 1; i < argc; i++){ /* * The assembler flags start with '-' except that "--" is recognized * as assemble from stdin and that flag "--" is not allowed to be * grouped with other flags (so "-a-" is not the same as "-a --"). */ if(argv[i][0] == '-' && !(argv[i][1] == '-' && argv[i][2] == '0')){ /* * the assembler allows single letter flags to be grouped * together so "-abc" is the same as "-a -b -c". So that * logic must be followed here. */ for(p = &(argv[i][1]); (c = *p); p++){ /* * The assembler simply ignores the high bit of flag * characters and not treat them as different characters * as they are (but the argument following the flag * character is not treated this way). So it's done * here as well to match it. */ c &= 0x7F; switch(c){ /* * Flags that take a single argument. The argument is the * rest of the current argument if there is any or the it is * the next argument. Again errors like missing arguments * are not handled here but left to the assembler. */ case 'o': /* -o name */ oflag_specified = TRUE; case 'I': /* -I directory */ case 'm': /* -mc68000, -mc68010 and mc68020 */ case 'N': /* -NEXTSTEP-deployment-target */ if(p[1] == '\0') i++; break; case 'a': if(strcmp(p, "arch") == 0){ if(i + 1 >= argc) fatal("missing argument to %s option", argv[i]); if(arch_name != NULL) fatal("more than one %s option (not allowed, " "use cc(1) instead)", argv[i]); arch_name = argv[i+1]; break; } /* fall through for non "-arch" */ case 'f': case 'k': case 'g': case 'v': case 'W': case 'L': default: /* just recognize it, do nothing */ break; case 'l': if(strcmp(p, "llvm-mc") == 0) run_llvm_mc = i; /* also just recognize 'l' and do nothing */ break; case 'V': verbose = 1; break; } } } } /* * If the -llvm-mc flag was specified then run llvm-mc from the same * directory as the driver. */ if(run_llvm_mc != 0){ as = makestr(prefix, LLVM_MC, NULL); if(access(as, F_OK) != 0){ printf("%s: assembler (%s) not installed\n", progname, as); exit(1); } llvm_mc_argv = allocate(argc + 3); llvm_mc_argv[0] = as; j = 1; for(i = 1; i < argc; i++){ /* * Do not pass -llvm-mc */ if(i != run_llvm_mc){ /* * Do not pass command line argument that are Unknown to * to llvm-mc. */ if(strcmp(argv[i], "-v") != 0 && strcmp(argv[i], "-V") != 0 && strcmp(argv[i], "-force_cpusubtype_ALL") != 0){ llvm_mc_argv[j] = argv[i]; j++; } } } /* * Add -filetype=obj or llvm-mc will write to stdout. */ llvm_mc_argv[j] = "-filetype=obj"; j++; /* * llvm-mc requires a "-o a.out" if not -o is specified. */ if(oflag_specified == FALSE){ llvm_mc_argv[j] = "-o"; j++; llvm_mc_argv[j] = "a.out"; j++; } llvm_mc_argv[j] = NULL; if(execute(llvm_mc_argv, verbose)) exit(0); else exit(1); } /* * Construct the name of the assembler to run from the given -arch * <arch_flag> or if none then from the value returned from * get_arch_from_host(). */ if(arch_name == NULL){ if(get_arch_from_host(&arch_flag, NULL)){ #if __LP64__ /* * If runing as a 64-bit binary and on an Intel x86 host * default to the 64-bit assember. */ if(arch_flag.cputype == CPU_TYPE_I386) arch_flag = *get_arch_family_from_cputype(CPU_TYPE_X86_64); #endif /* __LP64__ */ arch_name = arch_flag.name; } else fatal("unknown host architecture (can't determine which " "assembler to run)"); } else{ /* * Convert a possible machine specific architecture name to a * family name to base the name of the assembler to run. */ if(get_arch_from_flag(arch_name, &arch_flag) != 0){ family_arch_flag = get_arch_family_from_cputype(arch_flag.cputype); if(family_arch_flag != NULL) arch_name = (char *)(family_arch_flag->name); } } /* * If this assembler exist try to run it else print an error message. */ as = makestr(prefix, LIB, arch_name, AS, NULL); if(access(as, F_OK) == 0){ argv[0] = as; if(execute(argv, verbose)) exit(0); else exit(1); } as_local = makestr(prefix, LOCALLIB, arch_name, AS, NULL); if(access(as_local, F_OK) == 0){ argv[0] = as_local; if(execute(argv, verbose)) exit(0); else exit(1); } printf("%s: assembler (%s or %s) for architecture %s not installed\n", progname, as, as_local, arch_name); arch_flags = get_arch_flags(); count = 0; for(i = 0; arch_flags[i].name != NULL; i++){ as = makestr(prefix, LIB, arch_flags[i].name, AS, NULL); if(access(as, F_OK) == 0){ if(count == 0) printf("Installed assemblers are:\n"); printf("%s for architecture %s\n", as, arch_flags[i].name); count++; } else{ as_local = makestr(prefix, LOCALLIB, arch_flags[i].name, AS, NULL); if(access(as_local, F_OK) == 0){ if(count == 0) printf("Installed assemblers are:\n"); printf("%s for architecture %s\n", as_local, arch_flags[i].name); count++; } } } if(count == 0) printf("%s: no assemblers installed\n", progname); exit(1); }
int main( int argc, char **argv, char **envp) { const char *LIB = "../libexec/as/"; const char *LOCALLIB = "../local/libexec/as/"; const char *AS = "/as"; int i, j; uint32_t count, verbose, run_clang; char *p, c, *arch_name, *as, *as_local; char **new_argv; const char *CLANG = "clang"; char *prefix, buf[MAXPATHLEN], resolved_name[PATH_MAX]; uint32_t bufsize; struct arch_flag arch_flag; const struct arch_flag *arch_flags, *family_arch_flag; enum bool oflag_specified, qflag, Qflag, some_input_files; progname = argv[0]; arch_name = NULL; verbose = 0; run_clang = 0; oflag_specified = FALSE; qflag = FALSE; Qflag = FALSE; some_input_files = FALSE; /* * Construct the prefix to the assembler driver. */ bufsize = MAXPATHLEN; p = buf; i = _NSGetExecutablePath(p, &bufsize); if(i == -1){ p = allocate(bufsize); _NSGetExecutablePath(p, &bufsize); } prefix = realpath(p, resolved_name); if(realpath == NULL) system_fatal("realpath(3) for %s failed", p); p = rindex(prefix, '/'); if(p != NULL) p[1] = '\0'; /* * Process the assembler flags exactly like the assembler would (except * let the assembler complain about multiple flags, bad combinations of * flags, unknown single letter flags and the like). The main thing * here is to parse out the "-arch <arch_flag>" and to do so the * multiple argument and multiple character flags need to be known how * to be stepped over correctly. */ for(i = 1; i < argc; i++){ /* * The assembler flags start with '-' except that "--" is recognized * as assemble from stdin and that flag "--" is not allowed to be * grouped with other flags (so "-a-" is not the same as "-a --"). */ if(argv[i][0] == '-' && !(argv[i][1] == '-' && argv[i][2] == '\0')){ /* * Treat a single "-" as reading from stdin input also. */ if(argv[i][1] == '\0') some_input_files = TRUE; /* * the assembler allows single letter flags to be grouped * together so "-abc" is the same as "-a -b -c". So that * logic must be followed here. */ for(p = &(argv[i][1]); (c = *p); p++){ /* * The assembler simply ignores the high bit of flag * characters and not treat them as different characters * as they are (but the argument following the flag * character is not treated this way). So it's done * here as well to match it. */ c &= 0x7F; switch(c){ /* * Flags that take a single argument. The argument is the * rest of the current argument if there is any or the it is * the next argument. Again errors like missing arguments * are not handled here but left to the assembler. */ case 'o': /* -o name */ oflag_specified = TRUE; case 'I': /* -I directory */ case 'm': /* -mc68000, -mc68010 and mc68020 */ case 'N': /* -NEXTSTEP-deployment-target */ /* * We want to skip the next argv if the value is not * contained in this argv eg: -I dir . */ if(p[1] == '\0') i++; /* * And in case the value is contained in this argv * (eg: -Idir), skip the rest. */ while(p[1]) p++; p = " "; /* Finished with this arg. */ break; case 'g': if(strcmp(p, "gstabs") == 0 || strcmp(p, "gdwarf2") == 0 || strcmp(p, "gdwarf-2") == 0){ p = " "; /* Finished with this arg. */ } break; case 'd': if(strcmp(p, "dynamic") == 0){ p = " "; /* Finished with this arg. */ } break; case 's': if(strcmp(p, "static") == 0){ p = " "; /* Finished with this arg. */ } break; case 'a': if(strcmp(p, "arch_multiple") == 0){ p = " "; /* Finished with this arg. */ } if(strcmp(p, "arch") == 0){ if(i + 1 >= argc) fatal("missing argument to %s option", argv[i]); if(arch_name != NULL) fatal("more than one %s option (not allowed, " "use cc(1) instead)", argv[i]); arch_name = argv[i+1]; p = " "; /* Finished with this arg. */ i++; break; } /* fall through for non "-arch" */ case 'f': if(strcmp(p, "force_cpusubtype_ALL") == 0){ p = " "; /* Finished with this arg. */ break; } case 'k': case 'v': case 'W': case 'L': case 'l': default: /* just recognize it, do nothing */ break; case 'q': qflag = TRUE; break; case 'Q': Qflag = TRUE; break; case 'V': verbose = 1; break; } } } else{ some_input_files = TRUE; } } /* * Construct the name of the assembler to run from the given -arch * <arch_flag> or if none then from the value returned from * get_arch_from_host(). */ if(arch_name == NULL){ if(get_arch_from_host(&arch_flag, NULL)){ #if __LP64__ /* * If runing as a 64-bit binary and on an Intel x86 host * default to the 64-bit assember. */ if(arch_flag.cputype == CPU_TYPE_I386) arch_flag = *get_arch_family_from_cputype(CPU_TYPE_X86_64); #endif /* __LP64__ */ arch_name = arch_flag.name; } else fatal("unknown host architecture (can't determine which " "assembler to run)"); } else{ /* * Convert a possible machine specific architecture name to a * family name to base the name of the assembler to run. */ if(get_arch_from_flag(arch_name, &arch_flag) != 0){ family_arch_flag = get_arch_family_from_cputype(arch_flag.cputype); if(family_arch_flag != NULL) arch_name = (char *)(family_arch_flag->name); } } if(qflag == TRUE && Qflag == TRUE){ printf("%s: can't specifiy both -q and -Q\n", progname); exit(1); } /* * If the environment variable AS_INTEGRATED_ASSEMBLER is set then set * the qflag to call clang(1) with -integrated-as unless the -Q flag is * set and do this for the supported architectures. */ if(Qflag == FALSE && getenv("AS_INTEGRATED_ASSEMBLER") != NULL && (arch_flag.cputype == CPU_TYPE_X86_64 || arch_flag.cputype == CPU_TYPE_I386 || arch_flag.cputype == CPU_TYPE_ARM64 || arch_flag.cputype == CPU_TYPE_ARM)){ qflag = TRUE; } if(qflag == TRUE && (arch_flag.cputype != CPU_TYPE_X86_64 && arch_flag.cputype != CPU_TYPE_I386 && arch_flag.cputype != CPU_TYPE_ARM64 && arch_flag.cputype != CPU_TYPE_ARM)){ printf("%s: can't specifiy -q with -arch %s\n", progname, arch_flag.name); exit(1); } /* * When the target assembler is for arm64, for now: * rdar://8913781 ARM64: cctools 'as' driver should invoke clang * for ARM64 assembly files * use clang. Later for: * rdar://8928193 ARM64: Standalone 'as' driver * when there is and llvm-mc based standalone 'as' driver and it is * in the usual place as the other target assemblers this use of clang * will be removed. */ if(arch_flag.cputype == CPU_TYPE_ARM64){ if(Qflag == TRUE){ printf("%s: can't specifiy -Q with -arch arm64\n", progname); exit(1); } run_clang = 1; } #if 0 /* * See rdar://9801003 where this will be changed before before NMOs and NMiOS. */ /* * Use the LLVM integrated assembler as the default with the as(1) * driver for Intel (64-bit & 32-bit) as well as ARM for 32-bit too * (64-bit ARM handled above) via running clang. */ if(arch_flag.cputype == CPU_TYPE_X86_64 || arch_flag.cputype == CPU_TYPE_I386 || arch_flag.cputype == CPU_TYPE_ARM) run_clang = 1; #endif /* * Use the clang as the assembler if is the default or asked to with * the -q flag. But don't use it asked to use the system assembler * with the -Q flag. */ if((run_clang || qflag) && !Qflag && (arch_flag.cputype == CPU_TYPE_X86_64 || arch_flag.cputype == CPU_TYPE_I386 || arch_flag.cputype == CPU_TYPE_ARM64 || arch_flag.cputype == CPU_TYPE_ARM)){ as = makestr(prefix, CLANG, NULL); if(access(as, F_OK) != 0){ printf("%s: assembler (%s) not installed\n", progname, as); exit(1); } new_argv = allocate((argc + 8) * sizeof(char *)); new_argv[0] = as; j = 1; /* * Add "-x assembler" in case the input does not end in .s this must * come before "-" or the clang driver will issue an error: * "error: -E or -x required when input is from standard input" */ new_argv[j] = "-x"; j++; new_argv[j] = "assembler"; j++; /* * If we have not seen some some_input_files or a "-" or "--" to * indicate we are assembling stdin add a "-" so clang will * assemble stdin as as(1) would. */ if(some_input_files == FALSE){ new_argv[j] = "-"; j++; } for(i = 1; i < argc; i++){ /* * Translate as(1) use of "--" for stdin to clang's use of "-". */ if(strcmp(argv[i], "--") == 0){ new_argv[j] = "-"; j++; } /* * Do not pass command line argument that are Unknown to * to clang. */ else if(strcmp(argv[i], "-V") != 0 && strcmp(argv[i], "-q") != 0 && strcmp(argv[i], "-Q") != 0){ new_argv[j] = argv[i]; j++; } } /* * clang requires a "-o a.out" if not -o is specified. */ if(oflag_specified == FALSE){ new_argv[j] = "-o"; j++; new_argv[j] = "a.out"; j++; } /* Add -integrated-as or clang will run as(1). */ new_argv[j] = "-integrated-as"; j++; /* Add -c or clang will run ld(1). */ new_argv[j] = "-c"; j++; new_argv[j] = NULL; if(execute(new_argv, verbose)) exit(0); else exit(1); } /* * If this assembler exist try to run it else print an error message. */ as = makestr(prefix, LIB, arch_name, AS, NULL); new_argv = allocate((argc + 1) * sizeof(char *)); new_argv[0] = as; j = 1; for(i = 1; i < argc; i++){ /* * Do not pass command line argument that are unknown to as. */ if(strcmp(argv[i], "-q") != 0 && strcmp(argv[i], "-Q") != 0){ new_argv[j] = argv[i]; j++; } } new_argv[j] = NULL; if(access(as, F_OK) == 0){ argv[0] = as; if(execute(new_argv, verbose)) exit(0); else exit(1); } as_local = makestr(prefix, LOCALLIB, arch_name, AS, NULL); new_argv[0] = as_local; if(access(as_local, F_OK) == 0){ argv[0] = as_local; if(execute(new_argv, verbose)) exit(0); else exit(1); } printf("%s: assembler (%s or %s) for architecture %s not installed\n", progname, as, as_local, arch_name); arch_flags = get_arch_flags(); count = 0; for(i = 0; arch_flags[i].name != NULL; i++){ as = makestr(prefix, LIB, arch_flags[i].name, AS, NULL); if(access(as, F_OK) == 0){ if(count == 0) printf("Installed assemblers are:\n"); printf("%s for architecture %s\n", as, arch_flags[i].name); count++; } else{ as_local = makestr(prefix, LOCALLIB, arch_flags[i].name, AS, NULL); if(access(as_local, F_OK) == 0){ if(count == 0) printf("Installed assemblers are:\n"); printf("%s for architecture %s\n", as_local, arch_flags[i].name); count++; } } } if(count == 0) printf("%s: no assemblers installed\n", progname); exit(1); }
void getnfile( void) { uint32_t i, j, ncmds; uint64_t text_highpc; struct load_command *lc; struct segment_command *sg; struct segment_command_64 *sg64; struct section *s; struct section_64 *s64; struct symtab_command *st; struct nlist *symbols; struct nlist_64 *symbols64; #ifdef notdef struct ofile lib_ofile; unsigned long k; struct fvmlib_command *fl; struct load_command *lib_lc; struct symtab_command *lib_st; char *lib_name; #endif nname = 0; n_files = 0; if(get_arch_from_host(&host_arch_flag, NULL) == 0) fatal("can't determine the host architecture"); if(ofile_map(a_outname, NULL, NULL, &ofile, FALSE) == FALSE) return; /* * Pick the host architecture first if it is there, or the 64-bit * version of the host architecture next if it is there. */ if(ofile.file_type == OFILE_FAT){ (void)ofile_first_arch(&ofile); do{ if(host_arch_flag.cputype == ofile.mh_cputype) goto good; }while(ofile_next_arch(&ofile) == TRUE); (void)ofile_first_arch(&ofile); do{ if((host_arch_flag.cputype | CPU_ARCH_ABI64) == ofile.mh_cputype){ host_arch_flag.cputype |= CPU_ARCH_ABI64; goto good; } }while(ofile_next_arch(&ofile) == TRUE); error("file: %s does not contain the host architecture", a_outname); return; } else if(ofile.file_type == OFILE_ARCHIVE){ error("file: %s is not an Mach-O file executable", a_outname); return; } else if(ofile.file_type == OFILE_Mach_O){ if(host_arch_flag.cputype == ofile.mh_cputype) goto good; if((host_arch_flag.cputype | CPU_ARCH_ABI64) == ofile.mh_cputype){ host_arch_flag.cputype |= CPU_ARCH_ABI64; goto good; } error("file: %s is not of the host architecture", a_outname); return; } else{ /* ofile.file_type == OFILE_UNKNOWN */ error("file: %s is not an Mach-O file executable", a_outname); return; } good: if((ofile.mh == NULL && ofile.mh64 == NULL) || (ofile.mh_filetype != MH_EXECUTE && ofile.mh_filetype != MH_DYLIB && ofile.mh_filetype != MH_DYLINKER)) fatal("file: %s is not a Mach-O executable file", a_outname); /* * Pass 1 count symbols and files. */ st = NULL; lc = ofile.load_commands; if(ofile.mh != NULL){ text_highpc = 0xfffffffe; ncmds = ofile.mh->ncmds; } else{ text_highpc = 0xfffffffffffffffeULL; ncmds = ofile.mh64->ncmds; } for(i = 0; i < ncmds; i++){ if(lc->cmd == LC_SEGMENT){ sg = (struct segment_command *)lc; s = (struct section *) ((char *)sg + sizeof(struct segment_command)); for(j = 0; j < sg->nsects; j++){ if(strcmp(s->sectname, SECT_TEXT) == 0 && strcmp(s->segname, SEG_TEXT) == 0){ textspace = (unsigned char *)ofile.object_addr + s->offset; text_highpc = s->addr + s->size; } s++; } } else if(lc->cmd == LC_SEGMENT_64){ sg64 = (struct segment_command_64 *)lc; s64 = (struct section_64 *) ((char *)sg64 + sizeof(struct segment_command_64)); for(j = 0; j < sg64->nsects; j++){ if(strcmp(s64->sectname, SECT_TEXT) == 0 && strcmp(s64->segname, SEG_TEXT) == 0){ textspace = (unsigned char *)ofile.object_addr + s64->offset; text_highpc = s64->addr + s64->size; } s64++; } } #ifdef notdef else if(lc->cmd == LC_LOADFVMLIB){ fl = (struct fvmlib_command *)lc; lib_name = (char *)fl + fl->fvmlib.name.offset; if(ofile_map(lib_name, &host_arch_flag, NULL, &lib_ofile, FALSE) == FALSE) goto done1; if(lib_ofile.mh == NULL || lib_ofile.mh->filetype != MH_FVMLIB){ warning("file: %s is not a shared library file", lib_name); goto done_and_unmap1; } lib_st = NULL; lib_lc = lib_ofile.load_commands; for(j = 0; j < lib_ofile.mh->ncmds; j++){ if(lib_st == NULL && lib_lc->cmd == LC_SYMTAB){ lib_st = (struct symtab_command *)lib_lc; count_func_symbols((struct nlist *) (lib_ofile.object_addr + lib_st->symoff), lib_st->nsyms, lib_ofile.object_addr + lib_st->stroff, lib_st->strsize); break; } else if(lib_lc->cmd == LC_SEGMENT){ sg = (struct segment_command *)lib_lc; s = (struct section *) ((char *)sg + sizeof(struct segment_command)); for(k = 0; k < sg->nsects; k++){ if(strcmp(s->sectname, SECT_TEXT) == 0 && strcmp(s->segname, SEG_TEXT) == 0){ shlib_text_ranges = reallocate(shlib_text_ranges, (nshlib_text_ranges + 1) * sizeof(struct shlib_text_range)); shlib_text_ranges[nshlib_text_ranges].lowpc = s->addr; shlib_text_ranges[nshlib_text_ranges].highpc = s->addr + s->size; nshlib_text_ranges++; } s++; } } lib_lc = (struct load_command *) ((char *)lib_lc + lib_lc->cmdsize); } done_and_unmap1: ofile_unmap(&lib_ofile); done1: ; } #endif else if(st == NULL && lc->cmd == LC_SYMTAB){ st = (struct symtab_command *)lc; if(ofile.mh != NULL){ symbols = (struct nlist *) (ofile.object_addr + st->symoff); symbols64 = NULL; } else{ symbols64 = (struct nlist_64 *) (ofile.object_addr + st->symoff); symbols = NULL; } count_func_symbols(symbols, symbols64, st->nsyms, ofile.object_addr + st->stroff, st->strsize); count_N_SO_stabs(symbols, symbols64, st->nsyms, ofile.object_addr + st->stroff, st->strsize); } lc = (struct load_command *)((char *)lc + lc->cmdsize); } if(nname == 0) fatal("executable file %s: has no symbols", a_outname); /* * Allocate the data structures for the symbols and files. */ nl = (nltype *)calloc(nname + 2, sizeof(nltype)); if(nl == NULL) fatal("No room for %lu bytes of symbol table\n", (nname + 2) * sizeof(nltype)); npe = nl; files = (struct file *)calloc(n_files/2, sizeof(struct file)); if(files == NULL) fatal("No room for %lu bytes of file table\n", n_files/2 * sizeof(struct file)); n_files = 0; /* * Pass 2 load symbols and files. */ if(st != NULL){ if(ofile.mh != NULL){ symbols = (struct nlist *) (ofile.object_addr + st->symoff); symbols64 = NULL; } else{ symbols64 = (struct nlist_64 *) (ofile.object_addr + st->symoff); symbols = NULL; } load_func_symbols(symbols, symbols64, st->nsyms, ofile.object_addr + st->stroff, st->strsize, 0); load_files(symbols, symbols64, st->nsyms, ofile.object_addr + st->stroff, st->strsize); } #ifdef notdef lc = ofile.load_commands; for(i = 0; i < ofile.mh->ncmds; i++){ if(lc->cmd == LC_LOADFVMLIB){ fl = (struct fvmlib_command *)lc; lib_name = (char *)fl + fl->fvmlib.name.offset; if(ofile_map(lib_name, &host_arch_flag, NULL, &lib_ofile, FALSE) == TRUE){ lib_st = NULL; lib_lc = lib_ofile.load_commands; for(j = 0; j < lib_ofile.mh->ncmds; j++){ lib_lc = (struct load_command *) ((char *)lib_lc + lib_lc->cmdsize); if(lib_st == NULL && lib_lc->cmd == LC_SYMTAB){ lib_st = (struct symtab_command *)lib_lc; load_func_symbols((struct nlist *) (lib_ofile.object_addr + lib_st->symoff), lib_st->nsyms, lib_ofile.object_addr + lib_st->stroff, lib_st->strsize, 0); break; } } } } lc = (struct load_command *)((char *)lc + lc->cmdsize); } #endif npe->value = text_highpc; npe->name = "past end of text"; npe++; nname++; if(ofile.mh != NULL) npe->value = npe->svalue = 0xffffffff; else npe->value = npe->svalue = 0xffffffffffffffffULL; npe->name = "top of memory"; qsort(nl, nname, sizeof(nltype), (int (*)(const void *, const void *))valcmp); #ifdef DEBUG if(debug & AOUTDEBUG){ for(i = 0; i < nname; i++){ printf("[getnfile] "); if(ofile.mh != NULL) printf("0x%08x", (unsigned int)nl[i].value); else printf("%016llx", nl[i].value); printf("\t%s\n", nl[i].name); } } #endif /* DEBUG */ }