mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-17 13:10:12 +08:00
Extend ld's -Map=<dir> functionality by allowing '%' to be replaced with the output file path.
* lexsup.c (parse_args): Add more checks of the mapfile. If it is a directory use the basename of the output file as the file component. If the % character is present, replace it with the full output filepath. * testsuite/ld-scripts/map-address.exp: Add test of % functionality. * ld.texi: Document the new behaviour.
This commit is contained in:
parent
9c905051aa
commit
2c72361c81
10
ld/ChangeLog
10
ld/ChangeLog
@ -1,3 +1,13 @@
|
||||
2020-11-06 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* lexsup.c (parse_args): Add more checks of the mapfile. If it is
|
||||
a directory use the basename of the output file as the file
|
||||
component. If the % character is present, replace it with the
|
||||
full output filepath.
|
||||
* testsuite/ld-scripts/map-address.exp: Add test of %
|
||||
functionality.
|
||||
* ld.texi: Document the new behaviour.
|
||||
|
||||
2020-11-06 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* po/sr.po: Updated Serbian translation.
|
||||
|
32
ld/ld.texi
32
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
|
||||
|
68
ld/lexsup.c
68
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,69 @@ 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. */
|
||||
percent[0] = 0;
|
||||
res = asprintf (&new_name, "%s%s%s", config.map_filename,
|
||||
output_filename,
|
||||
percent[1] ? percent + 1 : ".map");
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user