* dwarf2-frame.c (struct dwarf2_cie): Make initial_instructions, end
authorDoug Evans <dje@google.com>
Tue, 22 May 2012 18:45:22 +0000 (18:45 +0000)
committerDoug Evans <dje@google.com>
Tue, 22 May 2012 18:45:22 +0000 (18:45 +0000)
"const gdb_byte *".
(struct dwarf2_fde): Make instructions, end "const gdb_byte *".
(execute_cfa_program): Update to match API of leb128 functions.
(read_1_byte, read_4_bytes, read_8_bytes): Make buf parameter
"const gdb_byte *".
(read_unsigned_leb128, read_signed_leb128): Delete.
(read_initial_length): Change type of buf argument to
"const gdb_byte *".
(read_encoded_value): Update to match API of leb128 functions.
(decode_frame_entry): Change result to "const gdb_byte *", and
similarly for "start" parameter.
(decode_frame_entry_1): Ditto.  Use new leb128 reader functions.
(dwarf2_build_frame_info): Change local frame_ptr to
"const gdb_byte *".
* dwarf2expr.c (safe_read_uleb128, safe_read_sleb128): Replaces
read_uleb128, read_sleb128.  All callers updated.
(safe_skip_leb128): New function.
(dwarf_block_to_dwarf_reg): Update to match API of leb128 functions.
Call gdb_read_uleb128, gdb_skip_leb128 instead of read_uleb128.
(dwarf_block_to_dwarf_reg_deref): Update to match API of leb128
functions.  Call gdb_read_uleb128, gdb_read_sleb128 instead of
read_uleb128, read_sleb128.
(dwarf_block_to_fb_offset, dwarf_block_to_sp_offset): Ditto.
(execute_stack_op): Update to match API of leb128 functions.
* dwarf2expr.h: #include "leb128.h".
(read_uleb128, read_sleb128): Delete.
(gdb_read_uleb128, gdb_read_sleb128, gdb_skip_leb128): New functions.
(safe_read_uleb128, safe_read_sleb128, safe_skip_leb128): Declare.
* dwarf2loc.c (debug_loc_kind): New enum.
(decode_debug_loc_addresses): New function.
(decode_debug_loc_dwo_addresses): New function.
(dwarf2_find_location_expression): Rewrite.
(dwarf2_compile_expr_to_ax): Update to match API of leb128 functions.
(locexpr_describe_location_piece): Ditto.
(disassemble_dwarf_expression): Ditto.
(locexpr_describe_location_1): Ditto.
(loclist_describe_location): Rewrite.
* dwarf2loc.h (dwarf2_loclist_baton): New member "from_dwo".
* dwarf2read.c (die_reader_specs): New member "buffer_end".
(dwarf2_section_buffer_overflow_complaint): Renamed from
dwarf2_macros_too_long_complaint.  All callers updated.
(skip_leb128): Delete.
(init_cu_die_reader): Initialize reader->buffer_end.
(skip_one_die): Replace call to skip_leb128 with safe_skip_leb128.
(skip_form_bytes): New arg buffer_end.  All callers updated.
Replace call to skip_leb128 with gdb_skip_leb128.
(skip_unknown_opcode): New arg mac_end.  All callers updated.
(fill_in_loclist_baton): Initialize baton->from_dwo.

gdb/ChangeLog
gdb/dwarf2-frame.c
gdb/dwarf2expr.c
gdb/dwarf2expr.h
gdb/dwarf2loc.c
gdb/dwarf2loc.h
gdb/dwarf2read.c

index 90cc26c3390e11f4f92cef1e4d8eb9ba88602b54..98ffd2f5fea722a594f7d645c803c30e611a7cdf 100644 (file)
@@ -1,3 +1,55 @@
+2012-05-22  Doug Evans  <dje@google.com>
+
+       * dwarf2-frame.c (struct dwarf2_cie): Make initial_instructions, end
+       "const gdb_byte *".
+       (struct dwarf2_fde): Make instructions, end "const gdb_byte *".
+       (execute_cfa_program): Update to match API of leb128 functions.
+       (read_1_byte, read_4_bytes, read_8_bytes): Make buf parameter
+       "const gdb_byte *".
+       (read_unsigned_leb128, read_signed_leb128): Delete.
+       (read_initial_length): Change type of buf argument to
+       "const gdb_byte *".
+       (read_encoded_value): Update to match API of leb128 functions.
+       (decode_frame_entry): Change result to "const gdb_byte *", and
+       similarly for "start" parameter.
+       (decode_frame_entry_1): Ditto.  Use new leb128 reader functions.
+       (dwarf2_build_frame_info): Change local frame_ptr to
+       "const gdb_byte *".
+       * dwarf2expr.c (safe_read_uleb128, safe_read_sleb128): Replaces
+       read_uleb128, read_sleb128.  All callers updated.
+       (safe_skip_leb128): New function.
+       (dwarf_block_to_dwarf_reg): Update to match API of leb128 functions.
+       Call gdb_read_uleb128, gdb_skip_leb128 instead of read_uleb128.
+       (dwarf_block_to_dwarf_reg_deref): Update to match API of leb128
+       functions.  Call gdb_read_uleb128, gdb_read_sleb128 instead of
+       read_uleb128, read_sleb128.
+       (dwarf_block_to_fb_offset, dwarf_block_to_sp_offset): Ditto.
+       (execute_stack_op): Update to match API of leb128 functions.
+       * dwarf2expr.h: #include "leb128.h".
+       (read_uleb128, read_sleb128): Delete.
+       (gdb_read_uleb128, gdb_read_sleb128, gdb_skip_leb128): New functions.
+       (safe_read_uleb128, safe_read_sleb128, safe_skip_leb128): Declare.
+       * dwarf2loc.c (debug_loc_kind): New enum.
+       (decode_debug_loc_addresses): New function.
+       (decode_debug_loc_dwo_addresses): New function.
+       (dwarf2_find_location_expression): Rewrite.
+       (dwarf2_compile_expr_to_ax): Update to match API of leb128 functions.
+       (locexpr_describe_location_piece): Ditto.
+       (disassemble_dwarf_expression): Ditto.
+       (locexpr_describe_location_1): Ditto.
+       (loclist_describe_location): Rewrite.
+       * dwarf2loc.h (dwarf2_loclist_baton): New member "from_dwo".
+       * dwarf2read.c (die_reader_specs): New member "buffer_end".
+       (dwarf2_section_buffer_overflow_complaint): Renamed from
+       dwarf2_macros_too_long_complaint.  All callers updated.
+       (skip_leb128): Delete.
+       (init_cu_die_reader): Initialize reader->buffer_end.
+       (skip_one_die): Replace call to skip_leb128 with safe_skip_leb128.
+       (skip_form_bytes): New arg buffer_end.  All callers updated.
+       Replace call to skip_leb128 with gdb_skip_leb128.
+       (skip_unknown_opcode): New arg mac_end.  All callers updated.
+       (fill_in_loclist_baton): Initialize baton->from_dwo.
+
 2012-05-22  Maciej W. Rozycki  <macro@codesourcery.com>
 
        * mips-linux-nat.c (mips_linux_read_description): Use a more
index 670e26f2de90c0757c4108cef40781cf947147c3..96fa4516a65872b5dc61a05d9ea2aed5b64b3c53 100644 (file)
@@ -68,8 +68,8 @@ struct dwarf2_cie
   ULONGEST return_address_register;
 
   /* Instruction sequence to initialize a register set.  */
-  gdb_byte *initial_instructions;
-  gdb_byte *end;
+  const gdb_byte *initial_instructions;
+  const gdb_byte *end;
 
   /* Saved augmentation, in case it's needed later.  */
   char *augmentation;
@@ -116,8 +116,8 @@ struct dwarf2_fde
   CORE_ADDR address_range;
 
   /* Instruction sequence.  */
-  gdb_byte *instructions;
-  gdb_byte *end;
+  const gdb_byte *instructions;
+  const gdb_byte *end;
 
   /* True if this FDE is read from a .eh_frame instead of a .debug_frame
      section.  */
@@ -416,8 +416,8 @@ execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr,
   while (insn_ptr < insn_end && fs->pc <= pc)
     {
       gdb_byte insn = *insn_ptr++;
-      ULONGEST utmp, reg;
-      LONGEST offset;
+      unsigned long long utmp, reg;
+      long long offset;
 
       if ((insn & 0xc0) == DW_CFA_advance_loc)
        fs->pc += (insn & 0x3f) * fs->code_align;
@@ -425,7 +425,7 @@ execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr,
        {
          reg = insn & 0x3f;
          reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
-         insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+         insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
          offset = utmp * fs->data_align;
          dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
          fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET;
@@ -467,9 +467,9 @@ execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr,
              break;
 
            case DW_CFA_offset_extended:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
              offset = utmp * fs->data_align;
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET;
@@ -477,28 +477,28 @@ execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr,
              break;
 
            case DW_CFA_restore_extended:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              dwarf2_restore_rule (gdbarch, reg, fs, eh_frame_p);
              break;
 
            case DW_CFA_undefined:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_UNDEFINED;
              break;
 
            case DW_CFA_same_value:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAME_VALUE;
              break;
 
            case DW_CFA_register:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
              utmp = dwarf2_frame_adjust_regnum (gdbarch, utmp, eh_frame_p);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_REG;
@@ -536,8 +536,9 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
              break;
 
            case DW_CFA_def_cfa:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->regs.cfa_reg);
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
+             fs->regs.cfa_reg = reg;
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
 
              if (fs->armcc_cfa_offsets_sf)
                utmp *= fs->data_align;
@@ -547,15 +548,14 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
              break;
 
            case DW_CFA_def_cfa_register:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->regs.cfa_reg);
-             fs->regs.cfa_reg = dwarf2_frame_adjust_regnum (gdbarch,
-                                                             fs->regs.cfa_reg,
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
+             fs->regs.cfa_reg = dwarf2_frame_adjust_regnum (gdbarch, reg,
                                                              eh_frame_p);
              fs->regs.cfa_how = CFA_REG_OFFSET;
              break;
 
            case DW_CFA_def_cfa_offset:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
 
              if (fs->armcc_cfa_offsets_sf)
                utmp *= fs->data_align;
@@ -568,18 +568,18 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
              break;
 
            case DW_CFA_def_cfa_expression:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end,
-                                       &fs->regs.cfa_exp_len);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
+             fs->regs.cfa_exp_len = utmp;
              fs->regs.cfa_exp = insn_ptr;
              fs->regs.cfa_how = CFA_EXP;
              insn_ptr += fs->regs.cfa_exp_len;
              break;
 
            case DW_CFA_expression:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
              fs->regs.reg[reg].loc.exp = insn_ptr;
              fs->regs.reg[reg].exp_len = utmp;
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_EXP;
@@ -587,9 +587,9 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
              break;
 
            case DW_CFA_offset_extended_sf:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
-             insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
+             insn_ptr = safe_read_sleb128 (insn_ptr, insn_end, &offset);
              offset *= fs->data_align;
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET;
@@ -597,27 +597,27 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
              break;
 
            case DW_CFA_val_offset:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
              offset = utmp * fs->data_align;
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
              fs->regs.reg[reg].loc.offset = offset;
              break;
 
            case DW_CFA_val_offset_sf:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
-             insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
+             insn_ptr = safe_read_sleb128 (insn_ptr, insn_end, &offset);
              offset *= fs->data_align;
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET;
              fs->regs.reg[reg].loc.offset = offset;
              break;
 
            case DW_CFA_val_expression:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
              fs->regs.reg[reg].loc.exp = insn_ptr;
              fs->regs.reg[reg].exp_len = utmp;
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_EXP;
@@ -625,17 +625,16 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
              break;
 
            case DW_CFA_def_cfa_sf:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->regs.cfa_reg);
-             fs->regs.cfa_reg = dwarf2_frame_adjust_regnum (gdbarch,
-                                                             fs->regs.cfa_reg,
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
+             fs->regs.cfa_reg = dwarf2_frame_adjust_regnum (gdbarch, reg,
                                                              eh_frame_p);
-             insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
+             insn_ptr = safe_read_sleb128 (insn_ptr, insn_end, &offset);
              fs->regs.cfa_offset = offset * fs->data_align;
              fs->regs.cfa_how = CFA_REG_OFFSET;
              break;
 
            case DW_CFA_def_cfa_offset_sf:
-             insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
+             insn_ptr = safe_read_sleb128 (insn_ptr, insn_end, &offset);
              fs->regs.cfa_offset = offset * fs->data_align;
              /* cfa_how deliberately not set.  */
              break;
@@ -667,13 +666,13 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
 
            case DW_CFA_GNU_args_size:
              /* Ignored.  */
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
              break;
 
            case DW_CFA_GNU_negative_offset_extended:
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &reg);
              reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
-             insn_ptr = read_uleb128 (insn_ptr, insn_end, &offset);
+             insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &offset);
              offset *= fs->data_align;
              dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
              fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET;
@@ -1501,82 +1500,26 @@ dwarf2_frame_cfa (struct frame_info *this_frame)
 const struct objfile_data *dwarf2_frame_objfile_data;
 
 static unsigned int
-read_1_byte (bfd *abfd, gdb_byte *buf)
+read_1_byte (bfd *abfd, const gdb_byte *buf)
 {
   return bfd_get_8 (abfd, buf);
 }
 
 static unsigned int
-read_4_bytes (bfd *abfd, gdb_byte *buf)
+read_4_bytes (bfd *abfd, const gdb_byte *buf)
 {
   return bfd_get_32 (abfd, buf);
 }
 
 static ULONGEST
-read_8_bytes (bfd *abfd, gdb_byte *buf)
+read_8_bytes (bfd *abfd, const gdb_byte *buf)
 {
   return bfd_get_64 (abfd, buf);
 }
 
 static ULONGEST
-read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
-{
-  ULONGEST result;
-  unsigned int num_read;
-  int shift;
-  gdb_byte byte;
-
-  result = 0;
-  shift = 0;
-  num_read = 0;
-
-  do
-    {
-      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
-      buf++;
-      num_read++;
-      result |= ((byte & 0x7f) << shift);
-      shift += 7;
-    }
-  while (byte & 0x80);
-
-  *bytes_read_ptr = num_read;
-
-  return result;
-}
-
-static LONGEST
-read_signed_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
-{
-  LONGEST result;
-  int shift;
-  unsigned int num_read;
-  gdb_byte byte;
-
-  result = 0;
-  shift = 0;
-  num_read = 0;
-
-  do
-    {
-      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
-      buf++;
-      num_read++;
-      result |= ((byte & 0x7f) << shift);
-      shift += 7;
-    }
-  while (byte & 0x80);
-
-  if (shift < 8 * sizeof (result) && (byte & 0x40))
-    result |= -(((LONGEST)1) << shift);
-
-  *bytes_read_ptr = num_read;
-
-  return result;
-}
-
-static ULONGEST
-read_initial_length (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
+read_initial_length (bfd *abfd, const gdb_byte *buf,
+                    unsigned int *bytes_read_ptr)
 {
   LONGEST result;
 
@@ -1685,10 +1628,10 @@ read_encoded_value (struct comp_unit *unit, gdb_byte encoding,
     {
     case DW_EH_PE_uleb128:
       {
-       ULONGEST value;
+       unsigned long long value;
        const gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
 
-       *bytes_read_ptr += read_uleb128 (buf, end_buf, &value) - buf;
+       *bytes_read_ptr += safe_read_uleb128 (buf, end_buf, &value) - buf;
        return base + value;
       }
     case DW_EH_PE_udata2:
@@ -1702,10 +1645,10 @@ read_encoded_value (struct comp_unit *unit, gdb_byte encoding,
       return (base + bfd_get_64 (unit->abfd, (bfd_byte *) buf));
     case DW_EH_PE_sleb128:
       {
-       LONGEST value;
+       long long value;
        const gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
 
-       *bytes_read_ptr += read_sleb128 (buf, end_buf, &value) - buf;
+       *bytes_read_ptr += safe_read_sleb128 (buf, end_buf, &value) - buf;
        return base + value;
       }
     case DW_EH_PE_sdata2:
@@ -1863,28 +1806,32 @@ enum eh_frame_type
   EH_CIE_OR_FDE_TYPE_ID = EH_CIE_TYPE_ID | EH_FDE_TYPE_ID
 };
 
-static gdb_byte *decode_frame_entry (struct comp_unit *unit, gdb_byte *start,
-                                    int eh_frame_p,
-                                     struct dwarf2_cie_table *cie_table,
-                                     struct dwarf2_fde_table *fde_table,
-                                     enum eh_frame_type entry_type);
+static const gdb_byte *decode_frame_entry (struct comp_unit *unit,
+                                          const gdb_byte *start,
+                                          int eh_frame_p,
+                                          struct dwarf2_cie_table *cie_table,
+                                          struct dwarf2_fde_table *fde_table,
+                                          enum eh_frame_type entry_type);
 
 /* Decode the next CIE or FDE, entry_type specifies the expected type.
    Return NULL if invalid input, otherwise the next byte to be processed.  */
 
-static gdb_byte *
-decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p,
+static const gdb_byte *
+decode_frame_entry_1 (struct comp_unit *unit, const gdb_byte *start,
+                     int eh_frame_p,
                       struct dwarf2_cie_table *cie_table,
                       struct dwarf2_fde_table *fde_table,
                       enum eh_frame_type entry_type)
 {
   struct gdbarch *gdbarch = get_objfile_arch (unit->objfile);
-  gdb_byte *buf, *end;
+  const gdb_byte *buf, *end;
   LONGEST length;
   unsigned int bytes_read;
   int dwarf64_p;
   ULONGEST cie_id;
   ULONGEST cie_pointer;
+  long long sleb128;
+  unsigned long long uleb128;
 
   buf = start;
   length = read_initial_length (unit->abfd, buf, &bytes_read);
@@ -2000,37 +1947,41 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p,
       else
        cie->ptr_size = cie->addr_size;
 
-      cie->code_alignment_factor =
-       read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
-      buf += bytes_read;
+      buf = gdb_read_uleb128 (buf, end, &uleb128);
+      if (buf == NULL)
+       return NULL;
+      cie->code_alignment_factor = uleb128;
 
-      cie->data_alignment_factor =
-       read_signed_leb128 (unit->abfd, buf, &bytes_read);
-      buf += bytes_read;
+      buf = gdb_read_sleb128 (buf, end, &sleb128);
+      if (buf == NULL)
+       return NULL;
+      cie->data_alignment_factor = sleb128;
 
       if (cie_version == 1)
        {
          cie->return_address_register = read_1_byte (unit->abfd, buf);
-         bytes_read = 1;
+         ++buf;
        }
       else
-       cie->return_address_register = read_unsigned_leb128 (unit->abfd, buf,
-                                                            &bytes_read);
+       {
+         buf = gdb_read_uleb128 (buf, end, &uleb128);
+         if (buf == NULL)
+           return NULL;
+         cie->return_address_register = uleb128;
+       }
+
       cie->return_address_register
        = dwarf2_frame_adjust_regnum (gdbarch,
                                      cie->return_address_register,
                                      eh_frame_p);
 
-      buf += bytes_read;
-
       cie->saw_z_augmentation = (*augmentation == 'z');
       if (cie->saw_z_augmentation)
        {
-         ULONGEST length;
+         unsigned long long length;
 
-         length = read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
-         buf += bytes_read;
-         if (buf > end)
+         buf = gdb_read_uleb128 (buf, end, &length);
+         if (buf == NULL)
            return NULL;
          cie->initial_instructions = buf + length;
          augmentation++;
@@ -2144,10 +2095,12 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p,
         can skip the whole thing.  */
       if (fde->cie->saw_z_augmentation)
        {
-         ULONGEST length;
+         unsigned long long length;
 
-         length = read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
-         buf += bytes_read + length;
+         buf = gdb_read_uleb128 (buf, end, &length);
+         if (buf == NULL)
+           return NULL;
+         buf += length;
          if (buf > end)
            return NULL;
        }
@@ -2166,14 +2119,15 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p,
 /* Read a CIE or FDE in BUF and decode it. Entry_type specifies whether we
    expect an FDE or a CIE.  */
 
-static gdb_byte *
-decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p,
+static const gdb_byte *
+decode_frame_entry (struct comp_unit *unit, const gdb_byte *start,
+                   int eh_frame_p,
                     struct dwarf2_cie_table *cie_table,
                     struct dwarf2_fde_table *fde_table,
                     enum eh_frame_type entry_type)
 {
   enum { NONE, ALIGN4, ALIGN8, FAIL } workaround = NONE;
-  gdb_byte *ret;
+  const gdb_byte *ret;
   ptrdiff_t start_offset;
 
   while (1)
@@ -2285,7 +2239,7 @@ void
 dwarf2_build_frame_info (struct objfile *objfile)
 {
   struct comp_unit *unit;
-  gdb_byte *frame_ptr;
+  const gdb_byte *frame_ptr;
   struct dwarf2_cie_table cie_table;
   struct dwarf2_fde_table fde_table;
   struct dwarf2_fde_table *fde_table2;
index 83d8e049832bff6675619b99e3aa4a5c6e4dac5d..80c6e173a31706077afea61e61d80a107d99a9dd 100644 (file)
@@ -369,60 +369,36 @@ dwarf_expr_eval (struct dwarf_expr_context *ctx, const gdb_byte *addr,
   gdb_assert (ctx->recursion_depth == old_recursion_depth);
 }
 
-/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
-   by R, and return the new value of BUF.  Verify that it doesn't extend
-   past BUF_END.  R can be NULL, the constant is then only skipped.  */
+/* Helper to read a uleb128 value or throw an error.  */
 
 const gdb_byte *
-read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, ULONGEST * r)
+safe_read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end,
+                  unsigned long long *r)
 {
-  unsigned shift = 0;
-  ULONGEST result = 0;
-  gdb_byte byte;
-
-  while (1)
-    {
-      if (buf >= buf_end)
-       error (_("read_uleb128: Corrupted DWARF expression."));
-
-      byte = *buf++;
-      result |= ((ULONGEST) (byte & 0x7f)) << shift;
-      if ((byte & 0x80) == 0)
-       break;
-      shift += 7;
-    }
-  if (r)
-    *r = result;
+  buf = gdb_read_uleb128 (buf, buf_end, r);
+  if (buf == NULL)
+    error (_("DWARF expression error: ran off end of buffer reading uleb128 value"));
   return buf;
 }
 
-/* Decode the signed LEB128 constant at BUF into the variable pointed to
-   by R, and return the new value of BUF.  Verify that it doesn't extend
-   past BUF_END.  R can be NULL, the constant is then only skipped.  */
+/* Helper to read a sleb128 value or throw an error.  */
 
 const gdb_byte *
-read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, LONGEST * r)
+safe_read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end,
+                  long long *r)
 {
-  unsigned shift = 0;
-  LONGEST result = 0;
-  gdb_byte byte;
-
-  while (1)
-    {
-      if (buf >= buf_end)
-       error (_("read_sleb128: Corrupted DWARF expression."));
-
-      byte = *buf++;
-      result |= ((ULONGEST) (byte & 0x7f)) << shift;
-      shift += 7;
-      if ((byte & 0x80) == 0)
-       break;
-    }
-  if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
-    result |= -(((LONGEST) 1) << shift);
+  buf = gdb_read_sleb128 (buf, buf_end, r);
+  if (buf == NULL)
+    error (_("DWARF expression error: ran off end of buffer reading sleb128 value"));
+  return buf;
+}
 
-  if (r)
-    *r = result;
+const gdb_byte *
+safe_skip_leb128 (const gdb_byte *buf, const gdb_byte *buf_end)
+{
+  buf = gdb_skip_leb128 (buf, buf_end);
+  if (buf == NULL)
+    error (_("DWARF expression error: ran off end of buffer reading leb128 value"));
   return buf;
 }
 \f
@@ -489,7 +465,7 @@ dwarf_get_base_type (struct dwarf_expr_context *ctx, cu_offset die, int size)
 int
 dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end)
 {
-  ULONGEST dwarf_reg;
+  unsigned long long dwarf_reg;
 
   if (buf_end <= buf)
     return -1;
@@ -503,13 +479,19 @@ dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end)
   if (*buf == DW_OP_GNU_regval_type)
     {
       buf++;
-      buf = read_uleb128 (buf, buf_end, &dwarf_reg);
-      buf = read_uleb128 (buf, buf_end, NULL);
+      buf = gdb_read_uleb128 (buf, buf_end, &dwarf_reg);
+      if (buf == NULL)
+       return -1;
+      buf = gdb_skip_leb128 (buf, buf_end);
+      if (buf == NULL)
+       return -1;
     }
   else if (*buf == DW_OP_regx)
     {
       buf++;
-      buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+      buf = gdb_read_uleb128 (buf, buf_end, &dwarf_reg);
+      if (buf == NULL)
+       return -1;
     }
   else
     return -1;
@@ -527,31 +509,35 @@ int
 dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf, const gdb_byte *buf_end,
                                CORE_ADDR *deref_size_return)
 {
-  ULONGEST dwarf_reg;
-  LONGEST offset;
+  unsigned long long dwarf_reg;
+  long long offset;
 
   if (buf_end <= buf)
     return -1;
+
   if (*buf >= DW_OP_breg0 && *buf <= DW_OP_breg31)
     {
       dwarf_reg = *buf - DW_OP_breg0;
       buf++;
+      if (buf >= buf_end)
+       return -1;
     }
   else if (*buf == DW_OP_bregx)
     {
       buf++;
-      buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+      buf = gdb_read_uleb128 (buf, buf_end, &dwarf_reg);
+      if (buf == NULL)
+       return -1;
       if ((int) dwarf_reg != dwarf_reg)
        return -1;
     }
   else
     return -1;
 
-  buf = read_sleb128 (buf, buf_end, &offset);
-  if (offset != 0)
+  buf = gdb_read_sleb128 (buf, buf_end, &offset);
+  if (buf == NULL)
     return -1;
-
-  if (buf >= buf_end)
+  if (offset != 0)
     return -1;
 
   if (*buf == DW_OP_deref)
@@ -582,7 +568,7 @@ int
 dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end,
                          CORE_ADDR *fb_offset_return)
 {
-  LONGEST fb_offset;
+  long long fb_offset;
 
   if (buf_end <= buf)
     return 0;
@@ -591,7 +577,9 @@ dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end,
     return 0;
   buf++;
 
-  buf = read_sleb128 (buf, buf_end, &fb_offset);
+  buf = gdb_read_sleb128 (buf, buf_end, &fb_offset);
+  if (buf == NULL)
+    return 0;
   *fb_offset_return = fb_offset;
   if (buf != buf_end || fb_offset != (LONGEST) *fb_offset_return)
     return 0;
@@ -607,8 +595,8 @@ int
 dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
                          const gdb_byte *buf_end, CORE_ADDR *sp_offset_return)
 {
-  ULONGEST dwarf_reg;
-  LONGEST sp_offset;
+  unsigned long long dwarf_reg;
+  long long sp_offset;
 
   if (buf_end <= buf)
     return 0;
@@ -622,14 +610,18 @@ dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
       if (*buf != DW_OP_bregx)
        return 0;
       buf++;
-      buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+      buf = gdb_read_uleb128 (buf, buf_end, &dwarf_reg);
+      if (buf == NULL)
+       return 0;
     }
 
   if (gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_reg)
       != gdbarch_sp_regnum (gdbarch))
     return 0;
 
-  buf = read_sleb128 (buf, buf_end, &sp_offset);
+  buf = gdb_read_sleb128 (buf, buf_end, &sp_offset);
+  if (buf == NULL)
+    return 0;
   *sp_offset_return = sp_offset;
   if (buf != buf_end || sp_offset != (LONGEST) *sp_offset_return)
     return 0;
@@ -673,8 +665,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
         This is just an optimization, so it's always ok to punt
         and leave this as 0.  */
       int in_stack_memory = 0;
-      ULONGEST uoffset, reg;
-      LONGEST offset;
+      unsigned long long uoffset, reg;
+      long long offset;
       struct value *result_val = NULL;
 
       /* The DWARF expression might have a bug causing an infinite
@@ -733,7 +725,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
          break;
 
        case DW_OP_GNU_addr_index:
-         op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
+         op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
          result = (ctx->funcs->get_addr_index) (ctx->baton, uoffset);
          result_val = value_from_ulongest (address_type, result);
          break;
@@ -779,12 +771,12 @@ execute_stack_op (struct dwarf_expr_context *ctx,
          op_ptr += 8;
          break;
        case DW_OP_constu:
-         op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
+         op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
          result = uoffset;
          result_val = value_from_ulongest (address_type, result);
          break;
        case DW_OP_consts:
-         op_ptr = read_sleb128 (op_ptr, op_end, &offset);
+         op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
          result = offset;
          result_val = value_from_ulongest (address_type, result);
          break;
@@ -837,7 +829,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
          break;
 
        case DW_OP_regx:
-         op_ptr = read_uleb128 (op_ptr, op_end, &reg);
+         op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
          dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx");
 
          result = reg;
@@ -847,9 +839,9 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
        case DW_OP_implicit_value:
          {
-           ULONGEST len;
+           unsigned long long len;
 
-           op_ptr = read_uleb128 (op_ptr, op_end, &len);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &len);
            if (op_ptr + len > op_end)
              error (_("DW_OP_implicit_value: too few bytes available."));
            ctx->len = len;
@@ -868,7 +860,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
        case DW_OP_GNU_implicit_pointer:
          {
-           LONGEST len;
+           long long len;
 
            if (ctx->ref_addr_size == -1)
              error (_("DWARF-2 expression error: DW_OP_GNU_implicit_pointer "
@@ -880,7 +872,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
            op_ptr += ctx->ref_addr_size;
 
            /* The byte offset into the data.  */
-           op_ptr = read_sleb128 (op_ptr, op_end, &len);
+           op_ptr = safe_read_sleb128 (op_ptr, op_end, &len);
            result = (ULONGEST) len;
            result_val = value_from_ulongest (address_type, result);
 
@@ -923,7 +915,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
        case DW_OP_breg30:
        case DW_OP_breg31:
          {
-           op_ptr = read_sleb128 (op_ptr, op_end, &offset);
+           op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
            result = (ctx->funcs->read_reg) (ctx->baton, op - DW_OP_breg0);
            result += offset;
            result_val = value_from_ulongest (address_type, result);
@@ -931,8 +923,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
          break;
        case DW_OP_bregx:
          {
-           op_ptr = read_uleb128 (op_ptr, op_end, &reg);
-           op_ptr = read_sleb128 (op_ptr, op_end, &offset);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
+           op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
            result = (ctx->funcs->read_reg) (ctx->baton, reg);
            result += offset;
            result_val = value_from_ulongest (address_type, result);
@@ -944,7 +936,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
            size_t datalen;
            unsigned int before_stack_len;
 
-           op_ptr = read_sleb128 (op_ptr, op_end, &offset);
+           op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
            /* Rather than create a whole new context, we simply
               record the stack length before execution, then reset it
               afterwards, effectively erasing whatever the recursive
@@ -1038,7 +1030,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
              {
                cu_offset type_die;
 
-               op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
+               op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
                type_die.cu_off = uoffset;
                type = dwarf_get_base_type (ctx, type_die, 0);
              }
@@ -1089,7 +1081,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
              case DW_OP_plus_uconst:
                dwarf_require_integral (value_type (result_val));
                result = value_as_long (result_val);
-               op_ptr = read_uleb128 (op_ptr, op_end, &reg);
+               op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
                result += reg;
                result_val = value_from_ulongest (address_type, result);
                break;
@@ -1299,10 +1291,10 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
         case DW_OP_piece:
           {
-            ULONGEST size;
+            unsigned long long size;
 
             /* Record the piece.  */
-            op_ptr = read_uleb128 (op_ptr, op_end, &size);
+            op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
            add_piece (ctx, 8 * size, 0);
 
             /* Pop off the address/regnum, and reset the location
@@ -1316,11 +1308,11 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
        case DW_OP_bit_piece:
          {
-           ULONGEST size, offset;
+           unsigned long long size, offset;
 
             /* Record the piece.  */
-           op_ptr = read_uleb128 (op_ptr, op_end, &size);
-           op_ptr = read_uleb128 (op_ptr, op_end, &offset);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &offset);
            add_piece (ctx, size, offset);
 
             /* Pop off the address/regnum, and reset the location
@@ -1362,11 +1354,11 @@ execute_stack_op (struct dwarf_expr_context *ctx,
        
        case DW_OP_GNU_entry_value:
          {
-           ULONGEST len;
+           unsigned long long len;
            int dwarf_reg;
            CORE_ADDR deref_size;
 
-           op_ptr = read_uleb128 (op_ptr, op_end, &len);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &len);
            if (op_ptr + len > op_end)
              error (_("DW_OP_GNU_entry_value: too few bytes available."));
 
@@ -1405,7 +1397,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
            const gdb_byte *data;
            struct type *type;
 
-           op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
            type_die.cu_off = uoffset;
            n = *op_ptr++;
            data = op_ptr;
@@ -1421,8 +1413,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
            cu_offset type_die;
            struct type *type;
 
-           op_ptr = read_uleb128 (op_ptr, op_end, &reg);
-           op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
            type_die.cu_off = uoffset;
 
            type = dwarf_get_base_type (ctx, type_die, 0);
@@ -1439,7 +1431,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
            cu_offset type_die;
            struct type *type;
 
-           op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
            type_die.cu_off = uoffset;
 
            if (type_die.cu_off == 0)
index 3699dbbe63a3745c18e96873fd92c3a400b30bb9..82a5a93e1050eac46da3c9348a2a85a7b94373ff 100644 (file)
@@ -23,6 +23,8 @@
 #if !defined (DWARF2EXPR_H)
 #define DWARF2EXPR_H
 
+#include "leb128.h"
+
 struct dwarf_expr_context;
 
 /* Offset relative to the start of its containing CU (compilation unit).  */
@@ -273,12 +275,6 @@ struct value *dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n);
 CORE_ADDR dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n);
 int dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n);
 
-
-const gdb_byte *read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end,
-                             ULONGEST * r);
-const gdb_byte *read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end,
-                             LONGEST * r);
-
 void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *,
                                     const char *);
 
@@ -310,4 +306,50 @@ int dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
                              const gdb_byte *buf_end,
                              CORE_ADDR *sp_offset_return);
 
+/* Wrappers around the leb128 reader routines to simplify them for our
+   purposes.  */
+
+static inline const gdb_byte *
+gdb_read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end,
+                 unsigned long long *r)
+{
+  size_t bytes_read = read_uleb128_to_ull (buf, buf_end, r);
+
+  if (bytes_read == 0)
+    return NULL;
+  return buf + bytes_read;
+}
+
+static inline const gdb_byte *
+gdb_read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end,
+                 long long *r)
+{
+  size_t bytes_read = read_sleb128_to_ll (buf, buf_end, r);
+
+  if (bytes_read == 0)
+    return NULL;
+  return buf + bytes_read;
+}
+
+static inline const gdb_byte *
+gdb_skip_leb128 (const gdb_byte *buf, const gdb_byte *buf_end)
+{
+  size_t bytes_read = skip_leb128 (buf, buf_end);
+
+  if (bytes_read == 0)
+    return NULL;
+  return buf + bytes_read;
+}
+
+extern const gdb_byte *safe_read_uleb128 (const gdb_byte *buf,
+                                         const gdb_byte *buf_end,
+                                         unsigned long long *r);
+
+extern const gdb_byte *safe_read_sleb128 (const gdb_byte *buf,
+                                         const gdb_byte *buf_end,
+                                         long long *r);
+
+extern const gdb_byte *safe_skip_leb128 (const gdb_byte *buf,
+                                        const gdb_byte *buf_end);
+
 #endif /* dwarf2expr.h */
index c251b70c9cc232415142b5fe0bf827ae2f29dd8b..9bd77417e4df5a652d21f4d1160aa7f181efc5ff 100644 (file)
@@ -58,6 +58,121 @@ static struct value *dwarf2_evaluate_loc_desc_full (struct type *type,
                                              struct dwarf2_per_cu_data *per_cu,
                                                    LONGEST byte_offset);
 
+/* Until these have formal names, we define these here.
+   ref: http://gcc.gnu.org/wiki/DebugFission
+   Each entry in .debug_loc.dwo begins with a byte that describes the entry,
+   and is then followed by data specific to that entry.  */
+
+enum debug_loc_kind
+{
+  /* Indicates the end of the list of entries.  */
+  DEBUG_LOC_END_OF_LIST = 0,
+
+  /* This is followed by an unsigned LEB128 number that is an index into
+     .debug_addr and specifies the base address for all following entries.  */
+  DEBUG_LOC_BASE_ADDRESS = 1,
+
+  /* This is followed by two unsigned LEB128 numbers that are indices into
+     .debug_addr and specify the beginning and ending addresses, and then
+     a normal location expression as in .debug_loc.  */
+  DEBUG_LOC_NORMAL = 2,
+
+  /* An internal value indicating there is insufficient data.  */
+  DEBUG_LOC_BUFFER_OVERFLOW = -1,
+
+  /* An internal value indicating an invalid kind of entry was found.  */
+  DEBUG_LOC_INVALID_ENTRY = -2
+};
+
+/* Decode the addresses in a non-dwo .debug_loc entry.
+   A pointer to the next byte to examine is returned in *NEW_PTR.
+   The encoded low,high addresses are return in *LOW,*HIGH.
+   The result indicates the kind of entry found.  */
+
+static enum debug_loc_kind
+decode_debug_loc_addresses (const gdb_byte *loc_ptr, const gdb_byte *buf_end,
+                           const gdb_byte **new_ptr,
+                           CORE_ADDR *low, CORE_ADDR *high,
+                           enum bfd_endian byte_order,
+                           unsigned int addr_size,
+                           int signed_addr_p)
+{
+  CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
+
+  if (buf_end - loc_ptr < 2 * addr_size)
+    return DEBUG_LOC_BUFFER_OVERFLOW;
+
+  if (signed_addr_p)
+    *low = extract_signed_integer (loc_ptr, addr_size, byte_order);
+  else
+    *low = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
+  loc_ptr += addr_size;
+
+  if (signed_addr_p)
+    *high = extract_signed_integer (loc_ptr, addr_size, byte_order);
+  else
+    *high = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
+  loc_ptr += addr_size;
+
+  *new_ptr = loc_ptr;
+
+  /* A base-address-selection entry.  */
+  if ((*low & base_mask) == base_mask)
+    return DEBUG_LOC_BASE_ADDRESS;
+
+  /* An end-of-list entry.  */
+  if (*low == 0 && *high == 0)
+    return DEBUG_LOC_END_OF_LIST;
+
+  return DEBUG_LOC_NORMAL;
+}
+
+/* Decode the addresses in .debug_loc.dwo entry.
+   A pointer to the next byte to examine is returned in *NEW_PTR.
+   The encoded low,high addresses are return in *LOW,*HIGH.
+   The result indicates the kind of entry found.  */
+
+static enum debug_loc_kind
+decode_debug_loc_dwo_addresses (struct dwarf2_per_cu_data *per_cu,
+                               const gdb_byte *loc_ptr,
+                               const gdb_byte *buf_end,
+                               const gdb_byte **new_ptr,
+                               CORE_ADDR *low, CORE_ADDR *high)
+{
+  unsigned long long low_index, high_index;
+
+  if (loc_ptr == buf_end)
+    return DEBUG_LOC_BUFFER_OVERFLOW;
+
+  switch (*loc_ptr++)
+    {
+    case DEBUG_LOC_END_OF_LIST:
+      *new_ptr = loc_ptr;
+      return DEBUG_LOC_END_OF_LIST;
+    case DEBUG_LOC_BASE_ADDRESS:
+      *low = 0;
+      loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &high_index);
+      if (loc_ptr == NULL)
+       return DEBUG_LOC_BUFFER_OVERFLOW;
+      *high = dwarf2_read_addr_index (per_cu, high_index);
+      *new_ptr = loc_ptr;
+      return DEBUG_LOC_BASE_ADDRESS;
+    case DEBUG_LOC_NORMAL:
+      loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &low_index);
+      if (loc_ptr == NULL)
+       return DEBUG_LOC_BUFFER_OVERFLOW;
+      *low = dwarf2_read_addr_index (per_cu, low_index);
+      loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &high_index);
+      if (loc_ptr == NULL)
+       return DEBUG_LOC_BUFFER_OVERFLOW;
+      *high = dwarf2_read_addr_index (per_cu, high_index);
+      *new_ptr = loc_ptr;
+      return DEBUG_LOC_NORMAL;
+    default:
+      return DEBUG_LOC_INVALID_ENTRY;
+    }
+}
+
 /* A function for dealing with location lists.  Given a
    symbol baton (BATON) and a pc value (PC), find the appropriate
    location expression, set *LOCEXPR_LENGTH, and return a pointer
@@ -70,52 +185,52 @@ const gdb_byte *
 dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton,
                                 size_t *locexpr_length, CORE_ADDR pc)
 {
-  CORE_ADDR low, high;
-  const gdb_byte *loc_ptr, *buf_end;
-  int length;
   struct objfile *objfile = dwarf2_per_cu_objfile (baton->per_cu);
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   unsigned int addr_size = dwarf2_per_cu_addr_size (baton->per_cu);
   int signed_addr_p = bfd_get_sign_extend_vma (objfile->obfd);
-  CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
   /* Adjust base_address for relocatable objects.  */
   CORE_ADDR base_offset = dwarf2_per_cu_text_offset (baton->per_cu);
   CORE_ADDR base_address = baton->base_address + base_offset;
+  const gdb_byte *loc_ptr, *buf_end;
 
   loc_ptr = baton->data;
   buf_end = baton->data + baton->size;
 
   while (1)
     {
-      if (buf_end - loc_ptr < 2 * addr_size)
-       error (_("dwarf2_find_location_expression: "
-                "Corrupted DWARF expression."));
-
-      if (signed_addr_p)
-       low = extract_signed_integer (loc_ptr, addr_size, byte_order);
-      else
-       low = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
-      loc_ptr += addr_size;
-
-      if (signed_addr_p)
-       high = extract_signed_integer (loc_ptr, addr_size, byte_order);
+      CORE_ADDR low = 0, high = 0; /* init for gcc -Wall */
+      int length;
+      enum debug_loc_kind kind;
+      const gdb_byte *new_ptr = NULL; /* init for gcc -Wall */
+
+      if (baton->from_dwo)
+       kind = decode_debug_loc_dwo_addresses (baton->per_cu,
+                                              loc_ptr, buf_end, &new_ptr,
+                                              &low, &high);
       else
-       high = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
-      loc_ptr += addr_size;
-
-      /* A base-address-selection entry.  */
-      if ((low & base_mask) == base_mask)
-       {
-         base_address = high + base_offset;
-         continue;
-       }
-
-      /* An end-of-list entry.  */
-      if (low == 0 && high == 0)
+       kind = decode_debug_loc_addresses (loc_ptr, buf_end, &new_ptr,
+                                          &low, &high,
+                                          byte_order, addr_size,
+                                          signed_addr_p);
+      loc_ptr = new_ptr;
+      switch (kind)
        {
+       case DEBUG_LOC_END_OF_LIST:
          *locexpr_length = 0;
          return NULL;
+       case DEBUG_LOC_BASE_ADDRESS:
+         base_address = high + base_offset;
+         continue;
+       case DEBUG_LOC_NORMAL:
+         break;
+       case DEBUG_LOC_BUFFER_OVERFLOW:
+       case DEBUG_LOC_INVALID_ENTRY:
+         error (_("dwarf2_find_location_expression: "
+                  "Corrupted DWARF expression."));
+       default:
+         gdb_assert_not_reached ("bad debug_loc_kind");
        }
 
       /* Otherwise, a location expression entry.  */
@@ -2451,8 +2566,8 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
   while (op_ptr < op_end)
     {
       enum dwarf_location_atom op = *op_ptr;
-      ULONGEST uoffset, reg;
-      LONGEST offset;
+      unsigned long long uoffset, reg;
+      long long offset;
       int i;
 
       offsets[op_ptr - base] = expr->len;
@@ -2556,11 +2671,11 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
          op_ptr += 8;
          break;
        case DW_OP_constu:
-         op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
+         op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
          ax_const_l (expr, uoffset);
          break;
        case DW_OP_consts:
-         op_ptr = read_sleb128 (op_ptr, op_end, &offset);
+         op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
          ax_const_l (expr, offset);
          break;
 
@@ -2602,7 +2717,7 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
          break;
 
        case DW_OP_regx:
-         op_ptr = read_uleb128 (op_ptr, op_end, &reg);
+         op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
          dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx");
          loc->u.reg = translate_register (arch, reg);
          loc->kind = axs_lvalue_register;
@@ -2610,9 +2725,9 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
 
        case DW_OP_implicit_value:
          {
-           ULONGEST len;
+           unsigned long long len;
 
-           op_ptr = read_uleb128 (op_ptr, op_end, &len);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &len);
            if (op_ptr + len > op_end)
              error (_("DW_OP_implicit_value: too few bytes available."));
            if (len > sizeof (ULONGEST))
@@ -2666,7 +2781,7 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
        case DW_OP_breg29:
        case DW_OP_breg30:
        case DW_OP_breg31:
-         op_ptr = read_sleb128 (op_ptr, op_end, &offset);
+         op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
          i = translate_register (arch, op - DW_OP_breg0);
          ax_reg (expr, i);
          if (offset != 0)
@@ -2677,8 +2792,8 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
          break;
        case DW_OP_bregx:
          {
-           op_ptr = read_uleb128 (op_ptr, op_end, &reg);
-           op_ptr = read_sleb128 (op_ptr, op_end, &offset);
+           op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
+           op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
            i = translate_register (arch, reg);
            ax_reg (expr, i);
            if (offset != 0)
@@ -2709,7 +2824,7 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
            dwarf_expr_frame_base_1 (framefunc, expr->scope,
                                     &datastart, &datalen);
 
-           op_ptr = read_sleb128 (op_ptr, op_end, &offset);
+           op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
            dwarf2_compile_expr_to_ax (expr, loc, arch, addr_size, datastart,
                                       datastart + datalen, per_cu);
 
@@ -2810,7 +2925,7 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
          break;
 
        case DW_OP_plus_uconst:
-         op_ptr = read_uleb128 (op_ptr, op_end, &reg);
+         op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
          /* It would be really weird to emit `DW_OP_plus_uconst 0',
             but we micro-optimize anyhow.  */
          if (reg != 0)
@@ -2960,20 +3075,20 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
         case DW_OP_piece:
        case DW_OP_bit_piece:
          {
-           ULONGEST size, offset;
+           unsigned long long size, offset;
 
            if (op_ptr - 1 == previous_piece)
              error (_("Cannot translate empty pieces to agent expressions"));
            previous_piece = op_ptr - 1;
 
-            op_ptr = read_uleb128 (op_ptr, op_end, &size);
+            op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
            if (op == DW_OP_piece)
              {
                size *= 8;
                offset = 0;
              }
            else
-             op_ptr = read_uleb128 (op_ptr, op_end, &offset);
+             op_ptr = safe_read_uleb128 (op_ptr, op_end, &offset);
 
            if (bits_collected + size > 8 * sizeof (LONGEST))
              error (_("Expression pieces exceed word size"));
@@ -3133,7 +3248,8 @@ locexpr_regname (struct gdbarch *gdbarch, int dwarf_regnum)
 /* Nicely describe a single piece of a location, returning an updated
    position in the bytecode sequence.  This function cannot recognize
    all locations; if a location is not recognized, it simply returns
-   DATA.  */
+   DATA.  If there is an error during reading, e.g. we run off the end
+   of the buffer, an error is thrown.  */
 
 static const gdb_byte *
 locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
@@ -3151,9 +3267,9 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
     }
   else if (data[0] == DW_OP_regx)
     {
-      ULONGEST reg;
+      unsigned long long reg;
 
-      data = read_uleb128 (data + 1, end, &reg);
+      data = safe_read_uleb128 (data + 1, end, &reg);
       fprintf_filtered (stream, _("a variable in $%s"),
                        locexpr_regname (gdbarch, reg));
     }
@@ -3162,12 +3278,12 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
       struct block *b;
       struct symbol *framefunc;
       int frame_reg = 0;
-      LONGEST frame_offset;
+      long long frame_offset;
       const gdb_byte *base_data, *new_data, *save_data = data;
       size_t base_size;
-      LONGEST base_offset = 0;
+      long long base_offset = 0;
 
-      new_data = read_sleb128 (data + 1, end, &frame_offset);
+      new_data = safe_read_sleb128 (data + 1, end, &frame_offset);
       if (!piece_end_p (new_data, end))
        return data;
       data = new_data;
@@ -3191,8 +3307,8 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
          const gdb_byte *buf_end;
          
          frame_reg = base_data[0] - DW_OP_breg0;
-         buf_end = read_sleb128 (base_data + 1,
-                                 base_data + base_size, &base_offset);
+         buf_end = safe_read_sleb128 (base_data + 1, base_data + base_size,
+                                      &base_offset);
          if (buf_end != base_data + base_size)
            error (_("Unexpected opcode after "
                     "DW_OP_breg%u for symbol \"%s\"."),
@@ -3219,9 +3335,9 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
   else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31
           && piece_end_p (data, end))
     {
-      LONGEST offset;
+      long long offset;
 
-      data = read_sleb128 (data + 1, end, &offset);
+      data = safe_read_sleb128 (data + 1, end, &offset);
 
       fprintf_filtered (stream,
                        _("a variable at offset %s from base reg $%s"),
@@ -3276,7 +3392,9 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
 /* Disassemble an expression, stopping at the end of a piece or at the
    end of the expression.  Returns a pointer to the next unread byte
    in the input expression.  If ALL is nonzero, then this function
-   will keep going until it reaches the end of the expression.  */
+   will keep going until it reaches the end of the expression.
+   If there is an error during reading, e.g. we run off the end
+   of the buffer, an error is thrown.  */
 
 static const gdb_byte *
 disassemble_dwarf_expression (struct ui_file *stream,
@@ -3291,8 +3409,8 @@ disassemble_dwarf_expression (struct ui_file *stream,
             || (data[0] != DW_OP_piece && data[0] != DW_OP_bit_piece)))
     {
       enum dwarf_location_atom op = *data++;
-      ULONGEST ul;
-      LONGEST l;
+      unsigned long long ul;
+      long long l;
       const char *name;
 
       name = get_DW_OP_name (op);
@@ -3353,11 +3471,11 @@ disassemble_dwarf_expression (struct ui_file *stream,
          fprintf_filtered (stream, " %s", plongest (l));
          break;
        case DW_OP_constu:
-         data = read_uleb128 (data, end, &ul);
+         data = safe_read_uleb128 (data, end, &ul);
          fprintf_filtered (stream, " %s", pulongest (ul));
          break;
        case DW_OP_consts:
-         data = read_sleb128 (data, end, &l);
+         data = safe_read_sleb128 (data, end, &l);
          fprintf_filtered (stream, " %s", plongest (l));
          break;
 
@@ -3398,13 +3516,13 @@ disassemble_dwarf_expression (struct ui_file *stream,
          break;
 
        case DW_OP_regx:
-         data = read_uleb128 (data, end, &ul);
+         data = safe_read_uleb128 (data, end, &ul);
          fprintf_filtered (stream, " %s [$%s]", pulongest (ul),
                            locexpr_regname (arch, (int) ul));
          break;
 
        case DW_OP_implicit_value:
-         data = read_uleb128 (data, end, &ul);
+         data = safe_read_uleb128 (data, end, &ul);
          data += ul;
          fprintf_filtered (stream, " %s", pulongest (ul));
          break;
@@ -3441,14 +3559,14 @@ disassemble_dwarf_expression (struct ui_file *stream,
        case DW_OP_breg29:
        case DW_OP_breg30:
        case DW_OP_breg31:
-         data = read_sleb128 (data, end, &l);
+         data = safe_read_sleb128 (data, end, &l);
          fprintf_filtered (stream, " %s [$%s]", plongest (l),
                            locexpr_regname (arch, op - DW_OP_breg0));
          break;
 
        case DW_OP_bregx:
-         data = read_uleb128 (data, end, &ul);
-         data = read_sleb128 (data, end, &l);
+         data = safe_read_uleb128 (data, end, &ul);
+         data = safe_read_sleb128 (data, end, &l);
          fprintf_filtered (stream, " register %s [$%s] offset %s",
                            pulongest (ul),
                            locexpr_regname (arch, (int) ul),
@@ -3456,7 +3574,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
          break;
 
        case DW_OP_fbreg:
-         data = read_sleb128 (data, end, &l);
+         data = safe_read_sleb128 (data, end, &l);
          fprintf_filtered (stream, " %s", plongest (l));
          break;
 
@@ -3468,7 +3586,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
          break;
 
        case DW_OP_plus_uconst:
-         data = read_uleb128 (data, end, &ul);
+         data = safe_read_uleb128 (data, end, &ul);
          fprintf_filtered (stream, " %s", pulongest (ul));
          break;
 
@@ -3506,16 +3624,16 @@ disassemble_dwarf_expression (struct ui_file *stream,
          break;
 
         case DW_OP_piece:
-         data = read_uleb128 (data, end, &ul);
+         data = safe_read_uleb128 (data, end, &ul);
          fprintf_filtered (stream, " %s (bytes)", pulongest (ul));
          break;
 
        case DW_OP_bit_piece:
          {
-           ULONGEST offset;
+           unsigned long long offset;
 
-           data = read_uleb128 (data, end, &ul);
-           data = read_uleb128 (data, end, &offset);
+           data = safe_read_uleb128 (data, end, &ul);
+           data = safe_read_uleb128 (data, end, &offset);
            fprintf_filtered (stream, " size %s offset %s (bits)",
                              pulongest (ul), pulongest (offset));
          }
@@ -3527,7 +3645,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
                                           gdbarch_byte_order (arch));
            data += offset_size;
 
-           data = read_sleb128 (data, end, &l);
+           data = safe_read_sleb128 (data, end, &l);
 
            fprintf_filtered (stream, " DIE %s offset %s",
                              phex_nz (ul, offset_size),
@@ -3541,7 +3659,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
            cu_offset offset;
            struct type *type;
 
-           data = read_uleb128 (data, end, &ul);
+           data = safe_read_uleb128 (data, end, &ul);
            offset.cu_off = ul;
            type = dwarf2_get_die_type (offset, per_cu);
            fprintf_filtered (stream, "<");
@@ -3556,7 +3674,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
            cu_offset type_die;
            struct type *type;
 
-           data = read_uleb128 (data, end, &ul);
+           data = safe_read_uleb128 (data, end, &ul);
            type_die.cu_off = ul;
            type = dwarf2_get_die_type (type_die, per_cu);
            fprintf_filtered (stream, "<");
@@ -3567,12 +3685,12 @@ disassemble_dwarf_expression (struct ui_file *stream,
 
        case DW_OP_GNU_regval_type:
          {
-           ULONGEST reg;
+           unsigned long long reg;
            cu_offset type_die;
            struct type *type;
 
-           data = read_uleb128 (data, end, &reg);
-           data = read_uleb128 (data, end, &ul);
+           data = safe_read_uleb128 (data, end, &reg);
+           data = safe_read_uleb128 (data, end, &ul);
            type_die.cu_off = ul;
 
            type = dwarf2_get_die_type (type_die, per_cu);
@@ -3589,7 +3707,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
          {
            cu_offset type_die;
 
-           data = read_uleb128 (data, end, &ul);
+           data = safe_read_uleb128 (data, end, &ul);
            type_die.cu_off = ul;
 
            if (type_die.cu_off == 0)
@@ -3607,7 +3725,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
          break;
 
        case DW_OP_GNU_entry_value:
-         data = read_uleb128 (data, end, &ul);
+         data = safe_read_uleb128 (data, end, &ul);
          fputc_filtered ('\n', stream);
          disassemble_dwarf_expression (stream, arch, addr_size, offset_size,
                                        start, data, data + ul, indent + 2,
@@ -3676,9 +3794,9 @@ locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr,
            fprintf_filtered (stream, "   ");
          if (data[0] == DW_OP_piece)
            {
-             ULONGEST bytes;
+             unsigned long long bytes;
 
-             data = read_uleb128 (data + 1, end, &bytes);
+             data = safe_read_uleb128 (data + 1, end, &bytes);
 
              if (empty)
                fprintf_filtered (stream, _("an empty %s-byte piece"),
@@ -3689,10 +3807,10 @@ locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr,
            }
          else if (data[0] == DW_OP_bit_piece)
            {
-             ULONGEST bits, offset;
+             unsigned long long bits, offset;
 
-             data = read_uleb128 (data + 1, end, &bits);
-             data = read_uleb128 (data, end, &offset);
+             data = safe_read_uleb128 (data + 1, end, &bits);
+             data = safe_read_uleb128 (data, end, &offset);
 
              if (empty)
                fprintf_filtered (stream,
@@ -3832,19 +3950,18 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
                           struct ui_file *stream)
 {
   struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
-  CORE_ADDR low, high;
   const gdb_byte *loc_ptr, *buf_end;
-  int length, first = 1;
+  int first = 1;
   struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
   int offset_size = dwarf2_per_cu_offset_size (dlbaton->per_cu);
   int signed_addr_p = bfd_get_sign_extend_vma (objfile->obfd);
-  CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
   /* Adjust base_address for relocatable objects.  */
   CORE_ADDR base_offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
   CORE_ADDR base_address = dlbaton->base_address + base_offset;
+  int done = 0;
 
   loc_ptr = dlbaton->data;
   buf_end = dlbaton->data + dlbaton->size;
@@ -3852,37 +3969,43 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
   fprintf_filtered (stream, _("multi-location:\n"));
 
   /* Iterate through locations until we run out.  */
-  while (1)
+  while (!done)
     {
-      if (buf_end - loc_ptr < 2 * addr_size)
-       error (_("Corrupted DWARF expression for symbol \"%s\"."),
-              SYMBOL_PRINT_NAME (symbol));
-
-      if (signed_addr_p)
-       low = extract_signed_integer (loc_ptr, addr_size, byte_order);
-      else
-       low = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
-      loc_ptr += addr_size;
-
-      if (signed_addr_p)
-       high = extract_signed_integer (loc_ptr, addr_size, byte_order);
+      CORE_ADDR low = 0, high = 0; /* init for gcc -Wall */
+      int length;
+      enum debug_loc_kind kind;
+      const gdb_byte *new_ptr = NULL; /* init for gcc -Wall */
+
+      if (dlbaton->from_dwo)
+       kind = decode_debug_loc_dwo_addresses (dlbaton->per_cu,
+                                              loc_ptr, buf_end, &new_ptr,
+                                              &low, &high);
       else
-       high = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
-      loc_ptr += addr_size;
-
-      /* A base-address-selection entry.  */
-      if ((low & base_mask) == base_mask)
+       kind = decode_debug_loc_addresses (loc_ptr, buf_end, &new_ptr,
+                                          &low, &high,
+                                          byte_order, addr_size,
+                                          signed_addr_p);
+      loc_ptr = new_ptr;
+      switch (kind)
        {
+       case DEBUG_LOC_END_OF_LIST:
+         done = 1;
+         continue;
+       case DEBUG_LOC_BASE_ADDRESS:
          base_address = high + base_offset;
          fprintf_filtered (stream, _("  Base address %s"),
                            paddress (gdbarch, base_address));
          continue;
+       case DEBUG_LOC_NORMAL:
+         break;
+       case DEBUG_LOC_BUFFER_OVERFLOW:
+       case DEBUG_LOC_INVALID_ENTRY:
+         error (_("Corrupted DWARF expression for symbol \"%s\"."),
+                SYMBOL_PRINT_NAME (symbol));
+       default:
+         gdb_assert_not_reached ("bad debug_loc_kind");
        }
 
-      /* An end-of-list entry.  */
-      if (low == 0 && high == 0)
-       break;
-
       /* Otherwise, a location expression entry.  */
       low += base_address;
       high += base_address;
index 370402e0a42579ebcffc460b90ffa952eb34c2d7..e9d06a330d3e3b6c12183682619cf708390b645a 100644 (file)
@@ -119,6 +119,10 @@ struct dwarf2_loclist_baton
   /* The compilation unit containing the symbol whose location
      we're computing.  */
   struct dwarf2_per_cu_data *per_cu;
+
+  /* Non-zero if the location list lives in .debug_loc.dwo.
+     The format of entries in this section are different.  */
+  unsigned char from_dwo;
 };
 
 extern const struct symbol_computed_ops dwarf2_locexpr_funcs;
index 6ddf23657b6bc3a4beb2126e71bd6b571747bc4f..b590134d4760f0c97170dca5bec0f5008cc9a45a 100644 (file)
@@ -606,6 +606,9 @@ struct die_reader_specs
 
   /* die_section->buffer.  */
   gdb_byte *buffer;
+
+  /* The end of the buffer.  */
+  const gdb_byte *buffer_end;
 };
 
 /* Type of function passed to init_cutu_and_read_dies, et.al.  */
@@ -968,11 +971,13 @@ dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
 }
 
 static void
-dwarf2_macros_too_long_complaint (struct dwarf2_section_info *section)
+dwarf2_section_buffer_overflow_complaint (struct dwarf2_section_info *section)
 {
   complaint (&symfile_complaints,
-            _("macro info runs off end of `%s' section"),
-            section->asection->name);
+            _("debug info runs off end of %s section"
+              " [in module %s]"),
+            section->asection->name,
+            bfd_get_filename (section->asection->owner));
 }
 
 static void
@@ -1104,8 +1109,6 @@ static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *, gdb_byte *,
 static char *read_str_index (const struct die_reader_specs *reader,
                             struct dwarf2_cu *cu, ULONGEST str_index);
 
-static gdb_byte *skip_leb128 (bfd *, gdb_byte *);
-
 static void set_cu_language (unsigned int, struct dwarf2_cu *);
 
 static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
@@ -3656,6 +3659,7 @@ init_cu_die_reader (struct die_reader_specs *reader,
   reader->dwo_file = dwo_file;
   reader->die_section = section;
   reader->buffer = section->buffer;
+  reader->buffer_end = section->buffer + section->size;
 }
 
 /* Find the base address of the compilation unit for range lists and
@@ -5034,6 +5038,8 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
   bfd *abfd = reader->abfd;
   struct dwarf2_cu *cu = reader->cu;
   gdb_byte *buffer = reader->buffer;
+  const gdb_byte *buffer_end = reader->buffer_end;
+  gdb_byte *start_info_ptr = info_ptr;
   unsigned int form, i;
 
   for (i = 0; i < abbrev->num_attrs; i++)
@@ -5112,7 +5118,7 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
        case DW_FORM_ref_udata:
        case DW_FORM_GNU_addr_index:
        case DW_FORM_GNU_str_index:
-         info_ptr = skip_leb128 (abfd, info_ptr);
+         info_ptr = (gdb_byte *) safe_skip_leb128 (info_ptr, buffer_end);
          break;
        case DW_FORM_indirect:
          form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
@@ -12273,22 +12279,6 @@ read_str_index (const struct die_reader_specs *reader,
   return (char *) (sections->str.buffer + str_offset);
 }
 
-/* Return a pointer to just past the end of an LEB128 number in BUF.  */
-
-static gdb_byte *
-skip_leb128 (bfd *abfd, gdb_byte *buf)
-{
-  int byte;
-
-  while (1)
-    {
-      byte = bfd_get_8 (abfd, buf);
-      buf++;
-      if ((byte & 128) == 0)
-       return buf;
-    }
-}
-
 /* Return the length of an LEB128 number in BUF.  */
 
 static int
@@ -15783,7 +15773,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
    Returns the new pointer.  */
 
 static gdb_byte *
-skip_form_bytes (bfd *abfd, gdb_byte *bytes,
+skip_form_bytes (bfd *abfd, gdb_byte *bytes, gdb_byte *buffer_end,
                 enum dwarf_form form,
                 unsigned int offset_size,
                 struct dwarf2_section_info *section)
@@ -15838,7 +15828,12 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes,
     case DW_FORM_udata:
     case DW_FORM_GNU_addr_index:
     case DW_FORM_GNU_str_index:
-      bytes = skip_leb128 (abfd, bytes);
+      bytes = (gdb_byte *) gdb_skip_leb128 (bytes, buffer_end);
+      if (bytes == NULL)
+       {
+         dwarf2_section_buffer_overflow_complaint (section);
+         return NULL;
+       }
       break;
 
     default:
@@ -15862,7 +15857,7 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes,
 static gdb_byte *
 skip_unknown_opcode (unsigned int opcode,
                     gdb_byte **opcode_definitions,
-                    gdb_byte *mac_ptr,
+                    gdb_byte *mac_ptr, gdb_byte *mac_end,
                     bfd *abfd,
                     unsigned int offset_size,
                     struct dwarf2_section_info *section)
@@ -15885,7 +15880,8 @@ skip_unknown_opcode (unsigned int opcode,
 
   for (i = 0; i < arg; ++i)
     {
-      mac_ptr = skip_form_bytes (abfd, mac_ptr, defn[i], offset_size, section);
+      mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end, defn[i], offset_size,
+                                section);
       if (mac_ptr == NULL)
        {
          /* skip_form_bytes already issued the complaint.  */
@@ -15996,7 +15992,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
       /* Do we at least have room for a macinfo type byte?  */
       if (mac_ptr >= mac_end)
        {
-         dwarf2_macros_too_long_complaint (section);
+         dwarf2_section_buffer_overflow_complaint (section);
          break;
        }
 
@@ -16123,7 +16119,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
                   /* Do we at least have room for a macinfo type byte?  */
                   if (mac_ptr >= mac_end)
                     {
-                     dwarf2_macros_too_long_complaint (section);
+                     dwarf2_section_buffer_overflow_complaint (section);
                       return;
                     }
 
@@ -16191,7 +16187,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
 
        default:
          mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
-                                        mac_ptr, abfd, offset_size,
+                                        mac_ptr, mac_end, abfd, offset_size,
                                         section);
          if (mac_ptr == NULL)
            return;
@@ -16334,7 +16330,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
 
        default:
          mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
-                                        mac_ptr, abfd, offset_size,
+                                        mac_ptr, mac_end, abfd, offset_size,
                                         section);
          if (mac_ptr == NULL)
            return;
@@ -16450,6 +16446,7 @@ fill_in_loclist_baton (struct dwarf2_cu *cu,
   baton->size = section->size - DW_UNSND (attr);
   baton->data = section->buffer + DW_UNSND (attr);
   baton->base_address = cu->base_address;
+  baton->from_dwo = cu->dwo_unit != NULL;
 }
 
 static void