2006-07-19 Paul Gilliam * ppc-linux-tdep.c (ppc64_linux_convert_from_func_ptr_addr): Change name and update to work for both ppc-64 and ppc-32. (ppc_linux_init_abi): Arange for "gdbarch_convert_from_func_ptr_addr" to be set for both ppc-64 and ppc-32. * solib-svr4.c (solib_break_names): Remove "._dl_debug_state" and the comment explaining it. (bfd_lookup_symbol): Change the meaning of the parameter "sect_flags" so that any bit can be on instead of all bits. (enable_break): Change the call to bfd_lookup_symbol() to search both code and data sections and change the comment to explain why, getting rid of any mention of 'dot' symbols. Index: ppc-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v retrieving revision 1.78 diff -a -u -r1.78 ppc-linux-tdep.c --- ppc-linux-tdep.c 18 Apr 2006 19:20:06 -0000 1.78 +++ ppc-linux-tdep.c 19 Jul 2006 21:10:41 -0000 @@ -725,17 +725,25 @@ } -/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG) on PPC64 +/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG) on PPC GNU/Linux. Usually a function pointer's representation is simply the address - of the function. On GNU/Linux on the 64-bit PowerPC however, a - function pointer is represented by a pointer to a TOC entry. This - TOC entry contains three words, the first word is the address of - the function, the second word is the TOC pointer (r2), and the - third word is the static chain value. Throughout GDB it is - currently assumed that a function pointer contains the address of - the function, which is not easy to fix. In addition, the + of the function. On GNU/Linux on the PowerPC however, a function + pointer is, in fact, a pointer to a function descriptor. + + For PPC64, a function descriptor is a TOC entry, in a data section, + which contains three words: the first word is the address of the + function, the second word is the TOC pointer (r2), and the third word + is the static chain value. + + For PPC32, there are two kinds of function descriptors: non-secure + and secure. Non-secure function descriptors are in a code section, + are executable and thus need no translation. Secure ones are in a + data section and contain one word: the address of the function. + + Throughout GDB it is currently assumed that a function pointer contains + the address of the function, which is not easy to fix. In addition, the conversion of a function address to a function pointer would require allocation of a TOC entry in the inferior's memory space, with all its drawbacks. To be able to call C++ virtual methods in @@ -744,20 +752,44 @@ from a function pointer. */ /* If ADDR points at what is clearly a function descriptor, transform - it into the address of the corresponding function. Be + it into the address of the corresponding function, if needed. Be conservative, otherwize GDB will do the transformation on any random addresses such as occures when there is no symbol table. */ static CORE_ADDR -ppc64_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch, - CORE_ADDR addr, - struct target_ops *targ) +ppc_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch, + CORE_ADDR addr, + struct target_ops *targ) { + struct gdbarch_tdep *tdep; struct section_table *s = target_section_by_addr (targ, addr); + char *sect_name = 0; + + if (!s) + return addr; + + tdep = gdbarch_tdep (gdbarch); + + switch (tdep->wordsize) + { + case 4: + sect_name = ".plt"; + break; + case 8: + sect_name = ".opd"; + break; + default: + internal_error (__FILE__, __LINE__, + _("failed internal consitency check")); + } /* Check if ADDR points to a function descriptor. */ - if (s && strcmp (s->the_bfd_section->name, ".opd") == 0) - return get_target_memory_unsigned (targ, addr, 8); + + /* NOTE: this depends on the coincidence that the address of a functions + entry point is contained in the first word of its function descriptor + for both PPC-64 and for PPC-32 with secure PLTs. */ + if ((strcmp (s->the_bfd_section->name, sect_name) == 0) + && s->the_bfd_section->flags & SEC_DATA) + return get_target_memory_unsigned (targ, addr, tdep->wordsize); return addr; } @@ -1034,6 +1066,11 @@ /* NOTE: cagney/2005-01-25: True for both 32- and 64-bit. */ set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT); + /* Handle PPC GNU/Linux function pointers (which are really function + descriptors). */ + set_gdbarch_convert_from_func_ptr_addr + (gdbarch, ppc_linux_convert_from_func_ptr_addr); + if (tdep->wordsize == 4) { /* Until November 2001, gcc did not comply with the 32 bit SysV @@ -1055,27 +1092,27 @@ (gdbarch, svr4_ilp32_fetch_link_map_offsets); /* Trampolines. */ - tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sigaction_tramp_frame); - tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sighandler_tramp_frame); + tramp_frame_prepend_unwinder (gdbarch, + &ppc32_linux_sigaction_tramp_frame); + tramp_frame_prepend_unwinder (gdbarch, + &ppc32_linux_sighandler_tramp_frame); } if (tdep->wordsize == 8) { - /* Handle PPC64 GNU/Linux function pointers (which are really - function descriptors). */ - set_gdbarch_convert_from_func_ptr_addr - (gdbarch, ppc64_linux_convert_from_func_ptr_addr); - set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); - /* Shared library handling. */ + set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_lp64_fetch_link_map_offsets); /* Trampolines. */ - tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sigaction_tramp_frame); - tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sighandler_tramp_frame); + tramp_frame_prepend_unwinder (gdbarch, + &ppc64_linux_sigaction_tramp_frame); + tramp_frame_prepend_unwinder (gdbarch, + &ppc64_linux_sighandler_tramp_frame); } - set_gdbarch_regset_from_core_section (gdbarch, ppc_linux_regset_from_core_section); + set_gdbarch_regset_from_core_section (gdbarch, + ppc_linux_regset_from_core_section); /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, Index: solib-svr4.c =================================================================== RCS file: /cvs/src/src/gdb/solib-svr4.c,v retrieving revision 1.58 diff -a -u -r1.58 solib-svr4.c --- solib-svr4.c 18 May 2006 20:38:56 -0000 1.58 +++ solib-svr4.c 19 Jul 2006 21:10:41 -0000 @@ -85,16 +85,6 @@ "rtld_db_dlactivity", "_rtld_debug_state", - /* On the 64-bit PowerPC, the linker symbol with the same name as - the C function points to a function descriptor, not to the entry - point. The linker symbol whose name is the C function name - prefixed with a '.' points to the function's entry point. So - when we look through this table, we ignore symbols that point - into the data section (thus skipping the descriptor's symbol), - and eventually try this one, giving us the real entry point - address. */ - "._dl_debug_state", - NULL }; @@ -287,7 +277,7 @@ interface structures in the shared library. If SECT_FLAGS is non-zero, only match symbols in sections whose - flags include all those in SECT_FLAGS. + flags include any of those in SECT_FLAGS. Note that 0 is specifically allowed as an error return (no such symbol). @@ -316,7 +306,7 @@ { sym = *symbol_table++; if (strcmp (sym->name, symname) == 0 - && (sym->section->flags & sect_flags) == sect_flags) + && (sym->section->flags & sect_flags)) { /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; @@ -345,7 +335,7 @@ sym = *symbol_table++; if (strcmp (sym->name, symname) == 0 - && (sym->section->flags & sect_flags) == sect_flags) + && (sym->section->flags & sect_flags)) { /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; @@ -1043,16 +1033,19 @@ /* Now try to set a breakpoint in the dynamic linker. */ for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++) { - /* On ABI's that use function descriptors, there are usually - two linker symbols associated with each C function: one - pointing at the actual entry point of the machine code, - and one pointing at the function's descriptor. The - latter symbol has the same name as the C function. - - What we're looking for here is the machine code entry - point, so we are only interested in symbols in code - sections. */ - sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep, SEC_CODE); + /* On ABI's that use function descriptors, the linker symbol + with the same name as a C function points to a function + descriptor that can be in either a code or data section. + In either case, pointers to a function desciptors are + converted to "breakpointable" addresses in set_raw_breakpoint() + using gdbarch_adjust_breakpoint_address(), if needed. + + On ABI's that don't use function descriptors, there is no + need for set_raw_breakpoint() to adjust the address. Also, + we assume that none of the symbols in the solib_break_names + table are in a data section. */ + sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep, + SEC_CODE | SEC_DATA); if (sym_addr != 0) break; }