* readelf.c (display_debug_info): Apply RELA relocations on the
authorAlexandre Oliva <aoliva@redhat.com>
Wed, 9 Apr 2003 04:07:56 +0000 (04:07 +0000)
committerAlexandre Oliva <aoliva@redhat.com>
Wed, 9 Apr 2003 04:07:56 +0000 (04:07 +0000)
entire section.
(byte_put_little_endian, byte_put_big_endian): New functions.
(byte_put): New variable.
(get_file_header): Initialize it.

binutils/ChangeLog
binutils/readelf.c

index 1aae5dedf2343cb3505b19fac83c33adee6dfc71..01e88e5ae340dd23698a40102f7fc0f443e7e361 100644 (file)
@@ -1,3 +1,11 @@
+2003-04-09  Alexandre Oliva  <aoliva@redhat.com>
+
+       * readelf.c (display_debug_info): Apply RELA relocations on the
+       entire section.
+       (byte_put_little_endian, byte_put_big_endian): New functions.
+       (byte_put): New variable.
+       (get_file_header): Initialize it.
+
 2003-04-05  Dimitrie O. Paun <dpaun@rogers.com>
 
        * windres.c: Add -l for compatibility with wrc, and rc.
index 16733d91693d0bb149b9fb025d1b3e73bfb30472..7e288fef3b0d95b94aa322fc50a13ab9cb47f568 100644 (file)
@@ -173,6 +173,12 @@ static bfd_vma byte_get_little_endian
   PARAMS ((unsigned char *, int));
 static bfd_vma byte_get_big_endian
   PARAMS ((unsigned char *, int));
+static void (*byte_put)
+  PARAMS ((unsigned char *, bfd_vma, int));
+static void byte_put_little_endian
+  PARAMS ((unsigned char *, bfd_vma, int));
+static void byte_put_big_endian
+  PARAMS ((unsigned char *, bfd_vma, int));
 static const char *get_mips_dynamic_type
   PARAMS ((unsigned long));
 static const char *get_sparc64_dynamic_type
@@ -550,6 +556,37 @@ byte_get_little_endian (field, size)
     }
 }
 
+static void
+byte_put_little_endian (field, value, size)
+     unsigned char * field;
+     bfd_vma        value;
+     int             size;
+{
+  switch (size)
+    {
+    case 8:
+      field[7] = (((value >> 24) >> 24) >> 8) & 0xff;
+      field[6] = ((value >> 24) >> 24) & 0xff;
+      field[5] = ((value >> 24) >> 16) & 0xff;
+      field[4] = ((value >> 24) >> 8) & 0xff;
+      /* Fall through.  */
+    case 4:
+      field[3] = (value >> 24) & 0xff;
+      field[2] = (value >> 16) & 0xff;
+      /* Fall through.  */
+    case 2:
+      field[1] = (value >> 8) & 0xff;
+      /* Fall through.  */
+    case 1:
+      field[0] = value & 0xff;
+      break;
+
+    default:
+      error (_("Unhandled data length: %d\n"), size);
+      abort ();
+    }
+}
+
 /* Print a VMA value.  */
 static void
 print_vma (vma, mode)
@@ -708,6 +745,41 @@ byte_get_big_endian (field, size)
     }
 }
 
+static void
+byte_put_big_endian (field, value, size)
+     unsigned char * field;
+     bfd_vma        value;
+     int             size;
+{
+  switch (size)
+    {
+    case 8:
+      field[7] = value & 0xff;
+      field[6] = (value >> 8) & 0xff;
+      field[5] = (value >> 16) & 0xff;
+      field[4] = (value >> 24) & 0xff;
+      value >>= 16;
+      value >>= 16;
+      /* Fall through.  */
+    case 4:
+      field[3] = value & 0xff;
+      field[2] = (value >> 8) & 0xff;
+      value >>= 16;
+      /* Fall through.  */
+    case 2:
+      field[1] = value & 0xff;
+      value >>= 8;
+      /* Fall through.  */
+    case 1:
+      field[0] = value & 0xff;
+      break;
+
+    default:
+      error (_("Unhandled data length: %d\n"), size);
+      abort ();
+    }
+}
+
 /* Guess the relocation size commonly used by the specific machines.  */
 
 static int
@@ -8290,15 +8362,7 @@ display_debug_info (section, start, file)
       compunit.cu_version = byte_get (hdrptr, 2);
       hdrptr += 2;
 
-      cu_abbrev_offset_ptr = hdrptr;
-      compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
-      hdrptr += offset_size;
-
-      compunit.cu_pointer_size = byte_get (hdrptr, 1);
-      hdrptr += 1;
-
-      /* Check for RELA relocations in the
-        abbrev_offset address, and apply them.  */
+      /* Apply addends of RELA relocations.  */
       for (relsec = section_headers;
           relsec < section_headers + elf_header.e_shnum;
           ++relsec)
@@ -8323,8 +8387,13 @@ display_debug_info (section, start, file)
 
          for (rp = rela; rp < rela + nrelas; ++rp)
            {
-             if (rp->r_offset
-                 != (bfd_vma) (cu_abbrev_offset_ptr - section_begin))
+             unsigned char *loc;
+
+             if (rp->r_offset >= (bfd_vma) (hdrptr - section_begin)
+                 && section->sh_size > (bfd_vma) offset_size
+                 && rp->r_offset <= section->sh_size - offset_size)
+               loc = section_begin + rp->r_offset;
+             else
                continue;
 
              if (is_32bit_elf)
@@ -8352,14 +8421,20 @@ display_debug_info (section, start, file)
                    }
                }
 
-             compunit.cu_abbrev_offset = rp->r_addend;
-             break;
+             byte_put (loc, rp->r_addend, offset_size);
            }
 
          free (rela);
          break;
        }
 
+      cu_abbrev_offset_ptr = hdrptr;
+      compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
+      hdrptr += offset_size;
+
+      compunit.cu_pointer_size = byte_get (hdrptr, 1);
+      hdrptr += 1;
+
       tags = hdrptr;
       cu_offset = start - section_begin;
       start += compunit.cu_length + initial_length_size;
@@ -10294,8 +10369,14 @@ get_file_header (file)
     {
     default: /* fall through */
     case ELFDATANONE: /* fall through */
-    case ELFDATA2LSB: byte_get = byte_get_little_endian; break;
-    case ELFDATA2MSB: byte_get = byte_get_big_endian; break;
+    case ELFDATA2LSB:
+      byte_get = byte_get_little_endian;
+      byte_put = byte_put_little_endian;
+      break;
+    case ELFDATA2MSB:
+      byte_get = byte_get_big_endian;
+      byte_put = byte_put_big_endian;
+      break;
     }
 
   /* For now we only support 32 bit and 64 bit ELF files.  */