From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23354 invoked by alias); 14 Jun 2003 00:03:58 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 23206 invoked from network); 14 Jun 2003 00:03:57 -0000 Received: from unknown (HELO zenia.home) (12.223.225.216) by sources.redhat.com with SMTP; 14 Jun 2003 00:03:57 -0000 Received: by zenia.home (Postfix, from userid 5433) id 876AD20D85; Fri, 13 Jun 2003 19:04:16 -0500 (EST) To: Kevin Buettner Cc: gdb-patches@sources.redhat.com Subject: Re: [ppc64-linux]: correctly find a BFD's code entry point address References: <1030613054523.ZM346@localhost.localdomain> From: Jim Blandy Date: Sat, 14 Jun 2003 00:03:00 -0000 In-Reply-To: <1030613054523.ZM346@localhost.localdomain> Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2003-06/txt/msg00490.txt.bz2 Kevin Buettner writes: > On Jun 12, 6:12pm, Jim Blandy wrote: > > > + /* Return the unrelocated code address at which execution begins for > > + ABFD, under the 64-bit PowerPC Linux ABI. On that system, the ELF > > + header e_entry field (which is what bfd_get_start_address gives > > + you) is the address of the function descriptor for the startup > > + function, not the address of the actual machine instruction you > > + jump to. > > + > > + This function doesn't just go and read the entry point from the > > + function descriptor. We need it to work when ABFD is the dynamic > > + linker, immediately after an exec. But ld.so is a dynamic > > + executable itself on PPC64 Linux, so it appears in memory whereever > > + the kernel drops it; this means that bfd_get_start_address's result > > + needs to be adjusted --- by some offset we don't know. So we can't > > + find the descriptor's address in memory to read the entry point > > + from it. > > + > > + Instead, we do it all based on ABFD's symbol table. We take the > > + address from bfd_get_start_address, find each symbol at that > > + address, stick a '.' on the front of its name to get the entry > > + point symbol name, try to look that up, and return the value of > > + what we find, if anything. We never touch memory, or talk with the > > + kernel about the inferior at all. > > + > > + Now, this address we return is straight from the symbol table, so > > + it hasn't been adjusted to take into account where ABFD was loaded. > > + But that's okay --- our job is just to return the unrelocated code > > + address. */ > > This approach strikes me as somewhat more complicated (and fragile) > than need be. I think it would be preferable to simply fetch the > necessary bytes from the address given by bfd_get_start_address in the > executable (or object) file. > > Nice description though; I really appreciate comments like this. Thanks! I redid the patch as you suggest, and it's much smaller and simpler. How's this: 2003-06-12 Jim Blandy * ppc-linux-tdep.c (ppc64_linux_bfd_entry_point): New function. (ppc_linux_init_abi): Register it as our bfd_entry_point method. Index: gdb/ppc-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v retrieving revision 1.32 diff -c -r1.32 ppc-linux-tdep.c *** gdb/ppc-linux-tdep.c 13 Jun 2003 00:06:11 -0000 1.32 --- gdb/ppc-linux-tdep.c 13 Jun 2003 22:46:59 -0000 *************** *** 884,889 **** --- 884,935 ---- } + /* 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, *************** *** 1008,1013 **** --- 1054,1061 ---- 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); } }