📄 linker.c
字号:
in the output file. If the value is <<discard_l>>, then all local symbols which begin with a certain prefix are discarded; this is controlled by the <<bfd_is_local_label_name>> entry point. The a.out backend handles symbols by calling <<aout_link_write_symbols>> on each input BFD and then traversing the global hash table with the function <<aout_link_write_other_symbol>>. It builds a string table while writing out the symbols, which is written to the output file at the end of <<NAME(aout,final_link)>>.*/static boolean generic_link_read_symbols PARAMS ((bfd *));static boolean generic_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *, boolean collect));static boolean generic_link_add_object_symbols PARAMS ((bfd *, struct bfd_link_info *, boolean collect));static boolean generic_link_check_archive_element_no_collect PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded));static boolean generic_link_check_archive_element_collect PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded));static boolean generic_link_check_archive_element PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded, boolean collect));static boolean generic_link_add_symbol_list PARAMS ((bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **, boolean collect));static bfd *hash_entry_bfd PARAMS ((struct bfd_link_hash_entry *));static void set_symbol_from_hash PARAMS ((asymbol *, struct bfd_link_hash_entry *));static boolean generic_add_output_symbol PARAMS ((bfd *, size_t *psymalloc, asymbol *));static boolean default_fill_link_order PARAMS ((bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *));static boolean default_indirect_link_order PARAMS ((bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *, boolean));/* The link hash table structure is defined in bfdlink.h. It provides a base hash table which the backend specific hash tables are built upon. *//* Routine to create an entry in the link hash table. */struct bfd_hash_entry *_bfd_link_hash_newfunc (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; const char *string;{ struct bfd_link_hash_entry *ret = (struct bfd_link_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (ret == (struct bfd_link_hash_entry *) NULL) ret = ((struct bfd_link_hash_entry *) bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry))); if (ret == (struct bfd_link_hash_entry *) NULL) return NULL; /* Call the allocation method of the superclass. */ ret = ((struct bfd_link_hash_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); if (ret) { /* Initialize the local fields. */ ret->type = bfd_link_hash_new; ret->next = NULL; } return (struct bfd_hash_entry *) ret;}/* Initialize a link hash table. The BFD argument is the one responsible for creating this table. */boolean_bfd_link_hash_table_init (table, abfd, newfunc) struct bfd_link_hash_table *table; bfd *abfd; struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));{ table->creator = abfd->xvec; table->undefs = NULL; table->undefs_tail = NULL; return bfd_hash_table_init (&table->table, newfunc);}/* Look up a symbol in a link hash table. If follow is true, we follow bfd_link_hash_indirect and bfd_link_hash_warning links to the real symbol. */struct bfd_link_hash_entry *bfd_link_hash_lookup (table, string, create, copy, follow) struct bfd_link_hash_table *table; const char *string; boolean create; boolean copy; boolean follow;{ struct bfd_link_hash_entry *ret; ret = ((struct bfd_link_hash_entry *) bfd_hash_lookup (&table->table, string, create, copy)); if (follow && ret != (struct bfd_link_hash_entry *) NULL) { while (ret->type == bfd_link_hash_indirect || ret->type == bfd_link_hash_warning) ret = ret->u.i.link; } return ret;}/* Look up a symbol in the main linker hash table if the symbol might be wrapped. This should only be used for references to an undefined symbol, not for definitions of a symbol. */struct bfd_link_hash_entry *bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow) bfd *abfd; struct bfd_link_info *info; const char *string; boolean create; boolean copy; boolean follow;{ if (info->wrap_hash != NULL) { const char *l; l = string; if (*l == bfd_get_symbol_leading_char (abfd)) ++l;#undef WRAP#define WRAP "__wrap_" if (bfd_hash_lookup (info->wrap_hash, l, false, false) != NULL) { char *n; struct bfd_link_hash_entry *h; /* This symbol is being wrapped. We want to replace all references to SYM with references to __wrap_SYM. */ n = (char *) bfd_malloc (strlen (l) + sizeof WRAP + 1); if (n == NULL) return NULL; /* Note that symbol_leading_char may be '\0'. */ n[0] = bfd_get_symbol_leading_char (abfd); n[1] = '\0'; strcat (n, WRAP); strcat (n, l); h = bfd_link_hash_lookup (info->hash, n, create, true, follow); free (n); return h; }#undef WRAP#undef REAL#define REAL "__real_" if (*l == '_' && strncmp (l, REAL, sizeof REAL - 1) == 0 && bfd_hash_lookup (info->wrap_hash, l + sizeof REAL - 1, false, false) != NULL) { char *n; struct bfd_link_hash_entry *h; /* This is a reference to __real_SYM, where SYM is being wrapped. We want to replace all references to __real_SYM with references to SYM. */ n = (char *) bfd_malloc (strlen (l + sizeof REAL - 1) + 2); if (n == NULL) return NULL; /* Note that symbol_leading_char may be '\0'. */ n[0] = bfd_get_symbol_leading_char (abfd); n[1] = '\0'; strcat (n, l + sizeof REAL - 1); h = bfd_link_hash_lookup (info->hash, n, create, true, follow); free (n); return h; }#undef REAL } return bfd_link_hash_lookup (info->hash, string, create, copy, follow);}/* Traverse a generic link hash table. The only reason this is not a macro is to do better type checking. This code presumes that an argument passed as a struct bfd_hash_entry * may be caught as a struct bfd_link_hash_entry * with no explicit cast required on the call. */voidbfd_link_hash_traverse (table, func, info) struct bfd_link_hash_table *table; boolean (*func) PARAMS ((struct bfd_link_hash_entry *, PTR)); PTR info;{ bfd_hash_traverse (&table->table, ((boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) func), info);}/* Add a symbol to the linker hash table undefs list. */INLINE voidbfd_link_add_undef (table, h) struct bfd_link_hash_table *table; struct bfd_link_hash_entry *h;{ BFD_ASSERT (h->next == NULL); if (table->undefs_tail != (struct bfd_link_hash_entry *) NULL) table->undefs_tail->next = h; if (table->undefs == (struct bfd_link_hash_entry *) NULL) table->undefs = h; table->undefs_tail = h;}/* Routine to create an entry in an generic link hash table. */struct bfd_hash_entry *_bfd_generic_link_hash_newfunc (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; const char *string;{ struct generic_link_hash_entry *ret = (struct generic_link_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (ret == (struct generic_link_hash_entry *) NULL) ret = ((struct generic_link_hash_entry *) bfd_hash_allocate (table, sizeof (struct generic_link_hash_entry))); if (ret == (struct generic_link_hash_entry *) NULL) return NULL; /* Call the allocation method of the superclass. */ ret = ((struct generic_link_hash_entry *) _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); if (ret) { /* Set local fields. */ ret->written = false; ret->sym = NULL; } return (struct bfd_hash_entry *) ret;}/* Create an generic link hash table. */struct bfd_link_hash_table *_bfd_generic_link_hash_table_create (abfd) bfd *abfd;{ struct generic_link_hash_table *ret; ret = ((struct generic_link_hash_table *) bfd_alloc (abfd, sizeof (struct generic_link_hash_table))); if (ret == NULL) return (struct bfd_link_hash_table *) NULL; if (! _bfd_link_hash_table_init (&ret->root, abfd, _bfd_generic_link_hash_newfunc)) { free (ret); return (struct bfd_link_hash_table *) NULL; } return &ret->root;}/* Grab the symbols for an object file when doing a generic link. We store the symbols in the outsymbols field. We need to keep them around for the entire link to ensure that we only read them once. If we read them multiple times, we might wind up with relocs and the hash table pointing to different instances of the symbol structure. */static booleangeneric_link_read_symbols (abfd) bfd *abfd;{ if (bfd_get_outsymbols (abfd) == (asymbol **) NULL) { long symsize; long symcount; symsize = bfd_get_symtab_upper_bound (abfd); if (symsize < 0) return false; bfd_get_outsymbols (abfd) = (asymbol **) bfd_alloc (abfd, symsize); if (bfd_get_outsymbols (abfd) == NULL && symsize != 0) return false; symcount = bfd_canonicalize_symtab (abfd, bfd_get_outsymbols (abfd)); if (symcount < 0) return false; bfd_get_symcount (abfd) = symcount; } return true;}/* Generic function to add symbols to from an object file to the global hash table. This version does not automatically collect constructors by name. */boolean_bfd_generic_link_add_symbols (abfd, info) bfd *abfd; struct bfd_link_info *info;{ return generic_link_add_symbols (abfd, info, false);}/* Generic function to add symbols from an object file to the global hash table. This version automatically collects constructors by name, as the collect2 program does. It should be used for any target which does not provide some other mechanism for setting up constructors and destructors; these are approximately those targets for which gcc uses collect2 and do not support stabs. */boolean_bfd_generic_link_add_symbols_collect (abfd, info) bfd *abfd; struct bfd_link_info *info;{ return generic_link_add_symbols (abfd, info, true);}/* Add symbols from an object file to the global hash table. */static booleangeneric_link_add_symbols (abfd, info, collect) bfd *abfd; struct bfd_link_info *info; boolean collect;{ boolean ret; switch (bfd_get_format (abfd)) { case bfd_object: ret = generic_link_add_object_symbols (abfd, info, collect); break; case bfd_archive: ret = (_bfd_generic_link_add_archive_symbols (abfd, info, (collect ? generic_link_check_archive_element_collect : generic_link_check_archive_element_no_collect))); break; default: bfd_set_error (bfd_error_wrong_format); ret = false; } return ret;}/* Add symbols from an object file to the global hash table. */static booleangeneric_link_add_object_symbols (abfd, info, collect) bfd *abfd; struct bfd_link_info *info; boolean collect;{ if (! generic_link_read_symbols (abfd)) return false; return generic_link_add_symbol_list (abfd, info, _bfd_generic_link_get_symcount (abfd), _bfd_generic_link_get_symbols (abfd), collect);}/* We build a hash table of all symbols defined in an archive. *//* An archive symbol may be defined by multiple archive elements.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -