This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]