ldmain.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,328 行 · 第 1/3 页
C
1,328 行
} END_PROGRESS (program_name); if (config.stats) {#ifdef HAVE_SBRK char *lim = (char *) sbrk (0);#endif long run_time = get_run_time () - start_time; fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"), program_name, run_time / 1000000, run_time % 1000000);#ifdef HAVE_SBRK fprintf (stderr, _("%s: data size %ld\n"), program_name, (long) (lim - (char *) &environ));#endif } /* Prevent remove_output from doing anything, after a successful link. */ output_filename = NULL; xexit (0); return 0;}/* We need to find any explicitly given emulation in order to initialize the state that's needed by the lex&yacc argument parser (parse_args). */static char *get_emulation (argc, argv) int argc; char **argv;{ char *emulation; int i; emulation = getenv (EMULATION_ENVIRON); if (emulation == NULL) emulation = DEFAULT_EMULATION; for (i = 1; i < argc; i++) { if (!strncmp (argv[i], "-m", 2)) { if (argv[i][2] == '\0') { /* -m EMUL */ if (i < argc - 1) { emulation = argv[i + 1]; i++; } else { einfo (_("%P%F: missing argument to -m\n")); } } else if (strcmp (argv[i], "-mips1") == 0 || strcmp (argv[i], "-mips2") == 0 || strcmp (argv[i], "-mips3") == 0 || strcmp (argv[i], "-mips4") == 0) { /* FIXME: The arguments -mips1, -mips2 and -mips3 are passed to the linker by some MIPS compilers. They generally tell the linker to use a slightly different library path. Perhaps someday these should be implemented as emulations; until then, we just ignore the arguments and hope that nobody ever creates emulations named ips1, ips2 or ips3. */ } else if (strcmp (argv[i], "-m486") == 0) { /* FIXME: The argument -m486 is passed to the linker on some Linux systems. Hope that nobody creates an emulation named 486. */ } else { /* -mEMUL */ emulation = &argv[i][2]; } } } return emulation;}/* If directory DIR contains an "ldscripts" subdirectory, add DIR to the library search path and return true, else return false. */static booleancheck_for_scripts_dir (dir) char *dir;{ size_t dirlen; char *buf; struct stat s; boolean res; dirlen = strlen (dir); /* sizeof counts the terminating NUL. */ buf = (char *) xmalloc (dirlen + sizeof ("/ldscripts")); sprintf (buf, "%s/ldscripts", dir); res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode); free (buf); if (res) ldfile_add_library_path (dir, false); return res;}/* Set the default directory for finding script files. Libraries will be searched for here too, but that's ok. We look for the "ldscripts" directory in: SCRIPTDIR (passed from Makefile) the dir where this program is (for using it from the build tree) the dir where this program is/../lib (for installing the tool suite elsewhere) */static voidset_scripts_dir (){ char *end, *dir; size_t dirlen; if (check_for_scripts_dir (SCRIPTDIR)) /* We've been installed normally. */ return; /* Look for "ldscripts" in the dir where our binary is. */ end = strrchr (program_name, '/');#ifdef HAVE_DOS_BASED_FILE_SYSTEM { /* We could have \foo\bar, or /foo\bar. */ char *bslash = strrchr (program_name, '\\'); if (end == NULL || (bslash != NULL && bslash > end)) end = bslash; }#endif if (end == NULL) { /* Don't look for ldscripts in the current directory. There is too much potential for confusion. */ return; } dirlen = end - program_name; /* Make a copy of program_name in dir. Leave room for later "/../lib". */ dir = (char *) xmalloc (dirlen + 8); strncpy (dir, program_name, dirlen); dir[dirlen] = '\0'; if (check_for_scripts_dir (dir)) /* Don't free dir. */ return; /* Look for "ldscripts" in <the dir where our binary is>/../lib. */ strcpy (dir + dirlen, "/../lib"); if (check_for_scripts_dir (dir)) return; /* Well, we tried. */ free (dir);}voidadd_ysym (name) const char *name;{ if (link_info.notice_hash == (struct bfd_hash_table *) NULL) { link_info.notice_hash = ((struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table))); if (! bfd_hash_table_init_n (link_info.notice_hash, bfd_hash_newfunc, 61)) einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); } if (bfd_hash_lookup (link_info.notice_hash, name, true, true) == (struct bfd_hash_entry *) NULL) einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));}/* Record a symbol to be wrapped, from the --wrap option. */voidadd_wrap (name) const char *name;{ if (link_info.wrap_hash == NULL) { link_info.wrap_hash = ((struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table))); if (! bfd_hash_table_init_n (link_info.wrap_hash, bfd_hash_newfunc, 61)) einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); } if (bfd_hash_lookup (link_info.wrap_hash, name, true, true) == NULL) einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));}/* Handle the -retain-symbols-file option. */voidadd_keepsyms_file (filename) const char *filename;{ FILE *file; char *buf; size_t bufsize; int c; if (link_info.strip == strip_some) einfo (_("%X%P: error: duplicate retain-symbols-file\n")); file = fopen (filename, "r"); if (file == (FILE *) NULL) { bfd_set_error (bfd_error_system_call); einfo ("%X%P: %s: %E\n", filename); return; } link_info.keep_hash = ((struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table))); if (! bfd_hash_table_init (link_info.keep_hash, bfd_hash_newfunc)) einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); bufsize = 100; buf = (char *) xmalloc (bufsize); c = getc (file); while (c != EOF) { while (isspace (c)) c = getc (file); if (c != EOF) { size_t len = 0; while (! isspace (c) && c != EOF) { buf[len] = c; ++len; if (len >= bufsize) { bufsize *= 2; buf = xrealloc (buf, bufsize); } c = getc (file); } buf[len] = '\0'; if (bfd_hash_lookup (link_info.keep_hash, buf, true, true) == (struct bfd_hash_entry *) NULL) einfo (_("%P%F: bfd_hash_lookup for insertion failed: %E\n")); } } if (link_info.strip != strip_none) einfo (_("%P: `-retain-symbols-file' overrides `-s' and `-S'\n")); link_info.strip = strip_some;}/* Callbacks from the BFD linker routines. *//* This is called when BFD has decided to include an archive member in a link. */static booleanadd_archive_element (info, abfd, name) struct bfd_link_info *info ATTRIBUTE_UNUSED; bfd *abfd; const char *name;{ lang_input_statement_type *input; input = ((lang_input_statement_type *) xmalloc (sizeof (lang_input_statement_type))); input->filename = abfd->filename; input->local_sym_name = abfd->filename; input->the_bfd = abfd; input->asymbols = NULL; input->next = NULL; input->just_syms_flag = false; input->loaded = false; input->search_dirs_flag = false; /* FIXME: The following fields are not set: header.next, header.type, closed, passive_position, symbol_count, next_real_file, is_archive, target, real. This bit of code is from the old decode_library_subfile function. I don't know whether any of those fields matters. */ ldlang_add_file (input); if (config.map_file != (FILE *) NULL) { static boolean header_printed; struct bfd_link_hash_entry *h; bfd *from; int len; h = bfd_link_hash_lookup (link_info.hash, name, false, false, true); if (h == NULL) from = NULL; else { switch (h->type) { default: from = NULL; break; case bfd_link_hash_defined: case bfd_link_hash_defweak: from = h->u.def.section->owner; break; case bfd_link_hash_undefined: case bfd_link_hash_undefweak: from = h->u.undef.abfd; break; case bfd_link_hash_common: from = h->u.c.p->section->owner; break; } } if (! header_printed) { char buf[100]; sprintf (buf, "%-29s %s\n\n", _("Archive member included"), _("because of file (symbol)")); minfo ("%s", buf); header_printed = true; } if (bfd_my_archive (abfd) == NULL) { minfo ("%s", bfd_get_filename (abfd)); len = strlen (bfd_get_filename (abfd)); } else { minfo ("%s(%s)", bfd_get_filename (bfd_my_archive (abfd)), bfd_get_filename (abfd)); len = (strlen (bfd_get_filename (bfd_my_archive (abfd))) + strlen (bfd_get_filename (abfd)) + 2); } if (len >= 29) { print_nl (); len = 0; } while (len < 30) { print_space (); ++len; } if (from != NULL) minfo ("%B ", from); if (h != NULL) minfo ("(%T)\n", h->root.string); else minfo ("(%s)\n", name); } if (trace_files || trace_file_tries) info_msg ("%I\n", input); return true;}/* This is called when BFD has discovered a symbol which is defined multiple times. */static booleanmultiple_definition (info, name, obfd, osec, oval, nbfd, nsec, nval) struct bfd_link_info *info ATTRIBUTE_UNUSED; const char *name; bfd *obfd; asection *osec; bfd_vma oval; bfd *nbfd; asection *nsec; bfd_vma nval;{ /* If either section has the output_section field set to bfd_abs_section_ptr, it means that the section is being discarded, and this is not really a multiple definition at all. FIXME: It would be cleaner to somehow ignore symbols defined in sections which are being discarded. */ if ((osec->output_section != NULL && ! bfd_is_abs_section (osec) && bfd_is_abs_section (osec->output_section)) || (nsec->output_section != NULL && ! bfd_is_abs_section (nsec) && bfd_is_abs_section (nsec->output_section))) return true; einfo (_("%X%C: multiple definition of `%T'\n"), nbfd, nsec, nval, name); if (obfd != (bfd *) NULL) einfo (_("%D: first defined here\n"), obfd, osec, oval); if (command_line.relax) { einfo (_("%P: Disabling relaxation: it will not work with multiple definitions\n")); command_line.relax = 0; } return true;}/* This is called when there is a definition of a common symbol, or when a common symbol is found for a symbol that is already defined, or when two common symbols are found. We only do something if -warn-common was used. */static booleanmultiple_common (info, name, obfd, otype, osize, nbfd, ntype, nsize) struct bfd_link_info *info ATTRIBUTE_UNUSED; const char *name; bfd *obfd; enum bfd_link_hash_type otype; bfd_vma osize; bfd *nbfd;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?