From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18321 invoked by alias); 25 Aug 2010 03:06:04 -0000 Received: (qmail 18288 invoked by uid 22791); 25 Aug 2010 03:06:03 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,TW_EG,TW_XT,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 25 Aug 2010 03:05:58 +0000 Received: (qmail 10596 invoked from network); 25 Aug 2010 03:05:57 -0000 Received: from unknown (HELO codesourcery.com) (yao@127.0.0.2) by mail.codesourcery.com with ESMTPA; 25 Aug 2010 03:05:57 -0000 Date: Wed, 25 Aug 2010 03:06:00 -0000 From: Yao Qi To: Mark Kettenis , Daniel Jacobowitz Cc: gdb-patches@sourceware.org Subject: Re: [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall Message-ID: <20100825030554.GC29794@codesourcery.com> References: <20100824063854.GA29794@codesourcery.com> <201008241127.o7OBR38E024928@glazunov.sibelius.xs4all.nl> <20100824141253.GA13547@caradoc.them.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="pvezYHf7grwyp3Bc" Content-Disposition: inline In-Reply-To: <20100824141253.GA13547@caradoc.them.org> User-Agent: Mutt/1.5.17+20080114 (2008-01-14) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-08/txt/msg00429.txt.bz2 --pvezYHf7grwyp3Bc Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 1007 On Tue, Aug 24, 2010 at 10:12:57AM -0400, Daniel Jacobowitz wrote: > On Tue, Aug 24, 2010 at 01:27:03PM +0200, Mark Kettenis wrote: > > > Date: Mon, 23 Aug 2010 23:38:54 -0700 > > > From: Yao Qi > > > > > > Hi, > > > This patch is to calculate correct address of 'next pc' of syscall > > > sigreturn and rt_sigreturn. > > > > You're polluting the genric arm code with Linux-specific stuff. > > Please don't do that. If something like this is needed, it should be > > added to code in arm-linux-tdep.c. > > There's a couple of ways to do that; one example is > mips_linux_syscall_next_pc. Here is the updated patch, in which: 1. Add arm_linux_syscall_next_pc, similar to mips_linux_syscall_next_pc. Compute the return address of SWI in both ARM mode and Thumb mode. 2. Extract some common code from arm_linux_copy_svc. Tested on armv7l-unknown-linux-gnueabi again. Result is the same as my previous post. -- Yao Qi CodeSourcery yao@codesourcery.com (650) 331-3385 x739 --pvezYHf7grwyp3Bc Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="return_addr_sigreturn.patch" Content-length: 6256 2010-08-25 Yao Qi * arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New. (arm_linux_syscall_next_pc): New. (arm_linux_copy_svc): Use arm_linux_sigreturn_return_addr instead. (arm_linux_init_abi): Initialize syscall_next_pc. * arm-tdep.c (thumb_get_next_pc_raw): Get next pc of SWI in Thumb mode. (arm_get_next_pc_raw): Get next pc of SWI in ARM mode. * arm-tdep.h (struct gdbarch_tdep): Add a function pointer syscall_next_pc. Declare arm_frame_is_thumb. diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index 682054c..106cd85 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -630,6 +630,53 @@ arm_linux_regset_from_core_section (struct gdbarch *gdbarch, return NULL; } +/* Get the value of next pc of sigreturn and rt_sigrturn. Return 0 if it is + not a rt_sigreturn/sigreturn syscall. */ +static int +arm_linux_sigreturn_return_addr(struct frame_info *frame, + unsigned long svc_number) +{ + /* Is this a sigreturn or rt_sigreturn syscall? Note: these are only useful + for EABI. */ + if (svc_number == 119 || svc_number == 173) + { + if (get_frame_type (frame) == SIGTRAMP_FRAME) + { + return frame_unwind_caller_pc (frame); + } + } + return 0; +} + +/* When FRAME is at a syscall instruction, return the PC of the next + instruction to be executed. */ + +static CORE_ADDR +arm_linux_syscall_next_pc (struct frame_info *frame) +{ + CORE_ADDR pc = get_frame_pc (frame); + CORE_ADDR return_addr = 0; + return_addr = arm_linux_sigreturn_return_addr(frame, + get_frame_register_unsigned (frame, 7)); + + if (return_addr) + return return_addr; + + if (arm_frame_is_thumb (frame)) + { + return_addr = pc + 2; + /* Addresses for calling Thumb functions have the bit 0 set. */ + return_addr |= 1; + } + else + { + return_addr = pc + 4; + } + + return return_addr; +} + + /* Insert a single step breakpoint at the next executed instruction. */ static int @@ -688,6 +735,8 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to, struct regcache *regs, struct displaced_step_closure *dsc) { CORE_ADDR from = dsc->insn_addr; + CORE_ADDR return_to = 0; + struct frame_info *frame; unsigned int svc_number = displaced_read_reg (regs, from, 7); @@ -697,13 +746,9 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to, frame = get_current_frame (); - /* Is this a sigreturn or rt_sigreturn syscall? Note: these are only useful - for EABI. */ - if (svc_number == 119 || svc_number == 173) - { - if (get_frame_type (frame) == SIGTRAMP_FRAME) + return_to = arm_linux_sigreturn_return_addr(frame, svc_number); + if (return_to) { - CORE_ADDR return_to; struct symtab_and_line sal; if (debug_displaced) @@ -711,7 +756,6 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to, "sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n", (unsigned long) get_frame_pc (frame)); - return_to = frame_unwind_caller_pc (frame); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. " "Setting momentary breakpoint.\n", (unsigned long) return_to); @@ -743,7 +787,7 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to, else if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn " "SVC call not in signal trampoline frame\n"); - } + /* Preparation: If we detect sigreturn, set momentary breakpoint at resume location, else nothing. @@ -946,6 +990,9 @@ arm_linux_init_abi (struct gdbarch_info info, set_gdbarch_displaced_step_free_closure (gdbarch, simple_displaced_step_free_closure); set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point); + + + tdep->syscall_next_pc = arm_linux_syscall_next_pc; } /* Provide a prototype to silence -Wmissing-prototypes. */ diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 1ac8817..518e4e8 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -257,7 +257,7 @@ int arm_apcs_32 = 1; /* Determine if FRAME is executing in Thumb mode. */ -static int +int arm_frame_is_thumb (struct frame_info *frame) { CORE_ADDR cpsr; @@ -2808,7 +2808,16 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt) else if ((inst1 & 0xf000) == 0xd000) /* conditional branch */ { unsigned long cond = bits (inst1, 8, 11); - if (cond != 0x0f && condition_true (cond, status)) /* 0x0f = SWI */ + if (cond == 0x0f) /* 0x0f = SWI */ + { + struct gdbarch_tdep *tdep; + tdep = gdbarch_tdep (get_frame_arch (frame)); + + if (tdep->syscall_next_pc != NULL) + nextpc = tdep->syscall_next_pc (frame); + + } + else if (cond != 0x0f && condition_true (cond, status)) nextpc = pc_val + (sbits (inst1, 0, 7) << 1); } else if ((inst1 & 0xf800) == 0xe000) /* unconditional branch */ @@ -3257,7 +3266,16 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt) case 0xc: case 0xd: case 0xe: /* coproc ops */ + break; case 0xf: /* SWI */ + { + struct gdbarch_tdep *tdep; + tdep = gdbarch_tdep (get_frame_arch (frame)); + + if (tdep->syscall_next_pc != NULL) + nextpc = tdep->syscall_next_pc (frame); + + } break; default: diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h index b6283ef..2f4e99b 100644 --- a/gdb/arm-tdep.h +++ b/gdb/arm-tdep.h @@ -193,6 +193,10 @@ struct gdbarch_tdep struct type *arm_ext_type; struct type *neon_double_type; struct type *neon_quad_type; + + /* Return the expected next PC if FRAME is stopped at a syscall + instruction. */ + CORE_ADDR (*syscall_next_pc) (struct frame_info *frame); }; /* Structures used for displaced stepping. */ @@ -294,6 +298,7 @@ extern void CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR); CORE_ADDR arm_get_next_pc (struct frame_info *, CORE_ADDR); int arm_software_single_step (struct frame_info *); +int arm_frame_is_thumb (struct frame_info *frame); extern struct displaced_step_closure * arm_displaced_step_copy_insn (struct gdbarch *, CORE_ADDR, CORE_ADDR, --pvezYHf7grwyp3Bc--