diff options
author | Ulrich Drepper <drepper@redhat.com> | 2009-06-01 07:38:32 -0700 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2009-06-01 07:38:32 -0700 |
commit | b47d290a36509e26e145f6d3eb2e6590ec6c554d (patch) | |
tree | 42076e6b9c556729618b25b4dedf29606b4e4aee | |
parent | e94b1b2bec403afb5fd4696a05e1ade09fdb3e59 (diff) |
Add support for IRELATIVE relocations.
That's the second part of the IFUNC support. So far x86 and x86-64
only.
-rw-r--r-- | backends/ChangeLog | 5 | ||||
-rw-r--r-- | backends/i386_reloc.def | 3 | ||||
-rw-r--r-- | backends/x86_64_reloc.def | 3 | ||||
-rw-r--r-- | libelf/ChangeLog | 4 | ||||
-rw-r--r-- | libelf/elf.h | 6 | ||||
-rw-r--r-- | src/ChangeLog | 8 | ||||
-rw-r--r-- | src/readelf.c | 143 |
7 files changed, 139 insertions, 33 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog index c764f9ef..a1aa351f 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,8 @@ +2009-06-01 Ulrich Drepper <drepper@redhat.com> + + * i386_reloc.def: Add IRELATIVE entry. + * x86_64_reloc.def: Likewise. + 2009-04-16 Roland McGrath <roland@redhat.com> * arm_regs.c (arm_register_info): Handle VFP registers. diff --git a/backends/i386_reloc.def b/backends/i386_reloc.def index bc1b835d..1befd1b6 100644 --- a/backends/i386_reloc.def +++ b/backends/i386_reloc.def @@ -1,5 +1,5 @@ /* List the relocation types for i386. -*- C -*- - Copyright (C) 2000, 2001, 2002, 2003, 2005 Red Hat, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2005, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -64,3 +64,4 @@ RELOC_TYPE (TLS_TPOFF32, EXEC|DYN) RELOC_TYPE (TLS_GOTDESC, REL) RELOC_TYPE (TLS_DESC_CALL, REL) RELOC_TYPE (TLS_DESC, EXEC) +RELOC_TYPE (IRELATIVE, EXEC|DYN) diff --git a/backends/x86_64_reloc.def b/backends/x86_64_reloc.def index e6c5a84b..5d70f47c 100644 --- a/backends/x86_64_reloc.def +++ b/backends/x86_64_reloc.def @@ -1,5 +1,5 @@ /* List the relocation types for x86-64. -*- C -*- - Copyright (C) 2000, 2001, 2002, 2003, 2005 Red Hat, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2005, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -49,3 +49,4 @@ RELOC_TYPE (TLSLD, REL) RELOC_TYPE (DTPOFF32, REL) RELOC_TYPE (GOTTPOFF, REL) RELOC_TYPE (TPOFF32, REL) +RELOC_TYPE (IRELATIVE, EXEC|DYN) diff --git a/libelf/ChangeLog b/libelf/ChangeLog index bfc3ee5f..2fd5381b 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,7 @@ +2009-06-01 Ulrich Drepper <drepper@redhat.com> + + * elf.h: Update from glibc. + 2009-04-14 Roland McGrath <roland@redhat.com> * elf.h: Update from glibc. diff --git a/libelf/elf.h b/libelf/elf.h index 062ef00f..8fdf74b0 100644 --- a/libelf/elf.h +++ b/libelf/elf.h @@ -1177,8 +1177,9 @@ typedef struct pointer to code and to argument, returning the TLS offset for the symbol. */ +#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ /* Keep this the last entry. */ -#define R_386_NUM 42 +#define R_386_NUM 43 /* SUN SPARC specific definitions. */ @@ -2625,8 +2626,9 @@ typedef Elf32_Addr Elf32_Conflict; #define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS descriptor. */ #define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ -#define R_X86_64_NUM 37 +#define R_X86_64_NUM 38 /* AM33 relocations. */ diff --git a/src/ChangeLog b/src/ChangeLog index f6fd86f3..01a2414a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2009-06-01 Ulrich Drepper <drepper@redhat.com> + + * readelf.c (print_relocs): Expect ELF header argument and pass on + to handle_relocs_rel* functions. Adjust caller. + (handle_relocs_rel): Add ELF header argument. Add special case for + the IRELATIVE relocations in statically linked executables. + (handle_relocs_rela): Likewise. + 2009-04-29 Ulrich Drepper <drepper@redhat.com> * elflint.c (check_symtab): Add tests of st_other field. diff --git a/src/readelf.c b/src/readelf.c index 1c790650..9ce46042 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -211,9 +211,11 @@ static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr); static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr); static void print_scngrp (Ebl *ebl); static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr); -static void print_relocs (Ebl *ebl); -static void handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); -static void handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); +static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr); +static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, + GElf_Shdr *shdr); +static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, + GElf_Shdr *shdr); static void print_symtab (Ebl *ebl, int type); static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); static void print_verinfo (Ebl *ebl); @@ -652,7 +654,7 @@ process_elf_file (Dwfl_Module *dwflmod, int fd) if (print_dynamic_table) print_dynamic (ebl, ehdr); if (print_relocations) - print_relocs (pure_ebl); + print_relocs (pure_ebl, ehdr); if (print_histogram) handle_hash (ebl); if (print_symbol_table) @@ -1449,7 +1451,7 @@ print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr) /* Print relocations. */ static void -print_relocs (Ebl *ebl) +print_relocs (Ebl *ebl, GElf_Ehdr *ehdr) { /* Find all relocation sections and handle them. */ Elf_Scn *scn = NULL; @@ -1463,9 +1465,9 @@ print_relocs (Ebl *ebl) if (likely (shdr != NULL)) { if (shdr->sh_type == SHT_REL) - handle_relocs_rel (ebl, scn, shdr); + handle_relocs_rel (ebl, ehdr, scn, shdr); else if (shdr->sh_type == SHT_RELA) - handle_relocs_rela (ebl, scn, shdr); + handle_relocs_rela (ebl, ehdr, scn, shdr); } } } @@ -1473,7 +1475,7 @@ print_relocs (Ebl *ebl) /* Handle a relocation section. */ static void -handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) +handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) { int class = gelf_getclass (ebl->elf); int nentries = shdr->sh_size / shdr->sh_entsize; @@ -1545,6 +1547,7 @@ handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) Offset Type Value Name\n"), stdout); + int is_statically_linked = 0; for (int cnt = 0; cnt < nentries; ++cnt) { GElf_Rel relmem; @@ -1558,16 +1561,56 @@ handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) GELF_R_SYM (rel->r_info), &symmem, &xndx); if (unlikely (sym == NULL)) - printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", - class == ELFCLASS32 ? 10 : 18, rel->r_offset, - ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) - /* Avoid the leading R_ which isn't carrying any - information. */ - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), - buf, sizeof (buf)) + 2 - : gettext ("<INVALID RELOC>"), - gettext ("INVALID SYMBOL"), - (long int) GELF_R_SYM (rel->r_info)); + { + /* As a special case we have to handle relocations in static + executables. This only happens for IRELATIVE relocations + (so far). There is no symbol table. */ + if (is_statically_linked == 0) + { + /* Find the program header and look for a PT_INTERP entry. */ + is_statically_linked = -1; + if (ehdr->e_type == ET_EXEC) + { + is_statically_linked = 1; + + for (size_t inner = 0; inner < ehdr->e_phnum; ++inner) + { + GElf_Phdr phdr_mem; + GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner, + &phdr_mem); + if (phdr != NULL && phdr->p_type == PT_INTERP) + { + is_statically_linked = -1; + break; + } + } + } + } + + if (is_statically_linked > 0 && shdr->sh_link == 0) + printf ("\ + %#0*" PRIx64 " %-20s %*s %s\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext ("<INVALID RELOC>"), + class == ELFCLASS32 ? 10 : 18, "", + elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + else + printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext ("<INVALID RELOC>"), + gettext ("INVALID SYMBOL"), + (long int) GELF_R_SYM (rel->r_info)); + } else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", class == ELFCLASS32 ? 10 : 18, rel->r_offset, @@ -1618,7 +1661,7 @@ handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Handle a relocation section. */ static void -handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) +handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) { int class = gelf_getclass (ebl->elf); int nentries = shdr->sh_size / shdr->sh_entsize; @@ -1676,6 +1719,7 @@ handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) Offset Type Value Addend Name\n"), stdout); + int is_statically_linked = 0; for (int cnt = 0; cnt < nentries; ++cnt) { GElf_Rela relmem; @@ -1690,16 +1734,57 @@ handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) &symmem, &xndx); if (unlikely (sym == NULL)) - printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", - class == ELFCLASS32 ? 10 : 18, rel->r_offset, - ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) - /* Avoid the leading R_ which isn't carrying any - information. */ - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), - buf, sizeof (buf)) + 2 - : gettext ("<INVALID RELOC>"), - gettext ("INVALID SYMBOL"), - (long int) GELF_R_SYM (rel->r_info)); + { + /* As a special case we have to handle relocations in static + executables. This only happens for IRELATIVE relocations + (so far). There is no symbol table. */ + if (is_statically_linked == 0) + { + /* Find the program header and look for a PT_INTERP entry. */ + is_statically_linked = -1; + if (ehdr->e_type == ET_EXEC) + { + is_statically_linked = 1; + + for (size_t inner = 0; inner < ehdr->e_phnum; ++inner) + { + GElf_Phdr phdr_mem; + GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner, + &phdr_mem); + if (phdr != NULL && phdr->p_type == PT_INTERP) + { + is_statically_linked = -1; + break; + } + } + } + } + + if (is_statically_linked > 0 && shdr->sh_link == 0) + printf ("\ + %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext ("<INVALID RELOC>"), + class == ELFCLASS32 ? 10 : 18, "", + rel->r_addend, + elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + else + printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext ("<INVALID RELOC>"), + gettext ("INVALID SYMBOL"), + (long int) GELF_R_SYM (rel->r_info)); + } else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) printf ("\ %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n", |