From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27167 invoked by alias); 27 Mar 2010 17:55:26 -0000 Received: (qmail 27159 invoked by uid 22791); 27 Mar 2010 17:55:25 -0000 X-SWARE-Spam-Status: No, hits=-2.0 required=5.0 tests=BAYES_00,SARE_MSGID_LONG40 X-Spam-Check-By: sourceware.org Received: from mail-fx0-f227.google.com (HELO mail-fx0-f227.google.com) (209.85.220.227) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 27 Mar 2010 17:55:21 +0000 Received: by fxm27 with SMTP id 27so536040fxm.8 for ; Sat, 27 Mar 2010 10:55:18 -0700 (PDT) MIME-Version: 1.0 Received: by 10.239.181.212 with HTTP; Sat, 27 Mar 2010 10:55:18 -0700 (PDT) Date: Sat, 27 Mar 2010 17:55:00 -0000 Received: by 10.239.188.146 with SMTP id p18mr198259hbh.208.1269712518343; Sat, 27 Mar 2010 10:55:18 -0700 (PDT) Message-ID: <737ad3551003271055o91a78i3f5ff305b927e441@mail.gmail.com> Subject: patch: fix stack unwind through uClibc syscall() on mips From: =?UTF-8?B?SsOhbiBTdGFuxI1law==?= To: gdb-patches@sourceware.org Content-Type: text/plain; charset=ISO-8859-1 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-03/txt/msg00935.txt.bz2 uClibc syscall() is macro which modifies stack before syscall instruction, gdb is only looking at function prologue and misses the stack modification made in syscall(). Because of this unwind doesn't work. Attached is a patch, which is looking at actual $pc and $pc-4, and in case of syscall it modifies $sp, so mip32_scan_prologue finds correct values. Description of bug is also available here: http://www.listware.net/201003/gnu-gdb/26893.html 2010-03-27 Jan Stancek * mips-tdep.c: fix stack unwind through uClibc syscall() on mips --- cut --- --- mips-tdep.c.orig 2010-03-27 17:04:57.000000000 +0100 +++ mips-tdep.c 2010-03-27 18:47:46.000000000 +0100 @@ -1895,6 +1895,44 @@ reset_saved_regs (struct gdbarch *gdbarc } } +/* + * fix the $sp by looking around actual $pc + * Currently this handles only uClibc syscalls, + * which adjust $sp before syscall itsels + */ +int mips32_get_sp_adjustment(struct frame_info *this_frame, CORE_ADDR start_pc) +{ + CORE_ADDR pc = get_frame_address_in_block (this_frame); + struct gdbarch *gdbarch = get_frame_arch (this_frame); + unsigned long inst, high_word, low_word, ret; + int reg; + + inst = (unsigned long) mips_fetch_instruction (gdbarch, pc); + + ret = 0; + high_word = (inst >> 16) & 0xffff; + low_word = inst & 0xffff; + reg = high_word & 0x1f; + + if (high_word == 0x27bd /* addiu $sp,$sp,-i */ + || high_word == 0x23bd /* addi $sp,$sp,-i */ + || high_word == 0x67bd) /* daddiu $sp,$sp,-i */ + { + if ( reg == MIPS_SP_REGNUM + && (low_word & 0x8000) == 0 /* positive stack adjustment */ + && (pc-4) > start_pc ) + { + pc = pc - 4; + inst = (unsigned long) mips_fetch_instruction (gdbarch, pc); + if (inst==0x0000000c) /* syscall */ + { + ret = low_word; + } + } + } + return ret; +} + /* Analyze the function prologue from START_PC to LIMIT_PC. Builds the associated FRAME_CACHE if not null. Return the address of the first instruction past the prologue. */ @@ -1920,9 +1958,12 @@ mips32_scan_prologue (struct gdbarch *gd /* Can be called when there's no process, and hence when there's no THIS_FRAME. */ if (this_frame != NULL) - sp = get_frame_register_signed (this_frame, - gdbarch_num_regs (gdbarch) - + MIPS_SP_REGNUM); + { + sp = get_frame_register_signed (this_frame, + gdbarch_num_regs (gdbarch) + + MIPS_SP_REGNUM); + sp += mips32_get_sp_adjustment(this_frame, start_pc); + } else sp = 0;