* [PATCH] allow empty string as argument to -Map @ 2020-05-26 7:01 Rasmus Villemoes 2020-05-27 16:50 ` Nick Clifton 0 siblings, 1 reply; 17+ messages in thread From: Rasmus Villemoes @ 2020-05-26 7:01 UTC (permalink / raw) To: binutils; +Cc: Rasmus Villemoes In meta-build systems like Yocto, it's rather easy to add flags like -fdata-sections, -ffunction-sections, -Wl,--gc-sections to global CFLAGS/LDFLAGS. But when digging into what effect those had on the build of a particular package, it would be nice to also have a map file automatically generated. That's currently a bit harder, since it requires patching the build system of each individual package to add something like -Wl,-Map=$@.map somewhere. My first instinct was to make the argument to -Map optional, but that will of course break anybody that uses the form "-Map foo.map" rather than "-Map=foo.map". So, as the next best thing, use a previously bogus value (the empty string) as a sentinel to indicate "use the output filename + .map". Signed-off-by: Rasmus Villemoes <rv@rasmusvillemoes.dk> --- ld/ld.texi | 4 +++- ld/lexsup.c | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ld/ld.texi b/ld/ld.texi index 9f562935be..25ce1d6524 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -1759,7 +1759,9 @@ Print a summary of all target-specific options on the standard output and exit. @kindex -Map=@var{mapfile} @item -Map=@var{mapfile} Print a link map to the file @var{mapfile}. See the description of the -@option{-M} option, above. +@option{-M} option, above. Specifying the empty string as @var{mapfile} +(that is, @code{-Map=}) causes the link map to be written to a file +named after the @var{output} file, with @code{.map} appended. @cindex memory usage @kindex --no-keep-memory diff --git a/ld/lexsup.c b/ld/lexsup.c index 2597e2d630..e7ab07b50f 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -1617,6 +1617,11 @@ parse_args (unsigned argc, char **argv) } } + if (config.map_filename && !config.map_filename[0]) { + if (asprintf (&config.map_filename, "%s.map", output_filename) < 0) + einfo (_("%F%P: %s: can not create name of map file: %E\n")); + } + if (command_line.soname && command_line.soname[0] == '\0') { einfo (_("%P: SONAME must not be empty string; ignored\n")); -- 2.23.0 ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-05-26 7:01 [PATCH] allow empty string as argument to -Map Rasmus Villemoes @ 2020-05-27 16:50 ` Nick Clifton 2020-05-28 0:33 ` Rasmus Villemoes 0 siblings, 1 reply; 17+ messages in thread From: Nick Clifton @ 2020-05-27 16:50 UTC (permalink / raw) To: Rasmus Villemoes, binutils Hi Rasmus, > So, as the next best thing, use a previously bogus value (the empty > string) as a sentinel to indicate "use the output filename + .map". Thanks for suggesting this patch. I have applied it along with a couple of changes: * If a filename is supplied, but it references a directory, then create a file inside that directory, again based upon the output filename with .map appended. (I actually did this to make it easier to test the new feature, but it strikes that it might be useful in its own right). * Added a test case. * Added an entry to the ld/NEWS file. * Updated the --help output from the linker to show that the filename is optional. * Minor formatting fixes, and the addition of a few comments. * Created a ChangeLog entry. Cheers Nick ld/ChangeLog 2020-05-27 Rasmus Villemoes <rv@rasmusvillemoes.dk> Nick Clifton <nickc@redhat.com> * lexsup.c (parse_args): If the map filename is defined but empty create a name based upon the output file name. If the name is defined but refers to a directory create a file inside the directory based on the output file name. * ld.texi: Document the new feature. * testsuite/ld-script/map-address.exp: Add test of new feature. * NEWS: Mention the new feature. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-05-27 16:50 ` Nick Clifton @ 2020-05-28 0:33 ` Rasmus Villemoes 2020-05-28 4:23 ` Fangrui Song 2020-05-28 9:54 ` Nick Clifton 0 siblings, 2 replies; 17+ messages in thread From: Rasmus Villemoes @ 2020-05-28 0:33 UTC (permalink / raw) To: Nick Clifton, binutils On 27/05/2020 18.50, Nick Clifton wrote: > Hi Rasmus, > >> So, as the next best thing, use a previously bogus value (the empty >> string) as a sentinel to indicate "use the output filename + .map". > > Thanks for suggesting this patch. I have applied it along with a couple > of changes: > > * If a filename is supplied, but it references a directory, then > create a file inside that directory, again based upon the output > filename with .map appended. (I actually did this to make it > easier to test the new feature, but it strikes that it might be > useful in its own right). That makes a lot of sense, thanks. And one can get "my" behaviour by passing "-Map=." or "-Map .", which... > * Updated the --help output from the linker to show that the > filename is optional. ... eliminates the somewhat clumsy need to specify the empty string as argument, either via -Map= or actually have the shell insert an empty string, -Map ''. I actually did attempt to modify the help text, but as the argument isn't really optional, I couldn't find a way to indicate that the empty string was meaningful - I worry a bit that the current -Map [FILE] Write a map file (default: <outputname>.map) can lead people to think that one can actually omit the argument - and -Map --gc-sections would just put the map in the file --gc-sections, but otherwise work. So before this gets set in stone, can I retract my suggestion of assigning meaning to the empty string (maybe continue to handle it internally equivalent to ".", but not advertising it)? For the help text, it's hard to explain in one line, but perhaps something like -Map FILE/DIR Write a map file to FILE or DIR/<outputname>.map (And perhaps change "map file" to "link map" or "linker map") Rasmus ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-05-28 0:33 ` Rasmus Villemoes @ 2020-05-28 4:23 ` Fangrui Song 2020-05-28 9:54 ` Nick Clifton 1 sibling, 0 replies; 17+ messages in thread From: Fangrui Song @ 2020-05-28 4:23 UTC (permalink / raw) To: Rasmus Villemoes; +Cc: Nick Clifton, binutils On Wed, May 27, 2020 at 5:33 PM Rasmus Villemoes <rv@rasmusvillemoes.dk> wrote: > > On 27/05/2020 18.50, Nick Clifton wrote: > > Hi Rasmus, > > > >> So, as the next best thing, use a previously bogus value (the empty > >> string) as a sentinel to indicate "use the output filename + .map". > > > > Thanks for suggesting this patch. I have applied it along with a couple > > of changes: > > > > * If a filename is supplied, but it references a directory, then > > create a file inside that directory, again based upon the output > > filename with .map appended. (I actually did this to make it > > easier to test the new feature, but it strikes that it might be > > useful in its own right). > > That makes a lot of sense, thanks. And one can get "my" behaviour by > passing "-Map=." or "-Map .", which... > > > * Updated the --help output from the linker to show that the > > filename is optional. > > ... eliminates the somewhat clumsy need to specify the empty string as > argument, either via -Map= or actually have the shell insert an empty > string, -Map ''. I actually did attempt to modify the help text, but as > the argument isn't really optional, I couldn't find a way to indicate > that the empty string was meaningful - I worry a bit that the current > > -Map [FILE] Write a map file (default: <outputname>.map) > > can lead people to think that one can actually omit the argument - and > > -Map --gc-sections > > would just put the map in the file --gc-sections, but otherwise work. > > So before this gets set in stone, can I retract my suggestion of > assigning meaning to the empty string (maybe continue to handle it > internally equivalent to ".", but not advertising it)? For the help > text, it's hard to explain in one line, but perhaps something like > > -Map FILE/DIR Write a map file to FILE or DIR/<outputname>.map > > (And perhaps change "map file" to "link map" or "linker map") > > Rasmus > An empty argument value is very uncommon. Does an empty string work in a response file? ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-05-28 0:33 ` Rasmus Villemoes 2020-05-28 4:23 ` Fangrui Song @ 2020-05-28 9:54 ` Nick Clifton 2020-10-23 12:31 ` Rasmus Villemoes 1 sibling, 1 reply; 17+ messages in thread From: Nick Clifton @ 2020-05-28 9:54 UTC (permalink / raw) To: Rasmus Villemoes, binutils [-- Attachment #1: Type: text/plain, Size: 1059 bytes --] Hi Rasmus, > That makes a lot of sense, thanks. And one can get "my" behaviour by > passing "-Map=." or "-Map .", Ha! I had not even though of that. > ... eliminates the somewhat clumsy need to specify the empty string as > argument, Agreed. > So before this gets set in stone, can I retract my suggestion of > assigning meaning to the empty string (maybe continue to handle it > internally equivalent to ".", but not advertising it)? I have made the change. See the attached patch. I decided that for the empty string case it would be best to generate a message telling the user and ignoring the map file request. > (And perhaps change "map file" to "link map" or "linker map") Also done. Cheers Nick ld/ChangeLog 2020-05-28 Nick Clifton <nickc@redhat.com> * lexsup.c (parse_args): Generate an error if a name is not provided to the -Map option. (ld_options): Mention that the -Map option supports a directory name as an argument. * NEWS: Remove mention of support for an empty string as an argument to -Map. * ld.texi: Likewise. [-- Attachment #2: map.patch --] [-- Type: text/x-patch, Size: 3906 bytes --] diff --git a/ld/NEWS b/ld/NEWS index 98f07a73e1..2240aeb788 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,9 +1,8 @@ -*- text -*- * The -Map=<filename> command line option has been extended so that if - <filename> is omitted then a file called <output-filename>.map will be - created. Plus if <filename> is a directory then - <filename>/<output-filename>.map will be created. + <filename> is a directory then <filename>/<output-filename>.map will be + created. * Add a command-line option for ELF linker, --warn-textrel, to warn that DT_TEXTREL is set in a position-independent executable or shared object. diff --git a/ld/ld.texi b/ld/ld.texi index 52342523ed..cb38f47cd3 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -1760,12 +1760,10 @@ Print a summary of all target-specific options on the standard output and exit. @kindex -Map=@var{mapfile} @item -Map=@var{mapfile} Print a link map to the file @var{mapfile}. See the description of the -@option{-M} option, above. Specifying the empty string as @var{mapfile} -(that is, @code{-Map=}) causes the link map to be written to a file -named after the @var{output} file, with @code{.map} appended. -Specifying a directory as @var{mapfile} causes the link map to be -written into a file inside the directory. The name of the file is -again based upon the @var{output} filename with @code{.map} appended. +@option{-M} option, above. Specifying a directory as @var{mapfile} +causes the linker map to be written into a file inside the directory. +The name of the file is based upon the @var{output} filename with +@code{.map} appended. @cindex memory usage @kindex --no-keep-memory diff --git a/ld/lexsup.c b/ld/lexsup.c index 49c4f23950..781f58aff7 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -359,7 +359,7 @@ static const struct ld_option ld_options[] = { {"init", required_argument, NULL, OPTION_INIT}, '\0', N_("SYMBOL"), N_("Call SYMBOL at load-time"), ONE_DASH }, { {"Map", required_argument, NULL, OPTION_MAP}, - '\0', N_("[FILE]"), N_("Write a map file (default: <outputname>.map)"), ONE_DASH }, + '\0', N_("FILE/DIR"), N_("Write a linker map to FILE or DIR/<outputname>.map"), ONE_DASH }, { {"no-define-common", no_argument, NULL, OPTION_NO_DEFINE_COMMON}, '\0', NULL, N_("Do not define Common storage"), TWO_DASHES }, { {"no-demangle", no_argument, NULL, OPTION_NO_DEMANGLE }, @@ -1598,29 +1598,33 @@ parse_args (unsigned argc, char **argv) /* Run a couple of checks on the map filename. */ if (config.map_filename) { - /* If name has been provided then use the - output filename with a .map extension. */ if (config.map_filename[0] == 0) { - /* FIXME: This is a memory leak as the string is never freed. */ - if (asprintf (&config.map_filename, "%s.map", output_filename) < 0) - einfo (_("%F%P: %s: can not create name of map file: %E\n")); + einfo (_("%P: no file/directory name provided for map output; ignored\n")); + config.map_filename = NULL; } else { struct stat s; /* If the map filename is actually a directory then create - a file inside it, again based upon the output filename. */ + a file inside it, based upon the output filename. */ if (stat (config.map_filename, &s) >= 0 && S_ISDIR (s.st_mode)) { char * new_name; - /* FIXME: Another memory leak. */ + /* FIXME: This is a (trivial) memory leak. */ if (asprintf (&new_name, "%s/%s.map", config.map_filename, output_filename) < 0) - einfo (_("%F%P: %s: can not create name of map file: %E\n")); + { + /* If this alloc fails then something is probably very + wrong. Better to halt now rather than continue on + into more problems. */ + einfo (_("%P%F: cannot create name for linker map file: %E\n")); + new_name = NULL; + } + config.map_filename = new_name; } } ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-05-28 9:54 ` Nick Clifton @ 2020-10-23 12:31 ` Rasmus Villemoes 2020-10-29 15:52 ` Nick Clifton 0 siblings, 1 reply; 17+ messages in thread From: Rasmus Villemoes @ 2020-10-23 12:31 UTC (permalink / raw) To: Nick Clifton, binutils On 28/05/2020 11.54, Nick Clifton wrote: > Hi Rasmus, > >> That makes a lot of sense, thanks. And one can get "my" behaviour by >> passing "-Map=." or "-Map .", > > Ha! I had not even though of that. > >> ... eliminates the somewhat clumsy need to specify the empty string as >> argument, > > Agreed. Sorry for resurrecting this, and not thinking of this sooner, but it just occurred to me that passing -Map=. only works automatically if the -o argument is a relative path. If the -o argument is absolute, that will lead to trying to create a map file at, say, ".//home/ravi/some/project/foo.so.out", which won't work given that the working directory is very likely already "/home/ravi/some/project". One could pass -Map=/, but that would then break in the other direction when the -o argument is relative. Since the main point of this is to be able to just do "LDFLAGS += <something>" to always get a linker map for each output artifact, without hooking into each individual project's build system and figuring out how to add that flag to each build target, can we special-case . to always mean "generate a map file next to the output file", i.e. in that case check whether output_filename starts with '/' and if so do not prepend "./" (but still append ".map", of course)? Or is there some better way? Rasmus ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-10-23 12:31 ` Rasmus Villemoes @ 2020-10-29 15:52 ` Nick Clifton 2020-10-30 12:37 ` Rasmus Villemoes 0 siblings, 1 reply; 17+ messages in thread From: Nick Clifton @ 2020-10-29 15:52 UTC (permalink / raw) To: Rasmus Villemoes, binutils Hi Rasmus, > Sorry for resurrecting this, and not thinking of this sooner, but it > just occurred to me that passing -Map=. only works automatically if the > -o argument is a relative path. If the -o argument is absolute, that > will lead to trying to create a map file at, say, > ".//home/ravi/some/project/foo.so.out", which won't work given that the > working directory is very likely already "/home/ravi/some/project". One > could pass -Map=/, but that would then break in the other direction when > the -o argument is relative. > Since the main point of this is to be able to just do "LDFLAGS += > <something>" to always get a linker map for each output artifact, > without hooking into each individual project's build system and figuring > out how to add that flag to each build target, can we special-case . to > always mean "generate a map file next to the output file", i.e. in that > case check whether output_filename starts with '/' and if so do not > prepend "./" (but still append ".map", of course)? Or is there some > better way? Hmm, I think that that would be confusing. Suppose for example that the link involved "-Map=.. -o /foo/bar". Where would the user expect the map file to appear ? In ../foo/bar.map or ../bar.map or /foo/bar.map ? My feeling is that we ought to extract the basename of any output file and use that, and always honour the directory name specified in the -Map option. ie: -Map=. -o foo => creates ./foo.map -Map=. -o /foo => creates ./foo.map -Map=. -o /foo/bar => creates ./bar.map -Map=/ -o foo => creates /foo.map -Map=/ -o /foo/bar => creates /bar.map -Map=/foo -o bar => creates /foo/bar.map -Map=../ -o foo/bar => creates ../bar.map. (NB/ does not create ../foo/bar.map) Thoughts ? Cheers Nick ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-10-29 15:52 ` Nick Clifton @ 2020-10-30 12:37 ` Rasmus Villemoes 2020-10-30 16:35 ` Nick Clifton 0 siblings, 1 reply; 17+ messages in thread From: Rasmus Villemoes @ 2020-10-30 12:37 UTC (permalink / raw) To: Nick Clifton, binutils On 29/10/2020 16.52, Nick Clifton wrote: > Hi Rasmus, > >> Sorry for resurrecting this, and not thinking of this sooner, but it >> just occurred to me that passing -Map=. only works automatically if the >> -o argument is a relative path. If the -o argument is absolute, that >> will lead to trying to create a map file at, say, >> ".//home/ravi/some/project/foo.so.out", which won't work given that the >> working directory is very likely already "/home/ravi/some/project". One >> could pass -Map=/, but that would then break in the other direction when >> the -o argument is relative. > >> Since the main point of this is to be able to just do "LDFLAGS += >> <something>" to always get a linker map for each output artifact, >> without hooking into each individual project's build system and figuring >> out how to add that flag to each build target, can we special-case . to >> always mean "generate a map file next to the output file", i.e. in that >> case check whether output_filename starts with '/' and if so do not >> prepend "./" (but still append ".map", of course)? Or is there some >> better way? > > Hmm, I think that that would be confusing. Suppose for example that > the link involved "-Map=.. -o /foo/bar". Where would the user expect > the map file to appear ? In ../foo/bar.map or ../bar.map or /foo/bar.map ? > > My feeling is that we ought to extract the basename of any output file > and use that, and always honour the directory name specified in the -Map > option. ie: > > -Map=. -o foo => creates ./foo.map > -Map=. -o /foo => creates ./foo.map > -Map=. -o /foo/bar => creates ./bar.map > -Map=/ -o foo => creates /foo.map > -Map=/ -o /foo/bar => creates /bar.map > -Map=/foo -o bar => creates /foo/bar.map > -Map=../ -o foo/bar => creates ../bar.map. (NB/ does not create ../foo/bar.map) Yes, that's another problem with the current logic, even for relative -o arguments: If one specifies -Map=maps/, it may be that maps/ exists, but for -o foo/bar, we'd try to create maps/foo/bar.map - the Makefile (or whatnot) obviously ensures foo/ exists, but maps/foo/ would not automatically be created. However, the problem with using (only) the basename of the -o argument is that the build (not the single ld invocation, but the surrounding build system) could produce several binaries of the same name in different directories, so we (a) would clobber the .map files and (b) cannot tell which binary the single surviving .map belongs to. So I don't think there's any way around having _some_ magic value mean 'take the -o argument, append ".map"'. That magic value can be almost anything -Map=% -Map=/ # nobody would put stuff in the root directory -Map=AUTO (and if anybody really wants a map file called AUTO, they could say -Map=./AUTO). > Thoughts ? A whole other option, which may be even easier to hook into arbitrary build systems (not everybody honours/forwards LDFLAGS), is to say "If no -Map argument is given, but the env variable LDAUTOMAP is set, use the -o argument with .map appended". ld does already look at a few environment variables that can be overridden with options, so it's not completely unprecedented. Rasmus ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-10-30 12:37 ` Rasmus Villemoes @ 2020-10-30 16:35 ` Nick Clifton 2020-11-03 9:13 ` Rasmus Villemoes 0 siblings, 1 reply; 17+ messages in thread From: Nick Clifton @ 2020-10-30 16:35 UTC (permalink / raw) To: Rasmus Villemoes, binutils Hi Rasmus, >> My feeling is that we ought to extract the basename of any output file >> and use that, and always honour the directory name specified in the -Map >> option. > However, the problem with using (only) the basename of the -o argument > is that the build (not the single ld invocation, but the surrounding > build system) could produce several binaries of the same name in > different directories, so we (a) would clobber the .map files and (b) > cannot tell which binary the single surviving .map belongs to. That does not sound likely to me. In order for a clobber to occur the user would have to build multiple binaries with the same output name and using the same map directory. But in order for the output binaries not to clobber each other they would have to be built into different output directories. ie: -o foo/bar -Map=/mapdir -o baz/bar -Map=/mapdir It seems to me that this is only likely to occur when creating multiple versions of the same binary (eg with different ABI options) and the map dir is being automatically added to the build. (If the user added the -Map option then they would almost certainly include the discriminating directory name as well). > -Map=AUTO Hmm. maybe. Another possibility is to have the linker not overwrite an existing map file, but instead append a timestamp/random number instead. So -o foo -Map=. would create ./foo.map if it does not exist, or .foo.202010301630.map if foo.map exists. As distinguishing between these map files, I would assume that looking at their contents, and seeing the input files mentioned should be enough. > -Map argument is given, but the env variable LDAUTOMAP is set, I am strongly against environment variables, if they can be avoided. I know that they linker does use some, but I consider this to be a mistake. The bug problem with environment variables is that they make generating bug reports really hard. Most users never include environment variables in their reports, and often they do not even know that they are there. Cheers Nick ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-10-30 16:35 ` Nick Clifton @ 2020-11-03 9:13 ` Rasmus Villemoes 2020-11-04 11:07 ` Nick Clifton 0 siblings, 1 reply; 17+ messages in thread From: Rasmus Villemoes @ 2020-11-03 9:13 UTC (permalink / raw) To: Nick Clifton, binutils On 30/10/2020 17.35, Nick Clifton wrote: > Hi Rasmus, > >>> My feeling is that we ought to extract the basename of any output file >>> and use that, and always honour the directory name specified in the -Map >>> option. > >> However, the problem with using (only) the basename of the -o argument >> is that the build (not the single ld invocation, but the surrounding >> build system) could produce several binaries of the same name in >> different directories, so we (a) would clobber the .map files and (b) >> cannot tell which binary the single surviving .map belongs to. > > That does not sound likely to me. In order for a clobber to occur > the user would have to build multiple binaries with the same output > name and using the same map directory. But in order for the output > binaries not to clobber each other they would have to be built into > different output directories. ie: > > -o foo/bar -Map=/mapdir > -o baz/bar -Map=/mapdir > > It seems to me that this is only likely to occur when creating multiple > versions of the same binary (eg with different ABI options) and the map > dir is being automatically added to the build. (If the user added the > -Map option then they would almost certainly include the discriminating > directory name as well). Yes, exactly, please see my original use case: I'd like some way to get the build to produce map files for all the binaries/solibs etc. generated, without patching each individual project's build system and figuring out where to hook in. This is in the context of building an embedded system using Yocto. So apart from the job of looking at each piece of software (systemd, util-linux, busybox, glibc, ....) and understand how that gets built, I also have to create .patch files, and temporarily add them to the individual recipes. Most build systems do honour LDFLAGS set from outside, so I'd like to do that LDFLAGS += "-Map=something" globally. But also why an environment variable understood by ld itself would be even more convenient, as that wouldn't even rely on the build system passing on inherited LDFLAGS. > >> -Map=AUTO > > Hmm. maybe. > > Another possibility is to have the linker not overwrite an existing > map file, but instead append a timestamp/random number instead. So > > -o foo -Map=. > > would create ./foo.map if it does not exist, or .foo.202010301630.map > if foo.map exists. As distinguishing between these map files, I would > assume that looking at their contents, and seeing the input files mentioned > should be enough. I suppose you're right about the chance of different binaries in different directories having the same name is quite low, and that, in case of a clash, one could distinguish based on contents. But then the problem is that when one rebuilds without cleaning the destination directory, we're actually guaranteed to hit that clash, even if no binaries clash with each other. I think it would add too much complexity and potential for confusion. And actually, sometimes passing "-Map=." wouldn't work; the build system could have a read-only source directory be CWD and have all output go to some other directory. [*] So I still think that having _some way_ to ask ld to create a map file named "<-o argument>.map" is the most convenient; no issues with the target directory possibly not existing or not being writable; no issues with name clashes; the .map gets automatically truncated/overwritten when the binary gets rebuilt. > >> -Map argument is given, but the env variable LDAUTOMAP is set, > > I am strongly against environment variables, if they can be avoided. > I know that they linker does use some, but I consider this to be a > mistake. The bug problem with environment variables is that they make > generating bug reports really hard. Most users never include > environment variables in their reports, and often they do not even > know that they are there. So I agree with you in general. But I'd also argue that for the case of Map files, which are mostly/only for diagnostics, a developer setting LDAUTOMAP would know what he's doing. But if I can have some way of doing [*] via the command line, that would also work for the majority of cases. And instead of a magic -Map= value, it could also simply be a new --automap option (with an explicit -Map= taking precedence). Rasmus ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-11-03 9:13 ` Rasmus Villemoes @ 2020-11-04 11:07 ` Nick Clifton 2020-11-04 11:13 ` Rasmus Villemoes 0 siblings, 1 reply; 17+ messages in thread From: Nick Clifton @ 2020-11-04 11:07 UTC (permalink / raw) To: Rasmus Villemoes, binutils Hi Rasmus, > Yes, exactly, please see my original use case: I'd like some way to get > the build to produce map files for all the binaries/solibs etc. > generated, without patching each individual project's build system and > figuring out where to hook in. OK, so how about this: -Map=<file> Put the map into <file>. <file> can be relative or absolute. -Map=<dir> Put the map into <dir>/basename (outfile).map. Overwrites existing maps. -Map=% Put the map into (outfile).map. Includes all path components in (outfile) Would this work for you ? Cheers Nick ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-11-04 11:07 ` Nick Clifton @ 2020-11-04 11:13 ` Rasmus Villemoes 2020-11-05 0:47 ` Fangrui Song 0 siblings, 1 reply; 17+ messages in thread From: Rasmus Villemoes @ 2020-11-04 11:13 UTC (permalink / raw) To: Nick Clifton, binutils On 04/11/2020 12.07, Nick Clifton wrote: > Hi Rasmus, > >> Yes, exactly, please see my original use case: I'd like some way to get >> the build to produce map files for all the binaries/solibs etc. >> generated, without patching each individual project's build system and >> figuring out where to hook in. > > OK, so how about this: > > -Map=<file> Put the map into <file>. <file> can be relative or absolute. > -Map=<dir> Put the map into <dir>/basename (outfile).map. Overwrites existing maps. > -Map=% Put the map into (outfile).map. Includes all path components in (outfile) > > Would this work for you ? > Yes, absolutely. Thanks. Rasmus ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-11-04 11:13 ` Rasmus Villemoes @ 2020-11-05 0:47 ` Fangrui Song 2020-11-05 10:01 ` Nick Clifton 2020-11-05 11:41 ` Nick Clifton 0 siblings, 2 replies; 17+ messages in thread From: Fangrui Song @ 2020-11-05 0:47 UTC (permalink / raw) To: Rasmus Villemoes; +Cc: Nick Clifton, binutils On 2020-11-04, Rasmus Villemoes wrote: >On 04/11/2020 12.07, Nick Clifton wrote: >> Hi Rasmus, >> >>> Yes, exactly, please see my original use case: I'd like some way to get >>> the build to produce map files for all the binaries/solibs etc. >>> generated, without patching each individual project's build system and >>> figuring out where to hook in. >> >> OK, so how about this: >> >> -Map=<file> Put the map into <file>. <file> can be relative or absolute. >> -Map=<dir> Put the map into <dir>/basename (outfile).map. Overwrites existing maps. This looks like a complex operation. Is it really needed? >> -Map=% Put the map into (outfile).map. Includes all path components in (outfile) Maybe -Map=%.map to avoid hard coding the extension name? >> Would this work for you ? >> > >Yes, absolutely. Thanks. > >Rasmus ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-11-05 0:47 ` Fangrui Song @ 2020-11-05 10:01 ` Nick Clifton 2020-11-05 11:41 ` Nick Clifton 1 sibling, 0 replies; 17+ messages in thread From: Nick Clifton @ 2020-11-05 10:01 UTC (permalink / raw) To: Fangrui Song, Rasmus Villemoes; +Cc: binutils Hi Fangrui, >> -Map=<file> Put the map into <file>. <file> can be relative or absolute. >> -Map=<dir> Put the map into <dir>/basename (outfile).map. Overwrites existing maps. > This looks like a complex operation. Is it really needed? This actually reflects the current situation (well without the basename operation). Providing a directory name for the map option is useful as it allows build systems to use the option without having to worry about generating unique map names. >> -Map=% Put the map into (outfile).map. Includes all path components in (outfile) > > Maybe -Map=%.map to avoid hard coding the extension name? Except that we already hard code the .map extension when the directory version of the option is used. But it would be simple enough to extend the specification so that: -Map=% Puts the map into (outfile).map -Map=%.<foo> Puts the map into (outfile).<foo> Cheers Nick ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-11-05 0:47 ` Fangrui Song 2020-11-05 10:01 ` Nick Clifton @ 2020-11-05 11:41 ` Nick Clifton 2020-11-05 12:23 ` Rasmus Villemoes 1 sibling, 1 reply; 17+ messages in thread From: Nick Clifton @ 2020-11-05 11:41 UTC (permalink / raw) To: Fangrui Song, Rasmus Villemoes; +Cc: binutils [-- Attachment #1: Type: text/plain, Size: 162 bytes --] Hi Fangrui, Hi Rasmus, Any comments on the attached patch ? It implements the basename and % character changes as previously discussed. Cheers Nick [-- Attachment #2: ld-map-directory.patch --] [-- Type: text/x-patch, Size: 6924 bytes --] diff --git a/ld/ld.texi b/ld/ld.texi index cf8f05c39e..9b74b893c1 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -1866,10 +1866,34 @@ Print a summary of all target-specific options on the standard output and exit. @kindex -Map=@var{mapfile} @item -Map=@var{mapfile} Print a link map to the file @var{mapfile}. See the description of the -@option{-M} option, above. Specifying a directory as @var{mapfile} -causes the linker map to be written into a file inside the directory. -The name of the file is based upon the @var{output} filename with -@code{.map} appended. +@option{-M} option, above. If @var{mapfile} is just the character +@code{-} then the map will be written to stdout. + +Specifying a directory as @var{mapfile} causes the linker map to be +written as a file inside the directory. Normally name of the file +inside the directory is computed as the basename of the @var{output} +file with @code{.map} appended. If however the special character +@code{%} is used then this will be replaced by the full path of the +output file. Additionally if there are any characters after the +@var{%} symbol then @code{.map} will no longer be appended. + +@smallexample + -o foo.exe -Map=bar [Creates ./bar] + -o ../dir/foo.exe -Map=bar [Creates ./bar] + -o foo.exe -Map=../dir [Creates ../dir/foo.exe.map] + -o ../dir2/foo.exe -Map=../dir [Creates ../dir/foo.exe.map] + -o foo.exe -Map=% [Creates ./foo.exe.map] + -o ../dir/foo.exe -Map=% [Creates ../dir/foo.exe.map] + -o foo.exe -Map=%.bar [Creates ./foo.exe.bar] + -o ../dir/foo.exe -Map=%.bar [Creates ../dir/foo.exe.bar] + -o ../dir2/foo.exe -Map=../dir/% [Creates ../dir/../dir2/foo.exe.map] + -o ../dir2/foo.exe -Map=../dir/%.bar [Creates ../dir/../dir2/foo.exe.bar] +@end smallexample + +It is an error to specify more than one @code{%} character. + +If the map file already exists then it will be overwritten by this +operation. @cindex memory usage @kindex --no-keep-memory diff --git a/ld/lexsup.c b/ld/lexsup.c index eae64932df..45c29d82ff 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -22,8 +22,10 @@ #include "bfd.h" #include "bfdver.h" #include "libiberty.h" +#include "filenames.h" #include <stdio.h> #include <string.h> +#include <errno.h> #include "safe-ctype.h" #include "getopt.h" #include "bfdlink.h" @@ -1700,35 +1702,84 @@ parse_args (unsigned argc, char **argv) /* Run a couple of checks on the map filename. */ if (config.map_filename) { + char * new_name = NULL; + char * percent; + int res = 0; + if (config.map_filename[0] == 0) { einfo (_("%P: no file/directory name provided for map output; ignored\n")); config.map_filename = NULL; } + else if (strcmp (config.map_filename, "-") == 0) + ; /* Write to stdout. Handled in main(). */ + else if ((percent = strchr (config.map_filename, '%')) != NULL) + { + /* FIXME: Check for a second % character and issue an error ? */ + + /* Construct a map file by replacing the % character with the (full) + output filename. If the % character was the last character in + the original map filename then add a .map extension. */ + if (percent == config.map_filename) + { + if (percent[1] == 0) + res = asprintf (&new_name, "%s.map", output_filename); + else + res = asprintf (&new_name, "%s%s", + output_filename, percent + 1); + } + else + { + percent[0] = 0; + if (percent[1] == 0) + res = asprintf (&new_name, "%s%s.map", + config.map_filename, output_filename); + else + res = asprintf (&new_name, "%s%s%s", + config.map_filename, output_filename, + percent + 1); + } + + /* FIXME: Should we ensure that any directory components in new_name exist ? */ + } else { struct stat s; /* If the map filename is actually a directory then create a file inside it, based upon the output filename. */ - if (stat (config.map_filename, &s) >= 0 - && S_ISDIR (s.st_mode)) + if (stat (config.map_filename, &s) < 0) { - char * new_name; - - /* FIXME: This is a (trivial) memory leak. */ - if (asprintf (&new_name, "%s/%s.map", - config.map_filename, output_filename) < 0) - { - /* If this alloc fails then something is probably very - wrong. Better to halt now rather than continue on - into more problems. */ - einfo (_("%P%F: cannot create name for linker map file: %E\n")); - new_name = NULL; - } - - config.map_filename = new_name; + if (errno != ENOENT) + einfo (_("%P: cannot stat linker map file: %E\n")); + } + else if (S_ISDIR (s.st_mode)) + { + char lastc = config.map_filename[strlen (config.map_filename) - 1]; + res = asprintf (&new_name, "%s%s%s.map", + config.map_filename, + IS_DIR_SEPARATOR (lastc) ? "" : "/", + lbasename (output_filename)); + } + else if (! S_ISREG (s.st_mode)) + { + einfo (_("%P: linker map file is not a regular file\n")); + config.map_filename = NULL; } + /* else FIXME: Check write permission ? */ + } + + if (res < 0) + { + /* If the asprintf failed then something is probably very + wrong. Better to halt now rather than continue on + into more problems. */ + einfo (_("%P%F: cannot create name for linker map file: %E\n")); + } + else if (new_name != NULL) + { + /* This is a trivial memory leak. */ + config.map_filename = new_name; } } diff --git a/ld/testsuite/ld-scripts/map-address.exp b/ld/testsuite/ld-scripts/map-address.exp index 1f9457a8cd..e8d3683c01 100644 --- a/ld/testsuite/ld-scripts/map-address.exp +++ b/ld/testsuite/ld-scripts/map-address.exp @@ -46,6 +46,7 @@ if {[regexp_diff \ pass $testname } + set testname "map to directory" if {![ld_link $ld tmpdir/map-address \ @@ -67,3 +68,49 @@ if {[regexp_diff \ } else { pass $testname } + + +set testname "map to % directory" + +if {![ld_link $ld tmpdir/map-address \ + "$LDFLAGS -T $srcdir/$subdir/map-address.t \ + tmpdir/map-address.o \ + -Map=tmpdir/% --output fred"]} { + fail $testname + return +} + +if [is_remote host] then { + remote_upload host "tmpdir/fred.map" +} + +if {[regexp_diff \ + "tmpdir/fred.map" \ + "$srcdir/$subdir/map-address.d"]} { + fail $testname +} else { + pass $testname +} + + +set testname "map to %.foo directory" + +if {![ld_link $ld tmpdir/map-address \ + "$LDFLAGS -T $srcdir/$subdir/map-address.t \ + tmpdir/map-address.o \ + -Map=tmpdir/%.foo --output fred"]} { + fail $testname + return +} + +if [is_remote host] then { + remote_upload host "tmpdir/fred.foo" +} + +if {[regexp_diff \ + "tmpdir/fred.foo" \ + "$srcdir/$subdir/map-address.d"]} { + fail $testname +} else { + pass $testname +} ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-11-05 11:41 ` Nick Clifton @ 2020-11-05 12:23 ` Rasmus Villemoes 2020-11-06 14:38 ` Nick Clifton 0 siblings, 1 reply; 17+ messages in thread From: Rasmus Villemoes @ 2020-11-05 12:23 UTC (permalink / raw) To: Nick Clifton, Fangrui Song; +Cc: binutils On 05/11/2020 12.41, Nick Clifton wrote: > Hi Fangrui, Hi Rasmus, > > Any comments on the attached patch ? > > It implements the basename and % character changes as previously > discussed. LGTM. I think you can simplify it somewhat: Always overwrite the % with a nul byte and construct the path using the part of the -Map argument before the % (which will be empty in the case where % is the first character). So instead of the four different asprintf, I think you can just do percent[0] = 0; res = asprintf(&new_name, "%s%s%s", config.map_filename, output_filename, percent[1] ? percent + 1 : ".map"); no? Thanks for working on this. Rasmus ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] allow empty string as argument to -Map 2020-11-05 12:23 ` Rasmus Villemoes @ 2020-11-06 14:38 ` Nick Clifton 0 siblings, 0 replies; 17+ messages in thread From: Nick Clifton @ 2020-11-06 14:38 UTC (permalink / raw) To: Rasmus Villemoes, Fangrui Song; +Cc: binutils Hi Rasmus, > So instead of the four different asprintf, I think you can just do > > percent[0] = 0; > res = asprintf(&new_name, "%s%s%s", config.map_filename, > output_filename, percent[1] ? percent + 1 : ".map"); > > no? Good point - I have applied the patch with this change made. Cheers Nick ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2020-11-06 14:38 UTC | newest] Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-05-26 7:01 [PATCH] allow empty string as argument to -Map Rasmus Villemoes 2020-05-27 16:50 ` Nick Clifton 2020-05-28 0:33 ` Rasmus Villemoes 2020-05-28 4:23 ` Fangrui Song 2020-05-28 9:54 ` Nick Clifton 2020-10-23 12:31 ` Rasmus Villemoes 2020-10-29 15:52 ` Nick Clifton 2020-10-30 12:37 ` Rasmus Villemoes 2020-10-30 16:35 ` Nick Clifton 2020-11-03 9:13 ` Rasmus Villemoes 2020-11-04 11:07 ` Nick Clifton 2020-11-04 11:13 ` Rasmus Villemoes 2020-11-05 0:47 ` Fangrui Song 2020-11-05 10:01 ` Nick Clifton 2020-11-05 11:41 ` Nick Clifton 2020-11-05 12:23 ` Rasmus Villemoes 2020-11-06 14:38 ` Nick Clifton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).