From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30995 invoked by alias); 10 Jun 2004 06:12:39 -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 30982 invoked from network); 10 Jun 2004 06:12:33 -0000 Received: from unknown (HELO pippin.tausq.org) (64.81.244.94) by sourceware.org with SMTP; 10 Jun 2004 06:12:33 -0000 Received: by pippin.tausq.org (Postfix, from userid 1000) id A243CCD29F; Wed, 9 Jun 2004 23:12:34 -0700 (PDT) Date: Thu, 10 Jun 2004 06:12:00 -0000 From: Randolph Chung To: gdb-patches@sources.redhat.com Subject: [patch/rfc] Try to get dummy calls working on hpux again Message-ID: <20040610061234.GF561@tausq.org> Reply-To: Randolph Chung Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-GPG: for GPG key, see http://www.tausq.org/gpg.txt User-Agent: Mutt/1.5.5.1+cvs20040105i X-SW-Source: 2004-06/txt/msg00219.txt.bz2 A lot of the original code to handle dummy calls were ripped out of hppa-tdep.c in March. This patch brings back some of that logic so that we can start to make it work again on hpux. The PA has "space registers" (like segment registers on x86, sort of). We don't use this for hppa-linux, so simply using push_dummy_call was enough. HPUX uses it though.... Because the caller and callee may be in different spaces, we need to go through some hoops to set/reset the space registers across calls. The original code had many special cases to handle multiple targets, and multiple function types. This only brings back some of that logic, and it only works for 32-bit SOM at the moment. My plan is to try to fix this incrementally rather than get it "perfect" on the first try.... this fixes calling shared library functions from inside gdb, so it fixes quite a few test failures, but there are many more! :( comments? ok to check in? randolph 2004-06-09 Randolph Chung * hppa-hpux-tdep.c (hppa_hpux_som_find_global_pointer): New function. (hppa_hpux_push_dummy_code): New function. (hppa_hpux_init_abi): Set push_dummy_code and call_dummy_location. Set find_global_pointer method. Index: hppa-hpux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/hppa-hpux-tdep.c,v retrieving revision 1.20 diff -u -p -r1.20 hppa-hpux-tdep.c --- hppa-hpux-tdep.c 7 Jun 2004 02:17:29 -0000 1.20 +++ hppa-hpux-tdep.c 10 Jun 2004 05:30:40 -0000 @@ -1203,6 +1204,152 @@ hppa_hpux_sigtramp_unwind_sniffer (struc return NULL; } +static CORE_ADDR +hppa_hpux_som_find_global_pointer (struct value *function) +{ + CORE_ADDR faddr; + + faddr = value_as_address (function); + + /* Is this a plabel? If so, dereference it to get the gp value. */ + if (faddr & 2) + { + int status; + char buf[4]; + + faddr &= ~3; + + status = target_read_memory (faddr + 4, buf, sizeof (buf)); + if (status == 0) + return extract_unsigned_integer (buf, sizeof (buf)); + } + + return som_solib_get_got_by_pc (faddr); +} + +static CORE_ADDR +hppa_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, + CORE_ADDR funcaddr, int using_gcc, + struct value **args, int nargs, + struct type *value_type, + CORE_ADDR *real_pc, CORE_ADDR *bp_addr) +{ + /* FIXME: tausq/2004-06-09: This needs much more testing. It is broken + for pa64, but we should be able to get it to work with a little bit + of work. gdb-6.1 has a lot of code to handle various cases; I've tried to + simplify it and avoid compile-time conditionals. */ + + struct minimal_symbol *sym; + + /* Nonzero if we will use GCC's PLT call routine. This routine must be + passed an import stub, not a PLABEL. It is also necessary to get %r19 + before performing the call. (This is done by push_dummy_call.) */ + int use_gcc_plt_call = 1; + + /* See if __gcc_plt_call is available; if not we will use the HP version + instead. */ + sym = lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL); + if (sym == NULL) + use_gcc_plt_call = 0; + + /* If using __gcc_plt_call, we need to make sure we pass in an import + stub. funcaddr can be pointing to an export stub or a real function, + so we try to resolve it to the import stub. */ + if (use_gcc_plt_call) + { + struct objfile *objfile; + struct minimal_symbol *funsym, *stubsym; + CORE_ADDR stubaddr = 0; + + funsym = lookup_minimal_symbol_by_pc (funcaddr); + if (!funsym) + error ("Unable to find symbol for target function.\n"); + + ALL_OBJFILES (objfile) + { + stubsym = lookup_minimal_symbol_solib_trampoline + (SYMBOL_LINKAGE_NAME (funsym), objfile); + + if (stubsym) + { + struct unwind_table_entry *u; + + u = find_unwind_entry (SYMBOL_VALUE (stubsym)); + if (u == NULL + || (u->stub_unwind.stub_type != IMPORT + && u->stub_unwind.stub_type != IMPORT_SHLIB)) + continue; + + stubaddr = SYMBOL_VALUE (stubsym); + + /* If we found an IMPORT stub, then we can stop searching; + if we found an IMPORT_SHLIB, we want to continue the search + in the hopes that we will find an IMPORT stub. */ + if (u->stub_unwind.stub_type == IMPORT) + break; + } + } + + if (stubaddr != 0) + { + /* Argument to __gcc_plt_call is passed in r22. */ + regcache_cooked_write_unsigned (current_regcache, 22, stubaddr); + } + else + { + /* No import stub found; let's synthesize one. */ + + /* ldsid %r21, %r1 */ + write_memory_unsigned_integer (sp, 4, 0x02a010a1); + /* mtsp %r1,%sr0 */ + write_memory_unsigned_integer (sp + 4, 4, 0x00011820); + /* be 0(%sr0, %r21) */ + write_memory_unsigned_integer (sp + 8, 4, 0xe2a00000); + /* nop */ + write_memory_unsigned_integer (sp + 12, 4, 0x08000240); + + regcache_cooked_write_unsigned (current_regcache, 21, funcaddr); + regcache_cooked_write_unsigned (current_regcache, 22, sp); + } + + /* We set the breakpoint address and r31 to (close to) where the current + pc is; when __gcc_plt_call returns, it will restore pcsqh to the + current value based on this. The -4 is needed for frame unwinding + to work properly -- we need to land in a different function than + the current function. */ + *bp_addr = (read_register (HPPA_PCOQ_HEAD_REGNUM) & ~3) - 4; + regcache_cooked_write_unsigned (current_regcache, 31, *bp_addr); + + /* Continue from __gcc_plt_call. */ + *real_pc = SYMBOL_VALUE (sym); + } + else + { + unsigned int gp; + + /* Use __d_plt_call as a fallback; __d_plt_call expects to be called + with a plabel, so we need to build one. */ + + sym = lookup_minimal_symbol ("__d_plt_call", NULL, NULL); + if (sym == NULL) + error("Can't find an address for __d_plt_call or __gcc_plt_call " + "trampoline\nSuggest linking executable with -g or compiling " + "with gcc."); + + gp = gdbarch_tdep (gdbarch)->find_global_pointer (funcaddr); + write_memory_unsigned_integer (sp, 4, funcaddr); + write_memory_unsigned_integer (sp + 4, 4, gp); + + /* plabel is passed in r22 */ + regcache_cooked_write_unsigned (current_regcache, 22, sp); + } + + /* Pushed one stack frame, which has to be 64-byte aligned. */ + sp += 64; + + return sp; +} + static void hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -1219,7 +1375,10 @@ hppa_hpux_init_abi (struct gdbarch_info hppa_hpux_in_solib_return_trampoline); set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code); + set_gdbarch_push_dummy_code (gdbarch, hppa_hpux_push_dummy_code); + set_gdbarch_call_dummy_location (gdbarch, ON_STACK); + frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer); } static void @@ -1228,6 +1389,8 @@ hppa_hpux_som_init_abi (struct gdbarch_i struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); tdep->is_elf = 0; + + tdep->find_global_pointer = hppa_hpux_som_find_global_pointer; hppa_hpux_init_abi (info, gdbarch); } -- Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/