位于lang_process()中11行 。 该函数用于创建与目标有关的输出段的语句。这些语句将用于描述输出段的属性和分配。
- void
- ldemul_create_output_section_statements (void)
- {
- if (ld_emulation->create_output_section_statements)
- ld_emulation->create_output_section_statements ();
- }
static ld_emulation_xfer_type *ld_emulation;
- /* Create any output sections needed by the target. */
- void (*create_output_section_statements) (void); // 14
- typedef struct ld_emulation_xfer_struct {
- /* Run before parsing the command line and script file.
- Set the architecture, maybe other things. */
- void (*before_parse) (void); // 1
-
- /* Handle the SYSLIB (low level library) script command. */
- void (*syslib) (char *); // 2
-
- /* Handle the HLL (high level library) script command. */
- void (*hll) (char *); // 3
-
- /* Run after parsing the command line and script file. */
- void (*after_parse) (void); // 4
-
- /* Run after opening all input files, and loading the symbols. */
- void (*after_open) (void); // 5
-
- /* Run after allocating output sections. */
- void (*after_allocation) (void); // 6
-
- /* Set the output architecture and machine if possible. */
- void (*set_output_arch) (void); // 7
-
- /* Decide which target name to use. */
- char * (*choose_target) (int, char**); // 8
-
- /* Run before allocating output sections. */
- void (*before_allocation) (void); // 9
-
- /* Return the appropriate linker script. */
- char * (*get_script) (int *isfile); // 10
-
- /* The name of this emulation. */
- char *emulation_name; // 11
-
- /* The output format. */
- char *target_name; // 12
-
- /* Run after assigning values from the script. */
- void (*finish) (void); // 13
-
- /* Create any output sections needed by the target. */
- void (*create_output_section_statements) (void); // 14
-
- /* Try to open a dynamic library. ARCH is an architecture name, and
- is normally the empty string. ENTRY is the lang_input_statement
- that should be opened. */
- bfd_boolean (*open_dynamic_archive)
- (const char *arch, struct search_dirs *,
- struct lang_input_statement_struct *entry); // 15
-
- /* Place an orphan section. Return TRUE if it was placed, FALSE if
- the default action should be taken. This field may be NULL, in
- which case the default action will always be taken. */
- lang_output_section_statement_type *(*place_orphan)
- (asection *, const char *, int); // 16
-
- /* Run after assigning parsing with the args, but before
- reading the script. Used to initialize symbols used in the script. */
- void (*set_symbols) (void); // 17
-
- /* Parse args which the base linker doesn't understand.
- Return TRUE if the arg needs no further processing. */
- bfd_boolean (*parse_args) (int, char **); // 18
-
- /* Hook to add options to parameters passed by the base linker to
- getopt_long and getopt_long_only calls. */
- void (*add_options)
- (int, char **, int, struct option **, int, struct option **); // 19
-
- /* Companion to the above to handle an option. Returns TRUE if it is
- one of our options. */
- bfd_boolean (*handle_option) (int); // 20
-
- /* Run to handle files which are not recognized as object files or
- archives. Return TRUE if the file was handled. */
- bfd_boolean (*unrecognized_file)
- (struct lang_input_statement_struct *); // 21
-
- /* Run to list the command line options which parse_args handles. */
- void (* list_options) (FILE *); // 22
-
- /* Run to specially handle files which *are* recognized as object
- files or archives. Return TRUE if the file was handled. */
- bfd_boolean (*recognized_file)
- (struct lang_input_statement_struct *); // 23
-
- /* Called when looking for libraries in a directory specified
- via a linker command line option or linker script option.
- Files that match the pattern "lib*.a" have already been scanned.
- (For VMS files matching ":lib*.a" have also been scanned). */
- int (* find_potential_libraries)
- (char *, struct lang_input_statement_struct *); // 24
-
- /* Called when adding a new version pattern. PowerPC64-ELF uses
- this hook to add a pattern matching ".foo" for every "foo". */
- struct bfd_elf_version_expr * (*new_vers_pattern)
- (struct bfd_elf_version_expr *); // 25
-
- /* Called when printing the map file, in case there are
- emulation-specific sections for it. */
- void (*extra_map_file_text)
- (bfd *, struct bfd_link_info *, FILE *); // 26
-
- } ld_emulation_xfer_type;
将命令行中所有未定义的符号加入哈希表中

结构体类型:
struct bfd_sym_chain:
typedef struct bfd_sym_chain ldlang_undef_chain_list_type:
struct bfd_sym_chain创建了类型别名ldlang_undef_chain_list_type,以便更容易使用和声明这种类型的变量。#define ldlang_undef_chain_list_head entry_symbol.next:
ldlang_undef_chain_list_head定义为entry_symbol.next。它可能用作访问符号链节点的next字段的简写。- struct bfd_sym_chain
- {
- struct bfd_sym_chain *next;
- const char *name;
- };
-
- typedef struct bfd_sym_chain ldlang_undef_chain_list_type;
-
- #define ldlang_undef_chain_list_head entry_symbol.next
static void lang_place_undefineds(void):
lang_place_undefineds。它是一个静态函数,意味着它仅限于当前的翻译单元。这个函数的目的是遍历未定义符号(ldlang_undef_chain_list_type)的列表,并为每个符号的名称调用insert_undefined。- static void
- lang_place_undefineds (void)
- // /* Add to the hash table all undefineds on the command line. */
- {
- ldlang_undef_chain_list_type *ptr;
-
- for (ptr = ldlang_undef_chain_list_head; ptr != NULL; ptr = ptr->next)
- insert_undefined (ptr->name);
- }
static void insert_undefined(const char *name):
insert_undefined。它以字符串(name)作为参数。这个函数的目的是将未定义符号插入符号表中。它首先使用bfd_link_hash_lookup在哈希表中查找符号,如果找不到,则使用bfd_link_add_undef添加它。
- /* Insert NAME as undefined in the symbol table. */
-
- static void
- insert_undefined (const char *name)
- {
- struct bfd_link_hash_entry *h;
-
- h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE);
- if (h == NULL)
- einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
- if (h->type == bfd_link_hash_new)
- {
- h->type = bfd_link_hash_undefined;
- h->u.undef.abfd = NULL;
- bfd_link_add_undef (link_info.hash, h);
- }
- }
bfd_link_hash_lookup和bfd_hash_lookup函数:
bfd_link_hash_lookup似乎用于在符号哈希表中查找条目,而bfd_hash_lookup是一个更一般的哈希表查找函数。这些函数通过对输入字符串进行哈希并在哈希表中搜索相应的条目来工作。bfd_hash_insert函数:
- struct bfd_link_hash_entry *
- bfd_link_hash_lookup (struct bfd_link_hash_table *table,
- const char *string,
- bfd_boolean create, // T
- bfd_boolean copy, // F
- bfd_boolean follow) // T
- {
- struct bfd_link_hash_entry *ret;
-
- ret = ((struct bfd_link_hash_entry *)
- bfd_hash_lookup (&table->table, string, create, copy));
-
- if (follow && ret != NULL)
- {
- while (ret->type == bfd_link_hash_indirect
- || ret->type == bfd_link_hash_warning)
- ret = ret->u.i.link;
- }
-
- return ret;
- }
- struct bfd_hash_entry *
- bfd_hash_lookup (struct bfd_hash_table *table,
- const char *string,
- bfd_boolean create, // T
- bfd_boolean copy) // F
- {
- unsigned long hash;
- struct bfd_hash_entry *hashp;
- unsigned int len;
- unsigned int _index;
-
- hash = bfd_hash_hash (string, &len);
- _index = hash % table->size;
- for (hashp = table->table[_index];
- hashp != NULL;
- hashp = hashp->next)
- {
- if (hashp->hash == hash
- && strcmp (hashp->string, string) == 0)
- return hashp;
- }
-
- if (! create)
- return NULL;
-
- if (copy)
- {
- char *new_string;
-
- new_string = (char *) objalloc_alloc ((struct objalloc *) table->memory,
- len + 1);
- if (!new_string)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
- memcpy (new_string, string, len + 1);
- string = new_string;
- }
-
- return bfd_hash_insert (table, string, hash);
- }
- struct bfd_hash_entry *
- bfd_hash_insert (struct bfd_hash_table *table,
- const char *string,
- unsigned long hash)
- {
- struct bfd_hash_entry *hashp;
- unsigned int _index;
-
- hashp = (*table->newfunc) (NULL, table, string);
- if (hashp == NULL)
- return NULL;
- hashp->string = string;
- hashp->hash = hash;
- _index = hash % table->size;
- hashp->next = table->table[_index];
- table->table[_index] = hashp;
- table->count++;
-
- if (!table->frozen && table->count > table->size * 3 / 4)
- {
- unsigned long newsize = higher_prime_number (table->size);
- struct bfd_hash_entry **newtable;
- unsigned int hi;
- unsigned long alloc = newsize * sizeof (struct bfd_hash_entry *);
-
- /* If we can't find a higher prime, or we can't possibly alloc
- that much memory, don't try to grow the table. */
- if (newsize == 0 || alloc / sizeof (struct bfd_hash_entry *) != newsize)
- {
- table->frozen = 1;
- return hashp;
- }
-
- newtable = ((struct bfd_hash_entry **)
- objalloc_alloc ((struct objalloc *) table->memory, alloc));
- if (newtable == NULL)
- {
- table->frozen = 1;
- return hashp;
- }
- memset (newtable, 0, alloc);
-
- for (hi = 0; hi < table->size; hi ++)
- while (table->table[hi])
- {
- struct bfd_hash_entry *chain = table->table[hi];
- struct bfd_hash_entry *chain_end = chain;
-
- while (chain_end->next && chain_end->next->hash == chain->hash)
- chain_end = chain_end->next;
-
- table->table[hi] = chain_end->next;
- _index = chain->hash % newsize;
- chain_end->next = newtable[_index];
- newtable[_index] = chain;
- }
- table->table = newtable;
- table->size = newsize;
- }
-
- return hashp;
- }