Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(510)

Unified Diff: gdb/tilegx-tdep.c

Issue 124383005: GDB 7.6.50 (Closed) Base URL: http://git.chromium.org/native_client/nacl-gdb.git@upstream
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gdb/tilegx-tdep.h ('k') | gdb/top.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gdb/tilegx-tdep.c
diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index 9ec3aaa53fd23201afb21af91d65c8b027b64840..c115f4993307faa1f51e9849b140fab861583f60 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -1,6 +1,6 @@
/* Target-dependent code for the Tilera TILE-Gx processor.
- Copyright (C) 2012 Free Software Foundation, Inc.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
This file is part of GDB.
@@ -30,7 +30,7 @@
#include "value.h"
#include "dis-asm.h"
#include "inferior.h"
-#include "gdb_string.h"
+#include <string.h>
#include "gdb_assert.h"
#include "arch-utils.h"
#include "floatformat.h"
@@ -155,7 +155,7 @@ tilegx_register_name (struct gdbarch *gdbarch, int regnum)
"r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
"r48", "r49", "r50", "r51", "r52", "tp", "sp", "lr",
"sn", "idn0", "idn1", "udn0", "udn1", "udn2", "udn3", "zero",
- "pc"
+ "pc", "faultnum",
};
if (regnum < 0 || regnum >= TILEGX_NUM_REGS)
@@ -292,7 +292,7 @@ tilegx_push_dummy_call (struct gdbarch *gdbarch,
int argreg = TILEGX_R0_REGNUM;
int i, j;
int typelen, slacklen, alignlen;
- static const gdb_byte two_zero_words[8] = { 0 };
+ static const gdb_byte four_zero_words[16] = { 0 };
/* If struct_return is 1, then the struct return address will
consume one argument-passing register. */
@@ -326,38 +326,30 @@ tilegx_push_dummy_call (struct gdbarch *gdbarch,
/* Align SP. */
stack_dest = tilegx_frame_align (gdbarch, stack_dest);
- /* Loop backwards through arguments to determine stack alignment. */
- alignlen = 0;
-
- for (j = nargs - 1; j >= i; j--)
- {
- typelen = TYPE_LENGTH (value_enclosing_type (args[j]));
- alignlen += (typelen + 3) & (~3);
- }
-
- if (alignlen & 0x4)
- stack_dest -= 4;
-
/* Loop backwards through remaining arguments and push them on
the stack, word aligned. */
for (j = nargs - 1; j >= i; j--)
{
gdb_byte *val;
+ struct cleanup *back_to;
+ const gdb_byte *contents = value_contents (args[j]);
typelen = TYPE_LENGTH (value_enclosing_type (args[j]));
- slacklen = ((typelen + 3) & (~3)) - typelen;
- val = alloca (typelen + slacklen);
- memcpy (val, value_contents (args[j]), typelen);
+ slacklen = align_up (typelen, 8) - typelen;
+ val = xmalloc (typelen + slacklen);
+ back_to = make_cleanup (xfree, val);
+ memcpy (val, contents, typelen);
memset (val + typelen, 0, slacklen);
/* Now write data to the stack. The stack grows downwards. */
stack_dest -= typelen + slacklen;
write_memory (stack_dest, val, typelen + slacklen);
+ do_cleanups (back_to);
}
- /* Add 2 words for linkage space to the stack. */
- stack_dest = stack_dest - 8;
- write_memory (stack_dest, two_zero_words, 8);
+ /* Add 16 bytes for linkage space to the stack. */
+ stack_dest = stack_dest - 16;
+ write_memory (stack_dest, four_zero_words, 16);
/* Update stack pointer. */
regcache_cooked_write_unsigned (regcache, TILEGX_SP_REGNUM, stack_dest);
@@ -401,7 +393,7 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch,
struct tilegx_reverse_regs
new_reverse_frame[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
int dest_regs[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
- int reverse_frame_valid, prolog_done, branch_seen;
+ int reverse_frame_valid, prolog_done, branch_seen, lr_saved_on_stack_p;
LONGEST prev_sp_value;
int i, j;
@@ -417,6 +409,7 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch,
prolog_done = 0;
branch_seen = 0;
prev_sp_value = 0;
+ lr_saved_on_stack_p = 0;
/* To cut down on round-trip overhead, we fetch multiple bundles
at once. These variables describe the range of memory we have
@@ -440,6 +433,8 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch,
if (instbuf_size > size_on_same_page)
instbuf_size = size_on_same_page;
+
+ instbuf_size = min (instbuf_size, (end_addr - next_addr));
instbuf_start = next_addr;
status = safe_frame_unwind_memory (next_frame, instbuf_start,
@@ -480,7 +475,11 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch,
See trad-frame.h. */
cache->saved_regs[saved_register].realreg = saved_register;
cache->saved_regs[saved_register].addr = saved_address;
- }
+ }
+ else if (cache
+ && (operands[0] == TILEGX_SP_REGNUM)
+ && (operands[1] == TILEGX_LR_REGNUM))
+ lr_saved_on_stack_p = 1;
break;
case TILEGX_OPC_ADDI:
case TILEGX_OPC_ADDLI:
@@ -733,30 +732,45 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch,
}
}
+ if (lr_saved_on_stack_p)
+ {
+ cache->saved_regs[TILEGX_LR_REGNUM].realreg = TILEGX_LR_REGNUM;
+ cache->saved_regs[TILEGX_LR_REGNUM].addr =
+ cache->saved_regs[TILEGX_SP_REGNUM].addr;
+ }
+
return prolog_end;
}
/* This is the implementation of gdbarch method skip_prologue. */
static CORE_ADDR
-tilegx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+tilegx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
- struct symtab_and_line sal;
- CORE_ADDR func_start, func_end;
+ CORE_ADDR func_start, end_pc;
+ struct obj_section *s;
/* This is the preferred method, find the end of the prologue by
using the debugging information. */
- if (find_pc_partial_function (pc, NULL, &func_start, &func_end))
+ if (find_pc_partial_function (start_pc, NULL, &func_start, NULL))
{
- sal = find_pc_line (func_start, 0);
+ CORE_ADDR post_prologue_pc
+ = skip_prologue_using_sal (gdbarch, func_start);
- if (sal.end < func_end && pc <= sal.end)
- return sal.end;
+ if (post_prologue_pc != 0)
+ return max (start_pc, post_prologue_pc);
}
+ /* Don't straddle a section boundary. */
+ s = find_pc_section (start_pc);
+ end_pc = start_pc + 8 * TILEGX_BUNDLE_SIZE_IN_BYTES;
+ if (s != NULL)
+ end_pc = min (end_pc, obj_section_endaddr (s));
+
/* Otherwise, try to skip prologue the hard way. */
return tilegx_analyze_prologue (gdbarch,
- pc, pc + 8 * TILEGX_BUNDLE_SIZE_IN_BYTES,
+ start_pc,
+ end_pc,
NULL, NULL);
}
@@ -780,6 +794,59 @@ tilegx_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
return 0;
}
+/* This is the implementation of gdbarch method get_longjmp_target. */
+
+static int
+tilegx_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ CORE_ADDR jb_addr;
+ gdb_byte buf[8];
+
+ jb_addr = get_frame_register_unsigned (frame, TILEGX_R0_REGNUM);
+
+ /* TileGX jmp_buf contains 32 elements of type __uint_reg_t which
+ has a size of 8 bytes. The return address is stored in the 25th
+ slot. */
+ if (target_read_memory (jb_addr + 25 * 8, buf, 8))
+ return 0;
+
+ *pc = extract_unsigned_integer (buf, 8, byte_order);
+
+ return 1;
+}
+
+/* by assigning the 'faultnum' reg in kernel pt_regs with this value,
+ kernel do_signal will not check r0. see tilegx kernel/signal.c
+ for details. */
+#define INT_SWINT_1_SIGRETURN (~0)
+
+/* Implement the "write_pc" gdbarch method. */
+
+static void
+tilegx_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+ regcache_cooked_write_unsigned (regcache, TILEGX_PC_REGNUM, pc);
+
+ /* We must be careful with modifying the program counter. If we
+ just interrupted a system call, the kernel might try to restart
+ it when we resume the inferior. On restarting the system call,
+ the kernel will try backing up the program counter even though it
+ no longer points at the system call. This typically results in a
+ SIGSEGV or SIGILL. We can prevent this by writing INT_SWINT_1_SIGRETURN
+ in the "faultnum" pseudo-register.
+
+ Note that "faultnum" is saved when setting up a dummy call frame.
+ This means that it is properly restored when that frame is
+ popped, and that the interrupted system call will be restarted
+ when we resume the inferior on return from a function call from
+ within GDB. In all other cases the system call will not be
+ restarted. */
+ regcache_cooked_write_unsigned (regcache, TILEGX_FAULTNUM_REGNUM,
+ INT_SWINT_1_SIGRETURN);
+}
+
/* This is the implementation of gdbarch method breakpoint_from_pc. */
static const unsigned char *
@@ -817,11 +884,12 @@ tilegx_frame_cache (struct frame_info *this_frame, void **this_cache)
cache->base = get_frame_register_unsigned (this_frame, TILEGX_SP_REGNUM);
trad_frame_set_value (cache->saved_regs, TILEGX_SP_REGNUM, cache->base);
- cache->saved_regs[TILEGX_PC_REGNUM] = cache->saved_regs[TILEGX_LR_REGNUM];
if (cache->start_pc)
tilegx_analyze_prologue (gdbarch, cache->start_pc, current_pc,
cache, this_frame);
+ cache->saved_regs[TILEGX_PC_REGNUM] = cache->saved_regs[TILEGX_LR_REGNUM];
+
return cache;
}
@@ -911,7 +979,8 @@ tilegx_cannot_reference_register (struct gdbarch *gdbarch, int regno)
{
if (regno >= 0 && regno < TILEGX_NUM_EASY_REGS)
return 0;
- else if (regno == TILEGX_PC_REGNUM)
+ else if (regno == TILEGX_PC_REGNUM
+ || regno == TILEGX_FAULTNUM_REGNUM)
return 0;
else
return 1;
@@ -956,7 +1025,6 @@ tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_register_name (gdbarch, tilegx_register_name);
set_gdbarch_register_type (gdbarch, tilegx_register_type);
- set_gdbarch_char_signed (gdbarch, 0);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_long_bit (gdbarch, arch_size);
@@ -994,6 +1062,8 @@ tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* These values and methods are used when gdb calls a target function. */
set_gdbarch_push_dummy_call (gdbarch, tilegx_push_dummy_call);
+ set_gdbarch_get_longjmp_target (gdbarch, tilegx_get_longjmp_target);
+ set_gdbarch_write_pc (gdbarch, tilegx_write_pc);
set_gdbarch_breakpoint_from_pc (gdbarch, tilegx_breakpoint_from_pc);
set_gdbarch_return_value (gdbarch, tilegx_return_value);
« no previous file with comments | « gdb/tilegx-tdep.h ('k') | gdb/top.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698