Add several more elflint tests:
authorUlrich Drepper <drepper@redhat.com>
Wed, 3 Aug 2005 00:02:56 +0000 (00:02 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 3 Aug 2005 00:02:56 +0000 (00:02 +0000)
- check whether dynamic section matches PT_DYNAMIC program header entry
- make sure text relocation flag is used correctly

libelf needed one extension for this.

13 files changed:
NEWS
TODO
libelf/ChangeLog
libelf/Makefile.am
libelf/elf_error.c
libelf/gelf.h
libelf/libelf.h
libelf/libelf.map
libelf/libelfP.h
src/ChangeLog
src/elflint.c
tests/ChangeLog
tests/msg_tst.c

diff --git a/NEWS b/NEWS
index 02f5e45..24f1741 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ Version 0.112:
 
 elfcmp: some more relaxation.
 
+elflint: some more tests.
+
+libelf: Add elfXX_offscn and gelf_offscn.
+
 Version 0.111:
 
 libdw: now contains all of libdwfl.  The latter is not installed anymore.
diff --git a/TODO b/TODO
index bf4a033..0259f01 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
                      ToDo list for elfutils                      -*-outline-*-
                       ----------------------
 
-Time-stamp: <2003-08-07 12:52:49 drepper>
+Time-stamp: <2005-08-02 16:36:20 drepper>
 
 * mkinstalldirs
 
@@ -105,10 +105,6 @@ Time-stamp: <2003-08-07 12:52:49 drepper>
 
    1st GOT entry == _DYNAMIC
 
-   if TEXTREL check whether any relocation touches RO segment
-
-   if TEXTREL not set check that no relocation touches RO segment
-
    check versioning info:
 
      always BASE in verdef
index caa2b5b..6a1dfd9 100644 (file)
@@ -1,3 +1,13 @@
+2005-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+       * elf_error.c: Add handling of ELF_E_INVALID_OFFSET.
+       * elf32_offscn.c: New file.
+       * elf64_offscn.c: New file.
+       * gelf_offscn.c: New file.
+       * Makefile.am (libelf_a_SOURCES): Add elf32_offscn.c, elf64_offscn.c,
+       and gelf_offscn.c.
+       * libelf.sym: Export new symbols.
+
 2005-07-23  Ulrich Drepper  <drepper@redhat.com>
 
        * elf-knowledge.h (SECTION_STRIP_P): Don't handle removal of debug
index cf58190..d9caac6 100644 (file)
@@ -79,7 +79,8 @@ libelf_a_SOURCES = elf_version.c elf_hash.c elf_error.c elf_fill.c \
                   gelf_rawchunk.c gelf_freechunk.c \
                   libelf_crc32.c libelf_next_prime.c \
                   elf_clone.c \
-                  gelf_getlib.c gelf_update_lib.c
+                  gelf_getlib.c gelf_update_lib.c \
+                  elf32_offscn.c elf64_offscn.c gelf_offscn.c
 
 if !MUDFLAP
 libelf_pic_a_SOURCES =
index 168ce11..b51962b 100644 (file)
@@ -243,6 +243,11 @@ static const char msgstr[] =
   (ELF_E_INVALID_PHDR_IDX \
    + sizeof "program header only allowed in executables and shared objects")
   N_("file has no program header")
+  "\0"
+#define ELF_E_INVALID_OFFSET_IDX \
+  (ELF_E_NO_PHDR_IDX \
+   + sizeof "file has no program header")
+  N_("invalid offset")
 };
 
 
@@ -289,7 +294,8 @@ static const uint_fast16_t msgidx[ELF_E_NUM] =
   [ELF_E_NOFILE] = ELF_E_NOFILE_IDX,
   [ELF_E_GROUP_NOT_REL] = ELF_E_GROUP_NOT_REL_IDX,
   [ELF_E_INVALID_PHDR] = ELF_E_INVALID_PHDR_IDX,
-  [ELF_E_NO_PHDR] = ELF_E_NO_PHDR_IDX
+  [ELF_E_NO_PHDR] = ELF_E_NO_PHDR_IDX,
+  [ELF_E_INVALID_OFFSET] = ELF_E_INVALID_OFFSET_IDX
 };
 #define nmsgidx ((int) (sizeof (msgidx) / sizeof (msgidx[0])))
 
index 299d6c8..369a3a7 100644 (file)
@@ -153,6 +153,9 @@ extern int gelf_update_ehdr (Elf *__elf, GElf_Ehdr *__src);
 /* Create new ELF header if none exists.  */
 extern unsigned long int gelf_newehdr (Elf *__elf, int __class);
 
+/* Get section at OFFSET.  */
+extern Elf_Scn *gelf_offscn (Elf *__elf, GElf_Off __offset);
+
 /* Retrieve section header.  */
 extern GElf_Shdr *gelf_getshdr (Elf_Scn *__scn, GElf_Shdr *__dst);
 
index 5b3dc00..05a0341 100644 (file)
@@ -1,5 +1,5 @@
 /* Interface for libelf.
-   Copyright (C) 1998, 1999, 2000, 2002, 2004 Red Hat, Inc.
+   Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005 Red Hat, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -199,6 +199,11 @@ extern Elf64_Phdr *elf64_newphdr (Elf *__elf, size_t __cnt);
 /* Get section at INDEX.  */
 extern Elf_Scn *elf_getscn (Elf *__elf, size_t __index);
 
+/* Get section at OFFSET.  */
+extern Elf_Scn *elf32_offscn (Elf *__elf, Elf32_Off __offset);
+/* Similar bug this time the binary calls is ELFCLASS64.  */
+extern Elf_Scn *elf64_offscn (Elf *__elf, Elf64_Off __offset);
+
 /* Get index of section.  */
 extern size_t elf_ndxscn (Elf_Scn *__scn);
 
index f416da7..a5193b3 100644 (file)
@@ -7,6 +7,7 @@ ELFUTILS_1.0 {
     elf32_getshdr;
     elf32_newehdr;
     elf32_newphdr;
+    elf32_offscn;
     elf32_xlatetof;
     elf32_xlatetom;
     elf64_checksum;
@@ -16,6 +17,7 @@ ELFUTILS_1.0 {
     elf64_getshdr;
     elf64_newehdr;
     elf64_newphdr;
+    elf64_offscn;
     elf64_xlatetof;
     elf64_xlatetom;
     elf_begin;
@@ -75,6 +77,7 @@ ELFUTILS_1.0 {
     gelf_getversym;
     gelf_newehdr;
     gelf_newphdr;
+    gelf_offscn;
     gelf_rawchunk;
     gelf_update_dyn;
     gelf_update_ehdr;
index 100f349..fd6f825 100644 (file)
@@ -117,6 +117,7 @@ enum
   ELF_E_GROUP_NOT_REL,
   ELF_E_INVALID_PHDR,
   ELF_E_NO_PHDR,
+  ELF_E_INVALID_OFFSET,
   /* Keep this as the last entry.  */
   ELF_E_NUM
 };
@@ -453,6 +454,10 @@ extern Elf32_Phdr *__elf32_newphdr_internal (Elf *__elf, size_t __cnt)
      attribute_hidden;
 extern Elf64_Phdr *__elf64_newphdr_internal (Elf *__elf, size_t __cnt)
      attribute_hidden;
+extern Elf_Scn *__elf32_offscn_internal (Elf *__elf, Elf32_Off __offset)
+  attribute_hidden;
+extern Elf_Scn *__elf64_offscn_internal (Elf *__elf, Elf64_Off __offset)
+  attribute_hidden;
 extern int __elf_getshnum_internal (Elf *__elf, size_t *__dst)
      attribute_hidden;
 extern int __elf_getshstrndx_internal (Elf *__elf, size_t *__dst)
index 31a68ae..b3a9787 100644 (file)
@@ -5,6 +5,12 @@
        (check_one_reloc): New function.  Likewise.
        (check_rela): Use check_reloc_shdr and check_one_reloc.
        (check_rel): Likewise.
+       (check_program_header): Check that PT_DYNAMIC entry matches .dynamic
+       section.
+       Add checks that relocations against read-only segments are flagged,
+       that the text relocation flag is not set unnecessarily, and that
+       relocations in one section are either against loaded or not-loaded
+       segments.
 
 2005-08-01  Ulrich Drepper  <drepper@redhat.com>
 
index dca8a79..5b6ab10 100644 (file)
@@ -289,7 +289,7 @@ process_file (int fd, Elf *elf, const char *prefix, const char *suffix,
     default:
       /* We cannot do anything.  */
       ERROR (gettext ("\
-Not an ELF file - it has the wrong magic bytes at the start"));
+Not an ELF file - it has the wrong magic bytes at the start\n"));
       break;
     }
 }
@@ -898,36 +898,32 @@ section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"
                       idx, section_name (ebl, idx));
            }
          else if (strcmp (name, "_DYNAMIC") == 0)
-           {
-             /* Check that address and size match the dynamic
-                section.  We locate the dynamic section via the
-                program header entry.  */
-             int pcnt;
-
-             for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
-               {
-                 GElf_Phdr phdr_mem;
-                 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
+           /* Check that address and size match the dynamic section.
+              We locate the dynamic section via the program header
+              entry.  */
+           for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
+             {
+               GElf_Phdr phdr_mem;
+               GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
 
-                 if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
-                   {
-                     if (sym->st_value != phdr->p_vaddr)
-                       ERROR (gettext ("\
+               if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
+                 {
+                   if (sym->st_value != phdr->p_vaddr)
+                     ERROR (gettext ("\
 section [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
-                              idx, section_name (ebl, idx),
-                              (uint64_t) sym->st_value,
-                              (uint64_t) phdr->p_vaddr);
+                            idx, section_name (ebl, idx),
+                            (uint64_t) sym->st_value,
+                            (uint64_t) phdr->p_vaddr);
 
-                     if (!gnuld && sym->st_size != phdr->p_memsz)
-                       ERROR (gettext ("\
+                   if (!gnuld && sym->st_size != phdr->p_memsz)
+                     ERROR (gettext ("\
 section [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
-                              idx, section_name (ebl, idx),
-                              (uint64_t) sym->st_size,
-                              (uint64_t) phdr->p_memsz);
+                            idx, section_name (ebl, idx),
+                            (uint64_t) sym->st_size,
+                            (uint64_t) phdr->p_memsz);
 
-                     break;
-                   }
-               }
+                   break;
+                 }
            }
        }
     }
@@ -988,10 +984,26 @@ section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
 }
 
 
+struct loaded_segment
+{
+  GElf_Addr from;
+  GElf_Addr to;
+  bool read_only;
+  struct loaded_segment *next;
+};
+
+
+/* Check whether binary has text relocation flag set.  */
+static bool textrel;
+
+/* Keep track of whether text relocation flag is needed.  */
+static bool needed_textrel;
+
+
 static bool
 check_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr,
                  int idx, int reltype, GElf_Shdr **destshdrp,
-                 GElf_Shdr *destshdr_memp)
+                 GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp)
 {
   bool reldyn = false;
 
@@ -1037,14 +1049,83 @@ section [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\
 section [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
           idx, section_name (ebl, idx));
 
+  /* In preparation of checking whether relocations are text
+     relocations or not we need to determine whether the file is
+     flagged to have text relocation and we need to determine a) what
+     the loaded segments are and b) which are read-only.  This will
+     also allow us to determine whether the same reloc section is
+     modifying loaded and not loaded segments.  */
+  for (int i = 0; i < ehdr->e_phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
+      if (phdr == NULL)
+       continue;
+
+      if (phdr->p_type == PT_LOAD)
+       {
+         struct loaded_segment *newp = xmalloc (sizeof (*newp));
+         newp->from = phdr->p_vaddr;
+         newp->to = phdr->p_vaddr + phdr->p_memsz;
+         newp->read_only = (phdr->p_flags & PF_W) == 0;
+         newp->next = *loadedp;
+         *loadedp = newp;
+       }
+      else if (phdr->p_type == PT_DYNAMIC)
+       {
+         Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset);
+         GElf_Shdr dynshdr_mem;
+         GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
+         Elf_Data *dyndata = elf_getdata (dynscn, NULL);
+         if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
+             && dyndata != NULL)
+           for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
+             {
+               GElf_Dyn dyn_mem;
+               GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem);
+               if (dyn != NULL
+                   && (dyn->d_tag == DT_TEXTREL
+                       || (dyn->d_tag == DT_FLAGS
+                           && (dyn->d_un.d_val & DF_TEXTREL) != 0)))
+                 {
+                   textrel = true;
+                   break;
+                 }
+             }
+       }
+    }
+
+  /* A quick test which can be easily done here (although it is a bit
+     out of place): the text relocation flag makes only sense if there
+     is a segment which is not writable.  */
+  if (textrel)
+    {
+      struct loaded_segment *seg = *loadedp;
+      while (seg != NULL && !seg->read_only)
+       seg = seg->next;
+      if (seg == NULL)
+       ERROR (gettext ("\
+text relocation flag set but there is no read-only segment\n"));
+    }
+
   return reldyn;
 }
 
 
+enum load_state
+  {
+    state_undecided,
+    state_loaded,
+    state_unloaded,
+    state_error
+  };
+
+
 static void
 check_one_reloc (Ebl *ebl, int idx, size_t cnt, const GElf_Shdr *symshdr,
                 Elf_Data *symdata, GElf_Addr r_offset, GElf_Xword r_info,
-                const GElf_Shdr *destshdr, bool reldyn)
+                const GElf_Shdr *destshdr, bool reldyn,
+                struct loaded_segment *loaded, enum load_state *statep)
 {
   bool known_broken = gnuld;
 
@@ -1095,21 +1176,53 @@ section [%2d] '%s': relocation %zu: offset out of bounds\n"),
               idx, section_name (ebl, idx), cnt);
     }
 
-  if (symdata != NULL && ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info)))
-    {
+  GElf_Sym sym_mem;
+  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
+
+  if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info))
       /* Make sure the referenced symbol is an object or unspecified.  */
-      GElf_Sym sym_mem;
-      GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
-      if (sym != NULL
-         && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
-         && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
+      && sym != NULL
+      && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+      && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
+    {
+      char buf[64];
+      ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
+            idx, section_name (ebl, idx), cnt,
+            ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
+                                  buf, sizeof (buf)));
+    }
+
+  bool in_loaded_seg = false;
+  while (loaded != NULL)
+    {
+      if (r_offset < loaded->to
+         && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from)
        {
-         char buf[64];
-         ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
-                idx, section_name (ebl, idx), cnt,
-                ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
-                                      buf, sizeof (buf)));
+         /* The symbol is in this segment.  */
+         if  (loaded->read_only)
+           {
+             if (textrel)
+               needed_textrel = true;
+             else
+               ERROR (gettext ("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"),
+                      idx, section_name (ebl, idx), cnt);
+           }
+
+         in_loaded_seg = true;
        }
+
+      loaded = loaded->next;
+    }
+
+  if (*statep == state_undecided)
+    *statep = in_loaded_seg ? state_loaded : state_unloaded;
+  else if ((*statep == state_unloaded && in_loaded_seg)
+          || (*statep == state_loaded && !in_loaded_seg))
+    {
+      ERROR (gettext ("\
+section [%2d] '%s': relocations are against loaded and unloaded data\n"),
+            idx, section_name (ebl, idx));
+      *statep = state_error;
     }
 }
 
@@ -1128,13 +1241,15 @@ check_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
   /* Check the fields of the section header.  */
   GElf_Shdr destshdr_mem;
   GElf_Shdr *destshdr = NULL;
+  struct loaded_segment *loaded = NULL;
   bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr,
-                                 &destshdr_mem);
+                                 &destshdr_mem, &loaded);
 
   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   GElf_Shdr symshdr_mem;
   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   Elf_Data *symdata = elf_getdata (symscn, NULL);
+  enum load_state state = state_undecided;
 
   for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
     {
@@ -1149,7 +1264,14 @@ section [%2d] '%s': cannot get relocation %zu: %s\n"),
        }
 
       check_one_reloc (ebl, idx, cnt, symshdr, symdata, rela->r_offset,
-                      rela->r_info, destshdr, reldyn);
+                      rela->r_info, destshdr, reldyn, loaded, &state);
+    }
+
+  while (loaded != NULL)
+    {
+      struct loaded_segment *old = loaded;
+      loaded = loaded->next;
+      free (old);
     }
 }
 
@@ -1168,13 +1290,15 @@ check_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
   /* Check the fields of the section header.  */
   GElf_Shdr destshdr_mem;
   GElf_Shdr *destshdr = NULL;
+  struct loaded_segment *loaded = NULL;
   bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr,
-                                 &destshdr_mem);
+                                 &destshdr_mem, &loaded);
 
   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
   GElf_Shdr symshdr_mem;
   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
   Elf_Data *symdata = elf_getdata (symscn, NULL);
+  enum load_state state = state_undecided;
 
   for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
     {
@@ -1189,7 +1313,14 @@ section [%2d] '%s': cannot get relocation %zu: %s\n"),
        }
 
       check_one_reloc (ebl, idx, cnt, symshdr, symdata, rel->r_offset,
-                      rel->r_info, destshdr, reldyn);
+                      rel->r_info, destshdr, reldyn, loaded, &state);
+    }
+
+  while (loaded != NULL)
+    {
+      struct loaded_segment *old = loaded;
+      loaded = loaded->next;
+      free (old);
     }
 }
 
@@ -1199,11 +1330,8 @@ static int ndynamic;
 
 
 static void
-check_dynamic (Ebl *ebl, int idx)
+check_dynamic (Ebl *ebl, GElf_Shdr *shdr, int idx)
 {
-  Elf_Scn *scn;
-  GElf_Shdr shdr_mem;
-  GElf_Shdr *shdr;
   Elf_Data *data;
   GElf_Shdr strshdr_mem;
   GElf_Shdr *strshdr;
@@ -1258,11 +1386,7 @@ check_dynamic (Ebl *ebl, int idx)
   if (++ndynamic == 2)
     ERROR (gettext ("more than one dynamic section present\n"));
 
-  scn = elf_getscn (ebl->elf, idx);
-  shdr = gelf_getshdr (scn, &shdr_mem);
-  if (shdr == NULL)
-    return;
-  data = elf_getdata (scn, NULL);
+  data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
   if (data == NULL)
     {
       ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
@@ -2173,7 +2297,7 @@ section [%2zu] '%s': ELF header says this is the section header string table but
          break;
 
        case SHT_DYNAMIC:
-         check_dynamic (ebl, cnt);
+         check_dynamic (ebl, shdr, cnt);
          break;
 
        case SHT_SYMTAB_SHNDX:
@@ -2408,9 +2532,33 @@ more than one INTERP entry in program header\n"));
        }
       else if (phdr->p_type == PT_NOTE)
        check_note (ebl, ehdr, phdr, cnt);
-      else if (phdr->p_type == PT_DYNAMIC
-              && ehdr->e_type == ET_EXEC && ! has_interp_segment)
-       ERROR (gettext ("static executable cannot have dynamic sections\n"));
+      else if (phdr->p_type == PT_DYNAMIC)
+       {
+         if (ehdr->e_type == ET_EXEC && ! has_interp_segment)
+           ERROR (gettext ("\
+static executable cannot have dynamic sections\n"));
+         else
+           {
+             /* Check that the .dynamic section, if it exists, has
+                the same address.  */
+             Elf_Scn *scn = NULL;
+             while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+               {
+                 GElf_Shdr shdr_mem;
+                 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+                 if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
+                   {
+                     if (phdr->p_offset != shdr->sh_offset)
+                       ERROR (gettext ("\
+dynamic section reference in program header has wrong offset\n"));
+                     if (phdr->p_memsz != shdr->sh_size)
+                       ERROR (gettext ("\
+dynamic section size mismatch in program and section header\n"));
+                     break;
+                   }
+               }
+           }
+       }
       else if (phdr->p_type == PT_GNU_RELRO)
        {
          if (++num_pt_relro == 2)
@@ -2475,6 +2623,8 @@ process_elf_file (Elf *elf, const char *prefix, const char *suffix,
 {
   /* Reset variables.  */
   ndynamic = 0;
+  textrel = false;
+  needed_textrel = false;
 
   GElf_Ehdr ehdr_mem;
   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
@@ -2510,6 +2660,10 @@ process_elf_file (Elf *elf, const char *prefix, const char *suffix,
      headers at all.  */
   check_sections (ebl, ehdr);
 
+  /* Report if no relocation section needed the text relocation flag.  */
+  if (textrel && !needed_textrel)
+    ERROR (gettext ("text relocation flag set but not needed\n"));
+
   /* Free the resources.  */
   ebl_closebackend (ebl);
 }
index 39c3cee..22aee32 100644 (file)
@@ -1,3 +1,7 @@
+2005-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+       * msg_tst.c: Add new error message.
+
 2005-07-28  Ulrich Drepper  <drepper@redhat.com>
 
        * Makefile.am (dwflmodtest_LDADD): Add $(libebl).
index 67e63c0..a3a93d0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Red Hat, Inc.
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
    This program is Open Source software; you can redistribute it and/or
@@ -68,8 +68,8 @@ static struct
       "only relocatable files can contain section groups" },
     { ELF_E_INVALID_PHDR,
       "program header only allowed in executables and shared objects" },
-    { ELF_E_NO_PHDR,
-      "file has no program header" }
+    { ELF_E_NO_PHDR, "file has no program header" },
+    { ELF_E_INVALID_OFFSET, "invalid offset" }
   };