]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Rejigger calling conventions for dwarf_frame_{cfa,register}.
authorRoland McGrath <roland@redhat.com>
Wed, 22 Jul 2009 20:55:50 +0000 (13:55 -0700)
committerRoland McGrath <roland@redhat.com>
Wed, 22 Jul 2009 20:56:32 +0000 (13:56 -0700)
libdw/ChangeLog
libdw/dwarf_frame_cfa.c
libdw/dwarf_frame_register.c
libdw/dwarf_getlocation.c
libdw/libdw.h
libdw/libdwP.h
tests/ChangeLog
tests/addrcfi.c

index 1b19e9fc5835912453c5e701dfa4eb8c7c87abf5..76663eebf8f41a833b305c99e2610182ef8c2a23 100644 (file)
@@ -1,3 +1,19 @@
+2009-07-22  Roland McGrath  <roland@redhat.com>
+
+       * dwarf_frame_cfa.c: Change calling convention.
+       * libdw.h: Update decl.
+
+       * dwarf_frame_register.c: Change calling/return-value convention for
+       value-only results and undefined/same_value.
+       * libdw.h: Update decl.
+
+       * dwarf_getlocation.c (__libdw_intern_expression): Take new bool
+       argument, append DW_OP_stack_value if set.  Don't take NOPS argument,
+       return that value instead.
+       (getlocation): Update caller.
+       * dwarf_frame_cfa.c: Likewise.
+       * libdwP.h: Update decl.
+
 2009-07-21  Roland McGrath  <roland@redhat.com>
 
        * dwarf_getsrc_file.c: Ignore a CU that just has no DW_AT_stmt_list.
index ccd7702fc67aeab86a33c8785a51d64d392fa17e..d1c57108f52213b7892a4d0c1fa1a538f56e384a 100644 (file)
 #include <stdlib.h>
 
 int
-dwarf_frame_cfa (fs, ops)
+dwarf_frame_cfa (fs, ops, nops)
      Dwarf_Frame *fs;
      Dwarf_Op **ops;
+     size_t *nops;
 {
   /* Maybe there was a previous error.  */
   if (fs == NULL)
     return -1;
 
+  int result = 0;
   switch (fs->cfa_rule)
     {
     case cfa_undefined:
       *ops = NULL;
-      return 0;
+      *nops = 0;
+      break;
 
     case cfa_offset:
       /* The Dwarf_Op was already fully initialized by execute_cfi.  */
       *ops = &fs->cfa_data.offset;
-      return 1;
+      *nops = 1;
+      break;
 
     case cfa_expr:
-      {
-       unsigned int address_size = (fs->cache->e_ident[EI_CLASS] == ELFCLASS32
-                                    ? 4 : 8);
-       size_t nops;
-
-       /* Parse the expression into internal form.  */
-       int result = __libdw_intern_expression (NULL,
-                                               fs->cache->other_byte_order,
-                                               address_size,
-                                               &fs->cache->expr_tree,
-                                               &fs->cfa_data.expr,
-                                               ops, &nops,
-                                               IDX_debug_frame);
-       return result ?: (int) nops;
-      }
+      /* Parse the expression into internal form.  */
+      result = __libdw_intern_expression
+       (NULL, fs->cache->other_byte_order,
+        fs->cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8,
+        &fs->cache->expr_tree, &fs->cfa_data.expr, false,
+        ops, nops, IDX_debug_frame);
+      break;
 
     default:
       abort ();
     }
 
-  /*NOTREACHED*/
-  return -1;
+  return result;
 }
index 231459a6e5fbbf49e61a87794471f8db41e58643..3d232e95bf16fcb84ca03d707ff730d5755c6e0f 100644 (file)
@@ -58,7 +58,7 @@ int
 dwarf_frame_register (fs, regno, ops_mem, ops, nops)
      Dwarf_Frame *fs;
      int regno;
-     Dwarf_Op ops_mem[2];
+     Dwarf_Op ops_mem[3];
      Dwarf_Op **ops;
      size_t *nops;
 {
@@ -72,7 +72,8 @@ dwarf_frame_register (fs, regno, ops_mem, ops, nops)
       return -1;
     }
 
-  int result = 0;              /* A location, not a value.  */
+  *ops = ops_mem;
+  *nops = 0;
 
   if (unlikely ((size_t) regno >= fs->nregs))
     goto default_rule;
@@ -89,35 +90,32 @@ dwarf_frame_register (fs, regno, ops_mem, ops, nops)
       /*FALLTHROUGH*/
     case reg_undefined:
       /* The value is known to be unavailable.  */
-      result = 1;
-      /*FALLTHROUGH*/
+      break;
+
     case reg_same_value:
     same_value:
       /* The location is not known here, but the caller might know it.  */
       *ops = NULL;
-      *nops = 0;
       break;
 
-    case reg_val_offset:
-      result = 1;              /* A value, not a location.  */
-      /*FALLTHROUGH*/
     case reg_offset:
-      ops_mem[0] = (Dwarf_Op) { .atom = DW_OP_call_frame_cfa };
-      ops_mem[1] = (Dwarf_Op) { .atom = DW_OP_plus_uconst,
-                               .number = reg->value };
+    case reg_val_offset:
+      ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_call_frame_cfa };
+      if (reg->value != 0)
+       ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_plus_uconst,
+                                         .number = reg->value };
+      if (reg->rule == reg_val_offset)
+       /* A value, not a location.  */
+       ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_stack_value };
       *ops = ops_mem;
-      *nops = reg->value == 0 ? 1 : 2;
       break;
 
     case reg_register:
-      ops_mem[0] = (Dwarf_Op) { .atom = DW_OP_regx, .number = reg->value };
-      *ops = ops_mem;
-      *nops = 1;
+      ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_regx,
+                                       .number = reg->value };
       break;
 
     case reg_val_expression:
-      result = 1;              /* A value, not a location.  */
-      /*FALLTHROUGH*/
     case reg_expression:
       {
        unsigned int address_size = (fs->cache->e_ident[EI_CLASS] == ELFCLASS32
@@ -132,13 +130,13 @@ dwarf_frame_register (fs, regno, ops_mem, ops, nops)
        if (__libdw_intern_expression (NULL,
                                       fs->cache->other_byte_order,
                                       address_size,
-                                      &fs->cache->expr_tree,
-                                      &block, ops, nops,
-                                      IDX_debug_frame) < 0)
-         result = -1;
+                                      &fs->cache->expr_tree, &block,
+                                      reg->rule == reg_val_expression,
+                                      ops, nops, IDX_debug_frame) < 0)
+         return -1;
        break;
       }
     }
 
-  return result;
+  return 0;
 }
index 0ce10837f06deb70556618b1da63c94c2e6b492f..1488203b9ff2c6a07ccf35d8e62d82cede6ea099 100644 (file)
@@ -167,7 +167,7 @@ int
 internal_function
 __libdw_intern_expression (Dwarf *dbg,
                           bool other_byte_order, unsigned int address_size,
-                          void **cache, const Dwarf_Block *block,
+                          void **cache, const Dwarf_Block *block, bool valuep,
                           Dwarf_Op **llbuf, size_t *listlen, int sec_index)
 {
   /* Check whether we already looked at this list.  */
@@ -179,6 +179,12 @@ __libdw_intern_expression (Dwarf *dbg,
       *llbuf = (*found)->loc;
       *listlen = (*found)->nloc;
 
+      if (valuep)
+       {
+         assert (*listlen > 1);
+         assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
+       }
+
       return 0;
     }
 
@@ -358,6 +364,19 @@ __libdw_intern_expression (Dwarf *dbg,
       goto invalid;
     }
 
+  if (valuep)
+    {
+      struct loclist *newloc;
+      newloc = (struct loclist *) alloca (sizeof (struct loclist));
+      newloc->atom = DW_OP_stack_value;
+      newloc->number = 0;
+      newloc->number2 = 0;
+      newloc->offset = data - block->data;
+      newloc->next = loclist;
+      loclist = newloc;
+      ++n;
+    }
+
   /* Allocate the array.  */
   Dwarf_Op *result;
   if (dbg != NULL)
@@ -420,8 +439,8 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
             Dwarf_Op **llbuf, size_t *listlen, int sec_index)
 {
   return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
-                                   cu->address_size, &cu->locs,
-                                   block, llbuf, listlen, sec_index);
+                                   cu->address_size, &cu->locs, block, false,
+                                   llbuf, listlen, sec_index);
 }
 
 int
index 81c2b73e624a671861780027ab02d21cea4ba61d..ec352b4d3ac6a02a03c03e5193b4d7caf8e44d43 100644 (file)
@@ -750,34 +750,36 @@ extern int dwarf_cfi_addrframe (Dwarf_CFI *cache,
 extern int dwarf_frame_info (Dwarf_Frame *frame,
                             Dwarf_Addr *start, Dwarf_Addr *end, bool *signalp);
 
-/* Deliver a DWARF expression that yields the Canonical Frame Address at
-   this frame state.  Returns -1 for errors, or the number of operations
-   stored at *OPS.  That pointer can be used only as long as FRAME is alive
-   and unchanged.  Returns zero if the CFA cannot be determined here.  */
-extern int dwarf_frame_cfa (Dwarf_Frame *frame, Dwarf_Op **ops)
+/* Return a DWARF expression that yields the Canonical Frame Address at
+   this frame state.  Returns -1 for errors, or zero for success, with
+   *NOPS set to the number of operations stored at *OPS.  That pointer
+   can be used only as long as FRAME is alive and unchanged.  *NOPS is
+   zero if the CFA cannot be determined here.  Note that if nonempty,
+   *OPS is a DWARF expression, not a location description--append
+   DW_OP_stack_value to a get a location description for the CFA.  */
+extern int dwarf_frame_cfa (Dwarf_Frame *frame, Dwarf_Op **ops, size_t *nops)
   __nonnull_attribute__ (2);
 
-/* Deliver a DWARF expression that yields the location or value of
-   DWARF register number REGNO in the state described by FRAME.
+/* Deliver a DWARF location description that yields the location or
+   value of DWARF register number REGNO in the state described by FRAME.
 
-   Returns -1 for errors, 0 if REGNO has an accessible location,
-   or 1 if REGNO has only a computable value.  Stores at *NOPS
-   the number of operations in the array stored at *OPS.
-   With return value 0, this is a DWARF location expression.
-   With return value 1, this is a DWARF expression that computes the value.
+   Returns -1 for errors or zero for success, setting *NOPS to the
+   number of operations in the array stored at *OPS.  Note the last
+   operation is DW_OP_stack_value if there is no mutable location but
+   only a computable value.
 
-   Return value 1 with *NOPS zero means CFI says the caller's REGNO is
-   "undefined" here, i.e. it's call-clobbered and cannot be recovered.
+   *NOPS zero with *OPS set to OPS_MEM means CFI says the caller's
+   REGNO is "undefined", i.e. it's call-clobbered and cannot be recovered.
 
-   Return value 0 with *NOPS zero means CFI says the caller's REGNO is
-   "same_value" here, i.e. this frame did not change it; ask the caller
-   frame where to find it.
+   *NOPS zero with *OPS set to a null pointer means CFI says the
+   caller's REGNO is "same_value", i.e. this frame did not change it;
+   ask the caller frame where to find it.
 
    For common simple expressions *OPS is OPS_MEM.  For arbitrary DWARF
    expressions in the CFI, *OPS is an internal pointer that can be used as
    long as the Dwarf_CFI used to create FRAME remains alive.  */
 extern int dwarf_frame_register (Dwarf_Frame *frame, int regno,
-                                Dwarf_Op ops_mem[2],
+                                Dwarf_Op ops_mem[3],
                                 Dwarf_Op **ops, size_t *nops)
   __nonnull_attribute__ (3, 4, 5);
 
index 5c39b585e7627ffe61cca121ee87e4f297adf57b..a8f392475051fa9e062d52af95349704e5670028 100644 (file)
@@ -423,9 +423,10 @@ extern int __libdw_intern_expression (Dwarf *dbg,
                                      bool other_byte_order,
                                      unsigned int address_size,
                                      void **cache, const Dwarf_Block *block,
+                                     bool valuep,
                                      Dwarf_Op **llbuf, size_t *listlen,
                                      int sec_index)
-  __nonnull_attribute__ (4, 5, 6, 7) internal_function;
+  __nonnull_attribute__ (4, 5, 7, 8) internal_function;
 
 
 /* Return error code of last failing function call.  This value is kept
index 58eed00577b02b1f9552ea1b5c04d24164556496..87654d605bdccc4cdad15e608a15f3c06f4d0552 100644 (file)
@@ -1,3 +1,7 @@
+2009-07-22  Roland McGrath  <roland@redhat.com>
+
+       * addrcfi.c: Update dwarf_frame_{cfa,register} calling convention.
+
 2009-07-08  Roland McGrath  <roland@redhat.com>
 
        * addrcfi.c: New file.
index 6230621f02c2dc88def6b8ca5d9c1f59afb39e55..2a3db05c16e5ee49347552f41ea657de633f4838 100644 (file)
@@ -125,10 +125,11 @@ handle_cfi (Dwfl *dwfl, const char *which, Dwarf_CFI *cfi,
            ra_regno, signalp ? " (signal frame)" : "");
 
   Dwarf_Op *cfa_ops;
-  int cfa_nops = dwarf_frame_cfa (stuff->frame, &cfa_ops);
+  size_t cfa_nops;
+  result = dwarf_frame_cfa (stuff->frame, &cfa_ops, &cfa_nops);
 
   printf ("\tCFA ");
-  print_detail (cfa_nops < 0 ? -1 : 1, cfa_ops, cfa_nops, stuff->bias);
+  print_detail (result, cfa_ops, cfa_nops, stuff->bias);
 
   (void) dwfl_module_register_names (dwfl_addrmodule (dwfl, pc),
                                     &print_register, stuff);