diff options
author | Daniel Jacobowitz <drow@false.org> | 2005-06-13 16:15:40 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2005-06-13 16:15:40 +0000 |
commit | c1bd25fd1de1bc9e80bf95feb670c26be62c833b (patch) | |
tree | 040f83c9ea28a54f68672022b0a04975c5b9c37c /gdb | |
parent | 37f6032b8594c94b585732cf7ae09affe8614eee (diff) | |
download | gdb-c1bd25fd1de1bc9e80bf95feb670c26be62c833b.zip gdb-c1bd25fd1de1bc9e80bf95feb670c26be62c833b.tar.gz gdb-c1bd25fd1de1bc9e80bf95feb670c26be62c833b.tar.bz2 |
gdb/
* Makefile.in (symfile.o): Add $(exec_h).
* exec.h (exec_set_section_address): Add prototype.
* exec.c (exec_set_section_address): New function.
* symfile.c: Include "exec.h".
(struct place_section_arg, place_section): New.
(default_symfile_offsets): Call place_section for each
section of a relocatable file.
gdb/testsuite/
* gdb.base/relocate.c: Add a copyright notice.
(dummy): Remove.
* gdb.base/relocate.exp: Test printing the values of variables
from a relocatable file.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 10 | ||||
-rw-r--r-- | gdb/Makefile.in | 2 | ||||
-rw-r--r-- | gdb/exec.c | 21 | ||||
-rw-r--r-- | gdb/exec.h | 3 | ||||
-rw-r--r-- | gdb/symfile.c | 92 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/relocate.c | 24 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/relocate.exp | 16 |
8 files changed, 168 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6a5c47b..50b3b9e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2005-06-13 Daniel Jacobowitz <dan@codesourcery.com> + + * Makefile.in (symfile.o): Add $(exec_h). + * exec.h (exec_set_section_address): Add prototype. + * exec.c (exec_set_section_address): New function. + * symfile.c: Include "exec.h". + (struct place_section_arg, place_section): New. + (default_symfile_offsets): Call place_section for each + section of a relocatable file. + 2005-06-13 Joel Brobecker <brobecker@adacore.com> * hppa-tdep.c (hppa_pc_requires_run_before_use): Really test all diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 7a27d0b..2cdb1b7 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2642,7 +2642,7 @@ symfile.o: symfile.c $(defs_h) $(bfdlink_h) $(symtab_h) $(gdbtypes_h) \ $(complaints_h) $(demangle_h) $(inferior_h) $(filenames_h) \ $(gdb_stabs_h) $(gdb_obstack_h) $(completer_h) $(bcache_h) \ $(hashtab_h) $(readline_h) $(gdb_assert_h) $(block_h) \ - $(gdb_string_h) $(gdb_stat_h) $(observer_h) + $(gdb_string_h) $(gdb_stat_h) $(observer_h) $(exec_h) symfile-mem.o: symfile-mem.c $(defs_h) $(symtab_h) $(gdbcore_h) \ $(objfiles_h) $(exceptions_h) $(gdbcmd_h) $(target_h) $(value_h) \ $(symfile_h) $(observer_h) $(auxv_h) $(elf_common_h) @@ -670,6 +670,27 @@ set_section_command (char *args, int from_tty) error (_("Section %s not found"), secprint); } +/* If we can find a section in FILENAME with BFD index INDEX, and the + user has not assigned an address to it yet (via "set section"), adjust it + to ADDRESS. */ + +void +exec_set_section_address (const char *filename, int index, CORE_ADDR address) +{ + struct section_table *p; + + for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++) + { + if (strcmp (filename, p->bfd->filename) == 0 + && index == p->the_bfd_section->index + && p->addr == 0) + { + p->addr = address; + p->endaddr += address; + } + } +} + /* If mourn is being called in all the right places, this could be say `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */ @@ -36,4 +36,7 @@ extern struct target_ops exec_ops; extern int build_section_table (struct bfd *, struct section_table **, struct section_table **); +/* Set the loaded address of a section. */ +extern void exec_set_section_address (const char *, int, CORE_ADDR); + #endif diff --git a/gdb/symfile.c b/gdb/symfile.c index 8770943..7bd3853 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -49,6 +49,7 @@ #include "gdb_assert.h" #include "block.h" #include "observer.h" +#include "exec.h" #include <sys/types.h> #include <fcntl.h> @@ -456,6 +457,84 @@ init_objfile_sect_indices (struct objfile *objfile) } } +/* The arguments to place_section. */ + +struct place_section_arg +{ + struct section_offsets *offsets; + CORE_ADDR lowest; +}; + +/* Find a unique offset to use for loadable section SECT if + the user did not provide an offset. */ + +void +place_section (bfd *abfd, asection *sect, void *obj) +{ + struct place_section_arg *arg = obj; + CORE_ADDR *offsets = arg->offsets->offsets, start_addr; + int done; + + /* We are only interested in loadable sections. */ + if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0) + return; + + /* If the user specified an offset, honor it. */ + if (offsets[sect->index] != 0) + return; + + /* Otherwise, let's try to find a place for the section. */ + do { + asection *cur_sec; + ULONGEST align = 1 << bfd_get_section_alignment (abfd, sect); + + start_addr = (arg->lowest + align - 1) & -align; + done = 1; + + for (cur_sec = abfd->sections; cur_sec != NULL; cur_sec = cur_sec->next) + { + int indx = cur_sec->index; + CORE_ADDR cur_offset; + + /* We don't need to compare against ourself. */ + if (cur_sec == sect) + continue; + + /* We can only conflict with loadable sections. */ + if ((bfd_get_section_flags (abfd, cur_sec) & SEC_LOAD) == 0) + continue; + + /* We do not expect this to happen; just ignore sections in a + relocatable file with an assigned VMA. */ + if (bfd_section_vma (abfd, cur_sec) != 0) + continue; + + /* If the section offset is 0, either the section has not been placed + yet, or it was the lowest section placed (in which case LOWEST + will be past its end). */ + if (offsets[indx] == 0) + continue; + + /* If this section would overlap us, then we must move up. */ + if (start_addr + bfd_get_section_size (sect) > offsets[indx] + && start_addr < offsets[indx] + bfd_get_section_size (cur_sec)) + { + start_addr = offsets[indx] + bfd_get_section_size (cur_sec); + start_addr = (start_addr + align - 1) & -align; + done = 0; + continue; + } + + /* Otherwise, we appear to be OK. So far. */ + } + } + while (!done); + + offsets[sect->index] = start_addr; + arg->lowest = start_addr + bfd_get_section_size (sect); + + exec_set_section_address (bfd_get_filename (abfd), sect->index, start_addr); +} /* Parse the user's idea of an offset for dynamic linking, into our idea of how to represent it for fast symbol reading. This is the default @@ -492,6 +571,19 @@ default_symfile_offsets (struct objfile *objfile, (objfile->section_offsets)->offsets[osp->sectindex] = osp->addr; } + /* For relocatable files, all loadable sections will start at zero. + The zero is meaningless, so try to pick arbitrary addresses such + that no loadable sections overlap. This algorithm is quadratic, + but the number of sections in a single object file is generally + small. */ + if ((bfd_get_file_flags (objfile->obfd) & (EXEC_P | DYNAMIC)) == 0) + { + struct place_section_arg arg; + arg.offsets = objfile->section_offsets; + arg.lowest = 0; + bfd_map_over_sections (objfile->obfd, place_section, &arg); + } + /* Remember the bfd indexes for the .text, .data, .bss and .rodata sections. */ init_objfile_sect_indices (objfile); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 48bf65c..e8580db 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2005-06-13 Daniel Jacobowitz <dan@codesourcery.com> + + * gdb.base/relocate.c: Add a copyright notice. + (dummy): Remove. + * gdb.base/relocate.exp: Test printing the values of variables + from a relocatable file. + 2005-06-12 Daniel Jacobowitz <dan@codesourcery.com> * gdb.mi/mi-syn-frame.exp, gdb.mi/mi2-syn-frame.exp: Don't expect diff --git a/gdb/testsuite/gdb.base/relocate.c b/gdb/testsuite/gdb.base/relocate.c index 90e70ff..7e85efb 100644 --- a/gdb/testsuite/gdb.base/relocate.c +++ b/gdb/testsuite/gdb.base/relocate.c @@ -1,10 +1,26 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + static int static_foo = 1; static int static_bar = 2; -/* This padding is just for the benefit of the test harness. It - causes the globals to have different addresses than the functions. */ -int dummy[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - int global_foo = 3; int global_bar = 4; diff --git a/gdb/testsuite/gdb.base/relocate.exp b/gdb/testsuite/gdb.base/relocate.exp index 916ce1c..13ea62a 100644 --- a/gdb/testsuite/gdb.base/relocate.exp +++ b/gdb/testsuite/gdb.base/relocate.exp @@ -1,4 +1,4 @@ -# Copyright 2002, 2003 Free Software Foundation, Inc. +# Copyright 2002, 2003, 2005 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -131,4 +131,16 @@ if { "${function_foo_addr}" == "${new_function_foo_addr}" } { pass "function foo has a different address" } -return 0 +# Now try loading the object as an exec-file; we should be able to print +# the values of variables after we do this. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Check the values of the variables. +gdb_test "print static_foo" "\\\$$decimal = 1" +gdb_test "print static_bar" "\\\$$decimal = 2" +gdb_test "print global_foo" "\\\$$decimal = 3" +gdb_test "print global_bar" "\\\$$decimal = 4" |