ARM: stricter __stack_chk_guard check during prologue analysis
authorJoel Brobecker <brobecker@adacore.com>
Thu, 23 Oct 2014 15:25:20 +0000 (08:25 -0700)
committerJoel Brobecker <brobecker@adacore.com>
Wed, 29 Oct 2014 13:10:24 +0000 (06:10 -0700)
We are trying to insert a breakpoint on line 4 for the following
Ada code.

  3 procedure STR is
  4    XX : String (1 .. Blocks.Sz) := (others => 'X'); -- STOP
  5    K : Integer;
  6 begin
  7    K := 13;

The code generated on ARM (-march=armv7-m) starts like this:

    (gdb) disass str'address
    Dump of assembler code for function _ada_str:
       --# Line str.adb:3
       0x08000014 <+0>:     push    {r4, r7, lr}
       0x08000016 <+2>:     sub     sp, #28
       0x08000018 <+4>:     add     r7, sp, #0
       0x0800001a <+6>:     mov     r3, sp
       0x0800001c <+8>:     mov     r4, r3
       --# Line str.adb:4
       0x0800001e <+10>:    ldr     r3, [pc, #84]   ; (0x8000074 <_ada_str+96>)
       0x08000020 <+12>:    ldr     r3, [r3, #0]
       0x08000022 <+14>:    str     r3, [r7, #20]
       0x08000024 <+16>:    ldr     r3, [r7, #20]
       [...]

When computing the address related to str.adb:4, GDB correctly
resolves it to 0x0800001e first, but then considers the next
3 instructions as being part of the prologue because it thinks
they are part of stack-protector code. As a result, instead
of inserting the breakpoint at line 4, it skips those instruction
and consequently the rest of the instructions until the start
of the next line, which his line 7.

The stack-protector code is expected to start like this...

        ldr     Rn, .Label
        ....
        .Lable:
        .word   __stack_chk_guard

... but the implementation actually accepts a sequence where
the ldr location points to an address for which there is no symbol.
It only aborts if the address points to a symbol which is not
__stack_chk_guard.

Since the __stack_chk_guard symbol is always expected to exist
when used (it lives in .dynsym), this patch fixes the issue by
requiring that the ldr gets the address of the __stack_chk_guard
symbol. If the address could not be resolved, then it rejects
the sequence as being stack-protector code.

gdb/ChangeLog:

        * arm-tdep.c (arm_skip_stack_protector): Return early if
        address loaded by first "ldr" instruction does not have
        a corresponding minimal symbol.  Update comment.

Tested on arm-eabi using AdaCore's testsuite.
Tested on arm-linux-gnueabi by Yao as well.

gdb/ChangeLog
gdb/arm-tdep.c

index 708b78b16843f8be9cf33a1993aac533a5d1be5f..676793106721281de6635222b2154d9fb879f945 100644 (file)
@@ -1,3 +1,9 @@
+2014-10-29  Joel Brobecker  <brobecker@adacore.com>
+
+       * arm-tdep.c (arm_skip_stack_protector): Return early if
+       address loaded by first "ldr" instruction does not have
+       a corresponding minimal symbol.  Update comment.
+
 2014-10-29  Yao Qi  <yao@codesourcery.com>
 
        * arm-tdep.c (arm_analyze_load_stack_chk_guard): Compute the
index 699254bd3b2ffb75efee703cbddcd4eb00db3ad6..43520cc23a304aad64eb73f5dd724792243aa8fd 100644 (file)
@@ -1311,11 +1311,10 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch)
     return pc;
 
   stack_chk_guard = lookup_minimal_symbol_by_pc (addr);
-  /* If name of symbol doesn't start with '__stack_chk_guard', this
-     instruction sequence is not for stack protector.  If symbol is
-     removed, we conservatively think this sequence is for stack protector.  */
-  if (stack_chk_guard.minsym
-      && strncmp (MSYMBOL_LINKAGE_NAME (stack_chk_guard.minsym),
+  /* ADDR must correspond to a symbol whose name is __stack_chk_guard.
+     Otherwise, this sequence cannot be for stack protector.  */
+  if (stack_chk_guard.minsym == NULL
+      || strncmp (MSYMBOL_LINKAGE_NAME (stack_chk_guard.minsym),
                  "__stack_chk_guard",
                  strlen ("__stack_chk_guard")) != 0)
    return pc;