libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] [PATCH] Account for multiple CFA for args_size


From: Saleem Abdulrasool
Subject: [Libunwind-devel] [PATCH] Account for multiple CFA for args_size
Date: Wed, 18 Jan 2017 13:56:19 -0800

It is possible to have multiple CFA_args_size adjustments for a single
frame.  If the CFA_args_size adjustment is immediately following the
return from a function which can raise an exception, it is possible to
incorrectly adjust the stack pointer.  Consider the following:

  ...
  .cfi_escape 0x2e, 0x00
  call f
.Ltmp:
  .cfi_escape 0x2e, 0x10
  lea address@hidden(%ebx), %eax
  ...

Because we process the CFI program up to and *INCLUDING* IP, where the
IP is the RA, we would process the associated DW_CFA_GNU_args_size for
the post-call instruction.  The result would be a DW_CFA_GNU_args_size
of 0x10 rather than 0x00, resulting in an incorrect stack adjustment.
Handle this by processing the CFI operation but not adjusting the state
record unless we are below the current IP.
---
 src/dwarf/Gparser.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c
index 1831a58..3f16189 100644
--- a/src/dwarf/Gparser.c
+++ b/src/dwarf/Gparser.c
@@ -356,8 +356,11 @@ run_cfi_program (struct dwarf_cursor *c, 
dwarf_state_record_t *sr,
         case DW_CFA_GNU_args_size:
           if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
             goto fail;
-          sr->args_size = val;
-          Debug (15, "CFA_GNU_args_size %lu\n", (long) val);
+          if (curr_ip < ip)
+            {
+              sr->args_size = val;
+              Debug (15, "CFA_GNU_args_size %lu\n", (long) val);
+            }
           break;
 
         case DW_CFA_GNU_negative_offset_extended:
-- 
2.11.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]