* readelf.c (byte_get_signed): New.
authorRichard Henderson <rth@redhat.com>
Sat, 31 May 2003 19:29:19 +0000 (19:29 +0000)
committerRichard Henderson <rth@redhat.com>
Sat, 31 May 2003 19:29:19 +0000 (19:29 +0000)
        (get_encoded_value): New.
        (display_debug_frames): Use it.  Always pre-process opcodes.

binutils/ChangeLog
binutils/readelf.c

index 18a704452674bf01ce0754d0019221fd2ded3e2d..85d4f9790118e9ecb05afb793da5b7f08fdc4f02 100644 (file)
@@ -1,3 +1,9 @@
+2003-05-31  Richard Henderson  <rth@redhat.com>
+
+       * readelf.c (byte_get_signed): New.
+       (get_encoded_value): New.
+       (display_debug_frames): Use it.  Always pre-process opcodes.
+
 2003-05-20  Michal Ludvig  <mludvig@suse.cz>
 
        * readelf.c (display_debug_frames): Print both registers
index 8fcfda4bda6efc7b5e534b5d14818048e1c58a61..dbd802aa060c1363c1bacbbcecc948f984cada4f 100644 (file)
@@ -173,6 +173,8 @@ static bfd_vma byte_get_little_endian
   PARAMS ((unsigned char *, int));
 static bfd_vma byte_get_big_endian
   PARAMS ((unsigned char *, int));
+static bfd_vma byte_get_signed
+  PARAMS ((unsigned char *, int));
 static void (*byte_put)
   PARAMS ((unsigned char *, bfd_vma, int));
 static void byte_put_little_endian
@@ -556,6 +558,29 @@ byte_get_little_endian (field, size)
     }
 }
 
+static bfd_vma
+byte_get_signed (field, size)
+     unsigned char *field;
+     int size;
+{
+  bfd_vma x = byte_get (field, size);
+
+  switch (size)
+    {
+    case 1:
+      return (x ^ 0x80) - 0x80;
+    case 2:
+      return (x ^ 0x8000) - 0x8000;
+    case 4:
+      return (x ^ 0x80000000) - 0x80000000;
+    case 8:
+    case -8:
+      return x;
+    default:
+      abort ();
+    }
+}
+
 static void
 byte_put_little_endian (field, value, size)
      unsigned char * field;
@@ -8668,6 +8693,7 @@ Frame_Chunk;
 static void frame_need_space PARAMS ((Frame_Chunk *, int));
 static void frame_display_row PARAMS ((Frame_Chunk *, int *, int *));
 static int size_of_encoded_value PARAMS ((int));
+static bfd_vma get_encoded_value PARAMS ((unsigned char *, int));
 
 static void
 frame_need_space (fc, reg)
@@ -8775,6 +8801,18 @@ size_of_encoded_value (encoding)
     }
 }
 
+static bfd_vma
+get_encoded_value (data, encoding)
+     unsigned char *data;
+     int encoding;
+{
+  int size = size_of_encoded_value (encoding);
+  if (encoding & DW_EH_PE_signed)
+    return byte_get_signed (data, size);
+  else
+    return byte_get (data, size);
+}
+
 #define GET(N) byte_get (start, N); start += N
 #define LEB()  read_leb128 (start, & length_return, 0); start += length_return
 #define SLEB() read_leb128 (start, & length_return, 1); start += length_return
@@ -8980,7 +9018,7 @@ display_debug_frames (section, start, file)
          if (fc->fde_encoding)
            encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
-         fc->pc_begin = byte_get (start, encoded_ptr_size);
+         fc->pc_begin = get_encoded_value (start, fc->fde_encoding);
          if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
            fc->pc_begin += section->sh_addr + (start - section_start);
          start += encoded_ptr_size;
@@ -9011,8 +9049,12 @@ display_debug_frames (section, start, file)
 
       /* At this point, fc is the current chunk, cie (if any) is set, and we're
         about to interpret instructions for the chunk.  */
-
-      if (do_debug_frames_interp)
+      /* ??? At present we need to do this always, since this sizes the
+        fc->col_type and fc->col_offset arrays, which we write into always.
+        We should probably split the interpreted and non-interpreted bits
+        into two different routines, since there's so much that doesn't
+        really overlap between them.  */
+      if (1 || do_debug_frames_interp)
        {
          /* Start by making a pass over the chunk, allocating storage
             and taking note of what registers are used.  */
@@ -9175,7 +9217,7 @@ display_debug_frames (section, start, file)
              break;
 
            case DW_CFA_set_loc:
-             vma = byte_get (start, encoded_ptr_size);
+             vma = get_encoded_value (start, fc->fde_encoding);
              if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
                vma += section->sh_addr + (start - section_start);
              start += encoded_ptr_size;