From 291f9a9643f87fa4eb6a7c280eaa3877c11e3a1f Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 28 Jun 2018 08:33:17 +0200 Subject: [PATCH] Add an optional offset option to the "add-symbol-file" command 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 * 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 * gdb.texinfo (Files): Document "add-symbol-file -o offset". gdb/testsuite/ChangeLog: 2018-06-28 Petr Tesarik * gdb.base/relocate.exp: Add test for "add-symbol-file -o ". --- gdb/ChangeLog | 7 +++ gdb/NEWS | 4 ++ gdb/doc/ChangeLog | 4 ++ gdb/doc/gdb.texinfo | 6 ++- gdb/symfile.c | 83 +++++++++++++++++++++++++++-- gdb/testsuite/ChangeLog | 4 ++ gdb/testsuite/gdb.base/relocate.exp | 56 +++++++++++++++++++ 7 files changed, 160 insertions(+), 4 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bd19de96e89..80626191c91 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2018-06-28 Petr Tesarik + + * 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 * symfile.c (add_symbol_file_command): Make sure that sections diff --git a/gdb/NEWS b/gdb/NEWS index 54c0f1d19b1..016796a802a 100644 --- 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). diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 9fd3d3c3689..6954398e43e 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2018-06-28 Petr Tesarik + + * gdb.texinfo (Files): Document "add-symbol-file -o offset". + 2018-06-28 Petr Tesarik * gdb.texinfo (Files): The address argument for "add-symbol-file" diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 64c511d1e6d..7fb6ac56364 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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 diff --git a/gdb/symfile.c b/gdb/symfile.c index b592be74cfc..48eca5cc0ea 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -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 offsets (objf->num_sections, + { offset }); + + /* Create sorted lists of all sections in ADDRS as well as all + sections in OBJF. */ + + std::vector addrs_sorted + = addrs_section_sort (addrs); + + section_addr_info objf_addrs + = build_section_addr_info_from_objfile (objf); + std::vector 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::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_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, §ion_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); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index e3c91415645..f3856c4bc47 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-06-28 Petr Tesarik + + * gdb.base/relocate.exp: Add test for "add-symbol-file -o ". + 2018-06-28 Petr Tesarik * gdb.base/relocate.exp: Test add-symbol-file behavior when the diff --git a/gdb/testsuite/gdb.base/relocate.exp b/gdb/testsuite/gdb.base/relocate.exp index 2b4c4a70446..b6f18d9c69d 100644 --- a/gdb/testsuite/gdb.base/relocate.exp +++ b/gdb/testsuite/gdb.base/relocate.exp @@ -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. -- 2.30.2