2005-02-11 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / dwarf2-frame.c
index 7ee18db892a6daf212aa0d1112b3b13bd659bace..cedeaa1f547f42cb3e90106299a763b3321c8714 100644 (file)
@@ -162,7 +162,7 @@ dwarf2_frame_state_alloc_regs (struct dwarf2_frame_state_reg_info *rs,
 static struct dwarf2_frame_state_reg *
 dwarf2_frame_state_copy_regs (struct dwarf2_frame_state_reg_info *rs)
 {
-  size_t size = rs->num_regs * sizeof (struct dwarf2_frame_state_reg_info);
+  size_t size = rs->num_regs * sizeof (struct dwarf2_frame_state_reg);
   struct dwarf2_frame_state_reg *reg;
 
   reg = (struct dwarf2_frame_state_reg *) xmalloc (size);
@@ -227,14 +227,14 @@ static void
 no_get_frame_base (void *baton, unsigned char **start, size_t *length)
 {
   internal_error (__FILE__, __LINE__,
-                 "Support for DW_OP_fbreg is unimplemented");
+                 _("Support for DW_OP_fbreg is unimplemented"));
 }
 
 static CORE_ADDR
 no_get_tls_address (void *baton, CORE_ADDR offset)
 {
   internal_error (__FILE__, __LINE__,
-                 "Support for DW_OP_GNU_push_tls_address is unimplemented");
+                 _("Support for DW_OP_GNU_push_tls_address is unimplemented"));
 }
 
 static CORE_ADDR
@@ -374,8 +374,8 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
 
                if (old_rs == NULL)
                  {
-                   complaint (&symfile_complaints, "\
-bad CFI data; mismatched DW_CFA_restore_state at 0x%s", paddr (fs->pc));
+                   complaint (&symfile_complaints, _("\
+bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc));
                  }
                else
                  {
@@ -426,7 +426,7 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s", paddr (fs->pc));
            case DW_CFA_offset_extended_sf:
              insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
              insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
-             offset += fs->data_align;
+             offset *= fs->data_align;
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET;
              fs->regs.reg[reg].loc.offset = offset;
@@ -451,7 +451,7 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s", paddr (fs->pc));
              break;
 
            default:
-             internal_error (__FILE__, __LINE__, "Unknown CFI encountered.");
+             internal_error (__FILE__, __LINE__, _("Unknown CFI encountered."));
            }
        }
     }
@@ -471,6 +471,10 @@ struct dwarf2_frame_ops
 {
   /* Pre-initialize the register state REG for register REGNUM.  */
   void (*init_reg) (struct gdbarch *, int, struct dwarf2_frame_state_reg *);
+
+  /* Check whether the frame preceding NEXT_FRAME will be a signal
+     trampoline.  */
+  int (*signal_frame_p) (struct gdbarch *, struct frame_info *);
 };
 
 /* Default architecture-specific register state initialization
@@ -547,6 +551,33 @@ dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
 
   ops->init_reg (gdbarch, regnum, reg);
 }
+
+/* Set the architecture-specific signal trampoline recognition
+   function for GDBARCH to SIGNAL_FRAME_P.  */
+
+void
+dwarf2_frame_set_signal_frame_p (struct gdbarch *gdbarch,
+                                int (*signal_frame_p) (struct gdbarch *,
+                                                       struct frame_info *))
+{
+  struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data);
+
+  ops->signal_frame_p = signal_frame_p;
+}
+
+/* Query the architecture-specific signal frame recognizer for
+   NEXT_FRAME.  */
+
+static int
+dwarf2_frame_signal_frame_p (struct gdbarch *gdbarch,
+                            struct frame_info *next_frame)
+{
+  struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data);
+
+  if (ops->signal_frame_p == NULL)
+    return 0;
+  return ops->signal_frame_p (gdbarch, next_frame);
+}
 \f
 
 struct dwarf2_frame_cache
@@ -632,7 +663,7 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
       break;
 
     default:
-      internal_error (__FILE__, __LINE__, "Unknown CFA rule.");
+      internal_error (__FILE__, __LINE__, _("Unknown CFA rule."));
     }
 
   /* Initialize the register state.  */
@@ -674,9 +705,13 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
           table.  We need a way of iterating through all the valid
           DWARF2 register numbers.  */
        if (fs->regs.reg[column].how == DWARF2_FRAME_REG_UNSPECIFIED)
-         complaint (&symfile_complaints,
-                    "Incomplete CFI data; unspecified registers at 0x%s",
-                    paddr (fs->pc));
+         {
+           if (cache->reg[regnum].how == DWARF2_FRAME_REG_UNSPECIFIED)
+             complaint (&symfile_complaints, _("\
+incomplete CFI data; unspecified registers (e.g., %s) at 0x%s"),
+                        gdbarch_register_name (gdbarch, regnum),
+                        paddr_nz (fs->pc));
+         }
        else
          cache->reg[regnum] = fs->regs.reg[column];
       }
@@ -770,9 +805,12 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
       break;
 
     case DWARF2_FRAME_REG_SAVED_REG:
-      regnum = DWARF2_REG_TO_REGNUM (cache->reg[regnum].loc.reg);
-      frame_register_unwind (next_frame, regnum,
-                            optimizedp, lvalp, addrp, realnump, valuep);
+      *optimizedp = 0;
+      *lvalp = lval_register;
+      *addrp = 0;
+      *realnump = DWARF2_REG_TO_REGNUM (cache->reg[regnum].loc.reg);
+      if (valuep)
+       frame_unwind_register (next_frame, (*realnump), valuep);
       break;
 
     case DWARF2_FRAME_REG_SAVED_EXP:
@@ -797,13 +835,21 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
         "undefined").  Code above issues a complaint about this.
         Here just fudge the books, assume GCC, and that the value is
         more inner on the stack.  */
-      frame_register_unwind (next_frame, regnum,
-                            optimizedp, lvalp, addrp, realnump, valuep);
+      *optimizedp = 0;
+      *lvalp = lval_register;
+      *addrp = 0;
+      *realnump = regnum;
+      if (valuep)
+       frame_unwind_register (next_frame, (*realnump), valuep);
       break;
 
     case DWARF2_FRAME_REG_SAME_VALUE:
-      frame_register_unwind (next_frame, regnum,
-                            optimizedp, lvalp, addrp, realnump, valuep);
+      *optimizedp = 0;
+      *lvalp = lval_register;
+      *addrp = 0;
+      *realnump = regnum;
+      if (valuep)
+       frame_unwind_register (next_frame, (*realnump), valuep);
       break;
 
     case DWARF2_FRAME_REG_CFA:
@@ -819,7 +865,7 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
       break;
 
     default:
-      internal_error (__FILE__, __LINE__, "Unknown register rule.");
+      internal_error (__FILE__, __LINE__, _("Unknown register rule."));
     }
 }
 
@@ -830,6 +876,13 @@ static const struct frame_unwind dwarf2_frame_unwind =
   dwarf2_frame_prev_register
 };
 
+static const struct frame_unwind dwarf2_signal_frame_unwind =
+{
+  SIGTRAMP_FRAME,
+  dwarf2_frame_this_id,
+  dwarf2_frame_prev_register
+};
+
 const struct frame_unwind *
 dwarf2_frame_sniffer (struct frame_info *next_frame)
 {
@@ -837,10 +890,18 @@ dwarf2_frame_sniffer (struct frame_info *next_frame)
      function.  frame_pc_unwind(), for a no-return next function, can
      end up returning something past the end of this function's body.  */
   CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame);
-  if (dwarf2_frame_find_fde (&block_addr))
-    return &dwarf2_frame_unwind;
+  if (!dwarf2_frame_find_fde (&block_addr))
+    return NULL;
 
-  return NULL;
+  /* On some targets, signal trampolines may have unwind information.
+     We need to recognize them so that we set the frame type
+     correctly.  */
+
+  if (dwarf2_frame_signal_frame_p (get_frame_arch (next_frame),
+                                  next_frame))
+    return &dwarf2_signal_frame_unwind;
+
+  return &dwarf2_frame_unwind;
 }
 \f
 
@@ -890,9 +951,6 @@ struct comp_unit
   /* Linked list of CIEs for this object.  */
   struct dwarf2_cie *cie;
 
-  /* Address size for this unit - from unit header.  */
-  unsigned char addr_size;
-
   /* Pointer to the .debug_frame section loaded into memory.  */
   char *dwarf_frame_buffer;
 
@@ -1032,7 +1090,7 @@ encoding_for_size (unsigned int size)
     case 8:
       return DW_EH_PE_udata8;
     default:
-      internal_error (__FILE__, __LINE__, "Unsupported address size");
+      internal_error (__FILE__, __LINE__, _("Unsupported address size"));
     }
 }
 
@@ -1053,13 +1111,13 @@ size_of_encoded_value (unsigned char encoding)
     case DW_EH_PE_udata8:
       return 8;
     default:
-      internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding");
+      internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding"));
     }
 }
 
 static CORE_ADDR
 read_encoded_value (struct comp_unit *unit, unsigned char encoding,
-                   char *buf, unsigned int *bytes_read_ptr)
+                   unsigned char *buf, unsigned int *bytes_read_ptr)
 {
   int ptr_len = size_of_encoded_value (DW_EH_PE_absptr);
   ptrdiff_t offset;
@@ -1069,7 +1127,7 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding,
      FDE's.  */
   if (encoding & DW_EH_PE_indirect)
     internal_error (__FILE__, __LINE__, 
-                   "Unsupported encoding: DW_EH_PE_indirect");
+                   _("Unsupported encoding: DW_EH_PE_indirect"));
 
   *bytes_read_ptr = 0;
 
@@ -1080,7 +1138,7 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding,
       break;
     case DW_EH_PE_pcrel:
       base = bfd_get_section_vma (unit->bfd, unit->dwarf_frame_section);
-      base += (buf - unit->dwarf_frame_buffer);
+      base += ((char *) buf - unit->dwarf_frame_buffer);
       break;
     case DW_EH_PE_datarel:
       base = unit->dbase;
@@ -1098,7 +1156,7 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding,
       break;
     case DW_EH_PE_aligned:
       base = 0;
-      offset = buf - unit->dwarf_frame_buffer;
+      offset = (char *) buf - unit->dwarf_frame_buffer;
       if ((offset % ptr_len) != 0)
        {
          *bytes_read_ptr = ptr_len - (offset % ptr_len);
@@ -1106,14 +1164,21 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding,
        }
       break;
     default:
-      internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding");
+      internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding"));
     }
 
-  if ((encoding & 0x0f) == 0x00)
+  if ((encoding & 0x07) == 0x00)
     encoding |= encoding_for_size (ptr_len);
 
   switch (encoding & 0x0f)
     {
+    case DW_EH_PE_uleb128:
+      {
+       ULONGEST value;
+       unsigned char *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
+       *bytes_read_ptr += read_uleb128 (buf, end_buf, &value) - buf;
+       return base + value;
+      }
     case DW_EH_PE_udata2:
       *bytes_read_ptr += 2;
       return (base + bfd_get_16 (unit->abfd, (bfd_byte *) buf));
@@ -1123,6 +1188,13 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding,
     case DW_EH_PE_udata8:
       *bytes_read_ptr += 8;
       return (base + bfd_get_64 (unit->abfd, (bfd_byte *) buf));
+    case DW_EH_PE_sleb128:
+      {
+       LONGEST value;
+       char *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
+       *bytes_read_ptr += read_sleb128 (buf, end_buf, &value) - buf;
+       return base + value;
+      }
     case DW_EH_PE_sdata2:
       *bytes_read_ptr += 2;
       return (base + bfd_get_signed_16 (unit->abfd, (bfd_byte *) buf));
@@ -1133,7 +1205,7 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding,
       *bytes_read_ptr += 8;
       return (base + bfd_get_signed_64 (unit->abfd, (bfd_byte *) buf));
     default:
-      internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding");
+      internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding"));
     }
 }
 \f
@@ -1284,9 +1356,8 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p)
       cie->cie_pointer = cie_pointer;
 
       /* The encoding for FDE's in a normal .debug_frame section
-         depends on the target address size as specified in the
-         Compilation Unit Header.  */
-      cie->encoding = encoding_for_size (unit->addr_size);
+         depends on the target address size.  */
+      cie->encoding = DW_EH_PE_absptr;
 
       /* Check version number.  */
       cie_version = read_1_byte (unit->abfd, buf);
@@ -1359,8 +1430,10 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p)
          /* "P" indicates a personality routine in the CIE augmentation.  */
          else if (*augmentation == 'P')
            {
-             /* Skip.  */
-             buf += size_of_encoded_value (*buf++);
+             /* Skip.  Avoid indirection since we throw away the result.  */
+             unsigned char encoding = (*buf++) & ~DW_EH_PE_indirect;
+             read_encoded_value (unit, encoding, buf, &bytes_read);
+             buf += bytes_read;
              augmentation++;
            }
 
@@ -1514,21 +1587,21 @@ decode_frame_entry (struct comp_unit *unit, char *start, int eh_frame_p)
 
     case ALIGN4:
       complaint (&symfile_complaints,
-                "Corrupt data in %s:%s; align 4 workaround apparently succeeded",
+                _("Corrupt data in %s:%s; align 4 workaround apparently succeeded"),
                 unit->dwarf_frame_section->owner->filename,
                 unit->dwarf_frame_section->name);
       break;
 
     case ALIGN8:
       complaint (&symfile_complaints,
-                "Corrupt data in %s:%s; align 8 workaround apparently succeeded",
+                _("Corrupt data in %s:%s; align 8 workaround apparently succeeded"),
                 unit->dwarf_frame_section->owner->filename,
                 unit->dwarf_frame_section->name);
       break;
 
     default:
       complaint (&symfile_complaints,
-                "Corrupt data in %s:%s",
+                _("Corrupt data in %s:%s"),
                 unit->dwarf_frame_section->owner->filename,
                 unit->dwarf_frame_section->name);
       break;
@@ -1557,7 +1630,6 @@ dwarf2_build_frame_info (struct objfile *objfile)
   /* Build a minimal decoding of the DWARF2 compilation unit.  */
   unit.abfd = objfile->obfd;
   unit.objfile = objfile;
-  unit.addr_size = objfile->obfd->arch_info->bits_per_address / 8;
   unit.dbase = 0;
   unit.tbase = 0;
 
This page took 0.03649 seconds and 4 git commands to generate.