Bug 16566 - Please provide a way to include static symbols in linker map file
Summary: Please provide a way to include static symbols in linker map file
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.22
: P2 normal
Target Milestone: ---
Assignee: Nick Clifton
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-02-12 15:42 UTC by Paul Sokolovsky
Modified: 2023-05-10 09:32 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Proposed patch (538 bytes, patch)
2023-04-27 11:47 UTC, Nick Clifton
Details | Diff
Proposed patch (2.52 KB, patch)
2023-04-28 15:29 UTC, Nick Clifton
Details | Diff
Proposed patch (3.45 KB, patch)
2023-05-09 15:41 UTC, Nick Clifton
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Sokolovsky 2014-02-12 15:42:02 UTC
Link map file (-Map=) is one good way to get detailed information about complete ready-to-deploy binary product. Unfortunately, a map file doesn't include information about local (static in C-speak) symbols. Usage of static symbols is the best practice in contemporary C and other languages, and such situation means that a map file unfortunately is not suitable for many interesting analyses (like for example tracking detailed function sizes across application versions/optimization settings).

So, please consider:

1. Adding a linker option to include local/static symbols in generated map file.
2. Alternatively, it may be argued that users whu are interested in map files are probably want to have information about all symbols anyway, so it can be just changed to include local/static symbols unconditionally, without growing number of command-line options.

Thanks.
Comment 1 jon 2023-04-20 19:53:49 UTC
This would also be useful for when compiling with LTO, as currently gcc seems to convert globals to locals, so the map file ends up containing no information about what functions are included.
Comment 2 Nick Clifton 2023-04-27 11:47:25 UTC
Created attachment 14853 [details]
Proposed patch

Hi Paul, Hi Jon,

  Would either of you like to try out this potential patch ?

  It adds local symbols to the linker map at the appropriate places, with a
  prefix of "(local) " so that they can be quickly identified.  (Note local
  symbols are displayed after global symbols for a given section, rather than
  being mixed in with the global symbols).

  It is not complete yet.  I think that I am going to have to add a command
  line option to control its use, as I expect that there are people out there
  who rely on the current format not changing.  Plus I will need to add a
  testcase or two to the testsuite.

  I did find that *some* local symbols are already included in the linker map,
  eg _GLOBAL_OFFSET_TABLE_ and at the moment such symbols will appear twice.
  So I ought to try to find a way to stop that from happening as well.

Cheers
  Nick
Comment 3 jon 2023-04-27 12:40:09 UTC
Thanks Nick, I see local data and functions now.

Is there perhaps anyway to optionally filter out labels generated within functions (E.g. those normally declared beginning with L or .L that are the targets of branch instructions)?
Comment 4 Nick Clifton 2023-04-27 14:02:08 UTC
(In reply to jon from comment #3)

> Is there perhaps anyway to optionally filter out labels generated within
> functions (E.g. those normally declared beginning with L or .L that are the
> targets of branch instructions)?

Actually yes. :-)  There is a function is_local_label() in the BFD library which does exactly that.  I will add it to my patch.
Comment 5 Nick Clifton 2023-04-28 15:29:57 UTC
Created attachment 14855 [details]
Proposed patch

OK, here is a revised patch.  Changes include:

  * Temporary local symbols (.Lxxx etc) are not displayed.
  * A new command line option enables the feature: --print-map-locals
  * The new option is documented.
  * A new testcase for the feature.
Comment 6 jon 2023-04-28 16:47:17 UTC
Not sure why, but with the new patch, the addition of the condition:

    && bfd_link_hash_lookup (link_info.hash,
					       bfd_asymbol_name (sym), false,
					       false, true) == NULL

Seems to prevent the output of the symbols (functions / data when using -flto) that I'm interested in.
Comment 7 Nick Clifton 2023-05-02 11:18:10 UTC
(In reply to jon from comment #6)
> Not sure why, but with the new patch, the addition of the condition:
> 
>     && bfd_link_hash_lookup (link_info.hash,
> 					       bfd_asymbol_name (sym), false,
> 					       false, true) == NULL
> 
> Seems to prevent the output of the symbols (functions / data when using
> -flto) that I'm interested in.

Hmmm.  That test is designed to catch local symbols which have already been 
displayed by the normal linker-map-symbol-displaying code.  (eg __GLOBAL_OFFSET_TABLE__).

Can you give me a specific example of a symbol which is suppressed by this check, but which should not be ?  (A small test case would be ideal...)
Comment 8 jon 2023-05-08 15:31:14 UTC
test.c:

void func() {
}

int main() {
    func();
    return 0;
}

Compile with:

 arm-eabi-gcc test.c -o test.exe -Xlinker -Map=arm.map -flto -Xlinker --print-map-locals

With the bfd_link_hash_lookup condition, func doesn't appear in the map file.
Comment 9 Nick Clifton 2023-05-09 12:02:12 UTC
(In reply to jon from comment #8)
Hi Jon,

>  arm-eabi-gcc test.c -o test.exe -Xlinker -Map=arm.map -flto -Xlinker
> --print-map-locals
> 
> With the bfd_link_hash_lookup condition, func doesn't appear in the map file.

Ah - but if you remove the "-flto" option it works...

The problem is that the LTO compiler moves the func() code into its own section,
which confuses the local printing code.  I am looking to see if I can find a way
around this problem...

Cheers
  Nick
Comment 10 jon 2023-05-09 12:17:30 UTC
> Ah - but if you remove the "-flto" option it works...

Without -flto, func is a global symbol.

> The problem is that the LTO compiler moves the func() code into its own section,

I guess that may be target/gcc version specific. I just see it being changed from a global to a local in .text.
Comment 11 Nick Clifton 2023-05-09 15:41:08 UTC
Created attachment 14869 [details]
Proposed patch

OK, here is another version of the patch.  This version detects symbols in LTO generated object files and treats them slightly differently.  It works with the test case you gave me, and I think that it should work for all inputs, but please do give it a try with a real program and see if it works as you want.
Comment 12 jon 2023-05-10 09:01:14 UTC
Looks good, thanks Nick.
Comment 13 Sourceware Commits 2023-05-10 09:30:57 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=496917ce466c703c1ae3bf1cbbe753de1c091445

commit 496917ce466c703c1ae3bf1cbbe753de1c091445
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed May 10 10:29:52 2023 +0100

    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.
Comment 14 Nick Clifton 2023-05-10 09:32:24 UTC
Patch applied.  (With a couple of mistakes corrected).