This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] MIPS: Fix LUI/ADDIU sign-extension in MIPS16 trampolines
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: <gdb-patches at sourceware dot org>
- Date: Mon, 5 Dec 2011 13:31:03 +0000
- Subject: [PATCH] MIPS: Fix LUI/ADDIU sign-extension in MIPS16 trampolines
Hi,
The immediate operands to MIPS32 LUI and ADDIU instructions are
sign-extended values. These instructions are used in MIPS16 trampolines
and our instruction decoder extracts the immediate fields of the
respective instruction words as if they were zero-extended instead.
The fix below has been regression tested with the mips-sde-elf target
(MIPS16 multilib) with no changes to results, which essentially means the
test suite does not cover the case. However I think the changes are
simple enough to qualify as obviously correct.
OK to apply?
2011-12-05 Maciej W. Rozycki <macro@codesourcery.com>
gdb/
* mips-tdep.c (mips_skip_mips16_trampoline_code): Sign-extend
address chunks retrieved from decoded lui/addiu pairs.
Maciej
gdb-mips16-skip-trampoline.diff
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.c 2011-12-05 13:14:52.575561147 +0000
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c 2011-12-05 13:15:54.245561045 +0000
@@ -5667,7 +5667,6 @@ mips_skip_mips16_trampoline_code (struct
address from those two instructions. */
CORE_ADDR target_pc = get_frame_register_signed (frame, 2);
- ULONGEST inst;
int i;
/* See if the name of the target function is __fn_stub_*. */
@@ -5684,11 +5683,15 @@ mips_skip_mips16_trampoline_code (struct
instructions. FIXME. */
for (i = 0, pc = 0; i < 20; i++, target_pc += MIPS_INSN32_SIZE)
{
- inst = mips_fetch_instruction (gdbarch, target_pc);
+ ULONGEST inst = mips_fetch_instruction (gdbarch, target_pc);
+ CORE_ADDR addr = inst;
+
if ((inst & 0xffff0000) == 0x3c010000) /* lui $at */
- pc = (inst << 16) & 0xffff0000; /* high word */
+ pc = (((addr & 0xffff) ^ 0x8000) - 0x8000) << 16;
+ /* high word */
else if ((inst & 0xffff0000) == 0x24210000) /* addiu $at */
- return pc | (inst & 0xffff); /* low word */
+ return pc + ((addr & 0xffff) ^ 0x8000) - 0x8000;
+ /* low word */
}
/* Couldn't find the lui/addui pair, so return stub address. */