ldlang.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,418 行 · 第 1/5 页
C
2,418 行
einfo ("%F\n"); } else if (err != bfd_error_file_not_recognized || place == NULL) einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd); bfd_close (entry->the_bfd); entry->the_bfd = NULL; /* Try to interpret the file as a linker script. */ ldfile_open_command_file (entry->filename); hold = stat_ptr; stat_ptr = place; ldfile_assumed_script = true; parser_input = input_script; yyparse (); ldfile_assumed_script = false; stat_ptr = hold; return; } if (ldemul_recognized_file (entry)) return; /* We don't call ldlang_add_file for an archive. Instead, the add_symbols entry point will call ldlang_add_file, via the add_archive_element callback, for each element of the archive which is used. */ switch (bfd_get_format (entry->the_bfd)) { default: break; case bfd_object: ldlang_add_file (entry); if (trace_files || trace_file_tries) info_msg ("%I\n", entry); break; case bfd_archive: if (entry->whole_archive) { bfd *member = bfd_openr_next_archived_file (entry->the_bfd, (bfd *) NULL); while (member != NULL) { if (! bfd_check_format (member, bfd_object)) einfo (_("%F%B: object %B in archive is not object\n"), entry->the_bfd, member); if (! ((*link_info.callbacks->add_archive_element) (&link_info, member, "--whole-archive"))) abort (); if (! bfd_link_add_symbols (member, &link_info)) einfo (_("%F%B: could not read symbols: %E\n"), member); member = bfd_openr_next_archived_file (entry->the_bfd, member); } entry->loaded = true; return; } } if (! bfd_link_add_symbols (entry->the_bfd, &link_info)) einfo (_("%F%B: could not read symbols: %E\n"), entry->the_bfd); entry->loaded = true;}/* Handle a wild statement. SECTION or FILE or both may be NULL, indicating that it is a wildcard. Separate lang_input_section statements are created for each part of the expansion; they are added after the wild statement S. OUTPUT is the output section. */static voidwild (s, section, file, target, output) lang_wild_statement_type *s; const char *section; const char *file; const char *target ATTRIBUTE_UNUSED; lang_output_section_statement_type *output;{ walk_wild (s, section, file, output_section_callback, (PTR) output); if (section != (char *) NULL && strcmp (section, "COMMON") == 0 && default_common_section == NULL) { /* Remember the section that common is going to in case we later get something which doesn't know where to put it. */ default_common_section = output; }}/* Return true iff target is the sought target. */static intget_target (target, data) const bfd_target *target; PTR data;{ const char *sought = (const char *) data; return strcmp (target->name, sought) == 0;}/* Like strcpy() but convert to lower case as well. */static voidstricpy (dest, src) char *dest; char *src;{ char c; while ((c = *src++) != 0) { if (isupper ((unsigned char) c)) c = tolower (c); *dest++ = c; } *dest = 0;}/* Remove the first occurance of needle (if any) in haystack from haystack. */static voidstrcut (haystack, needle) char *haystack; char *needle;{ haystack = strstr (haystack, needle); if (haystack) { char *src; for (src = haystack + strlen (needle); *src;) *haystack++ = *src++; *haystack = 0; }}/* Compare two target format name strings. Return a value indicating how "similar" they are. */static intname_compare (first, second) char *first; char *second;{ char *copy1; char *copy2; int result; copy1 = xmalloc (strlen (first) + 1); copy2 = xmalloc (strlen (second) + 1); /* Convert the names to lower case. */ stricpy (copy1, first); stricpy (copy2, second); /* Remove and endian strings from the name. */ strcut (copy1, "big"); strcut (copy1, "little"); strcut (copy2, "big"); strcut (copy2, "little"); /* Return a value based on how many characters match, starting from the beginning. If both strings are the same then return 10 * their length. */ for (result = 0; copy1[result] == copy2[result]; result++) if (copy1[result] == 0) { result *= 10; break; } free (copy1); free (copy2); return result;}/* Set by closest_target_match() below. */static const bfd_target *winner;/* Scan all the valid bfd targets looking for one that has the endianness requirement that was specified on the command line, and is the nearest match to the original output target. */static intclosest_target_match (target, data) const bfd_target *target; PTR data;{ const bfd_target *original = (const bfd_target *) data; if (command_line.endian == ENDIAN_BIG && target->byteorder != BFD_ENDIAN_BIG) return 0; if (command_line.endian == ENDIAN_LITTLE && target->byteorder != BFD_ENDIAN_LITTLE) return 0; /* Must be the same flavour. */ if (target->flavour != original->flavour) return 0; /* If we have not found a potential winner yet, then record this one. */ if (winner == NULL) { winner = target; return 0; } /* Oh dear, we now have two potential candidates for a successful match. Compare their names and choose the better one. */ if (name_compare (target->name, original->name) > name_compare (winner->name, original->name)) winner = target; /* Keep on searching until wqe have checked them all. */ return 0;}/* Return the BFD target format of the first input file. */static char *get_first_input_target (){ char *target = NULL; LANG_FOR_EACH_INPUT_STATEMENT (s) { if (s->header.type == lang_input_statement_enum && s->real) { ldfile_open_file (s); if (s->the_bfd != NULL && bfd_check_format (s->the_bfd, bfd_object)) { target = bfd_get_target (s->the_bfd); if (target != NULL) break; } } } return target;}/* Open the output file. */static bfd *open_output (name) const char *name;{ bfd *output; /* Has the user told us which output format to use? */ if (output_target == (char *) NULL) { /* No - has the current target been set to something other than the default? */ if (current_target != default_target) output_target = current_target; /* No - can we determine the format of the first input file? */ else { output_target = get_first_input_target (); /* Failed - use the default output target. */ if (output_target == NULL) output_target = default_target; } } /* Has the user requested a particular endianness on the command line? */ if (command_line.endian != ENDIAN_UNSET) { const bfd_target *target; enum bfd_endian desired_endian; /* Get the chosen target. */ target = bfd_search_for_target (get_target, (PTR) output_target); /* If the target is not supported, we cannot do anything. */ if (target != NULL) { if (command_line.endian == ENDIAN_BIG) desired_endian = BFD_ENDIAN_BIG; else desired_endian = BFD_ENDIAN_LITTLE; /* See if the target has the wrong endianness. This should not happen if the linker script has provided big and little endian alternatives, but some scrips don't do this. */ if (target->byteorder != desired_endian) { /* If it does, then see if the target provides an alternative with the correct endianness. */ if (target->alternative_target != NULL && (target->alternative_target->byteorder == desired_endian)) output_target = target->alternative_target->name; else { /* Try to find a target as similar as possible to the default target, but which has the desired endian characteristic. */ (void) bfd_search_for_target (closest_target_match, (PTR) target); /* Oh dear - we could not find any targets that satisfy our requirements. */ if (winner == NULL) einfo (_("%P: warning: could not find any targets that match endianness requirement\n")); else output_target = winner->name; } } } } output = bfd_openw (name, output_target); if (output == (bfd *) NULL) { if (bfd_get_error () == bfd_error_invalid_target) einfo (_("%P%F: target %s not found\n"), output_target); einfo (_("%P%F: cannot open output file %s: %E\n"), name); } delete_output_file_on_failure = true;#if 0 output->flags |= D_PAGED;#endif if (! bfd_set_format (output, bfd_object)) einfo (_("%P%F:%s: can not make object file: %E\n"), name); if (! bfd_set_arch_mach (output, ldfile_output_architecture, ldfile_output_machine)) einfo (_("%P%F:%s: can not set architecture: %E\n"), name); link_info.hash = bfd_link_hash_table_create (output); if (link_info.hash == (struct bfd_link_hash_table *) NULL) einfo (_("%P%F: can not create link hash table: %E\n")); bfd_set_gp_size (output, g_switch_value); return output;}static voidldlang_open_output (statement) lang_statement_union_type *statement;{ switch (statement->header.type) { case lang_output_statement_enum: ASSERT (output_bfd == (bfd *) NULL); output_bfd = open_output (statement->output_statement.name); ldemul_set_output_arch (); if (config.magic_demand_paged && !link_info.relocateable) output_bfd->flags |= D_PAGED; else output_bfd->flags &= ~D_PAGED; if (config.text_read_only) output_bfd->flags |= WP_TEXT; else output_bfd->flags &= ~WP_TEXT; if (link_info.traditional_format) output_bfd->flags |= BFD_TRADITIONAL_FORMAT; else output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT; break; case lang_target_statement_enum: current_target = statement->target_statement.target; break; default: break; }}/* Open all the input files. */static voidopen_input_bfds (s, force) lang_statement_union_type *s; boolean force;{ for (; s != (lang_statement_union_type *) NULL; s = s->next) { switch (s->header.type) { case lang_constructors_statement_enum: open_input_bfds (constructor_list.head, force); break; case lang_output_section_statement_enum: open_input_bfds (s->output_section_statement.children.head, force); break; case lang_wild_statement_enum: /* Maybe we should load the file's symbols. */ if (s->wild_statement.filename && ! wildcardp (s->wild_statement.filename)) (void) lookup_name (s->wild_statement.filename); open_input_bfds (s->wild_statement.children.head, force); break; case lang_group_statement_enum: { struct bfd_link_hash_entry *undefs; /* We must continually search the entries in the group until no new symbols are added to the list of undefined symbols. */ do { undefs = link_info.hash->undefs_tail; open_input_bfds (s->group_statement.children.head, true); } while (undefs != link_info.hash->undefs_tail); } break; case lang_target_statement_enum: current_target = s->target_statement.target; break; case lang_input_statement_enum: if (s->input_statement.real) { lang_statement_list_type add; s->input_statement.target = current_target; /* If we are being called from within a group, and this is an archive which has already been searched, then force it to be researched unless the whole archive has been loaded already. */ if (force && !s->input_statement.whole_archive && s->input_statement.loaded && bfd_check_format (s->input_statement.the_bfd, bfd_archive)) s->input_statement.loaded = false; lang_list_init (&add); load_symbols (&s->input_statement, &add); if (add.head != NULL) { *add.tail = s->next; s->next = add.head; } } break; default: break; } }}/* If there are [COMMONS] statements, put a wild one into the bss section. */static void
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?