forked from Imagelibrary/binutils-gdb
gdb/
* solib-svr4.c (read_program_header): Support type == -1 to read all program headers. (read_program_headers_from_bfd): New function. (svr4_static_exec_displacement): Remove and move the comment ... (svr4_exec_displacement): ... here. Remove variable found. New variable displacement. Check also DYNAMIC. Verify DISPLACEMENT alignment for ELF targets. Compare target vs. exec_bfd PHDRs for ELF targets using read_program_headers_from_bfd. Remove the call of svr4_static_exec_displacement.
This commit is contained in:
@@ -1,3 +1,16 @@
|
|||||||
|
2010-03-14 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
* solib-svr4.c (read_program_header): Support type == -1 to read
|
||||||
|
all program headers.
|
||||||
|
(read_program_headers_from_bfd): New function.
|
||||||
|
(svr4_static_exec_displacement): Remove and move the comment ...
|
||||||
|
(svr4_exec_displacement): ... here. Remove variable found. New
|
||||||
|
variable displacement. Check also DYNAMIC. Verify DISPLACEMENT
|
||||||
|
alignment for ELF targets. Compare target vs. exec_bfd PHDRs for ELF
|
||||||
|
targets using read_program_headers_from_bfd. Remove the call of
|
||||||
|
svr4_static_exec_displacement.
|
||||||
|
|
||||||
2010-03-12 Pedro Alves <pedro@codesourcery.com>
|
2010-03-12 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
* target.c (memory_xfer_partial): Don't use the stack cache if
|
* target.c (memory_xfer_partial): Don't use the stack cache if
|
||||||
|
|||||||
159
gdb/solib-svr4.c
159
gdb/solib-svr4.c
@@ -451,6 +451,9 @@ bfd_lookup_symbol (bfd *abfd, char *symname)
|
|||||||
/* Read program header TYPE from inferior memory. The header is found
|
/* Read program header TYPE from inferior memory. The header is found
|
||||||
by scanning the OS auxillary vector.
|
by scanning the OS auxillary vector.
|
||||||
|
|
||||||
|
If TYPE == -1, return the program headers instead of the contents of
|
||||||
|
one program header.
|
||||||
|
|
||||||
Return a pointer to allocated memory holding the program header contents,
|
Return a pointer to allocated memory holding the program header contents,
|
||||||
or NULL on failure. If sucessful, and unless P_SECT_SIZE is NULL, the
|
or NULL on failure. If sucessful, and unless P_SECT_SIZE is NULL, the
|
||||||
size of those contents is returned to P_SECT_SIZE. Likewise, the target
|
size of those contents is returned to P_SECT_SIZE. Likewise, the target
|
||||||
@@ -483,8 +486,13 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size)
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Find .dynamic section via the PT_DYNAMIC PHDR. */
|
/* Find the requested segment. */
|
||||||
if (arch_size == 32)
|
if (type == -1)
|
||||||
|
{
|
||||||
|
sect_addr = at_phdr;
|
||||||
|
sect_size = at_phent * at_phnum;
|
||||||
|
}
|
||||||
|
else if (arch_size == 32)
|
||||||
{
|
{
|
||||||
Elf32_External_Phdr phdr;
|
Elf32_External_Phdr phdr;
|
||||||
int i;
|
int i;
|
||||||
@@ -1622,55 +1630,30 @@ svr4_special_symbol_handling (void)
|
|||||||
svr4_relocate_main_executable ();
|
svr4_relocate_main_executable ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decide if the objfile needs to be relocated. As indicated above,
|
/* Read the ELF program headers from ABFD. Return the contents and
|
||||||
we will only be here when execution is stopped at the beginning
|
set *PHDRS_SIZE to the size of the program headers. */
|
||||||
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
|
static gdb_byte *
|
||||||
arbitrary address at the outset. The job of finding it is
|
read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
|
||||||
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. ]
|
|
||||||
*/
|
|
||||||
|
|
||||||
static CORE_ADDR
|
|
||||||
svr4_static_exec_displacement (void)
|
|
||||||
{
|
{
|
||||||
asection *interp_sect;
|
Elf_Internal_Ehdr *ehdr;
|
||||||
struct regcache *regcache
|
gdb_byte *buf;
|
||||||
= get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
|
||||||
CORE_ADDR pc = regcache_read_pc (regcache);
|
|
||||||
|
|
||||||
interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
|
ehdr = elf_elfheader (abfd);
|
||||||
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;
|
*phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
|
||||||
|
if (*phdrs_size == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buf = xmalloc (*phdrs_size);
|
||||||
|
if (bfd_seek (abfd, ehdr->e_phoff, SEEK_SET) != 0
|
||||||
|
|| bfd_bread (buf, *phdrs_size, abfd) != *phdrs_size)
|
||||||
|
{
|
||||||
|
xfree (buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We relocate all of the sections by the same amount. This
|
/* We relocate all of the sections by the same amount. This
|
||||||
@@ -1692,23 +1675,93 @@ svr4_static_exec_displacement (void)
|
|||||||
memory image of the program during dynamic linking.
|
memory image of the program during dynamic linking.
|
||||||
|
|
||||||
The same language also appears in Edition 4.0 of the System V
|
The same language also appears in Edition 4.0 of the System V
|
||||||
ABI and is left unspecified in some of the earlier editions. */
|
ABI and is left unspecified in some of the earlier editions.
|
||||||
|
|
||||||
|
Decide if the objfile needs to be relocated. As indicated above, we will
|
||||||
|
only be here when execution is stopped. But during attachment PC can be at
|
||||||
|
arbitrary address therefore regcache_read_pc can be misleading (contrary to
|
||||||
|
the auxv AT_ENTRY value). Moreover for executable with interpreter section
|
||||||
|
regcache_read_pc would point to the interpreter and not the main executable.
|
||||||
|
|
||||||
|
So, to summarize, relocations are necessary when the start address obtained
|
||||||
|
from the executable is different from the address in auxv AT_ENTRY entry.
|
||||||
|
|
||||||
|
[ 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. - Kevin, Nov 2000. ] */
|
||||||
|
|
||||||
static CORE_ADDR
|
static CORE_ADDR
|
||||||
svr4_exec_displacement (void)
|
svr4_exec_displacement (void)
|
||||||
{
|
{
|
||||||
int found;
|
|
||||||
/* ENTRY_POINT is a possible function descriptor - before
|
/* ENTRY_POINT is a possible function descriptor - before
|
||||||
a call to gdbarch_convert_from_func_ptr_addr. */
|
a call to gdbarch_convert_from_func_ptr_addr. */
|
||||||
CORE_ADDR entry_point;
|
CORE_ADDR entry_point, displacement;
|
||||||
|
|
||||||
if (exec_bfd == NULL)
|
if (exec_bfd == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (target_auxv_search (¤t_target, AT_ENTRY, &entry_point) == 1)
|
/* Therefore for ELF it is ET_EXEC and not ET_DYN. Both shared libraries
|
||||||
return entry_point - bfd_get_start_address (exec_bfd);
|
being executed themselves and PIE (Position Independent Executable)
|
||||||
|
executables are ET_DYN. */
|
||||||
|
|
||||||
return svr4_static_exec_displacement ();
|
if ((bfd_get_file_flags (exec_bfd) & DYNAMIC) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (target_auxv_search (¤t_target, AT_ENTRY, &entry_point) <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
displacement = entry_point - bfd_get_start_address (exec_bfd);
|
||||||
|
|
||||||
|
/* Verify the DISPLACEMENT candidate complies with the required page
|
||||||
|
alignment. It is cheaper than the program headers comparison below. */
|
||||||
|
|
||||||
|
if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
|
||||||
|
{
|
||||||
|
const struct elf_backend_data *elf = get_elf_backend_data (exec_bfd);
|
||||||
|
|
||||||
|
/* p_align of PT_LOAD segments does not specify any alignment but
|
||||||
|
only congruency of addresses:
|
||||||
|
p_offset % p_align == p_vaddr % p_align
|
||||||
|
Kernel is free to load the executable with lower alignment. */
|
||||||
|
|
||||||
|
if ((displacement & (elf->minpagesize - 1)) != 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify that the auxilliary vector describes the same file as exec_bfd, by
|
||||||
|
comparing their program headers. If the program headers in the auxilliary
|
||||||
|
vector do not match the program headers in the executable, then we are
|
||||||
|
looking at a different file than the one used by the kernel - for
|
||||||
|
instance, "gdb program" connected to "gdbserver :PORT ld.so program". */
|
||||||
|
|
||||||
|
if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
|
||||||
|
{
|
||||||
|
/* Be optimistic and clear OK only if GDB was able to verify the headers
|
||||||
|
really do not match. */
|
||||||
|
int phdrs_size, phdrs2_size, ok = 1;
|
||||||
|
gdb_byte *buf, *buf2;
|
||||||
|
|
||||||
|
buf = read_program_header (-1, &phdrs_size, NULL);
|
||||||
|
buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size);
|
||||||
|
if (buf != NULL && buf2 != NULL
|
||||||
|
&& (phdrs_size != phdrs2_size
|
||||||
|
|| memcmp (buf, buf2, phdrs_size) != 0))
|
||||||
|
ok = 0;
|
||||||
|
|
||||||
|
xfree (buf);
|
||||||
|
xfree (buf2);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return displacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Relocate the main executable. This function should be called upon
|
/* Relocate the main executable. This function should be called upon
|
||||||
|
|||||||
Reference in New Issue
Block a user