2005-02-09 Andrew Cagney <cagney@gnu.org>

* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call)
	(convert_code_addr_to_desc_addr): Convert any function code
	address to the corresponding function's descriptor.
	(ppc64_sysv_abi_return_value): have TYPE_CODE_ENUM and
	TYPE_CODE_INT use the same code paths as TYPE_CODE_INT.  When
	writing, convert any function code address to the corresponding
	descriptor.
This commit is contained in:
Andrew Cagney
2005-02-09 16:51:43 +00:00
parent dbdfa66c30
commit b6e1c0277f
2 changed files with 85 additions and 44 deletions

View File

@ -1,10 +1,13 @@
2005-02-09 Corinna Vinschen <vinschen@redhat.com>
* symmisc.c: Include gdb_stat.h.
(maintenance_print_msymbols): Use inode numbers to compare files.
2005-02-09 Andrew Cagney <cagney@gnu.org> 2005-02-09 Andrew Cagney <cagney@gnu.org>
* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call)
(convert_code_addr_to_desc_addr): Convert any function code
address to the corresponding function's descriptor.
(ppc64_sysv_abi_return_value): have TYPE_CODE_ENUM and
TYPE_CODE_INT use the same code paths as TYPE_CODE_INT. When
writing, convert any function code address to the corresponding
descriptor.
* config/sh/linux.mt (TDEPFILES): Add symfile-mem.o. * config/sh/linux.mt (TDEPFILES): Add symfile-mem.o.
* config/powerpc/linux.mt (TDEPFILES): Ditto. * config/powerpc/linux.mt (TDEPFILES): Ditto.
* config/pa/linux.mt (TDEPFILES): Ditto. * config/pa/linux.mt (TDEPFILES): Ditto.
@ -14,6 +17,11 @@
* config/ia64/linux.mt (TDEPFILES): Ditto. * config/ia64/linux.mt (TDEPFILES): Ditto.
* config/arm/linux.mt (TDEPFILES): Ditto. * config/arm/linux.mt (TDEPFILES): Ditto.
2005-02-09 Corinna Vinschen <vinschen@redhat.com>
* symmisc.c: Include gdb_stat.h.
(maintenance_print_msymbols): Use inode numbers to compare files.
2005-02-08 Andrew Cagney <cagney@gnu.org> 2005-02-08 Andrew Cagney <cagney@gnu.org>
* value.h (METHOD_PTR_IS_VIRTUAL, METHOD_PTR_FROM_VOFFSET) * value.h (METHOD_PTR_IS_VIRTUAL, METHOD_PTR_FROM_VOFFSET)

View File

@ -534,6 +534,47 @@ ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch,
writebuf, 1); writebuf, 1);
} }
/* The helper function for 64-bit SYSV push_dummy_call. Converts the
function's code address back into the function's descriptor
address.
Find a value for the TOC register. Every symbol should have both
".FN" and "FN" in the minimal symbol table. "FN" points at the
FN's descriptor, while ".FN" points at the entry point (which
matches FUNC_ADDR). Need to reverse from FUNC_ADDR back to the
FN's descriptor address (while at the same time being careful to
find "FN" in the same object file as ".FN"). */
static int
convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
{
struct obj_section *dot_fn_section;
struct minimal_symbol *dot_fn;
struct minimal_symbol *fn;
CORE_ADDR toc;
/* Find the minimal symbol that corresponds to CODE_ADDR (should
have a name of the form ".FN"). */
dot_fn = lookup_minimal_symbol_by_pc (code_addr);
if (dot_fn == NULL || SYMBOL_LINKAGE_NAME (dot_fn)[0] != '.')
return 0;
/* Get the section that contains CODE_ADDR. Need this for the
"objfile" that it contains. */
dot_fn_section = find_pc_section (code_addr);
if (dot_fn_section == NULL || dot_fn_section->objfile == NULL)
return 0;
/* Now find the corresponding "FN" (dropping ".") minimal symbol's
address. Only look for the minimal symbol in ".FN"'s object file
- avoids problems when two object files (i.e., shared libraries)
contain a minimal symbol with the same name. */
fn = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn) + 1, NULL,
dot_fn_section->objfile);
if (fn == NULL)
return 0;
/* Found a descriptor. */
(*desc_addr) = SYMBOL_VALUE_ADDRESS (fn);
return 1;
}
/* Pass the arguments in either registers, or in the stack. Using the /* Pass the arguments in either registers, or in the stack. Using the
ppc 64 bit SysV ABI. ppc 64 bit SysV ABI.
@ -704,15 +745,25 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
} }
} }
else if ((TYPE_CODE (type) == TYPE_CODE_INT else if ((TYPE_CODE (type) == TYPE_CODE_INT
|| TYPE_CODE (type) == TYPE_CODE_ENUM) || TYPE_CODE (type) == TYPE_CODE_ENUM
|| TYPE_CODE (type) == TYPE_CODE_PTR)
&& TYPE_LENGTH (type) <= 8) && TYPE_LENGTH (type) <= 8)
{ {
/* Scalars get sign[un]extended and go in gpr3 .. gpr10. /* Scalars and Pointers get sign[un]extended and go in
They can also end up in memory. */ gpr3 .. gpr10. They can also end up in memory. */
if (write_pass) if (write_pass)
{ {
/* Sign extend the value, then store it unsigned. */ /* Sign extend the value, then store it unsigned. */
ULONGEST word = unpack_long (type, val); ULONGEST word = unpack_long (type, val);
/* Convert any function code addresses into
descriptors. */
if (TYPE_CODE (type) == TYPE_CODE_PTR
&& TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC)
{
CORE_ADDR desc = word;
convert_code_addr_to_desc_addr (word, &desc);
word = desc;
}
if (greg <= 10) if (greg <= 10)
regcache_cooked_write_unsigned (regcache, regcache_cooked_write_unsigned (regcache,
tdep->ppc_gp0_regnum + tdep->ppc_gp0_regnum +
@ -765,6 +816,11 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
value to memory. Fortunately, doing this value to memory. Fortunately, doing this
simplifies the code. */ simplifies the code. */
write_memory (gparam, val, TYPE_LENGTH (type)); write_memory (gparam, val, TYPE_LENGTH (type));
if (write_pass)
/* WARNING: cagney/2004-06-20: It appears that GCC
likes to put structures containing a single
floating-point member in an FP register instead of
general general purpose. */
/* Always consume parameter stack space. */ /* Always consume parameter stack space. */
gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize); gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
} }
@ -793,43 +849,18 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
breakpoint. */ breakpoint. */
regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr); regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
/* Find a value for the TOC register. Every symbol should have both /* Use the func_addr to find the descriptor, and use that to find
".FN" and "FN" in the minimal symbol table. "FN" points at the the TOC. */
FN's descriptor, while ".FN" points at the entry point (which
matches FUNC_ADDR). Need to reverse from FUNC_ADDR back to the
FN's descriptor address (while at the same time being careful to
find "FN" in the same object file as ".FN"). */
{ {
/* Find the minimal symbol that corresponds to FUNC_ADDR (should CORE_ADDR desc_addr;
have the name ".FN"). */ if (convert_code_addr_to_desc_addr (func_addr, &desc_addr))
struct minimal_symbol *dot_fn = lookup_minimal_symbol_by_pc (func_addr);
if (dot_fn != NULL && SYMBOL_LINKAGE_NAME (dot_fn)[0] == '.')
{ {
/* Get the section that contains FUNC_ADR. Need this for the /* The TOC is the second double word in the descriptor. */
"objfile" that it contains. */ CORE_ADDR toc =
struct obj_section *dot_fn_section = find_pc_section (func_addr); read_memory_unsigned_integer (desc_addr + tdep->wordsize,
if (dot_fn_section != NULL && dot_fn_section->objfile != NULL) tdep->wordsize);
{ regcache_cooked_write_unsigned (regcache,
/* Now find the corresponding "FN" (dropping ".") minimal tdep->ppc_gp0_regnum + 2, toc);
symbol's address. Only look for the minimal symbol in
".FN"'s object file - avoids problems when two object
files (i.e., shared libraries) contain a minimal symbol
with the same name. */
struct minimal_symbol *fn =
lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn) + 1, NULL,
dot_fn_section->objfile);
if (fn != NULL)
{
/* Got the address of that descriptor. The TOC is the
second double word. */
CORE_ADDR toc =
read_memory_unsigned_integer (SYMBOL_VALUE_ADDRESS (fn)
+ tdep->wordsize,
tdep->wordsize);
regcache_cooked_write_unsigned (regcache,
tdep->ppc_gp0_regnum + 2, toc);
}
}
} }
} }
@ -876,7 +907,9 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
} }
return RETURN_VALUE_REGISTER_CONVENTION; return RETURN_VALUE_REGISTER_CONVENTION;
} }
if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 8) if ((TYPE_CODE (valtype) == TYPE_CODE_INT
|| TYPE_CODE (valtype) == TYPE_CODE_ENUM)
&& TYPE_LENGTH (valtype) <= 8)
{ {
/* Integers in r3. */ /* Integers in r3. */
if (writebuf != NULL) if (writebuf != NULL)