diff options
author | Jim Blandy <jimb@codesourcery.com> | 2003-06-13 23:20:44 +0000 |
---|---|---|
committer | Jim Blandy <jimb@codesourcery.com> | 2003-06-13 23:20:44 +0000 |
commit | ee8c4d6b13e005fa52ebdba3e0e7c31415329417 (patch) | |
tree | 52ee7b79f3e08a9853dab62d6480c4e0c305d664 | |
parent | 182a9e9a1389b8e1a0f60f2f82eb559e18ebfcaa (diff) | |
download | gdb-ee8c4d6b13e005fa52ebdba3e0e7c31415329417.tar.gz |
* ppc-linux-tdep.c (ppc64_linux_bfd_entry_point): New function.
(ppc_linux_init_abi): Register it as our bfd_entry_point method.
-rw-r--r-- | gdb/ChangeLog | 3 | ||||
-rw-r--r-- | gdb/ppc-linux-tdep.c | 48 |
2 files changed, 51 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8b197bd692e..abcfb15c36a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,8 @@ 2003-06-13 Jim Blandy <jimb@redhat.com> + * ppc-linux-tdep.c (ppc64_linux_bfd_entry_point): New function. + (ppc_linux_init_abi): Register it as our bfd_entry_point method. + * gdbarch.sh (gdbarch_bfd_entry_point): New gdbarch method. * arch-utils.c (generic_bfd_entry_point): New function. * arch-utils.h (generic_bfd_entry_point): New declaration. diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 54d5d9ae9e8..ac35427bd31 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -941,6 +941,52 @@ ppc64_call_dummy_address (void) } +/* Return the unrelocated code address at which execution begins for + ABFD, under the 64-bit PowerPC Linux ABI. + + On that system, the ELF header's e_entry field (which is what + bfd_get_start_address gives you) is not the address of the actual + machine instruction you need to jump to, as it is on almost every + other target. Instead, it's the address of a function descriptor + for the start function. A function descriptor is a structure + containing three addresses: the entry point, the TOC pointer for + the function, and an environment pointer for the function. The + first field is what we want to return. + + So all we do is find the section containing the start address, read + the address-sized word there out of the BFD, and return that. */ +static CORE_ADDR +ppc64_linux_bfd_entry_point (struct gdbarch *gdbarch, bfd *abfd) +{ + CORE_ADDR start_address = bfd_get_start_address (abfd); + CORE_ADDR addr_size = (bfd_arch_bits_per_address (abfd) + / bfd_arch_bits_per_byte (abfd)); + unsigned char *entry_pt_buf = alloca (addr_size); + asection *sec; + + /* Find a data section containing an address word at the start + address. */ + for (sec = abfd->sections; sec; sec = sec->next) + if (bfd_get_section_vma (sec) <= start_address + && ((start_address + addr_size) + <= (bfd_get_section_vma (sec) + bfd_section_size (sec)))) + break; + if (! sec) + return 0; + + /* Seek to the start address, and read the address word there. */ + if (bfd_seek (abfd, + sec->filepos + (start_address - bfd_get_section_vma (sec)), + SEEK_SET) + || bfd_bread (entry_pt_buf, addr_size, abfd) != addr_size) + return 0; + + /* That's the actual code entry point. */ + return (CORE_ADDR) bfd_get (bfd_arch_bits_per_address (abfd), + abfd, entry_pt_buf); +} + + enum { ELF_NGREG = 48, ELF_NFPREG = 33, @@ -1072,6 +1118,8 @@ ppc_linux_init_abi (struct gdbarch_info info, set_gdbarch_in_solib_call_trampoline (gdbarch, ppc64_in_solib_call_trampoline); set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); + + set_gdbarch_bfd_entry_point (gdbarch, ppc64_linux_bfd_entry_point); } } |