Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA/powerpc] Add handling for stack-check sequences in prologue
@ 2008-09-01 16:47 Jerome Guitton
  2008-09-02 20:59 ` Joel Brobecker
  0 siblings, 1 reply; 3+ messages in thread
From: Jerome Guitton @ 2008-09-01 16:47 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1228 bytes --]

Hello,

On PPC targets, the debugger fails to unwind past some stack-check
sequences. The attached patch should fix that. I have double-checked
with Eric Botcazou to make sure that all possible cases are
caught... Roughly:

1) A small number of probes:
         stw 0, -<some immediate>(1) repeated any (small) number of times...

2) A probing loop:
         addi 12,1,-<some immediate>
         lis 0,-<some immediate>
         [possibly ori 0,0,<some immediate>]
         add 0,12,0
         cmpw 0,12,0
         beq 0,<disp>
         addi 12,12,-<some immediate>
         stw 0,0(12)
         b <disp>
         [possibly one last probe: stw 0,<some immediate>(12)]

3) No probe; instead, a comparizon between the stack size
     limit (saved in a run-time global variable) and the current stack
     pointer:

        addi 0,1,-<some immediate>
        lis 12,__gnat_stack_limit@ha
        lwz 12,__gnat_stack_limit@l(12)
        twllt 0,12


2008-09-01  Jerome Guitton  <guitton@adacore.com>

	* rs6000-tdep.c (rs6000_fetch_instruction)
	(rs6000_skip_stack_check): New functions.
	(skip_prologue): Skip stack check sequence.

Tested on AIX, no regression. I'll post my testcases in a minute. 
OK to apply?

Thanks,
- Jerome

[-- Attachment #2: stack-check.diff --]
[-- Type: text/x-diff, Size: 5682 bytes --]

Index: rs6000-tdep.c
===================================================================
--- rs6000-tdep.c	(revision 134839)
+++ rs6000-tdep.c	(working copy)
@@ -1374,6 +1374,191 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int ins
   return 0;
 }
 
+static unsigned long
+rs6000_fetch_instruction (const CORE_ADDR pc)
+{
+  gdb_byte buf[4];
+  unsigned long op;
+
+  /* Fetch the instruction and convert it to an integer.  */
+  if (target_read_memory (pc, buf, 4))
+    return 0;
+  op = extract_unsigned_integer (buf, 4);
+
+  return op;
+}
+
+/* GCC generates several well-known sequences of instructions at the begining
+   of each function prologue when compiling with -fstack-check.  If one of
+   such sequences starts at START_PC, then return the address of the
+   instruction immediately past this sequence.  Otherwise, return START_PC.  */
+   
+static CORE_ADDR
+rs6000_skip_stack_check (const CORE_ADDR start_pc)
+{
+  CORE_ADDR pc = start_pc;
+  unsigned long op = rs6000_fetch_instruction (pc);
+
+  /* First possible sequence: A small number of probes.
+         stw 0, -<some immediate>(1)
+         [repeat this instruction any (small) number of times]
+  */
+  
+  if ((op & 0xffff0000) == 0x90010000)
+    {
+      while ((op & 0xffff0000) == 0x90010000)
+        {
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (pc);
+        }
+      return pc;
+    }
+    
+  /* Second sequence: A probing loop.
+         addi 12,1,-<some immediate>
+         lis 0,-<some immediate>
+         [possibly ori 0,0,<some immediate>]
+         add 0,12,0
+         cmpw 0,12,0
+         beq 0,<disp>
+         addi 12,12,-<some immediate>
+         stw 0,0(12)
+         b <disp>
+         [possibly one last probe: stw 0,<some immediate>(12)]
+  */
+
+  while (1)
+    {
+      /* addi 12,1,-<some immediate> */
+      if ((op & 0xffff0000) != 0x39810000)
+        break;
+
+      /* lis 0,-<some immediate> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if ((op & 0xffff0000) != 0x3c000000)
+        break;
+      
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      /* [possibly ori 0,0,<some immediate>] */
+      if ((op & 0xffff0000) == 0x60000000)
+        {
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (pc);
+        }
+      /* add 0,12,0 */
+      if (op != 0x7c0c0214)
+        break;
+
+      /* cmpw 0,12,0 */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if (op != 0x7c0c0000)
+        break;
+      
+      /* beq 0,<disp> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if ((op & 0xff9f0001) != 0x41820000)
+        break;
+
+      /* addi 12,12,-<some immediate> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if ((op & 0xffff0000) != 0x398c0000)
+        break;
+
+      /* stw 0,0(12) */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if (op != 0x900c0000)
+        break;
+
+      /* b <disp> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if ((op & 0xfc000001) != 0x48000000)
+        break;
+
+      
+      /* [possibly one last probe: stw 0,<some immediate>(12)] */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if ((op & 0xffff0000) == 0x900c0000)
+        {
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (pc);
+        }
+
+      /* We found a valid stack-check sequence, return the new PC.  */
+      return pc;
+    }
+
+  /* Third sequence: No probe; instead, a comparizon between the stack size
+     limit (saved in a run-time global variable) and the current stack
+     pointer:
+
+        addi 0,1,-<some immediate>
+        lis 12,__gnat_stack_limit@ha
+        lwz 12,__gnat_stack_limit@l(12)
+        twllt 0,12
+
+     or, with a small variant in the case of a bigger stack frame:
+        addis 0,1,<some immediate>
+        addic 0,0,-<some immediate>
+        lis 12,__gnat_stack_limit@ha
+        lwz 12,__gnat_stack_limit@l(12)
+        twllt 0,12
+  */
+  while (1)
+    {
+      /* addi 0,1,-<some immediate> */
+      if ((op & 0xffff0000) != 0x38010000)
+        {
+          /* small stack frame variant not recognized; try the
+             big stack frame variant: */ 
+
+          /* addis 0,1,<some immediate> */
+          if ((op & 0xffff0000) != 0x3c010000)
+            break;
+
+          /* addic 0,0,-<some immediate> */
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (pc);
+          if ((op & 0xffff0000) != 0x30000000)
+            break;
+        }
+
+      
+      /* lis 12,<some immediate> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if ((op & 0xffff0000) != 0x3d800000)
+        break;
+      
+      /* lwz 12,<some immediate>(12) */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if ((op & 0xffff0000) != 0x818c0000)
+        break;
+      
+      /* twllt 0,12 */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (pc);
+      if ((op & 0xfffffffe) != 0x7c406008)
+        break;
+      
+      /* We found a valid stack-check sequence, return the new PC.  */
+      return pc;
+    }
+
+
+  /* No stack check code in our prologue, return the start_pc.  */
+  return start_pc;
+}
+
+
 /* return pc value after skipping a function prologue and also return
    information about a function frame.
 
@@ -1433,6 +1618,10 @@ skip_prologue (struct gdbarch *gdbarch, 
   fdata->nosavedpc = 1;
   fdata->lr_register = -1;
 
+  pc = rs6000_skip_stack_check (pc);
+  if (pc >= lim_pc)
+    pc = lim_pc;
+
   for (;; pc += 4)
     {
       /* Sometimes it isn't clear if an instruction is a prologue

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFA/powerpc] Add handling for stack-check sequences in prologue
  2008-09-01 16:47 [RFA/powerpc] Add handling for stack-check sequences in prologue Jerome Guitton
@ 2008-09-02 20:59 ` Joel Brobecker
  2008-09-08 16:21   ` Jerome Guitton
  0 siblings, 1 reply; 3+ messages in thread
From: Joel Brobecker @ 2008-09-02 20:59 UTC (permalink / raw)
  To: Jerome Guitton; +Cc: gdb-patches

> 2008-09-01  Jerome Guitton  <guitton@adacore.com>
> 
> 	* rs6000-tdep.c (rs6000_fetch_instruction)
> 	(rs6000_skip_stack_check): New functions.
> 	(skip_prologue): Skip stack check sequence.

I just reviewed the patch, and it looks OK to me. I think there are
other maintainers who are also interested in powerpc, so give it a
few more days (say until Fri) to see if they might want to comment
and then commit if no objection.

-- 
Joel


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFA/powerpc] Add handling for stack-check sequences in  prologue
  2008-09-02 20:59 ` Joel Brobecker
@ 2008-09-08 16:21   ` Jerome Guitton
  0 siblings, 0 replies; 3+ messages in thread
From: Jerome Guitton @ 2008-09-08 16:21 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

Joel Brobecker (brobecker@adacore.com):

> > 2008-09-01  Jerome Guitton  <guitton@adacore.com>
> > 
> > 	* rs6000-tdep.c (rs6000_fetch_instruction)
> > 	(rs6000_skip_stack_check): New functions.
> > 	(skip_prologue): Skip stack check sequence.
> 
> I just reviewed the patch, and it looks OK to me. I think there are
> other maintainers who are also interested in powerpc, so give it a
> few more days (say until Fri) to see if they might want to comment
> and then commit if no objection.

Time's up :)
Now committed.
Thanks,
Jerome


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-09-08 16:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-09-01 16:47 [RFA/powerpc] Add handling for stack-check sequences in prologue Jerome Guitton
2008-09-02 20:59 ` Joel Brobecker
2008-09-08 16:21   ` Jerome Guitton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox