int main( int argc, char **argv, char **envp) { int i; unsigned long j; struct arch_flag *arch_flags; unsigned long narch_flags; enum bool all_archs; char **files; progname = argv[0]; arch_flags = NULL; narch_flags = 0; all_archs = FALSE; output = stdout; cmd_flags.nfiles = 0; cmd_flags.c = FALSE; cmd_flags.x = FALSE; cmd_flags.ofile_name = NULL; cmd_flags.ofile_path = NULL; files = allocate(sizeof(char *) * argc); for(i = 1; i < argc; i++){ if(argv[i][0] == '-'){ if(argv[i][1] == '\0'){ for( ; i < argc; i++) files[cmd_flags.nfiles++] = argv[i]; break; } if(strcmp(argv[i], "-arch") == 0){ if(i + 1 == argc){ error("missing argument(s) to %s option", argv[i]); usage(); } if(strcmp("all", argv[i+1]) == 0){ all_archs = TRUE; } else{ arch_flags = reallocate(arch_flags, (narch_flags + 1) * sizeof(struct arch_flag)); if(get_arch_from_flag(argv[i+1], arch_flags + narch_flags) == 0){ error("unknown architecture specification flag: " "%s %s", argv[i], argv[i+1]); arch_usage(); usage(); } narch_flags++; } i++; } else{ for(j = 1; argv[i][j] != '\0'; j++){ switch(argv[i][j]){ case 'c': cmd_flags.c = TRUE; break; case 'x': cmd_flags.x = TRUE; break; case 'n': cmd_flags.n = TRUE; break; case 'o': cmd_flags.o = TRUE; break; default: error("invalid argument -%c", argv[i][j]); usage(); } } if(cmd_flags.n == TRUE && cmd_flags.ofile_name == NULL){ if(i + 1 == argc){ error("missing arguments to -n"); usage(); } cmd_flags.ofile_name = upper_string(argv[i+1]); i += 1; } if(cmd_flags.o == TRUE && cmd_flags.ofile_path == NULL){ if(i + 1 == argc){ error("missing arguments to -o"); usage(); } cmd_flags.ofile_path = argv[i+1]; i += 1; } } continue; } files[cmd_flags.nfiles++] = argv[i]; } if (cmd_flags.ofile_name == NULL) { if (cmd_flags.nfiles == 0) cmd_flags.ofile_name = upper_string("a.out"); else cmd_flags.ofile_name = upper_string(files[0]); } if (cmd_flags.o == TRUE) { output = fopen(cmd_flags.ofile_path, "w"); if (output == NULL) { error("couldn't open output file %s\n",cmd_flags.ofile_path); output = stdout; } } for(j = 0; j < cmd_flags.nfiles; j++) ofile_process(files[j], arch_flags, narch_flags, all_archs, FALSE, FALSE, TRUE, nm, &cmd_flags); if(cmd_flags.nfiles == 0) ofile_process("a.out", arch_flags, narch_flags, all_archs, FALSE, FALSE, TRUE, nm, &cmd_flags); if (cmd_flags.ofile_name != NULL) free(cmd_flags.ofile_name); if(errors == 0) return(EXIT_SUCCESS); else return(EXIT_FAILURE); }
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); }
/* * The codesign_allocate(1) tool has the following usage: * * codesign_allocate -i oldfile -a arch size ... -o newfile * * Where the oldfile is a Mach-O file that is input for the dynamic linker * and it creates or adds an */ int main( int argc, char **argv, char **envp) { uint32_t i; char *input, *output, *endp; struct arch *archs; uint32_t narchs; progname = argv[0]; input = NULL; output = NULL; archs = NULL; narchs = 0; for(i = 1; i < argc; i++) { if(strcmp(argv[i], "-i") == 0) { if(i + 1 == argc) { error("missing argument to: %s option", argv[i]); usage(); } if(input != NULL) { error("more than one: %s option specified", argv[i]); usage(); } input = argv[i+1]; i++; } else if(strcmp(argv[i], "-o") == 0) { if(i + 1 == argc) { error("missing argument to: %s option", argv[i]); usage(); } if(output != NULL) { error("more than one: %s option specified", argv[i]); usage(); } output = argv[i+1]; i++; } else if(strcmp(argv[i], "-a") == 0) { if(i + 2 == argc) { error("missing argument(s) to: %s option", argv[i]); usage(); } else { arch_signs = reallocate(arch_signs, (narch_signs + 1) * sizeof(struct arch_sign)); if(get_arch_from_flag(argv[i+1], &(arch_signs[narch_signs].arch_flag)) == 0) { error("unknown architecture specification flag: " "%s %s %s", argv[i], argv[i+1], argv[i+2]); arch_usage(); usage(); } arch_signs[narch_signs].datasize = strtoul(argv[i+2], &endp, 0); if(*endp != '\0') fatal("size for '-a %s %s' not a proper number", argv[i+1], argv[i+2]); if((arch_signs[narch_signs].datasize % 16) != 0) fatal("size for '-a %s %s' not a multiple of 16", argv[i+1], argv[i+2]); arch_signs[narch_signs].found = FALSE; narch_signs++; i += 2; } } else if(strcmp(argv[i], "-A") == 0) { if(i + 3 == argc) { error("missing argument(s) to: %s option", argv[i]); usage(); } else { arch_signs = reallocate(arch_signs, (narch_signs + 1) * sizeof(struct arch_sign)); arch_signs[narch_signs].arch_flag.cputype = strtoul(argv[i+1], &endp, 0); if(*endp != '\0') fatal("cputype for '-A %s %s %s' not a proper number", argv[i+1], argv[i+2], argv[i+3]); arch_signs[narch_signs].arch_flag.cpusubtype = strtoul(argv[i+2], &endp, 0); if(*endp != '\0') fatal("cpusubtype for '-A %s %s %s' not a proper " "number", argv[i+1], argv[i+2], argv[i+3]); arch_signs[narch_signs].arch_flag.name = (char *) get_arch_name_from_types( arch_signs[narch_signs].arch_flag.cputype, arch_signs[narch_signs].arch_flag.cpusubtype); arch_signs[narch_signs].datasize = strtoul(argv[i+3], &endp, 0); if(*endp != '\0') fatal("size for '-A %s %s %s' not a proper number", argv[i+1], argv[i+2], argv[i+3]); if((arch_signs[narch_signs].datasize % 16) != 0) fatal("size for '-A %s %s %s' not a multiple of 16", argv[i+1], argv[i+2], argv[i+3]); arch_signs[narch_signs].found = FALSE; narch_signs++; i += 3; } } else { error("unknown flag: %s", argv[i]); usage(); } } if(input == NULL || output == NULL || narch_signs == 0) usage(); breakout(input, &archs, &narchs, FALSE); if(errors) exit(EXIT_FAILURE); checkout(archs, narchs); process(archs, narchs); for(i = 0; i < narch_signs; i++) { if(arch_signs[i].found == FALSE) fatal("input file: %s does not contain a matching architecture " "for specified '-a %s %u' option", input, arch_signs[i].arch_flag.name, arch_signs[i].datasize); } writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); else return(EXIT_SUCCESS); }
/* * The ctf_insert(1) tool has the following usage: * * ctf_insert input -arch arch ctf_file ... -o output * * Where the input is a Mach-O file that is the ctf_file(s) are to be inserted * into and output is the file to be created. */ int main( int argc, char **argv, char **envp) { uint32_t i; char *input, *output, *contents; struct arch *archs; uint32_t narchs; struct stat stat_buf; int fd; progname = argv[0]; input = NULL; output = NULL; archs = NULL; narchs = 0; for(i = 1; i < argc; i++){ if(strcmp(argv[i], "-o") == 0){ if(i + 1 == argc){ error("missing argument to: %s option", argv[i]); usage(); } if(output != NULL){ error("more than one: %s option specified", argv[i]); usage(); } output = argv[i+1]; i++; } else if(strcmp(argv[i], "-arch") == 0){ if(i + 2 == argc){ error("missing argument(s) to: %s option", argv[i]); usage(); } else{ arch_ctfs = reallocate(arch_ctfs, (narch_ctfs + 1) * sizeof(struct arch_ctf)); if(get_arch_from_flag(argv[i+1], &(arch_ctfs[narch_ctfs].arch_flag)) == 0){ error("unknown architecture specification flag: " "%s %s %s", argv[i], argv[i+1], argv[i+2]); arch_usage(); usage(); } if((fd = open(argv[i+2], O_RDONLY, 0)) == -1) system_fatal("can't open file: %s", argv[i+2]); if(fstat(fd, &stat_buf) == -1) system_fatal("can't stat file: %s", argv[i+2]); /* * For some reason mapping files with zero size fails * so it has to be handled specially. */ contents = NULL; if(stat_buf.st_size != 0){ contents = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); if((intptr_t)contents == -1) system_error("can't map file : %s", argv[i+2]); } arch_ctfs[narch_ctfs].filename = argv[i+2]; arch_ctfs[narch_ctfs].contents = contents; arch_ctfs[narch_ctfs].size = stat_buf.st_size; arch_ctfs[narch_ctfs].arch_found = FALSE; narch_ctfs++; i += 2; } } else{ if(input != NULL){ error("more than one input file file: %s specified", input); usage(); } input = argv[i]; } } if(input == NULL || output == NULL || narch_ctfs == 0) usage(); breakout(input, &archs, &narchs, FALSE); if(errors) exit(EXIT_FAILURE); checkout(archs, narchs); process(archs, narchs); for(i = 0; i < narch_ctfs; i++){ if(arch_ctfs[i].arch_found == FALSE) fatal("input file: %s does not contain a matching architecture " "for specified '-arch %s %s' option", input, arch_ctfs[i].arch_flag.name, arch_ctfs[i].filename); } writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); else return(EXIT_SUCCESS); }
int main( int argc, char **argv, char **envp) { int i; enum bool args_left; struct flags flag; struct arch_flag *arch_flags; unsigned long narch_flags; enum bool all_archs; progname = argv[0]; arch_flags = NULL; narch_flags = 0; all_archs = FALSE; flag.nfiles = 0; flag.m = FALSE; flag.l = FALSE; flag.x = FALSE; for(i = 1; i < argc; i++){ if(argv[i][0] == '-'){ if(argv[i][1] == '\0'){ flag.nfiles += argc - i - 1; break; } if(strcmp(argv[i], "-m") == 0){ flag.m = TRUE; continue; } if(strcmp(argv[i], "-l") == 0){ flag.l = TRUE; flag.m = TRUE; continue; } if(strcmp(argv[i], "-x") == 0){ flag.x = TRUE; flag.m = TRUE; continue; } if(strcmp(argv[i], "-arch") == 0){ if(i + 1 == argc){ error("missing argument(s) to %s option", argv[i]); usage(); } if(strcmp("all", argv[i+1]) == 0){ all_archs = TRUE; } else{ arch_flags = reallocate(arch_flags, (narch_flags + 1) * sizeof(struct arch_flag)); if(get_arch_from_flag(argv[i+1], arch_flags + narch_flags) == 0){ error("unknown architecture specification flag: " "%s %s", argv[i], argv[i+1]); arch_usage(); usage(); } narch_flags++; } i++; continue; } } flag.nfiles++; } if(flag.m == FALSE) printf("__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n"); args_left = TRUE; for (i = 1; i < argc; i++) { if(args_left == TRUE && argv[i][0] == '-'){ if(argv[i][1] == '\0'){ args_left = FALSE; continue; } if(strcmp(argv[i], "-m") == 0) continue; if(strcmp(argv[i], "-l") == 0) continue; if(strcmp(argv[i], "-x") == 0) continue; if(strcmp(argv[i], "-arch") == 0){ i++; continue; } } ofile_process(argv[i], arch_flags, narch_flags, all_archs, FALSE, TRUE, TRUE, size, &flag); } if(flag.nfiles == 0) ofile_process("a.out", arch_flags, narch_flags, all_archs, FALSE, TRUE, TRUE, size, &flag); if(errors == 0) return(EXIT_SUCCESS); else return(EXIT_FAILURE); }
int main( int argc, char **argv, char **envp) { struct flags flags; int i; uint32_t j, nfiles; char *endp; struct arch_flag *arch_flags; uint32_t narch_flags; enum bool all_archs, rest_args_files, use_member_syntax; struct stat stat_buf; progname = argv[0]; nfiles = 0; arch_flags = NULL; narch_flags = 0; all_archs = FALSE; flags.treat_as_data = FALSE; flags.print_offsets = FALSE; flags.offset_format = NULL; flags.all_sections = FALSE; flags.minimum_length = 4; rest_args_files = FALSE; for(i = 1; i < argc; i++){ if(rest_args_files == FALSE && argv[i][0] == '-'){ if(argv[i][1] == '\0') flags.treat_as_data = TRUE; else if(strcmp(argv[i], "--") == 0) rest_args_files = TRUE; else if(strcmp(argv[i], "-arch") == 0){ if(i + 1 == argc){ error("missing argument(s) to %s option", argv[i]); usage(); } if(strcmp("all", argv[i+1]) == 0){ all_archs = TRUE; } else{ arch_flags = reallocate(arch_flags, (narch_flags + 1) * sizeof(struct arch_flag)); if(get_arch_from_flag(argv[i+1], arch_flags + narch_flags) == 0){ error("unknown architecture specification flag: " "%s %s", argv[i], argv[i+1]); arch_usage(); usage(); } narch_flags++; } i++; } else if(strcmp(argv[i], "-n") == 0){ if(i + 1 == argc){ error("missing argument to %s option", argv[i]); usage(); } flags.minimum_length = strtoul(argv[i+1], &endp, 10); if(*endp != '\0'){ error("invalid decimal number in option: %s %s", argv[i], argv[i+1]); usage(); } i++; } else if(strcmp(argv[i], "-t") == 0){ if(i + 1 == argc){ error("missing argument to %s option", argv[i]); usage(); } if(argv[i+1][1] != '\0'){ error("invalid argument to option: %s %s", argv[i], argv[i+1]); usage(); } switch(argv[i+1][0]){ case 'd': flags.print_offsets = TRUE; flags.offset_format = "%d"; break; case 'o': flags.print_offsets = TRUE; flags.offset_format = "%o"; break; case 'x': flags.print_offsets = TRUE; flags.offset_format = "%x"; break; default: error("invalid argument to option: %s %s", argv[i], argv[i+1]); usage(); } i++; } else{ endp = NULL; for(j = 1; argv[i][j] != '\0' && endp == NULL; j++){ switch(argv[i][j]){ case 'o': flags.print_offsets = TRUE; flags.offset_format = "%7lu"; break; case 'a': flags.all_sections = TRUE; break; default: if(!isdigit(argv[i][j])){ error("unknown flag: %s", argv[i]); usage(); } flags.minimum_length = strtoul(argv[i]+j,&endp,10); if(*endp != '\0'){ error("invalid decimal number in flag: %s", argv[i]); usage(); } } } } } else{ nfiles++; } } /* * Process the file or stdin if there are no files. */ rest_args_files = FALSE; if(nfiles != 0){ for(i = 1; i < argc; i++){ if(argv[i][0] != '-' || rest_args_files == TRUE){ if(flags.treat_as_data == TRUE){ if(freopen(argv[i], "r", stdin) == NULL) system_error("can't open: %s", argv[i]); rewind(stdin); find(UINT_MAX, &flags); } else{ /* * If there's a filename that's an exact match then use * that, else fall back to the member syntax. */ if(stat(argv[i], &stat_buf) == 0) use_member_syntax = FALSE; else use_member_syntax = TRUE; ofile_process(argv[i], arch_flags, narch_flags, all_archs, TRUE, TRUE, use_member_syntax, ofile_processor,&flags); } } else if(strcmp(argv[i], "-arch") == 0 || strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "-t") == 0) i++; else if(strcmp(argv[i], "--") == 0) rest_args_files = TRUE; } } else{ find(UINT_MAX, &flags); } if(errors == 0) return(EXIT_SUCCESS); else return(EXIT_FAILURE); }
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) { int i; struct cmd_flags cmd_flags; unsigned long j, table_size; struct arch_flag *arch_flags; unsigned long narch_flags; enum bool all_archs; char **files; progname = argv[0]; arch_flags = NULL; narch_flags = 0; all_archs = FALSE; cmd_flags.nfiles = 0; cmd_flags.rldtype = FALSE; cmd_flags.detail = FALSE; cmd_flags.verification = FALSE; cmd_flags.trey = FALSE; cmd_flags.check_dynamic_binary = TRUE; files = allocate(sizeof(char *) * argc); for(i = 1; i < argc; i++){ if(argv[i][0] == '-'){ if(argv[i][1] == '\0'){ for( ; i < argc; i++) files[cmd_flags.nfiles++] = argv[i]; break; } else if(strcmp(argv[i], "-arch") == 0){ if(i + 1 == argc){ error("missing argument(s) to %s option", argv[i]); usage(); } if(strcmp("all", argv[i+1]) == 0){ all_archs = TRUE; } else{ arch_flags = reallocate(arch_flags, (narch_flags + 1) * sizeof(struct arch_flag)); if(get_arch_from_flag(argv[i+1], arch_flags + narch_flags) == 0){ error("unknown architecture specification flag: " "%s %s", argv[i], argv[i+1]); arch_usage(); usage(); } narch_flags++; } i++; } else if(strcmp(argv[i], "-dylib_table") == 0){ if(i + 1 == argc){ error("missing argument(s) to %s option", argv[i]); usage(); } if(dylib_table_name != NULL){ error("more than one: %s option", argv[i]); usage(); } dylib_table_name = argv[i+1]; dylib_table = parse_dylib_table(argv[i+1], argv[i], argv[i+1]); i++; } else if(strcmp(argv[i], "-seg_addr_table") == 0){ if(i + 1 == argc){ error("missing argument(s) to %s option", argv[i]); usage(); } if(seg_addr_table_specified == TRUE){ error("more than one: %s option", argv[i]); usage(); } seg_addr_table_specified = TRUE; seg_addr_table_name = argv[i+1]; seg_addr_table = parse_seg_addr_table(argv[i+1], argv[i], argv[i+1], &table_size); i++; } else if(strcmp(argv[i], "-seg_addr_table_filename") == 0){ if(i + 1 == argc){ error("missing argument(s) to %s option", argv[i]); usage(); } if(seg_addr_table_filename != NULL){ error("more than one: %s option", argv[i]); usage(); } seg_addr_table_filename = argv[i+1]; i++; } else{ for(j = 1; argv[i][j] != '\0'; j++){ switch(argv[i][j]){ case 'r': cmd_flags.rldtype = TRUE; break; case 'd': cmd_flags.detail = TRUE; break; case 'v': cmd_flags.verification = TRUE; break; case 't': cmd_flags.trey = TRUE; break; case 'b': cmd_flags.check_dynamic_binary = TRUE; break; default: error("invalid argument -%c", argv[i][j]); usage(); } } } continue; } files[cmd_flags.nfiles++] = argv[i]; } if(arch_flags == NULL) all_archs = TRUE; if(cmd_flags.nfiles != 1) usage(); for(j = 0; j < cmd_flags.nfiles; j++) ofile_process(files[j], arch_flags, narch_flags, all_archs, TRUE, TRUE, FALSE, checksyms, &cmd_flags); if(errors == 0) return(exit_status); else return(EXIT_FAILURE); }