Add an optional offset option to the "add-symbol-file" command
authorPetr Tesarik <ptesarik@suse.cz>
Thu, 28 Jun 2018 06:33:17 +0000 (08:33 +0200)
committerPetr Tesarik <ptesarik@suse.cz>
Thu, 28 Jun 2018 06:35:34 +0000 (08:35 +0200)
If all sections of a symbol file are loaded with a fixed offset, it
is easier to specify that offset than listing all sections
explicitly.  There is also a similar option for "symbol-file".

gdb/ChangeLog:
2018-06-28  Petr Tesarik  <ptesarik@suse.cz>

* symfile.c (add_symbol_file_command, _initialize_symfile): Add
option "-o" to add-symbol-file-load to add an offset to each
section's load address.
* symfile.c (set_objfile_default_section_offset): New function.

gdb/doc/ChangeLog:
2018-06-28  Petr Tesarik  <ptesarik@suse.cz>

* gdb.texinfo (Files): Document "add-symbol-file -o offset".

gdb/testsuite/ChangeLog:
2018-06-28  Petr Tesarik  <ptesarik@suse.cz>

* gdb.base/relocate.exp: Add test for "add-symbol-file -o ".

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/symfile.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/relocate.exp

index bd19de96e89d06356aea4ba8ca5138c57c34c627..80626191c91e1d4c8326b52d6976547928d4fc2a 100644 (file)
@@ -1,3 +1,10 @@
+2018-06-28  Petr Tesarik  <ptesarik@suse.cz>
+
+       * symfile.c (add_symbol_file_command, _initialize_symfile): Add
+       option "-o" to add-symbol-file-load to add an offset to each
+       section's load address.
+       * symfile.c (set_objfile_default_section_offset): New function.
+
 2018-06-28  Petr Tesarik  <ptesarik@suse.cz>
 
        * symfile.c (add_symbol_file_command): Make sure that sections
index 54c0f1d19b199ad218d34302888106f9e62783af..016796a802ab3774d50b73565c194fe74a2bbe8a 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -6,6 +6,10 @@
 * The 'symbol-file' command now accepts an '-o' option to add a relative
   offset to all sections.
 
+* Similarly, the 'add-symbol-file' command also accepts an '-o' option to add
+  a relative offset to all sections, but it allows to override the load
+  address of individual sections using '-s'.
+
 * The 'add-symbol-file' command no longer requires the second argument
   (address of the text section).
 
index 9fd3d3c3689061e51f163532360897f6e9d8a962..6954398e43ee3f6a191bedd5677ec20c82bd7f6e 100644 (file)
@@ -1,3 +1,7 @@
+2018-06-28  Petr Tesarik  <ptesarik@suse.cz>
+
+       * gdb.texinfo (Files): Document "add-symbol-file -o offset".
+
 2018-06-28  Petr Tesarik  <ptesarik@suse.cz>
 
        * gdb.texinfo (Files): The address argument for "add-symbol-file"
index 64c511d1e6d2b93b526c1b9506ed4630bf05f61f..7fb6ac56364016b00c6f333c65553533d5fdedc9 100644 (file)
@@ -18918,7 +18918,7 @@ the program is running.  To do this, use the @code{kill} command
 
 @kindex add-symbol-file
 @cindex dynamic linking
-@item add-symbol-file @var{filename} @r{[} -readnow @r{|} -readnever @r{]} @r{[} @var{textaddress} @r{]} @r{[} -s @var{section} @var{address} @dots{} @r{]}
+@item add-symbol-file @var{filename} @r{[} -readnow @r{|} -readnever @r{]} @r{[} -o @var{offset} @r{]} @r{[} @var{textaddress} @r{]} @r{[} -s @var{section} @var{address} @dots{} @r{]}
 The @code{add-symbol-file} command reads additional symbol table
 information from the file @var{filename}.  You would use this command
 when @var{filename} has been dynamically loaded (by some other means)
@@ -18930,6 +18930,10 @@ If a section is omitted, @value{GDBN} will use its default addresses
 as found in @var{filename}.  Any @var{address} or @var{textaddress}
 can be given as an expression.
 
+If an optional @var{offset} is specified, it is added to the start
+address of each section, except those for which the address was
+specified explicitly.
+
 The symbol table of the file @var{filename} is added to the symbol table
 originally read with the @code{symbol-file} command.  You can use the
 @code{add-symbol-file} command any number of times; the new symbol data
index b592be74cfc1cdbbbd6a124c61dc1c21710796d2..48eca5cc0ea5b9c8c7310207fceba87b0c17758b 100644 (file)
@@ -2078,6 +2078,61 @@ print_transfer_performance (struct ui_file *stream,
   uiout->text (".\n");
 }
 
+/* Add an OFFSET to the start address of each section in OBJF, except
+   sections that were specified in ADDRS.  */
+
+static void
+set_objfile_default_section_offset (struct objfile *objf,
+                                   const section_addr_info &addrs,
+                                   CORE_ADDR offset)
+{
+  /* Add OFFSET to all sections by default.  */
+  std::vector<struct section_offsets> offsets (objf->num_sections,
+                                              { offset });
+
+  /* Create sorted lists of all sections in ADDRS as well as all
+     sections in OBJF.  */
+
+  std::vector<const struct other_sections *> addrs_sorted
+    = addrs_section_sort (addrs);
+
+  section_addr_info objf_addrs
+    = build_section_addr_info_from_objfile (objf);
+  std::vector<const struct other_sections *> objf_addrs_sorted
+    = addrs_section_sort (objf_addrs);
+
+  /* Walk the BFD section list, and if a matching section is found in
+     ADDRS_SORTED_LIST, set its offset to zero to keep its address
+     unchanged.
+
+     Note that both lists may contain multiple sections with the same
+     name, and then the sections from ADDRS are matched in BFD order
+     (thanks to sectindex).  */
+
+  std::vector<const struct other_sections *>::iterator addrs_sorted_iter
+    = addrs_sorted.begin ();
+  for (const struct other_sections *objf_sect : objf_addrs_sorted)
+    {
+      const char *objf_name = addr_section_name (objf_sect->name.c_str ());
+      int cmp = -1;
+
+      while (cmp < 0 && addrs_sorted_iter != addrs_sorted.end ())
+       {
+         const struct other_sections *sect = *addrs_sorted_iter;
+         const char *sect_name = addr_section_name (sect->name.c_str ());
+         cmp = strcmp (sect_name, objf_name);
+         if (cmp <= 0)
+           ++addrs_sorted_iter;
+       }
+
+      if (cmp == 0)
+       offsets[objf_sect->sectindex].offsets[0] = 0;
+    }
+
+  /* Apply the new section offsets.  */
+  objfile_relocate (objf, offsets.data ());
+}
+
 /* This function allows the addition of incrementally linked object files.
    It does not modify any state in the target, only in the debugger.  */
 /* Note: ezannoni 2000-04-13 This function/command used to have a
@@ -2109,6 +2164,7 @@ add_symbol_file_command (const char *args, int from_tty)
 
   std::vector<sect_opt> sect_opts = { { ".text", NULL } };
   bool stop_processing_options = false;
+  CORE_ADDR offset = 0;
 
   dont_repeat ();
 
@@ -2116,6 +2172,7 @@ add_symbol_file_command (const char *args, int from_tty)
     error (_("add-symbol-file takes a file name and an address"));
 
   bool seen_addr = false;
+  bool seen_offset = false;
   gdb_argv argv (args);
 
   for (arg = argv[0], argcnt = 0; arg != NULL; arg = argv[++argcnt])
@@ -2153,6 +2210,15 @@ add_symbol_file_command (const char *args, int from_tty)
          sect_opts.push_back (sect);
          argcnt += 2;
        }
+      else if (strcmp (arg, "-o") == 0)
+       {
+         arg = argv[++argcnt];
+         if (arg == NULL)
+           error (_("Missing argument to -o"));
+
+         offset = parse_and_eval_address (arg);
+         seen_offset = true;
+       }
       else if (strcmp (arg, "--") == 0)
        stop_processing_options = true;
       else
@@ -2202,7 +2268,13 @@ add_symbol_file_command (const char *args, int from_tty)
         At this point, we don't know what file type this is,
         so we can't determine what section names are valid.  */
     }
-  if (section_addrs.empty ())
+  if (seen_offset)
+      printf_unfiltered (_("%s offset by %s\n"),
+                        (section_addrs.empty ()
+                         ? _(" with all sections")
+                         : _("with other sections")),
+                        paddress (gdbarch, offset));
+  else if (section_addrs.empty ())
     printf_unfiltered ("\n");
 
   if (from_tty && (!query ("%s", "")))
@@ -2211,6 +2283,9 @@ add_symbol_file_command (const char *args, int from_tty)
   objf = symbol_file_add (filename.get (), add_flags, &section_addrs,
                          flags);
 
+  if (seen_offset)
+    set_objfile_default_section_offset (objf, section_addrs, offset);
+
   add_target_sections_of_objfile (objf);
 
   /* Getting new symbols may change our opinion about what is
@@ -3799,12 +3874,14 @@ to execute.\n" READNOW_READNEVER_HELP), &cmdlist);
 
   c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command, _("\
 Load symbols from FILE, assuming FILE has been dynamically loaded.\n\
-Usage: add-symbol-file FILE [-readnow | -readnever] [ADDR] \
+Usage: add-symbol-file FILE [-readnow | -readnever] [-o OFF] [ADDR] \
 [-s SECT-NAME SECT-ADDR]...\n\
 ADDR is the starting address of the file's text.\n\
 Each '-s' argument provides a section name and address, and\n\
 should be specified if the data and bss segments are not contiguous\n\
-with the text.  SECT-NAME is a section name to be loaded at SECT-ADDR.\n"
+with the text.  SECT-NAME is a section name to be loaded at SECT-ADDR.\n\
+OFF is an optional offset which is added to the default load addresses\n\
+of all sections for which no other address was specified.\n"
 READNOW_READNEVER_HELP),
               &cmdlist);
   set_cmd_completer (c, filename_completer);
index e3c91415645ae38ed53599685371ac4c2279588a..f3856c4bc4782e76ca3671b6916d006bbb31ac9e 100644 (file)
@@ -1,3 +1,7 @@
+2018-06-28  Petr Tesarik  <ptesarik@suse.cz>
+
+       * gdb.base/relocate.exp: Add test for "add-symbol-file -o ".
+
 2018-06-28  Petr Tesarik  <ptesarik@suse.cz>
 
        * gdb.base/relocate.exp: Test add-symbol-file behavior when the
index 2b4c4a70446065505ba1fd5aef34b315202311f3..b6f18d9c69dc22d352541009accb6e140f3ec3ef 100644 (file)
@@ -235,6 +235,62 @@ set new_function_foo_addr [get_var_address function_foo]
 gdb_assert {${new_function_foo_addr} == ${function_foo_addr} + $offset} \
     "function foo is moved by offset"
 
+# Load the object using add-symbol-file with an offset and check that
+# all addresses are moved by that offset.
+
+set offset 0x10000
+clean_restart
+gdb_test "add-symbol-file -o $offset $binfile" \
+    "Reading symbols from ${binfile}\.\.\.done\." \
+    "add-symbol-file with offset" \
+    "add symbol table from file \".*${testfile}\\.o\" with all sections offset by $offset\[\r\n\]+\\(y or n\\) " \
+    "y"
+
+# Make sure the address of a static variable is moved by offset.
+set new_static_foo_addr [get_var_address static_foo]
+gdb_assert { ${new_static_foo_addr} == ${static_foo_addr} + $offset } \
+    "static variable foo is moved by offset"
+
+# Make sure the address of a global variable is moved by offset.
+set new_global_foo_addr [get_var_address global_foo]
+gdb_assert { ${new_global_foo_addr} == ${global_foo_addr} + $offset } \
+    "global variable foo is moved by offset"
+
+# Make sure the address of a function is moved by offset.
+set new_function_foo_addr [get_var_address function_foo]
+gdb_assert { ${new_function_foo_addr} == ${function_foo_addr} + $offset } \
+    "function foo is moved by offset"
+
+# Re-load the object giving an explicit address for .text
+
+set text [ format "0x%x" [expr ${function_foo_addr} + 0x20000] ]
+clean_restart
+gdb_test "add-symbol-file $binfile -o $offset $text" \
+    "Reading symbols from ${binfile}\.\.\.done\." \
+    "add-symbol-file with offset, text address given" \
+    "add symbol table from file \".*${testfile}\\.o\" at\[ \t\r\n\]+\.text_addr = ${text}\[\r\n\]+with other sections offset by ${offset}\[\r\n\]+\\(y or n\\) " \
+    "y"
+
+# Make sure function has a different addresses now.
+set function_foo_addr [get_var_address function_foo]
+gdb_assert { ${function_foo_addr} != ${new_function_foo_addr} } \
+    "function foo has a different address"
+
+# Re-load the object giving an explicit address for .data
+
+set data [ format "0x%x" [expr ${global_foo_addr} + 0x20000] ]
+clean_restart
+gdb_test "add-symbol-file $binfile -o $offset -s .data $data" \
+    "Reading symbols from ${binfile}\.\.\.done\." \
+    "add-symbol-file with offset, data address given" \
+    "add symbol table from file \".*${testfile}\\.o\" at\[ \t\r\n\]+\.data_addr = ${data}\[\r\n\]+with other sections offset by ${offset}\[\r\n\]+\\(y or n\\) " \
+    "y"
+
+# Make sure variable has a different addresses now.
+set global_foo_addr [get_var_address global_foo]
+gdb_assert { ${global_foo_addr} != ${new_global_foo_addr} } \
+    "global variable foo has a different address"
+
 # Now try loading the object as an exec-file; we should be able to print
 # the values of variables after we do this.