📄 ld.c
字号:
Return 1 if the argument is a option complete in itself. Return 2 if the argument is a option which uses an argument. Thus, the value is the number of consecutive arguments that are part of options. */intclassify_arg (arg) register char *arg;{ if (*arg != '-') return 0; switch (arg[1]) { case 'A': case 'D': case 'e': case 'L': case 'l': case 'o': case 'u': case 'V': case 'y': if (arg[2]) return 1; return 2; case 'B': if (! strcmp (&arg[2], "static")) return 1; case 'T': if (arg[2] == 0) return 2; if (! strcmp (&arg[2], "text")) return 2; if (! strcmp (&arg[2], "data")) return 2; return 1; } return 1;}/* Process the command arguments, setting up file_table with an entry for each input file, and setting variables according to the options. */voiddecode_command (argc, argv) char **argv; int argc;{ register int i; register struct file_entry *p; char *cp; number_of_files = 0; output_filename = "a.out"; n_search_dirs = 0; search_dirs = (char **) xmalloc (sizeof (char *)); /* First compute number_of_files so we know how long to make file_table. */ /* Also process most options completely. */ for (i = 1; i < argc; i++) { register int code = classify_arg (argv[i]); if (code) { if (i + code > argc) fatal ("no argument following %s\n", argv[i]); decode_option (argv[i], argv[i+1]); if (argv[i][1] == 'l' || argv[i][1] == 'A') number_of_files++; i += code - 1; } else number_of_files++; } if (!number_of_files) fatal ("no input files", 0); p = file_table = (struct file_entry *) xmalloc (number_of_files * sizeof (struct file_entry)); bzero (p, number_of_files * sizeof (struct file_entry)); /* Now scan again and fill in file_table. */ /* All options except -A and -l are ignored here. */ for (i = 1; i < argc; i++) { register int code = classify_arg (argv[i]); if (code) { char *string; if (code == 2) string = argv[i+1]; else string = &argv[i][2]; if (argv[i][1] == 'A') { if (p != file_table) fatal ("-A specified before an input file other than the first"); p->filename = string; p->local_sym_name = string; p->just_syms_flag = 1; p++; } if (argv[i][1] == 'l') { if (cp = rindex(string, '/')) { *cp++ = '\0'; cp = concat (string, "/lib", cp); p->filename = concat (cp, ".a", ""); } else p->filename = concat ("lib", string, ".a"); p->local_sym_name = concat ("-l", string, ""); p->search_dirs_flag = 1; p++; } i += code - 1; } else { p->filename = argv[i]; p->local_sym_name = argv[i]; p++; } } /* Now check some option settings for consistency. */#ifdef NMAGIC if ((magic == ZMAGIC || magic == NMAGIC)#else if ((magic == ZMAGIC)#endif && (text_start - text_start_alignment) & (page_size - 1)) fatal ("-T argument not multiple of page size, with sharable output", 0); /* Append the standard search directories to the user-specified ones. */ { int n = sizeof standard_search_dirs / sizeof standard_search_dirs[0]; n_search_dirs += n; search_dirs = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *)); bcopy (standard_search_dirs, &search_dirs[n_search_dirs - n], n * sizeof (char *)); }}voidadd_cmdline_ref (sp) struct glosym *sp;{ struct glosym **ptr; for (ptr = cmdline_references; ptr < cmdline_references + cl_refs_allocated && *ptr; ptr++) ; if (ptr >= cmdline_references + cl_refs_allocated - 1) { int diff = ptr - cmdline_references; cl_refs_allocated *= 2; cmdline_references = (struct glosym **) xrealloc (cmdline_references, cl_refs_allocated * sizeof (struct glosym *)); ptr = cmdline_references + diff; } *ptr++ = sp; *ptr = (struct glosym *) 0;}intset_element_prefixed_p (name) char *name;{ struct string_list_element *p; int i; for (p = set_element_prefixes; p; p = p->next) { for (i = 0; p->str[i] != '\0' && (p->str[i] == name[i]); i++) ; if (p->str[i] == '\0') return 1; } return 0;}int parse ();/* Record an option and arrange to act on it later. ARG should be the following command argument, which may or may not be used by this option. The `l' and `A' options are ignored here since they actually specify input files. */voiddecode_option (swt, arg) register char *swt, *arg;{ /* We get Bstatic from gcc on suns. */ if (! strcmp (swt + 1, "Bstatic")) return; if (! strcmp (swt + 1, "Ttext")) { text_start = parse (arg, "%x", "invalid argument to -Ttext"); T_flag_specified = 1; return; } if (! strcmp (swt + 1, "Tdata")) { data_start = parse (arg, "%x", "invalid argument to -Tdata"); Tdata_flag_specified = 1; return; } if (! strcmp (swt + 1, "noinhibit-exec")) { force_executable = 1; return; } if (swt[2] != 0) arg = &swt[2]; switch (swt[1]) { case 'A': return; case 'D': specified_data_size = parse (arg, "%x", "invalid argument to -D"); return; case 'd': force_common_definition = 1; return; case 'e': entry_symbol = getsym (arg); if (!entry_symbol->defined && !entry_symbol->referenced) undefined_global_sym_count++; entry_symbol->referenced = 1; add_cmdline_ref (entry_symbol); return; case 'l': /* If linking with libg++, use the C++ demangler. */ if (arg != NULL && strcmp (arg, "g++") == 0) demangler = cplus_demangle; return; case 'L': n_search_dirs++; search_dirs = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *)); search_dirs[n_search_dirs - 1] = arg; return; case 'M': write_map = 1; return; case 'N': magic = OMAGIC; return;#ifdef NMAGIC case 'n': magic = NMAGIC; return;#endif case 'o': output_filename = arg; return; case 'p': padtext = 1; return; case 'r': relocatable_output = 1; magic = OMAGIC; text_start = 0; return; case 'S': strip_symbols = STRIP_DEBUGGER; return; case 's': strip_symbols = STRIP_ALL; return; case 'T': text_start = parse (arg, "%x", "invalid argument to -T"); T_flag_specified = 1; return; case 't': trace_files = 1; return; case 'u': { register symbol *sp = getsym (arg); if (!sp->defined && !sp->referenced) undefined_global_sym_count++; sp->referenced = 1; add_cmdline_ref (sp); } return; case 'V': { struct string_list_element *new = (struct string_list_element *) xmalloc (sizeof (struct string_list_element)); new->str = arg; new->next = set_element_prefixes; set_element_prefixes = new; return; } case 'X': discard_locals = DISCARD_L; return; case 'x': discard_locals = DISCARD_ALL; return; case 'y': { register symbol *sp = getsym (&swt[2]); sp->trace = 1; } return; case 'z': magic = ZMAGIC; return; default: fatal ("invalid command option `%s'", swt); }}/** Convenient functions for operating on one or all files being */ /** loaded. */void print_file_name ();/* Call FUNCTION on each input file entry. Do not call for entries for libraries; instead, call once for each library member that is being loaded. FUNCTION receives two arguments: the entry, and ARG. */voideach_file (function, arg) register void (*function)(); register int arg;{ register int i; for (i = 0; i < number_of_files; i++) { register struct file_entry *entry = &file_table[i]; if (entry->library_flag) { register struct file_entry *subentry = entry->subfiles; for (; subentry; subentry = subentry->chain) (*function) (subentry, arg); } else (*function) (entry, arg); }}/* Call FUNCTION on each input file entry until it returns a non-zero value. Return this value. Do not call for entries for libraries; instead, call once for each library member that is being loaded. FUNCTION receives two arguments: the entry, and ARG. It must be a function returning unsigned long (though this can probably be fudged). */unsigned longcheck_each_file (function, arg) register unsigned long (*function)(); register int arg;{ register int i; register unsigned long return_val; for (i = 0; i < number_of_files; i++) { register struct file_entry *entry = &file_table[i]; if (entry->library_flag) { register struct file_entry *subentry = entry->subfiles; for (; subentry; subentry = subentry->chain) if (return_val = (*function) (subentry, arg)) return return_val; } else if (return_val = (*function) (entry, arg)) return return_val; } return 0;}/* Like `each_file' but ignore files that were just for symbol definitions. */voideach_full_file (function, arg) register void (*function)(); register int arg;{ register int i; for (i = 0; i < number_of_files; i++) { register struct file_entry *entry = &file_table[i]; if (entry->just_syms_flag) continue; if (entry->library_flag) { register struct file_entry *subentry = entry->subfiles; for (; subentry; subentry = subentry->chain) (*function) (subentry, arg); } else (*function) (entry, arg); }}/* Close the input file that is now open. */voidfile_close (){ close (input_desc); input_desc = 0; input_file = 0;}/* Open the input file specified by 'entry', and return a descriptor. The open file is remembered; if the same file is opened twice in a row, a new open is not actually done. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -