From: Nick Clifton Date: Wed, 10 May 2023 09:29:52 +0000 (+0100) Subject: Add linker option to include local symbols in the linker map. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=496917ce466c703c1ae3bf1cbbe753de1c091445;p=binutils-gdb.git Add linker option to include local symbols in the linker map. PR 16566 * ldlang.c (ld_is_local_symbol): New function. (print_input_section): Add code to display local symbols in the section. * ldlex.h (enum option_values): Add OPTION_PRINT_MAP_LOCALS and OPTION_PRINT_MAP_LOCALS. * lexsup.c (ld_options[]): Add entries for --print-map-locals and --no-print-map-locals. * NEWS: Mention the new feature. * ld.h (struct ld_config_type): Add print_map_locals field. * ld.texi: Document the new command line option. * testsuite/ld-scripts/sizeof.s: Add a local symbol. * testsuite/ld-scripts/map-locals.d: New test control file. * testsuite/ld-scripts/map-address.exp: Run the new test. --- diff --git a/ld/ChangeLog b/ld/ChangeLog index 121bdfd735f..dac58cd575b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,20 @@ +2023-05-10 Nick Clifton + + PR 16566 + * ldlang.c (ld_is_local_symbol): New function. + (print_input_section): Add code to display local symbols in the + section. + * ldlex.h (enum option_values): Add OPTION_PRINT_MAP_LOCALS and + OPTION_PRINT_MAP_LOCALS. + * lexsup.c (ld_options[]): Add entries for --print-map-locals + and --no-print-map-locals. + * NEWS: Mention the new feature. + * ld.h (struct ld_config_type): Add print_map_locals field. + * ld.texi: Document the new command line option. + * testsuite/ld-scripts/sizeof.s: Add a local symbol. + * testsuite/ld-scripts/map-locals.d: New test control file. + * testsuite/ld-scripts/map-address.exp: Run the new test. + 2023-05-04 Nick Clifton PR 30300 diff --git a/ld/NEWS b/ld/NEWS index 37041e7456f..9920d0209b8 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,5 +1,8 @@ -*- text -*- +* The linker command line option --print-map-locals can be used to include + local symbols in a linker map. (ELF targets only). + * For most ELF based targets, if the --enable-linker-version option is used then the version of the linker will be inserted as a string into the .comment section. diff --git a/ld/ld.h b/ld/ld.h index 05649ff61b8..1882a282020 100644 --- a/ld/ld.h +++ b/ld/ld.h @@ -297,6 +297,9 @@ typedef struct /* If set, print discarded sections in map file output. */ bool print_map_discarded; + /* If set, print local symbols in map file output. */ + bool print_map_locals; + /* If set, emit the names and types of statically-linked variables into the CTF. */ bool ctf_variables; diff --git a/ld/ld.texi b/ld/ld.texi index 1ea6874cbb0..012eec2e809 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -870,6 +870,16 @@ is 0x1, and @file{bar.o}, whose 0xc0010001 property value is 0x1. Print (or do not print) the list of discarded and garbage collected sections in the link map. Enabled by default. +@kindex --print-map-locals +@kindex --no-print-map-locals +@item --print-map-locals +@itemx --no-print-map-locals +Print (or do not print) local symbols in the link map. Local symbols +will have the text @samp{(local)} printed before their name, and will +be listed after all of the global symbols in a given section. +Temporary local symbols (typically those that start with @samp{.L}) +will not be included in the output. Disabled by default. + @kindex -n @cindex read-only text @cindex NMAGIC diff --git a/ld/ldlang.c b/ld/ldlang.c index aa01c81e661..a9c4a4d5bd7 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -2296,13 +2296,15 @@ lang_map (void) { if (! dis_header_printed) { - fprintf (config.map_file, _("\nDiscarded input sections\n\n")); + minfo (_("\nDiscarded input sections\n\n")); dis_header_printed = true; } print_input_section (s, true); } } + if (config.print_map_discarded && ! dis_header_printed) + minfo (_("\nThere are no discarded input sections\n")); minfo (_("\nMemory Configuration\n\n")); fprintf (config.map_file, "%-16s %-18s %-18s %s\n", @@ -2330,7 +2332,7 @@ lang_map (void) print_nl (); } - fprintf (config.map_file, _("\nLinker script and memory map\n\n")); + minfo (_("\nLinker script and memory map\n\n")); if (!link_info.reduce_memory_overheads) { @@ -4797,6 +4799,50 @@ print_all_symbols (asection *sec) obstack_free (&map_obstack, entries); } +/* Returns TRUE if SYM is a symbol suitable for printing + in a linker map as a local symbol. */ + +static bool +ld_is_local_symbol (asymbol * sym) +{ + const char * name = bfd_asymbol_name (sym); + + if (name == NULL || *name == 0) + return false; + + if (strcmp (name, "(null)") == 0) + return false; + + /* Skip .Lxxx and such like. */ + if (bfd_is_local_label (link_info.output_bfd, sym)) + return false; + + /* FIXME: This is intended to skip ARM mapping symbols, + which for some reason are not excluded by bfd_is_local_label, + but maybe it is wrong for other architectures. + It would be better to fix bfd_is_local_label. */ + if (*name == '$') + return false; + + /* Some local symbols, eg _GLOBAL_OFFSET_TABLE_, are present + in the hash table, so do not print duplicates here. */ + struct bfd_link_hash_entry * h; + h = bfd_link_hash_lookup (link_info.hash, name, false /* create */, + false /* copy */, true /* follow */); + if (h == NULL) + return true; + + /* Symbols from the plugin owned BFD will not get their own + iteration of this function, but can be on the link_info + list. So include them here. */ + if (h->u.def.section->owner != NULL + && ((bfd_get_file_flags (h->u.def.section->owner) & (BFD_LINKER_CREATED | BFD_PLUGIN)) + == (BFD_LINKER_CREATED | BFD_PLUGIN))) + return true; + + return false; +} + /* Print information about an input section to the map file. */ static void @@ -4852,6 +4898,44 @@ print_input_section (asection *i, bool is_discarded) later overlay is shorter than an earier one. */ if (addr + TO_ADDR (size) > print_dot) print_dot = addr + TO_ADDR (size); + + if (config.print_map_locals) + { + long storage_needed; + + /* FIXME: It would be better to cache this table, rather + than recreating it for each output section. */ + /* FIXME: This call is not working for non-ELF based targets. + Find out why. */ + storage_needed = bfd_get_symtab_upper_bound (link_info.output_bfd); + if (storage_needed > 0) + { + asymbol ** symbol_table; + long number_of_symbols; + long j; + + symbol_table = xmalloc (storage_needed); + number_of_symbols = bfd_canonicalize_symtab (link_info.output_bfd, symbol_table); + + for (j = 0; j < number_of_symbols; j++) + { + asymbol * sym = symbol_table[j]; + bfd_vma sym_addr = sym->value + i->output_section->vma; + + if (sym->section == i->output_section + && (sym->flags & BSF_LOCAL) != 0 + && sym_addr >= addr + && sym_addr < print_dot + && ld_is_local_symbol (sym)) + { + print_spaces (SECTION_NAME_MAP_LENGTH); + minfo ("0x%V (local) %s\n", sym_addr, bfd_asymbol_name (sym)); + } + } + + free (symbol_table); + } + } } } diff --git a/ld/ldlex.h b/ld/ldlex.h index 48d323d0265..be942ec4327 100644 --- a/ld/ldlex.h +++ b/ld/ldlex.h @@ -160,6 +160,8 @@ enum option_values OPTION_FORCE_GROUP_ALLOCATION, OPTION_PRINT_MAP_DISCARDED, OPTION_NO_PRINT_MAP_DISCARDED, + OPTION_PRINT_MAP_LOCALS, + OPTION_NO_PRINT_MAP_LOCALS, OPTION_NON_CONTIGUOUS_REGIONS, OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS, OPTION_DEPENDENCY_FILE, diff --git a/ld/lexsup.c b/ld/lexsup.c index 7dc2228a833..6090921bda4 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -605,6 +605,12 @@ static const struct ld_option ld_options[] = { {"no-print-map-discarded", no_argument, NULL, OPTION_NO_PRINT_MAP_DISCARDED}, '\0', NULL, N_("Do not show discarded sections in map file output"), TWO_DASHES }, + { {"print-map-locals", no_argument, NULL, OPTION_PRINT_MAP_LOCALS}, + '\0', NULL, N_("Show local symbols in map file output"), + TWO_DASHES }, + { {"no-print-map-locals", no_argument, NULL, OPTION_NO_PRINT_MAP_LOCALS}, + '\0', NULL, N_("Do not show local symbols in map file output (default)"), + TWO_DASHES }, { {"ctf-variables", no_argument, NULL, OPTION_CTF_VARIABLES}, '\0', NULL, N_("Emit names and types of static variables in CTF"), TWO_DASHES }, @@ -1748,6 +1754,14 @@ parse_args (unsigned argc, char **argv) config.print_map_discarded = true; break; + case OPTION_NO_PRINT_MAP_LOCALS: + config.print_map_locals = false; + break; + + case OPTION_PRINT_MAP_LOCALS: + config.print_map_locals = true; + break; + case OPTION_DEPENDENCY_FILE: config.dependency_file = optarg; break; diff --git a/ld/testsuite/ld-scripts/map-address.exp b/ld/testsuite/ld-scripts/map-address.exp index 0eeca10fdd8..fbea9064265 100644 --- a/ld/testsuite/ld-scripts/map-address.exp +++ b/ld/testsuite/ld-scripts/map-address.exp @@ -120,3 +120,30 @@ if {[regexp_diff \ } else { pass $testname } + +if { [is_elf_format] } { + set testname "map with locals" + + if {![ld_link $ld tmpdir/map-address \ + "$LDFLAGS -T $srcdir/$subdir/map-address.t \ + $IMAGE_BASE tmpdir/map-address.o \ + -Map=tmpdir/map-locals.map --print-map-locals"]} { + fail $testname + return + } + + if [is_remote host] then { + remote_upload host "tmpdir/map-locals.map" + } + + # Some ELF targets do not preserve their local symbols. + setup_xfail "d30v-*-*" "dlx-*-*" "pj-*-*" "s12z-*-*" "xgate-*-*" + + if {[regexp_diff \ + "tmpdir/map-locals.map" \ + "$srcdir/$subdir/map-locals.d"]} { + fail $testname + } else { + pass $testname + } +} diff --git a/ld/testsuite/ld-scripts/map-locals.d b/ld/testsuite/ld-scripts/map-locals.d new file mode 100644 index 00000000000..f3137f13814 --- /dev/null +++ b/ld/testsuite/ld-scripts/map-locals.d @@ -0,0 +1,5 @@ +#... +Linker script and memory map +#... +.*\(local\)[ ]+local_sym +#pass diff --git a/ld/testsuite/ld-scripts/sizeof.s b/ld/testsuite/ld-scripts/sizeof.s index e221ca3c0b3..7cd1677bc85 100644 --- a/ld/testsuite/ld-scripts/sizeof.s +++ b/ld/testsuite/ld-scripts/sizeof.s @@ -1 +1,2 @@ +local_sym: .space 16