summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--TODO6
-rw-r--r--libelf/ChangeLog10
-rw-r--r--libelf/Makefile.am3
-rw-r--r--libelf/elf_error.c8
-rw-r--r--libelf/gelf.h3
-rw-r--r--libelf/libelf.h7
-rw-r--r--libelf/libelf.map3
-rw-r--r--libelf/libelfP.h5
-rw-r--r--src/ChangeLog6
-rw-r--r--src/elflint.c268
-rw-r--r--tests/ChangeLog4
-rw-r--r--tests/msg_tst.c6
13 files changed, 265 insertions, 68 deletions
diff --git a/NEWS b/NEWS
index 02f5e456..24f17416 100644
--- 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 bf4a0333..0259f015 100644
--- 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
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index caa2b5bc..6a1dfd93 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,13 @@
+2005-08-02 Ulrich Drepper <[email protected]>
+
+ * 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 <[email protected]>
* elf-knowledge.h (SECTION_STRIP_P): Don't handle removal of debug
diff --git a/libelf/Makefile.am b/libelf/Makefile.am
index cf581902..d9caac65 100644
--- a/libelf/Makefile.am
+++ b/libelf/Makefile.am
@@ -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 =
diff --git a/libelf/elf_error.c b/libelf/elf_error.c
index 168ce113..b51962b9 100644
--- a/libelf/elf_error.c
+++ b/libelf/elf_error.c
@@ -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])))
diff --git a/libelf/gelf.h b/libelf/gelf.h
index 299d6c83..369a3a71 100644
--- a/libelf/gelf.h
+++ b/libelf/gelf.h
@@ -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);
diff --git a/libelf/libelf.h b/libelf/libelf.h
index 5b3dc00b..05a03412 100644
--- a/libelf/libelf.h
+++ b/libelf/libelf.h
@@ -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);
diff --git a/libelf/libelf.map b/libelf/libelf.map
index f416da7f..a5193b32 100644
--- a/libelf/libelf.map
+++ b/libelf/libelf.map
@@ -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;
diff --git a/libelf/libelfP.h b/libelf/libelfP.h
index 100f349a..fd6f825c 100644
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
@@ -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)
diff --git a/src/ChangeLog b/src/ChangeLog
index 31a68ae4..b3a9787e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -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 <[email protected]>
diff --git a/src/elflint.c b/src/elflint.c
index dca8a796..5b6ab100 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -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);
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 39c3cee4..22aee322 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2005-08-02 Ulrich Drepper <[email protected]>
+
+ * msg_tst.c: Add new error message.
+
2005-07-28 Ulrich Drepper <[email protected]>
* Makefile.am (dwflmodtest_LDADD): Add $(libebl).
diff --git a/tests/msg_tst.c b/tests/msg_tst.c
index 67e63c0e..a3a93d05 100644
--- a/tests/msg_tst.c
+++ b/tests/msg_tst.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Red Hat, Inc.
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
Written by Ulrich Drepper <[email protected]>, 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" }
};