/* Renesas M32C target-dependent code for GDB, the GNU debugger.
- Copyright 2004, 2005, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 2004-2015 Free Software Foundation, Inc.
This file is part of GDB.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
-
-#include <stdarg.h>
-
-#if defined (HAVE_STRING_H)
-#include <string.h>
-#endif
-
-#include "gdb_assert.h"
#include "elf-bfd.h"
#include "elf/m32c.h"
#include "gdb/sim-m32c.h"
#include "reggroups.h"
#include "prologue-value.h"
#include "target.h"
+#include "objfiles.h"
\f
/* The m32c tdep structure. */
/* The type of a function that moves the value of REG between CACHE or
BUF --- in either direction. */
-typedef void (m32c_move_reg_t) (struct m32c_reg *reg,
- struct regcache *cache,
- void *buf);
+typedef enum register_status (m32c_move_reg_t) (struct m32c_reg *reg,
+ struct regcache *cache,
+ void *buf);
struct m32c_reg
{
TYPE_UNSIGNED (tdep->ptr_voyd) = 1;
tdep->func_voyd = lookup_function_type (tdep->voyd);
- sprintf (type_name, "%s_data_addr_t",
- gdbarch_bfd_arch_info (arch)->printable_name);
+ xsnprintf (type_name, sizeof (type_name), "%s_data_addr_t",
+ gdbarch_bfd_arch_info (arch)->printable_name);
tdep->data_addr_reg_type
= arch_type (arch, TYPE_CODE_PTR, data_addr_reg_bits / TARGET_CHAR_BIT,
xstrdup (type_name));
TYPE_TARGET_TYPE (tdep->data_addr_reg_type) = tdep->voyd;
TYPE_UNSIGNED (tdep->data_addr_reg_type) = 1;
- sprintf (type_name, "%s_code_addr_t",
- gdbarch_bfd_arch_info (arch)->printable_name);
+ xsnprintf (type_name, sizeof (type_name), "%s_code_addr_t",
+ gdbarch_bfd_arch_info (arch)->printable_name);
tdep->code_addr_reg_type
= arch_type (arch, TYPE_CODE_PTR, code_addr_reg_bits / TARGET_CHAR_BIT,
xstrdup (type_name));
/* Copy the value of the raw register REG from CACHE to BUF. */
-static void
+static enum register_status
m32c_raw_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
- regcache_raw_read (cache, reg->num, buf);
+ return regcache_raw_read (cache, reg->num, buf);
}
/* Copy the value of the raw register REG from BUF to CACHE. */
-static void
+static enum register_status
m32c_raw_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
regcache_raw_write (cache, reg->num, (const void *) buf);
+
+ return REG_VALID;
}
If the value of the 'flg' register in CACHE has any of the bits
masked in REG->n set, then read REG->ry. Otherwise, read
REG->rx. */
-static void
+static enum register_status
m32c_banked_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
struct m32c_reg *bank_reg = m32c_banked_register (reg, cache);
- regcache_raw_read (cache, bank_reg->num, buf);
+ return regcache_raw_read (cache, bank_reg->num, buf);
}
If the value of the 'flg' register in CACHE has any of the bits
masked in REG->n set, then write REG->ry. Otherwise, write
REG->rx. */
-static void
+static enum register_status
m32c_banked_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
struct m32c_reg *bank_reg = m32c_banked_register (reg, cache);
regcache_raw_write (cache, bank_reg->num, (const void *) buf);
+
+ return REG_VALID;
}
/* Move the value of SB from CACHE to BUF. On bfd_mach_m32c, SB is a
banked register; on bfd_mach_m16c, it's not. */
-static void
+static enum register_status
m32c_sb_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
if (gdbarch_bfd_arch_info (reg->arch)->mach == bfd_mach_m16c)
- m32c_raw_read (reg->rx, cache, buf);
+ return m32c_raw_read (reg->rx, cache, buf);
else
- m32c_banked_read (reg, cache, buf);
+ return m32c_banked_read (reg, cache, buf);
}
/* Move the value of SB from BUF to CACHE. On bfd_mach_m32c, SB is a
banked register; on bfd_mach_m16c, it's not. */
-static void
+static enum register_status
m32c_sb_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
if (gdbarch_bfd_arch_info (reg->arch)->mach == bfd_mach_m16c)
m32c_raw_write (reg->rx, cache, buf);
else
m32c_banked_write (reg, cache, buf);
+
+ return REG_VALID;
}
to BUF. Treating the value of the register REG->rx as an array of
REG->type values, where higher indices refer to more significant
bits, read the value of the REG->n'th element. */
-static void
+static enum register_status
m32c_part_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
int offset, len;
+
memset (buf, 0, TYPE_LENGTH (reg->type));
m32c_find_part (reg, &offset, &len);
- regcache_cooked_read_part (cache, reg->rx->num, offset, len, buf);
+ return regcache_cooked_read_part (cache, reg->rx->num, offset, len, buf);
}
Treating the value of the register REG->rx as an array of REG->type
values, where higher indices refer to more significant bits, write
the value of the REG->n'th element. */
-static void
+static enum register_status
m32c_part_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
int offset, len;
+
m32c_find_part (reg, &offset, &len);
regcache_cooked_write_part (cache, reg->rx->num, offset, len, buf);
+
+ return REG_VALID;
}
/* Move the value of REG from CACHE to BUF. REG's value is the
concatenation of the values of the registers REG->rx and REG->ry,
with REG->rx contributing the more significant bits. */
-static void
+static enum register_status
m32c_cat_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
int high_bytes = TYPE_LENGTH (reg->rx->type);
int low_bytes = TYPE_LENGTH (reg->ry->type);
/* For address arithmetic. */
unsigned char *cbuf = buf;
+ enum register_status status;
gdb_assert (TYPE_LENGTH (reg->type) == high_bytes + low_bytes);
if (gdbarch_byte_order (reg->arch) == BFD_ENDIAN_BIG)
{
- regcache_cooked_read (cache, reg->rx->num, cbuf);
- regcache_cooked_read (cache, reg->ry->num, cbuf + high_bytes);
+ status = regcache_cooked_read (cache, reg->rx->num, cbuf);
+ if (status == REG_VALID)
+ status = regcache_cooked_read (cache, reg->ry->num, cbuf + high_bytes);
}
else
{
- regcache_cooked_read (cache, reg->rx->num, cbuf + low_bytes);
- regcache_cooked_read (cache, reg->ry->num, cbuf);
+ status = regcache_cooked_read (cache, reg->rx->num, cbuf + low_bytes);
+ if (status == REG_VALID)
+ status = regcache_cooked_read (cache, reg->ry->num, cbuf);
}
+
+ return status;
}
/* Move the value of REG from CACHE to BUF. REG's value is the
concatenation of the values of the registers REG->rx and REG->ry,
with REG->rx contributing the more significant bits. */
-static void
+static enum register_status
m32c_cat_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
int high_bytes = TYPE_LENGTH (reg->rx->type);
regcache_cooked_write (cache, reg->rx->num, cbuf + low_bytes);
regcache_cooked_write (cache, reg->ry->num, cbuf);
}
+
+ return REG_VALID;
}
/* Copy the value of the raw register REG from CACHE to BUF. REG is
the concatenation (from most significant to least) of r3, r2, r1,
and r0. */
-static void
+static enum register_status
m32c_r3r2r1r0_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (reg->arch);
int len = TYPE_LENGTH (tdep->r0->type);
+ enum register_status status;
/* For address arithmetic. */
unsigned char *cbuf = buf;
if (gdbarch_byte_order (reg->arch) == BFD_ENDIAN_BIG)
{
- regcache_cooked_read (cache, tdep->r0->num, cbuf + len * 3);
- regcache_cooked_read (cache, tdep->r1->num, cbuf + len * 2);
- regcache_cooked_read (cache, tdep->r2->num, cbuf + len * 1);
- regcache_cooked_read (cache, tdep->r3->num, cbuf);
+ status = regcache_cooked_read (cache, tdep->r0->num, cbuf + len * 3);
+ if (status == REG_VALID)
+ status = regcache_cooked_read (cache, tdep->r1->num, cbuf + len * 2);
+ if (status == REG_VALID)
+ status = regcache_cooked_read (cache, tdep->r2->num, cbuf + len * 1);
+ if (status == REG_VALID)
+ status = regcache_cooked_read (cache, tdep->r3->num, cbuf);
}
else
{
- regcache_cooked_read (cache, tdep->r0->num, cbuf);
- regcache_cooked_read (cache, tdep->r1->num, cbuf + len * 1);
- regcache_cooked_read (cache, tdep->r2->num, cbuf + len * 2);
- regcache_cooked_read (cache, tdep->r3->num, cbuf + len * 3);
+ status = regcache_cooked_read (cache, tdep->r0->num, cbuf);
+ if (status == REG_VALID)
+ status = regcache_cooked_read (cache, tdep->r1->num, cbuf + len * 1);
+ if (status == REG_VALID)
+ status = regcache_cooked_read (cache, tdep->r2->num, cbuf + len * 2);
+ if (status == REG_VALID)
+ status = regcache_cooked_read (cache, tdep->r3->num, cbuf + len * 3);
}
+
+ return status;
}
/* Copy the value of the raw register REG from BUF to CACHE. REG is
the concatenation (from most significant to least) of r3, r2, r1,
and r0. */
-static void
+static enum register_status
m32c_r3r2r1r0_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (reg->arch);
regcache_cooked_write (cache, tdep->r2->num, cbuf + len * 2);
regcache_cooked_write (cache, tdep->r3->num, cbuf + len * 3);
}
+
+ return REG_VALID;
}
-static void
+static enum register_status
m32c_pseudo_register_read (struct gdbarch *arch,
struct regcache *cache,
int cookednum,
gdb_assert (arch == tdep->regs[cookednum].arch);
reg = &tdep->regs[cookednum];
- reg->read (reg, cache, buf);
+ return reg->read (reg, cache, buf);
}
\f
/* Prologue analysis. */
+enum m32c_prologue_kind
+{
+ /* This function uses a frame pointer. */
+ prologue_with_frame_ptr,
+
+ /* This function has no frame pointer. */
+ prologue_sans_frame_ptr,
+
+ /* This function sets up the stack, so its frame is the first
+ frame on the stack. */
+ prologue_first_frame
+};
+
struct m32c_prologue
{
/* For consistency with the DWARF 2 .debug_frame info generated by
/* The architecture for which we generated this prologue info. */
struct gdbarch *arch;
- enum {
- /* This function uses a frame pointer. */
- prologue_with_frame_ptr,
-
- /* This function has no frame pointer. */
- prologue_sans_frame_ptr,
-
- /* This function sets up the stack, so its frame is the first
- frame on the stack. */
- prologue_first_frame
-
- } kind;
+ enum m32c_prologue_kind kind;
/* If KIND is prologue_with_frame_ptr, this is the offset from the
CFA to where the frame pointer points. This is always zero or
}
+enum srcdest_kind
+{
+ srcdest_reg,
+ srcdest_partial_reg,
+ srcdest_mem
+};
+
/* A source or destination location for an m16c or m32c
instruction. */
struct srcdest
If srcdest_partial_reg, the location is part of a register pointed
to by REG. We don't try to handle this too well.
If srcdest_mem, the location is memory whose address is ADDR. */
- enum { srcdest_reg, srcdest_partial_reg, srcdest_mem } kind;
+ enum srcdest_kind kind;
pv_t *reg, addr;
};
static CORE_ADDR
m32c_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR ip)
{
- char *name;
+ const char *name;
CORE_ADDR func_addr, func_end, sal_end;
struct m32c_prologue p;
*this_prologue_cache = FRAME_OBSTACK_ZALLOC (struct m32c_prologue);
m32c_analyze_prologue (get_frame_arch (this_frame),
- func_start, stop_addr, *this_prologue_cache);
+ func_start, stop_addr,
+ (struct m32c_prologue *) *this_prologue_cache);
}
- return *this_prologue_cache;
+ return (struct m32c_prologue *) *this_prologue_cache;
}
static const struct frame_unwind m32c_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
m32c_this_id,
m32c_prev_register,
NULL,
static enum return_value_convention
m32c_return_value (struct gdbarch *gdbarch,
- struct type *func_type,
+ struct value *function,
struct type *valtype,
struct regcache *regcache,
gdb_byte *readbuf,
/* Everything else is passed in mem0, using as many bytes as
needed. This is not what the Renesas tools do, but it's
what GCC does at the moment. */
- struct minimal_symbol *mem0
+ struct bound_minimal_symbol mem0
= lookup_minimal_symbol ("mem0", NULL, NULL);
- if (! mem0)
+ if (! mem0.minsym)
error (_("The return value is stored in memory at 'mem0', "
"but GDB cannot find\n"
"its address."));
- read_memory (SYMBOL_VALUE_ADDRESS (mem0), readbuf, valtype_len);
+ read_memory (BMSYMBOL_VALUE_ADDRESS (mem0), readbuf, valtype_len);
}
}
/* Everything else is passed in mem0, using as many bytes as
needed. This is not what the Renesas tools do, but it's
what GCC does at the moment. */
- struct minimal_symbol *mem0
+ struct bound_minimal_symbol mem0
= lookup_minimal_symbol ("mem0", NULL, NULL);
- if (! mem0)
+ if (! mem0.minsym)
error (_("The return value is stored in memory at 'mem0', "
"but GDB cannot find\n"
" its address."));
- write_memory (SYMBOL_VALUE_ADDRESS (mem0),
- (char *) writebuf, valtype_len);
+ write_memory (BMSYMBOL_VALUE_ADDRESS (mem0), writebuf, valtype_len);
}
}
someone loaded a new executable, and I'm not quite sure of the
best way to do that. find_pc_partial_function does do some
caching, so we'll see how this goes. */
- char *name;
+ const char *name;
CORE_ADDR start, end;
if (find_pc_partial_function (stop_pc, &name, &start, &end))
if (target_code == TYPE_CODE_FUNC || target_code == TYPE_CODE_METHOD)
{
- char *func_name;
+ const char *func_name;
char *tramp_name;
- struct minimal_symbol *tramp_msym;
+ struct bound_minimal_symbol tramp_msym;
/* Try to find a linker symbol at this address. */
- struct minimal_symbol *func_msym = lookup_minimal_symbol_by_pc (addr);
+ struct bound_minimal_symbol func_msym
+ = lookup_minimal_symbol_by_pc (addr);
- if (! func_msym)
+ if (! func_msym.minsym)
error (_("Cannot convert code address %s to function pointer:\n"
"couldn't find a symbol at that address, to find trampoline."),
paddress (gdbarch, addr));
- func_name = SYMBOL_LINKAGE_NAME (func_msym);
- tramp_name = xmalloc (strlen (func_name) + 5);
+ func_name = MSYMBOL_LINKAGE_NAME (func_msym.minsym);
+ tramp_name = (char *) xmalloc (strlen (func_name) + 5);
strcpy (tramp_name, func_name);
strcat (tramp_name, ".plt");
the name any more. */
xfree (tramp_name);
- if (! tramp_msym)
+ if (! tramp_msym.minsym)
{
CORE_ADDR ptrval;
else
{
/* The trampoline's address is our pointer. */
- addr = SYMBOL_VALUE_ADDRESS (tramp_msym);
+ addr = BMSYMBOL_VALUE_ADDRESS (tramp_msym);
}
}
{
/* See if there is a minimal symbol at that address whose name is
"NAME.plt". */
- struct minimal_symbol *ptr_msym = lookup_minimal_symbol_by_pc (ptr);
+ struct bound_minimal_symbol ptr_msym = lookup_minimal_symbol_by_pc (ptr);
- if (ptr_msym)
+ if (ptr_msym.minsym)
{
- char *ptr_msym_name = SYMBOL_LINKAGE_NAME (ptr_msym);
+ const char *ptr_msym_name = MSYMBOL_LINKAGE_NAME (ptr_msym.minsym);
int len = strlen (ptr_msym_name);
if (len > 4
&& strcmp (ptr_msym_name + len - 4, ".plt") == 0)
{
- struct minimal_symbol *func_msym;
+ struct bound_minimal_symbol func_msym;
/* We have a .plt symbol; try to find the symbol for the
corresponding function.
Since the trampoline contains a jump instruction, we
could also just extract the jump's target address. I
don't see much advantage one way or the other. */
- char *func_name = xmalloc (len - 4 + 1);
+ char *func_name = (char *) xmalloc (len - 4 + 1);
memcpy (func_name, ptr_msym_name, len - 4);
func_name[len - 4] = '\0';
func_msym
/* If we do have such a symbol, return its value as the
function's true address. */
- if (func_msym)
- ptr = SYMBOL_VALUE_ADDRESS (func_msym);
+ if (func_msym.minsym)
+ ptr = BMSYMBOL_VALUE_ADDRESS (func_msym);
}
}
else
{
ptr_msym = lookup_minimal_symbol_by_pc ((aspace << 16) | ptr);
- if (ptr_msym)
+ if (ptr_msym.minsym)
ptr |= aspace << 16;
}
}
int *frame_regnum,
LONGEST *frame_offset)
{
- char *name;
- CORE_ADDR func_addr, func_end, sal_end;
+ const char *name;
+ CORE_ADDR func_addr, func_end;
struct m32c_prologue p;
struct regcache *regcache = get_current_regcache ();
arches = gdbarch_list_lookup_by_info (arches->next, &info))
return arches->gdbarch;
- tdep = xcalloc (1, sizeof (*tdep));
+ tdep = XCNEW (struct gdbarch_tdep);
arch = gdbarch_alloc (&info, tdep);
/* Essential types. */