#include "gdb_assert.h"
#include "ppc-tdep.h"
#include "target.h"
+#include "objfiles.h"
/* Pass the arguments in either registers, or in the stack. Using the
ppc sysv ABI, the first eight words of the argument list (that might
static enum return_value_convention
do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
- struct regcache *regcache, const void *inval,
- void *outval, int broken_gcc)
+ struct regcache *regcache, void *readbuf,
+ const void *writebuf, int broken_gcc)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
gdb_assert (tdep->wordsize == 4);
&& TYPE_LENGTH (type) <= 8
&& ppc_floating_point_unit_p (gdbarch))
{
- if (outval)
+ if (readbuf)
{
/* Floats and doubles stored in "f1". Convert the value to
the required type. */
char regval[MAX_REGISTER_SIZE];
struct type *regtype = register_type (gdbarch, FP0_REGNUM + 1);
regcache_cooked_read (regcache, FP0_REGNUM + 1, regval);
- convert_typed_floating (regval, regtype, outval, type);
+ convert_typed_floating (regval, regtype, readbuf, type);
}
- if (inval)
+ if (writebuf)
{
/* Floats and doubles stored in "f1". Convert the value to
the register's "double" type. */
char regval[MAX_REGISTER_SIZE];
struct type *regtype = register_type (gdbarch, FP0_REGNUM);
- convert_typed_floating (inval, type, regval, regtype);
+ convert_typed_floating (writebuf, type, regval, regtype);
regcache_cooked_write (regcache, FP0_REGNUM + 1, regval);
}
return RETURN_VALUE_REGISTER_CONVENTION;
if ((TYPE_CODE (type) == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
|| (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
{
- if (outval)
+ if (readbuf)
{
/* A long long, or a double stored in the 32 bit r3/r4. */
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
- (bfd_byte *) outval + 0);
+ (bfd_byte *) readbuf + 0);
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
- (bfd_byte *) outval + 4);
+ (bfd_byte *) readbuf + 4);
}
- if (inval)
+ if (writebuf)
{
/* A long long, or a double stored in the 32 bit r3/r4. */
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
- (bfd_byte *) inval + 0);
+ (const bfd_byte *) writebuf + 0);
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
- (bfd_byte *) inval + 4);
+ (const bfd_byte *) writebuf + 4);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_CODE (type) == TYPE_CODE_INT
&& TYPE_LENGTH (type) <= tdep->wordsize)
{
- if (outval)
+ if (readbuf)
{
/* Some sort of integer stored in r3. Since TYPE isn't
bigger than the register, sign extension isn't a problem
ULONGEST regval;
regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
®val);
- store_unsigned_integer (outval, TYPE_LENGTH (type), regval);
+ store_unsigned_integer (readbuf, TYPE_LENGTH (type), regval);
}
- if (inval)
+ if (writebuf)
{
/* Some sort of integer stored in r3. Use unpack_long since
that should handle any required sign extension. */
regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
- unpack_long (type, inval));
+ unpack_long (type, writebuf));
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type) && tdep->ppc_vr0_regnum >= 0)
{
- if (outval)
+ if (readbuf)
{
/* Altivec places the return value in "v2". */
- regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, outval);
+ regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
}
- if (inval)
+ if (writebuf)
{
/* Altivec places the return value in "v2". */
- regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, inval);
+ regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
corresponds to the entire r3 value for e500, whereas GDB's r3
only corresponds to the least significant 32-bits. So place
the 64-bit DSP type's value in ev3. */
- if (outval)
- regcache_cooked_read (regcache, tdep->ppc_ev0_regnum + 3, outval);
- if (inval)
- regcache_cooked_write (regcache, tdep->ppc_ev0_regnum + 3, inval);
+ if (readbuf)
+ regcache_cooked_read (regcache, tdep->ppc_ev0_regnum + 3, readbuf);
+ if (writebuf)
+ regcache_cooked_write (regcache, tdep->ppc_ev0_regnum + 3, writebuf);
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (broken_gcc && TYPE_LENGTH (type) <= 8)
{
- if (outval)
+ if (readbuf)
{
/* GCC screwed up. The last register isn't "left" aligned.
Need to extract the least significant part of each
regcache_cooked_read_unsigned (regcache,
tdep->ppc_gp0_regnum + 3 + word,
®);
- store_unsigned_integer (((bfd_byte *) outval
+ store_unsigned_integer (((bfd_byte *) readbuf
+ word * tdep->wordsize), len, reg);
word++;
}
}
- if (inval)
+ if (writebuf)
{
/* GCC screwed up. The last register isn't "left" aligned.
Need to extract the least significant part of each
break;
if (len > tdep->wordsize)
len = tdep->wordsize;
- reg = extract_unsigned_integer (((bfd_byte *) inval
+ reg = extract_unsigned_integer (((const bfd_byte *) writebuf
+ word * tdep->wordsize), len);
regcache_cooked_write_unsigned (regcache,
tdep->ppc_gp0_regnum + 3 + word,
}
if (TYPE_LENGTH (type) <= 8)
{
- if (outval)
+ if (readbuf)
{
/* This matches SVr4 PPC, it does not match GCC. */
/* The value is right-padded to 8 bytes and then loaded, as
if (TYPE_LENGTH (type) > tdep->wordsize)
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
regvals + 1 * tdep->wordsize);
- memcpy (outval, regvals, TYPE_LENGTH (type));
+ memcpy (readbuf, regvals, TYPE_LENGTH (type));
}
- if (inval)
+ if (writebuf)
{
/* This matches SVr4 PPC, it does not match GCC. */
/* The value is padded out to 8 bytes and then loaded, as
two "words" into r3/r4. */
char regvals[MAX_REGISTER_SIZE * 2];
memset (regvals, 0, sizeof regvals);
- memcpy (regvals, inval, TYPE_LENGTH (type));
+ memcpy (regvals, writebuf, TYPE_LENGTH (type));
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
regvals + 0 * tdep->wordsize);
if (TYPE_LENGTH (type) > tdep->wordsize)
enum return_value_convention
ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
- struct regcache *regcache, const void *inval, void *outval)
+ struct regcache *regcache, void *readbuf,
+ const void *writebuf)
{
- return do_ppc_sysv_return_value (gdbarch, valtype, regcache, inval, outval, 0);
+ return do_ppc_sysv_return_value (gdbarch, valtype, regcache, readbuf,
+ writebuf, 0);
}
enum return_value_convention
-ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch, struct type *valtype,
- struct regcache *regcache, const void *inval,
- void *outval)
+ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch,
+ struct type *valtype,
+ struct regcache *regcache,
+ void *readbuf, const void *writebuf)
{
- return do_ppc_sysv_return_value (gdbarch, valtype, regcache, inval, outval, 1);
+ return do_ppc_sysv_return_value (gdbarch, valtype, regcache, readbuf,
+ writebuf, 1);
}
/* Pass the arguments in either registers, or in the stack. Using the
".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. */
+ 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
have the name ".FN"). */
struct minimal_symbol *dot_fn = lookup_minimal_symbol_by_pc (func_addr);
if (dot_fn != NULL && SYMBOL_LINKAGE_NAME (dot_fn)[0] == '.')
{
- /* Now find the corresponding "FN" (dropping ".") minimal
- symbol's address. */
- struct minimal_symbol *fn =
- lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn) + 1, NULL,
- NULL);
- if (fn != NULL)
+ /* Get the section that contains FUNC_ADR. Need this for the
+ "objfile" that it contains. */
+ struct obj_section *dot_fn_section = find_pc_section (func_addr);
+ if (dot_fn_section != NULL && dot_fn_section->objfile != 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);
+ /* 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. */
+ 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);
+ }
}
}
}
0 if the return-value is instead stored on the stack (a.k.a.,
struct return convention).
- For a return-value stored in a register: when INVAL is non-NULL,
+ For a return-value stored in a register: when WRITEBUF is non-NULL,
copy the buffer to the corresponding register return-value location
- location; when OUTVAL is non-NULL, fill the buffer from the
+ location; when READBUF is non-NULL, fill the buffer from the
corresponding register return-value location. */
enum return_value_convention
ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
- struct regcache *regcache, const void *inval,
- void *outval)
+ struct regcache *regcache, void *readbuf,
+ const void *writebuf)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* Floats and doubles in F1. */
{
char regval[MAX_REGISTER_SIZE];
struct type *regtype = register_type (gdbarch, FP0_REGNUM);
- if (inval != NULL)
+ if (writebuf != NULL)
{
- convert_typed_floating (inval, valtype, regval, regtype);
+ convert_typed_floating (writebuf, valtype, regval, regtype);
regcache_cooked_write (regcache, FP0_REGNUM + 1, regval);
}
- if (outval != NULL)
+ if (readbuf != NULL)
{
regcache_cooked_read (regcache, FP0_REGNUM + 1, regval);
- convert_typed_floating (regval, regtype, outval, valtype);
+ convert_typed_floating (regval, regtype, readbuf, valtype);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 8)
{
/* Integers in r3. */
- if (inval != NULL)
+ if (writebuf != NULL)
{
/* Be careful to sign extend the value. */
regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
- unpack_long (valtype, inval));
+ unpack_long (valtype, writebuf));
}
- if (outval != NULL)
+ if (readbuf != NULL)
{
/* Extract the integer from r3. Since this is truncating the
value, there isn't a sign extension problem. */
ULONGEST regval;
regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
®val);
- store_unsigned_integer (outval, TYPE_LENGTH (valtype), regval);
+ store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), regval);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_CODE (valtype) == TYPE_CODE_PTR)
{
/* All pointers live in r3. */
- if (inval != NULL)
- regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, inval);
- if (outval != NULL)
- regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, outval);
+ if (writebuf != NULL)
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
+ if (readbuf != NULL)
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, readbuf);
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
/* Small character arrays are returned, right justified, in r3. */
int offset = (register_size (gdbarch, tdep->ppc_gp0_regnum + 3)
- TYPE_LENGTH (valtype));
- if (inval != NULL)
+ if (writebuf != NULL)
regcache_cooked_write_part (regcache, tdep->ppc_gp0_regnum + 3,
- offset, TYPE_LENGTH (valtype), inval);
- if (outval != NULL)
+ offset, TYPE_LENGTH (valtype), writebuf);
+ if (readbuf != NULL)
regcache_cooked_read_part (regcache, tdep->ppc_gp0_regnum + 3,
- offset, TYPE_LENGTH (valtype), outval);
+ offset, TYPE_LENGTH (valtype), readbuf);
return RETURN_VALUE_REGISTER_CONVENTION;
}
/* Big floating point values get stored in adjacent floating
if (TYPE_CODE (valtype) == TYPE_CODE_FLT
&& (TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 32))
{
- if (inval || outval != NULL)
+ if (writebuf || readbuf != NULL)
{
int i;
for (i = 0; i < TYPE_LENGTH (valtype) / 8; i++)
{
- if (inval != NULL)
+ if (writebuf != NULL)
regcache_cooked_write (regcache, FP0_REGNUM + 1 + i,
- (const bfd_byte *) inval + i * 8);
- if (outval != NULL)
+ (const bfd_byte *) writebuf + i * 8);
+ if (readbuf != NULL)
regcache_cooked_read (regcache, FP0_REGNUM + 1 + i,
- (bfd_byte *) outval + i * 8);
+ (bfd_byte *) readbuf + i * 8);
}
}
return RETURN_VALUE_REGISTER_CONVENTION;
char regval[MAX_REGISTER_SIZE];
struct type *regtype =
register_type (current_gdbarch, FP0_REGNUM);
- if (inval != NULL)
+ if (writebuf != NULL)
{
- convert_typed_floating ((const bfd_byte *) inval +
+ convert_typed_floating ((const bfd_byte *) writebuf +
i * (TYPE_LENGTH (valtype) / 2),
valtype, regval, regtype);
regcache_cooked_write (regcache, FP0_REGNUM + 1 + i,
regval);
}
- if (outval != NULL)
+ if (readbuf != NULL)
{
regcache_cooked_read (regcache, FP0_REGNUM + 1 + i, regval);
convert_typed_floating (regval, regtype,
- (bfd_byte *) outval +
+ (bfd_byte *) readbuf +
i * (TYPE_LENGTH (valtype) / 2),
valtype);
}
int i;
for (i = 0; i < 4; i++)
{
- if (inval != NULL)
+ if (writebuf != NULL)
regcache_cooked_write (regcache, FP0_REGNUM + 1 + i,
- (const bfd_byte *) inval + i * 8);
- if (outval != NULL)
+ (const bfd_byte *) writebuf + i * 8);
+ if (readbuf != NULL)
regcache_cooked_read (regcache, FP0_REGNUM + 1 + i,
- (bfd_byte *) outval + i * 8);
+ (bfd_byte *) readbuf + i * 8);
}
}
return RETURN_VALUE_REGISTER_CONVENTION;