]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Move read_rel and check_range_relocations to reloc module
authorPetr Machata <pmachata@redhat.com>
Tue, 21 Sep 2010 19:19:16 +0000 (21:19 +0200)
committerPetr Machata <pmachata@redhat.com>
Tue, 21 Sep 2010 19:19:16 +0000 (21:19 +0200)
dwarflint/Makefile.am
dwarflint/elf_file.ii [new file with mode: 0644]
dwarflint/low.c
dwarflint/low.h
dwarflint/reloc.cc
dwarflint/reloc.h

index b034f5cf138c0543de0d375b24a35cf28cab30fa..ea22753dae471c2ac400674812944c7e458a53f3 100644 (file)
@@ -42,7 +42,7 @@ dwarflint_SOURCES = \
        checkdescriptor.cc checkdescriptor.hh checkdescriptor.ii \
        checkrule.cc checkrule.hh \
        dwarflint.cc dwarflint.hh dwarflint.ii misc.h \
-       low.c low.h \
+       low.c low.h elf_file.ii \
        expected-at.cc expected.hh \
        coverage.cc coverage.h \
        readctx.c readctx.h \
diff --git a/dwarflint/elf_file.ii b/dwarflint/elf_file.ii
new file mode 100644 (file)
index 0000000..f1daaf0
--- /dev/null
@@ -0,0 +1,4 @@
+struct sec;
+struct elf_file;
+struct abbrev_table;
+struct cu;
index 85aafaa89c368a26409f5d7cdd4e3883ab834209..6a4e649a21761c80ad1c7d4bd631cc2068686ef6 100644 (file)
@@ -144,177 +144,3 @@ supported_version (unsigned version,
 
   return retval;
 }
-
-void
-check_range_relocations (enum message_category cat,
-                        struct where *where,
-                        struct elf_file const *file,
-                        GElf_Sym *begin_symbol,
-                        GElf_Sym *end_symbol,
-                        const char *description)
-{
-  if (begin_symbol != NULL
-      && end_symbol != NULL
-      && begin_symbol->st_shndx != end_symbol->st_shndx)
-    wr_message (cat | mc_impact_2 | mc_reloc, where,
-               ": %s relocated against different sections (%s and %s).\n",
-               description,
-               file->sec[begin_symbol->st_shndx].name,
-               file->sec[end_symbol->st_shndx].name);
-}
-
-static GElf_Rela *
-get_rel_or_rela (Elf_Data *data, int ndx,
-                GElf_Rela *dst, size_t type)
-{
-  if (type == SHT_RELA)
-    return gelf_getrela (data, ndx, dst);
-  else
-    {
-      assert (type == SHT_REL);
-      GElf_Rel rel_mem;
-      if (gelf_getrel (data, ndx, &rel_mem) == NULL)
-       return NULL;
-      dst->r_offset = rel_mem.r_offset;
-      dst->r_info = rel_mem.r_info;
-      dst->r_addend = 0;
-      return dst;
-    }
-}
-
-bool
-read_rel (struct elf_file *file,
-         struct sec *sec,
-         Elf_Data *reldata,
-         bool elf_64)
-{
-  assert (sec->rel.type == SHT_REL
-         || sec->rel.type == SHT_RELA);
-  bool is_rela = sec->rel.type == SHT_RELA;
-
-  struct read_ctx ctx;
-  read_ctx_init (&ctx, sec->data, file->other_byte_order);
-
-  size_t entrysize
-    = elf_64
-    ? (is_rela ? sizeof (Elf64_Rela) : sizeof (Elf64_Rel))
-    : (is_rela ? sizeof (Elf32_Rela) : sizeof (Elf32_Rel));
-  size_t count = reldata->d_size / entrysize;
-
-  struct where parent = WHERE (sec->id, NULL);
-  struct where where = WHERE (is_rela ? sec_rela : sec_rel, NULL);
-  where.ref = &parent;
-
-  for (unsigned i = 0; i < count; ++i)
-    {
-      where_reset_1 (&where, i);
-
-      REALLOC (&sec->rel, rel);
-      struct relocation *cur = sec->rel.rel + sec->rel.size++;
-      WIPE (*cur);
-
-      GElf_Rela rela_mem, *rela
-       = get_rel_or_rela (reldata, i, &rela_mem, sec->rel.type);
-      if (rela == NULL)
-       {
-         wr_error (&where, ": couldn't read relocation.\n");
-       skip:
-         cur->invalid = true;
-         continue;
-       }
-
-      int cur_type = GELF_R_TYPE (rela->r_info);
-      if (cur_type == 0) /* No relocation.  */
-       {
-         wr_message (mc_impact_3 | mc_reloc | mc_acc_bloat, &where,
-                     ": NONE relocation is superfluous.\n");
-         goto skip;
-       }
-
-      cur->offset = rela->r_offset;
-      cur->symndx = GELF_R_SYM (rela->r_info);
-      cur->type = cur_type;
-
-      where_reset_2 (&where, cur->offset);
-
-      Elf_Type type = ebl_reloc_simple_type (file->ebl, cur->type);
-      int width;
-
-      switch (type)
-       {
-       case ELF_T_WORD:
-       case ELF_T_SWORD:
-         width = 4;
-         break;
-
-       case ELF_T_XWORD:
-       case ELF_T_SXWORD:
-         width = 8;
-         break;
-
-       case ELF_T_BYTE:
-       case ELF_T_HALF:
-         /* Technically legal, but never used.  Better have dwarflint
-            flag them as erroneous, because it's more likely these
-            are a result of a bug than actually being used.  */
-         {
-           char buf[64];
-           wr_error (&where, ": 8 or 16-bit relocation type %s.\n",
-                     ebl_reloc_type_name (file->ebl, cur->type,
-                                          buf, sizeof (buf)));
-           goto skip;
-         }
-
-       default:
-         {
-           char buf[64];
-           wr_error (&where, ": invalid relocation %d (%s).\n",
-                     cur->type,
-                     ebl_reloc_type_name (file->ebl, cur->type,
-                                          buf, sizeof (buf)));
-           goto skip;
-         }
-       };
-
-      if (cur->offset + width >= sec->data->d_size)
-       {
-         wr_error (&where,
-                   ": relocation doesn't fall into relocated section.\n");
-         goto skip;
-       }
-
-      uint64_t value;
-      if (width == 4)
-       value = dwarflint_read_4ubyte_unaligned
-         (sec->data->d_buf + cur->offset, file->other_byte_order);
-      else
-       {
-         assert (width == 8);
-         value = dwarflint_read_8ubyte_unaligned
-           (sec->data->d_buf + cur->offset, file->other_byte_order);
-       }
-
-      if (is_rela)
-       {
-         if (value != 0)
-           wr_message (mc_impact_2 | mc_reloc, &where,
-                       ": SHR_RELA relocates a place with non-zero value (addend=%#"
-                       PRIx64", value=%#"PRIx64").\n", rela->r_addend, value);
-         cur->addend = rela->r_addend;
-       }
-      else
-       cur->addend = value;
-    }
-
-  /* Sort the reloc section so that the applicable addresses of
-     relocation entries are monotonously increasing.  */
-  int compare (const void *a, const void *b)
-  {
-    return ((struct relocation *)a)->offset
-      - ((struct relocation *)b)->offset;
-  }
-
-  qsort (sec->rel.rel, sec->rel.size,
-        sizeof (*sec->rel.rel), &compare);
-  return true;
-}
index fa4af1edab0b8cd620d6cdc704829f052685a232..57ab140505ccdb51d3874f90d1622caa121a73d8 100644 (file)
@@ -93,8 +93,6 @@ extern "C"
   // xxx some of that will go away
   extern struct abbrev *abbrev_table_find_abbrev (struct abbrev_table const *abbrevs,
                                                  uint64_t abbrev_code);
-  extern bool read_rel (struct elf_file *file, struct sec *sec,
-                       Elf_Data *reldata, bool elf_64);
   extern bool address_aligned (uint64_t addr, uint64_t align);
   extern bool necessary_alignment (uint64_t start, uint64_t length,
                                   uint64_t align);
@@ -121,13 +119,6 @@ extern "C"
   };
 
   // xxx low-level check entry points, will go away
-  struct cu;
-  extern void check_range_relocations (enum message_category cat,
-                                      struct where *where,
-                                      struct elf_file const *file,
-                                      GElf_Sym *begin_symbol,
-                                      GElf_Sym *end_symbol,
-                                      const char *description);
 
   extern int check_sibling_form (dwarf_version_h ver, uint64_t form);
   extern bool is_location_attrib (uint64_t name);
index 44114c21695f7fbd9dcf3aa909f0ce590b5604a5..f271185a3089b820571ccd8bdea327fd875243e4 100644 (file)
    Network licensing program, please visit www.openinventionnetwork.com
    <http://www.openinventionnetwork.com>.  */
 
+// xxx drop as soon as not necessary
+#define __STDC_FORMAT_MACROS
+
 #include "reloc.h"
 #include "messages.h"
 #include "low.h"
 #include <sstream>
 #include <libebl.h>
 #include <cassert>
+#include <inttypes.h>
 
 static struct where
 where_from_reloc (struct relocation_data *reloc, struct where const *ref)
@@ -273,3 +277,178 @@ relocate_one (struct elf_file const *file,
        }
     }
 }
+
+static GElf_Rela *
+get_rel_or_rela (Elf_Data *data, int ndx,
+                GElf_Rela *dst, size_t type)
+{
+  if (type == SHT_RELA)
+    return gelf_getrela (data, ndx, dst);
+  else
+    {
+      assert (type == SHT_REL);
+      GElf_Rel rel_mem;
+      if (gelf_getrel (data, ndx, &rel_mem) == NULL)
+       return NULL;
+      dst->r_offset = rel_mem.r_offset;
+      dst->r_info = rel_mem.r_info;
+      dst->r_addend = 0;
+      return dst;
+    }
+}
+
+/* Sort the reloc section so that the applicable addresses of
+   relocation entries are monotonously increasing.  */
+static int
+compare_rel (const void *a, const void *b)
+{
+  return ((struct relocation *)a)->offset
+    - ((struct relocation *)b)->offset;
+}
+
+bool
+read_rel (struct elf_file *file,
+         struct sec *sec,
+         Elf_Data *reldata,
+         bool elf_64)
+{
+  assert (sec->rel.type == SHT_REL
+         || sec->rel.type == SHT_RELA);
+  bool is_rela = sec->rel.type == SHT_RELA;
+
+  struct read_ctx ctx;
+  read_ctx_init (&ctx, sec->data, file->other_byte_order);
+
+  size_t entrysize
+    = elf_64
+    ? (is_rela ? sizeof (Elf64_Rela) : sizeof (Elf64_Rel))
+    : (is_rela ? sizeof (Elf32_Rela) : sizeof (Elf32_Rel));
+  size_t count = reldata->d_size / entrysize;
+
+  struct where parent = WHERE (sec->id, NULL);
+  struct where where = WHERE (is_rela ? sec_rela : sec_rel, NULL);
+  where.ref = &parent;
+
+  for (unsigned i = 0; i < count; ++i)
+    {
+      where_reset_1 (&where, i);
+
+      REALLOC (&sec->rel, rel);
+      struct relocation *cur = sec->rel.rel + sec->rel.size++;
+      WIPE (*cur);
+
+      GElf_Rela rela_mem, *rela
+       = get_rel_or_rela (reldata, i, &rela_mem, sec->rel.type);
+      if (rela == NULL)
+       {
+         wr_error (&where, ": couldn't read relocation.\n");
+       skip:
+         cur->invalid = true;
+         continue;
+       }
+
+      int cur_type = GELF_R_TYPE (rela->r_info);
+      if (cur_type == 0) /* No relocation.  */
+       {
+         wr_message (mc_impact_3 | mc_reloc | mc_acc_bloat, &where,
+                     ": NONE relocation is superfluous.\n");
+         goto skip;
+       }
+
+      cur->offset = rela->r_offset;
+      cur->symndx = GELF_R_SYM (rela->r_info);
+      cur->type = cur_type;
+
+      where_reset_2 (&where, cur->offset);
+
+      Elf_Type type = ebl_reloc_simple_type (file->ebl, cur->type);
+      int width;
+
+      switch (type)
+       {
+       case ELF_T_WORD:
+       case ELF_T_SWORD:
+         width = 4;
+         break;
+
+       case ELF_T_XWORD:
+       case ELF_T_SXWORD:
+         width = 8;
+         break;
+
+       case ELF_T_BYTE:
+       case ELF_T_HALF:
+         /* Technically legal, but never used.  Better have dwarflint
+            flag them as erroneous, because it's more likely these
+            are a result of a bug than actually being used.  */
+         {
+           char buf[64];
+           wr_error (&where, ": 8 or 16-bit relocation type %s.\n",
+                     ebl_reloc_type_name (file->ebl, cur->type,
+                                          buf, sizeof (buf)));
+           goto skip;
+         }
+
+       default:
+         {
+           char buf[64];
+           wr_error (&where, ": invalid relocation %d (%s).\n",
+                     cur->type,
+                     ebl_reloc_type_name (file->ebl, cur->type,
+                                          buf, sizeof (buf)));
+           goto skip;
+         }
+       };
+
+      if (cur->offset + width >= sec->data->d_size)
+       {
+         wr_error (&where,
+                   ": relocation doesn't fall into relocated section.\n");
+         goto skip;
+       }
+
+      uint64_t value;
+      if (width == 4)
+       value = dwarflint_read_4ubyte_unaligned
+         ((char *)sec->data->d_buf + cur->offset, file->other_byte_order);
+      else
+       {
+         assert (width == 8);
+         value = dwarflint_read_8ubyte_unaligned
+           ((char *)sec->data->d_buf + cur->offset, file->other_byte_order);
+       }
+
+      if (is_rela)
+       {
+         if (value != 0)
+           wr_message (mc_impact_2 | mc_reloc, &where,
+                       ": SHR_RELA relocates a place with non-zero value (addend=%#"
+                       PRIx64", value=%#"PRIx64").\n", rela->r_addend, value);
+         cur->addend = rela->r_addend;
+       }
+      else
+       cur->addend = value;
+    }
+
+  qsort (sec->rel.rel, sec->rel.size,
+        sizeof (*sec->rel.rel), &compare_rel);
+  return true;
+}
+
+void
+check_range_relocations (enum message_category cat,
+                        struct where *where,
+                        struct elf_file const *file,
+                        GElf_Sym *begin_symbol,
+                        GElf_Sym *end_symbol,
+                        const char *description)
+{
+  if (begin_symbol != NULL
+      && end_symbol != NULL
+      && begin_symbol->st_shndx != end_symbol->st_shndx)
+    wr_message (cat | mc_impact_2 | mc_reloc, where,
+               ": %s relocated against different sections (%s and %s).\n",
+               description,
+               file->sec[begin_symbol->st_shndx].name,
+               file->sec[end_symbol->st_shndx].name);
+}
index 42e4f0e549038db779577f1e70d31068147bb150..9f4442f18d986708a8303a44be15ab21f253689c 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files.
-   Copyright (C) 2008,2009 Red Hat, Inc.
+   Copyright (C) 2008, 2009, 2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
 #define DWARFLINT_RELOC_H
 
 #include "where.h"
+#include "elf_file.ii"
 #include <libelf.h>
 #include <gelf.h>
 
+// xxx remove
+#include "messages.h"
+
 #ifdef __cplusplus
 extern "C"
 {
@@ -37,8 +41,6 @@ extern "C"
 # include <stdbool.h>
 #endif
 
-  struct elf_file;
-
   struct relocation
   {
     uint64_t offset;
@@ -71,6 +73,9 @@ extern "C"
     skip_ok,
   };
 
+  bool read_rel (struct elf_file *file, struct sec *sec,
+                Elf_Data *reldata, bool elf_64);
+
   struct relocation *relocation_next (struct relocation_data *reloc,
                                      uint64_t offset,
                                      struct where const *where,
@@ -91,6 +96,13 @@ extern "C"
                     struct where const *where,
                     enum section_id offset_into, GElf_Sym **symptr);
 
+  void check_range_relocations (enum message_category cat,
+                               struct where *where,
+                               struct elf_file const *file,
+                               GElf_Sym *begin_symbol,
+                               GElf_Sym *end_symbol,
+                               const char *description);
+
 #define PRI_LACK_RELOCATION ": %s seems to lack a relocation.\n"
 
 #ifdef __cplusplus