diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2010-01-14 20:48:26 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2010-01-14 20:48:26 +0000 |
commit | b8040f198caee93044ccfc5aacaa0c3244057b0a (patch) | |
tree | 377164e5942eca841914b8e2169f7962d72e3275 /gdb/solib-svr4.c | |
parent | a2a7d12cfc7afce610d6f2c45e7f8883668c9c56 (diff) | |
download | gdb-b8040f198caee93044ccfc5aacaa0c3244057b0a.zip gdb-b8040f198caee93044ccfc5aacaa0c3244057b0a.tar.gz gdb-b8040f198caee93044ccfc5aacaa0c3244057b0a.tar.bz2 |
gdb/
* solib-svr4.c (svr4_relocate_main_executable): Move the static exec
code part to ...
(svr4_static_exec_displacement): ... a new function.
(svr4_exec_displacement): New function.
(svr4_relocate_main_executable): Call svr4_exec_displacement. Allocate
new_offsets using alloca now. Remove variable old_chain and changed.
Call objfile_relocate unconditionally now.
gdb/testsuite/
* gdb.base/break-interp.exp: New file.
Diffstat (limited to 'gdb/solib-svr4.c')
-rw-r--r-- | gdb/solib-svr4.c | 184 |
1 files changed, 96 insertions, 88 deletions
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 00e16b0..3ad067a 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -1535,111 +1535,119 @@ svr4_special_symbol_handling (void) { } -/* Relocate the main executable. This function should be called upon - stopping the inferior process at the entry point to the program. - The entry point from BFD is compared to the PC and if they are - different, the main executable is relocated by the proper amount. +/* Decide if the objfile needs to be relocated. As indicated above, + we will only be here when execution is stopped at the beginning + of the program. Relocation is necessary if the address at which + we are presently stopped differs from the start address stored in + the executable AND there's no interpreter section. The condition + regarding the interpreter section is very important because if + there *is* an interpreter section, execution will begin there + instead. When there is an interpreter section, the start address + is (presumably) used by the interpreter at some point to start + execution of the program. + + If there is an interpreter, it is normal for it to be set to an + arbitrary address at the outset. The job of finding it is + handled in enable_break(). + + So, to summarize, relocations are necessary when there is no + interpreter section and the start address obtained from the + executable is different from the address at which GDB is + currently stopped. - As written it will only attempt to relocate executables which - lack interpreter sections. It seems likely that only dynamic - linker executables will get relocated, though it should work - properly for a position-independent static executable as well. */ + [ The astute reader will note that we also test to make sure that + the executable in question has the DYNAMIC flag set. It is my + opinion that this test is unnecessary (undesirable even). It + was added to avoid inadvertent relocation of an executable + whose e_type member in the ELF header is not ET_DYN. There may + be a time in the future when it is desirable to do relocations + on other types of files as well in which case this condition + should either be removed or modified to accomodate the new file + type. (E.g, an ET_EXEC executable which has been built to be + position-independent could safely be relocated by the OS if + desired. It is true that this violates the ABI, but the ABI + has been known to be bent from time to time.) - Kevin, Nov 2000. ] + */ -static void -svr4_relocate_main_executable (void) +static CORE_ADDR +svr4_static_exec_displacement (void) { asection *interp_sect; struct regcache *regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); CORE_ADDR pc = regcache_read_pc (regcache); - /* Decide if the objfile needs to be relocated. As indicated above, - we will only be here when execution is stopped at the beginning - of the program. Relocation is necessary if the address at which - we are presently stopped differs from the start address stored in - the executable AND there's no interpreter section. The condition - regarding the interpreter section is very important because if - there *is* an interpreter section, execution will begin there - instead. When there is an interpreter section, the start address - is (presumably) used by the interpreter at some point to start - execution of the program. - - If there is an interpreter, it is normal for it to be set to an - arbitrary address at the outset. The job of finding it is - handled in enable_break(). - - So, to summarize, relocations are necessary when there is no - interpreter section and the start address obtained from the - executable is different from the address at which GDB is - currently stopped. - - [ The astute reader will note that we also test to make sure that - the executable in question has the DYNAMIC flag set. It is my - opinion that this test is unnecessary (undesirable even). It - was added to avoid inadvertent relocation of an executable - whose e_type member in the ELF header is not ET_DYN. There may - be a time in the future when it is desirable to do relocations - on other types of files as well in which case this condition - should either be removed or modified to accomodate the new file - type. (E.g, an ET_EXEC executable which has been built to be - position-independent could safely be relocated by the OS if - desired. It is true that this violates the ABI, but the ABI - has been known to be bent from time to time.) - Kevin, Nov 2000. ] - */ - interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); if (interp_sect == NULL && (bfd_get_file_flags (exec_bfd) & DYNAMIC) != 0 && (exec_entry_point (exec_bfd, &exec_ops) != pc)) + return pc - exec_entry_point (exec_bfd, &exec_ops); + + return 0; +} + +/* We relocate all of the sections by the same amount. This + behavior is mandated by recent editions of the System V ABI. + According to the System V Application Binary Interface, + Edition 4.1, page 5-5: + + ... Though the system chooses virtual addresses for + individual processes, it maintains the segments' relative + positions. Because position-independent code uses relative + addressesing between segments, the difference between + virtual addresses in memory must match the difference + between virtual addresses in the file. The difference + between the virtual address of any segment in memory and + the corresponding virtual address in the file is thus a + single constant value for any one executable or shared + object in a given process. This difference is the base + address. One use of the base address is to relocate the + memory image of the program during dynamic linking. + + The same language also appears in Edition 4.0 of the System V + ABI and is left unspecified in some of the earlier editions. */ + +static CORE_ADDR +svr4_exec_displacement (void) +{ + int found; + CORE_ADDR entry_point; + + if (exec_bfd == NULL) + return 0; + + if (target_auxv_search (¤t_target, AT_ENTRY, &entry_point) == 1) + return entry_point - exec_entry_point (exec_bfd, ¤t_target); + + return svr4_static_exec_displacement (); +} + +/* Relocate the main executable. This function should be called upon + stopping the inferior process at the entry point to the program. + The entry point from BFD is compared to the AT_ENTRY of AUXV and if they are + different, the main executable is relocated by the proper amount. */ + +static void +svr4_relocate_main_executable (void) +{ + CORE_ADDR displacement = svr4_exec_displacement (); + + /* Even if DISPLACEMENT is 0 still try to relocate it as this is a new + difference of in-memory vs. in-file addresses and we could already + relocate the executable at this function to improper address before. */ + + if (symfile_objfile) { - struct cleanup *old_chain; struct section_offsets *new_offsets; - int i, changed; - CORE_ADDR displacement; - - /* It is necessary to relocate the objfile. The amount to - relocate by is simply the address at which we are stopped - minus the starting address from the executable. - - We relocate all of the sections by the same amount. This - behavior is mandated by recent editions of the System V ABI. - According to the System V Application Binary Interface, - Edition 4.1, page 5-5: - - ... Though the system chooses virtual addresses for - individual processes, it maintains the segments' relative - positions. Because position-independent code uses relative - addressesing between segments, the difference between - virtual addresses in memory must match the difference - between virtual addresses in the file. The difference - between the virtual address of any segment in memory and - the corresponding virtual address in the file is thus a - single constant value for any one executable or shared - object in a given process. This difference is the base - address. One use of the base address is to relocate the - memory image of the program during dynamic linking. - - The same language also appears in Edition 4.0 of the System V - ABI and is left unspecified in some of the earlier editions. */ - - displacement = pc - exec_entry_point (exec_bfd, &exec_ops); - changed = 0; - - new_offsets = xcalloc (symfile_objfile->num_sections, - sizeof (struct section_offsets)); - old_chain = make_cleanup (xfree, new_offsets); + int i; - for (i = 0; i < symfile_objfile->num_sections; i++) - { - if (displacement != ANOFFSET (symfile_objfile->section_offsets, i)) - changed = 1; - new_offsets->offsets[i] = displacement; - } + new_offsets = alloca (symfile_objfile->num_sections + * sizeof (*new_offsets)); - if (changed) - objfile_relocate (symfile_objfile, new_offsets); + for (i = 0; i < symfile_objfile->num_sections; i++) + new_offsets->offsets[i] = displacement; - do_cleanups (old_chain); + objfile_relocate (symfile_objfile, new_offsets); } } |