@@ -384,4 +384,5 @@ ELFUTILS_0.192 {
dwfl_set_sysroot;
dwfl_frame_unwound_source;
dwfl_unwound_source_str;
+ dwelf_elf_remove_debug_relocations;
} ELFUTILS_0.191;
@@ -42,13 +42,14 @@ noinst_HEADERS = libdwelfP.h
libdwelf_a_SOURCES = dwelf_elf_gnu_debuglink.c dwelf_dwarf_gnu_debugaltlink.c \
dwelf_elf_gnu_build_id.c dwelf_scn_gnu_compressed_size.c \
dwelf_strtab.c dwelf_elf_begin.c \
- dwelf_elf_e_machine_string.c
+ dwelf_elf_e_machine_string.c \
+ dwelf_elf_remove_debug_relocations.c
libdwelf = $(libdw)
libdw = ../libdw/libdw.so
libelf = ../libelf/libelf.so
-libebl = ../libebl/libebl.a
+libebl = ../libebl/libebl.a ../backends/libebl_backends.a
libeu = ../lib/libeu.a
libdwelf_pic_a_SOURCES =
new file mode 100644
@@ -0,0 +1,400 @@
+/* Remove relocations from debug sections.
+ Copyright (C) 2014 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwelfP.h"
+#include "libelfP.h"
+#include "libebl.h"
+
+typedef uint8_t GElf_Byte;
+
+const char *
+secndx_name (Elf *elf, size_t ndx)
+{
+ size_t shstrndx;
+ GElf_Shdr mem;
+ Elf_Scn *sec = elf_getscn (elf, ndx);
+ GElf_Shdr *shdr = gelf_getshdr (sec, &mem);
+ if (shdr == NULL || elf_getshdrstrndx (elf, &shstrndx) < 0)
+ return "???";
+ return elf_strptr (elf, shstrndx, shdr->sh_name) ?: "???";
+}
+
+
+Elf_Data *
+get_xndxdata (Elf *elf, Elf_Scn *symscn)
+{
+ Elf_Data *xndxdata = NULL;
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
+ if (shdr != NULL && shdr->sh_type == SHT_SYMTAB)
+ {
+ size_t scnndx = elf_ndxscn (symscn);
+ Elf_Scn *xndxscn = NULL;
+ while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
+ {
+ GElf_Shdr xndxshdr_mem;
+ GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
+
+ if (xndxshdr != NULL
+ && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
+ && xndxshdr->sh_link == scnndx)
+ {
+ xndxdata = elf_getdata (xndxscn, NULL);
+ break;
+ }
+ }
+ }
+
+ return xndxdata;
+}
+
+
+bool
+relocate (Elf *elf, GElf_Addr offset, const GElf_Sxword addend,
+ Elf_Data *tdata, unsigned int ei_data, bool is_rela,
+ GElf_Sym *sym, int addsub, Elf_Type type)
+{
+ /* These are the types we can relocate. */
+#define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
+ DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
+ DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
+
+ size_t size;
+
+#define DO_TYPE(NAME, Name) GElf_##Name Name;
+ union { TYPES; } tmpbuf;
+#undef DO_TYPE
+
+ switch (type)
+ {
+#define DO_TYPE(NAME, Name) \
+ case ELF_T_##NAME: \
+ size = sizeof (GElf_##Name); \
+ tmpbuf.Name = 0; \
+ break;
+ TYPES;
+#undef DO_TYPE
+ default:
+ return false;
+ }
+
+ if (offset > tdata->d_size
+ || tdata->d_size - offset < size)
+ {
+ //__libelf_seterrno (ELF_E_INVALID_OFFSET);
+ return false;
+ }
+
+ /* When the symbol value is zero then for SHT_REL
+ sections this is all that needs to be checked.
+ The addend is contained in the original data at
+ the offset already. So if the (section) symbol
+ address is zero and the given addend is zero
+ just remove the relocation, it isn't needed
+ anymore. */
+ if (addend == 0 && sym->st_value == 0)
+ return true;
+
+ Elf_Data tmpdata =
+ {
+ .d_type = type,
+ .d_buf = &tmpbuf,
+ .d_size = size,
+ .d_version = EV_CURRENT,
+ };
+ Elf_Data rdata =
+ {
+ .d_type = type,
+ .d_buf = tdata->d_buf + offset,
+ .d_size = size,
+ .d_version = EV_CURRENT,
+ };
+
+ GElf_Addr value = sym->st_value;
+ if (is_rela)
+ {
+ /* For SHT_RELA sections we just take the
+ given addend and add it to the value. */
+ value += addend;
+ /* For ADD/SUB relocations we need to fetch the
+ current section contents. */
+ if (addsub != 0)
+ {
+ Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
+ &rdata,
+ ei_data);
+ if (d == NULL || d != &tmpdata)
+ {
+ //__libelf_seterrno (ELF_E_INVALID_HANDLE);
+ return false;
+ }
+ }
+ }
+ else
+ {
+ /* For SHT_REL sections we have to peek at
+ what is already in the section at the given
+ offset to get the addend. */
+ Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
+ &rdata,
+ ei_data);
+ if (d == NULL || d != &tmpdata)
+ {
+ //__libelf_seterrno (ELF_E_INVALID_HANDLE);
+ return false;
+ }
+ }
+
+ switch (type)
+ {
+#define DO_TYPE(NAME, Name) \
+ case ELF_T_##NAME: \
+ if (addsub < 0) \
+ tmpbuf.Name -= (GElf_##Name) value; \
+ else \
+ tmpbuf.Name += (GElf_##Name) value; \
+ break;
+ TYPES;
+#undef DO_TYPE
+ default:
+ //__libelf_seterrno (ELF_E_UNKNOWN_TYPE);
+ return false;
+ }
+
+ /* Now finally put in the new value. */
+ Elf_Data *s = gelf_xlatetof (elf, &rdata,
+ &tmpdata,
+ ei_data);
+ if (s == NULL || s != &rdata)
+ {
+ //__libelf_seterrno (ELF_E_INVALID_HANDLE);
+ return false;
+ }
+
+ return true;
+}
+
+
+int dwelf_elf_remove_debug_relocations (Elf *elf)
+{
+ size_t shstrndx;
+ if (elf_getshdrstrndx (elf, &shstrndx) < 0)
+ return -1;
+
+ GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+ if (ehdr == NULL)
+ return -1;
+
+ const unsigned int ei_data = ehdr->e_ident[EI_DATA];
+
+ Ebl *ebl = ebl_openbackend (elf);
+ if (ebl == NULL)
+ return -1;
+
+ int res = -1;
+ Elf_Scn *scn = NULL;
+ while ((scn = elf_nextscn (elf, scn)) != NULL)
+ {
+ /* We need the actual section and header from the elf
+ not just the cached original in shdr_info because we
+ might want to change the size. */
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+ if (shdr != NULL
+ && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
+ {
+ /* Make sure that this relocation section points to a
+ section to relocate with contents, that isn't
+ allocated and that is a debug section. */
+ Elf_Scn *tscn = elf_getscn (elf, shdr->sh_info);
+ GElf_Shdr tshdr_mem;
+ GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
+ if (tshdr == NULL
+ || tshdr->sh_type == SHT_NOBITS
+ || tshdr->sh_size == 0
+ || (tshdr->sh_flags & SHF_ALLOC) != 0)
+ continue;
+
+ const char *tname = elf_strptr (elf, shstrndx,
+ tshdr->sh_name);
+ if (! tname || ! ebl_debugscn_p (ebl, tname))
+ continue;
+
+ /* OK, lets relocate all trivial cross debug section
+ relocations. */
+ Elf_Data *reldata = elf_getdata (scn, NULL);
+ if (reldata == NULL || reldata->d_buf == NULL)
+ goto exit;
+
+ /* Make sure we adjust the uncompressed debug data
+ (and recompress if necessary at the end). */
+ GElf_Chdr tchdr;
+ int tcompress_type = 0;
+ bool is_gnu_compressed = false;
+ if (startswith (tname, ".zdebug"))
+ {
+ is_gnu_compressed = true;
+ if (elf_compress_gnu (tscn, 0, 0) != 1)
+ goto exit;
+ }
+ else
+ {
+ if (gelf_getchdr (tscn, &tchdr) != NULL)
+ {
+ tcompress_type = tchdr.ch_type;
+ if (elf_compress (tscn, 0, 0) != 1)
+ goto exit;
+ }
+ }
+
+ Elf_Data *tdata = elf_getdata (tscn, NULL);
+ if (tdata == NULL || tdata->d_buf == NULL
+ || tdata->d_type != ELF_T_BYTE)
+ goto exit;
+
+ /* Pick up the symbol table and shndx table to
+ resolve relocation symbol indexes. */
+ Elf64_Word symt = shdr->sh_link;
+ Elf_Data *symdata, *xndxdata;
+ Elf_Scn * symscn = elf_getscn (elf, symt);
+ symdata = elf_getdata (symscn, NULL);
+ xndxdata = get_xndxdata (elf, symscn);
+ if (symdata == NULL)
+ goto exit;
+
+ if (shdr->sh_entsize == 0)
+ goto exit;
+
+ size_t nrels = shdr->sh_size / shdr->sh_entsize;
+ size_t next = 0;
+ const bool is_rela = (shdr->sh_type == SHT_RELA);
+
+ for (size_t relidx = 0; relidx < nrels; ++relidx)
+ {
+ int rtype, symndx, offset, addend;
+ union { GElf_Rela rela; GElf_Rel rel; } mem;
+ void *rel_p; /* Pointer to either rela or rel above */
+
+ if (is_rela)
+ {
+ GElf_Rela *r = gelf_getrela (reldata, relidx, &mem.rela);
+ if (r == NULL)
+ goto exit;
+ offset = r->r_offset;
+ addend = r->r_addend;
+ rtype = GELF_R_TYPE (r->r_info);
+ symndx = GELF_R_SYM (r->r_info);
+ rel_p = r;
+ }
+ else
+ {
+ GElf_Rel *r = gelf_getrel (reldata, relidx, &mem.rel);
+ if (r == NULL)
+ goto exit;
+ offset = r->r_offset;
+ addend = 0;
+ rtype = GELF_R_TYPE (r->r_info);
+ symndx = GELF_R_SYM (r->r_info);
+ rel_p = r;
+ }
+
+ /* R_*_NONE relocs can always just be removed. */
+ if (rtype == 0)
+ continue;
+
+ /* We only do simple absolute relocations. */
+ int addsub = 0;
+ Elf_Type type = ebl_reloc_simple_type (ebl, rtype, &addsub);
+ if (type == ELF_T_NUM)
+ goto relocate_failed;
+
+ /* And only for relocations against other debug sections. */
+ GElf_Sym sym_mem;
+ Elf32_Word xndx;
+ GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
+ symndx, &sym_mem,
+ &xndx);
+ if (sym == NULL)
+ goto exit;
+ Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
+ ? xndx : sym->st_shndx);
+
+ bool dbg_scn = ebl_debugscn_p (ebl, secndx_name (elf, sec));
+
+ if (!dbg_scn)
+ goto relocate_failed;
+
+ if (! relocate (elf, offset, addend, tdata, ei_data, is_rela,
+ sym, addsub, type))
+ goto relocate_failed;
+
+ continue; /* Next */
+
+relocate_failed:
+ if (relidx != next)
+ {
+ int updated;
+ if (is_rela)
+ updated = gelf_update_rela (reldata, next, rel_p);
+ else
+ updated = gelf_update_rel (reldata, next, rel_p);
+ if (updated == 0)
+ goto exit;
+ }
+ ++next;
+ }
+
+ nrels = next;
+ shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
+ if (gelf_update_shdr (scn, shdr) == 0)
+ goto exit;
+
+ if (is_gnu_compressed)
+ {
+ if (elf_compress_gnu (tscn, 1, ELF_CHF_FORCE) != 1)
+ goto exit;
+ }
+ else if (tcompress_type != 0)
+ {
+ if (elf_compress (tscn, tcompress_type, ELF_CHF_FORCE) != 1)
+ goto exit;
+ }
+ }
+ }
+
+ res = 0;
+
+exit:
+ ebl_closebackend (ebl);
+ return res;
+}
@@ -140,6 +140,10 @@ extern Elf *dwelf_elf_begin (int fd);
value, or NULL if the given number isn't currently known. */
extern const char *dwelf_elf_e_machine_string (int machine);
+/* Remove relocations for debug sections. Returns 0 on success.
+ Returns -1 on failure and sets elf_errno. */
+extern int dwelf_elf_remove_debug_relocations (Elf *elf);
+
#ifdef __cplusplus
}
#endif
@@ -367,46 +367,6 @@ parse_opt (int key, char *arg, struct argp_state *state)
return 0;
}
-static const char *
-secndx_name (Elf *elf, size_t ndx)
-{
- size_t shstrndx;
- GElf_Shdr mem;
- Elf_Scn *sec = elf_getscn (elf, ndx);
- GElf_Shdr *shdr = gelf_getshdr (sec, &mem);
- if (shdr == NULL || elf_getshdrstrndx (elf, &shstrndx) < 0)
- return "???";
- return elf_strptr (elf, shstrndx, shdr->sh_name) ?: "???";
-}
-
-/* Get the extended section index table data for a symbol table section. */
-static Elf_Data *
-get_xndxdata (Elf *elf, Elf_Scn *symscn)
-{
- Elf_Data *xndxdata = NULL;
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
- if (shdr != NULL && shdr->sh_type == SHT_SYMTAB)
- {
- size_t scnndx = elf_ndxscn (symscn);
- Elf_Scn *xndxscn = NULL;
- while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
- {
- GElf_Shdr xndxshdr_mem;
- GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
-
- if (xndxshdr != NULL
- && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
- && xndxshdr->sh_link == scnndx)
- {
- xndxdata = elf_getdata (xndxscn, NULL);
- break;
- }
- }
- }
-
- return xndxdata;
-}
/* Updates the shdrstrndx for the given Elf by updating the Ehdr and
possibly the section zero extension field. Returns zero on success. */
@@ -440,306 +400,6 @@ update_shdrstrndx (Elf *elf, size_t shdrstrndx)
}
-/* Apply one relocation. Returns true when trivial
- relocation actually done. */
-static bool
-relocate (Elf *elf, GElf_Addr offset, const GElf_Sxword addend,
- Elf_Data *tdata, unsigned int ei_data, const char *fname,
- bool is_rela, GElf_Sym *sym, int addsub, Elf_Type type)
-{
- /* These are the types we can relocate. */
-#define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
- DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
- DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
-
- size_t size;
-
-#define DO_TYPE(NAME, Name) GElf_##Name Name;
- union { TYPES; } tmpbuf;
-#undef DO_TYPE
-
- switch (type)
- {
-#define DO_TYPE(NAME, Name) \
- case ELF_T_##NAME: \
- size = sizeof (GElf_##Name); \
- tmpbuf.Name = 0; \
- break;
- TYPES;
-#undef DO_TYPE
- default:
- return false;
- }
-
- if (offset > tdata->d_size
- || tdata->d_size - offset < size)
- {
- cleanup_debug ();
- error_exit (0, _("bad relocation"));
- }
-
- /* When the symbol value is zero then for SHT_REL
- sections this is all that needs to be checked.
- The addend is contained in the original data at
- the offset already. So if the (section) symbol
- address is zero and the given addend is zero
- just remove the relocation, it isn't needed
- anymore. */
- if (addend == 0 && sym->st_value == 0)
- return true;
-
- Elf_Data tmpdata =
- {
- .d_type = type,
- .d_buf = &tmpbuf,
- .d_size = size,
- .d_version = EV_CURRENT,
- };
- Elf_Data rdata =
- {
- .d_type = type,
- .d_buf = tdata->d_buf + offset,
- .d_size = size,
- .d_version = EV_CURRENT,
- };
-
- GElf_Addr value = sym->st_value;
- if (is_rela)
- {
- /* For SHT_RELA sections we just take the
- given addend and add it to the value. */
- value += addend;
- /* For ADD/SUB relocations we need to fetch the
- current section contents. */
- if (addsub != 0)
- {
- Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
- &rdata,
- ei_data);
- if (d == NULL)
- INTERNAL_ERROR (fname);
- assert (d == &tmpdata);
- }
- }
- else
- {
- /* For SHT_REL sections we have to peek at
- what is already in the section at the given
- offset to get the addend. */
- Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
- &rdata,
- ei_data);
- if (d == NULL)
- INTERNAL_ERROR (fname);
- assert (d == &tmpdata);
- }
-
- switch (type)
- {
-#define DO_TYPE(NAME, Name) \
- case ELF_T_##NAME: \
- if (addsub < 0) \
- tmpbuf.Name -= (GElf_##Name) value; \
- else \
- tmpbuf.Name += (GElf_##Name) value; \
- break;
- TYPES;
-#undef DO_TYPE
- default:
- abort ();
- }
-
- /* Now finally put in the new value. */
- Elf_Data *s = gelf_xlatetof (elf, &rdata,
- &tmpdata,
- ei_data);
- if (s == NULL)
- INTERNAL_ERROR (fname);
- assert (s == &rdata);
-
- return true;
-}
-
-/* Remove any relocations between debug sections in ET_REL
- for the debug file when requested. These relocations are always
- zero based between the unallocated sections. */
-static void
-remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
- const char *fname, size_t shstrndx)
-{
- Elf_Scn *scn = NULL;
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- /* We need the actual section and header from the elf
- not just the cached original in shdr_info because we
- might want to change the size. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr != NULL
- && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
- {
- /* Make sure that this relocation section points to a
- section to relocate with contents, that isn't
- allocated and that is a debug section. */
- Elf_Scn *tscn = elf_getscn (elf, shdr->sh_info);
- GElf_Shdr tshdr_mem;
- GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
- if (tshdr == NULL
- || tshdr->sh_type == SHT_NOBITS
- || tshdr->sh_size == 0
- || (tshdr->sh_flags & SHF_ALLOC) != 0)
- continue;
-
- const char *tname = elf_strptr (elf, shstrndx,
- tshdr->sh_name);
- if (! tname || ! ebl_debugscn_p (ebl, tname))
- continue;
-
- /* OK, lets relocate all trivial cross debug section
- relocations. */
- Elf_Data *reldata = elf_getdata (scn, NULL);
- if (reldata == NULL || reldata->d_buf == NULL)
- INTERNAL_ERROR (fname);
-
- /* Make sure we adjust the uncompressed debug data
- (and recompress if necessary at the end). */
- GElf_Chdr tchdr;
- int tcompress_type = 0;
- bool is_gnu_compressed = false;
- if (startswith (tname, ".zdebug"))
- {
- is_gnu_compressed = true;
- if (elf_compress_gnu (tscn, 0, 0) != 1)
- INTERNAL_ERROR (fname);
- }
- else
- {
- if (gelf_getchdr (tscn, &tchdr) != NULL)
- {
- tcompress_type = tchdr.ch_type;
- if (elf_compress (tscn, 0, 0) != 1)
- INTERNAL_ERROR (fname);
- }
- }
-
- Elf_Data *tdata = elf_getdata (tscn, NULL);
- if (tdata == NULL || tdata->d_buf == NULL
- || tdata->d_type != ELF_T_BYTE)
- INTERNAL_ERROR (fname);
-
- /* Pick up the symbol table and shndx table to
- resolve relocation symbol indexes. */
- Elf64_Word symt = shdr->sh_link;
- Elf_Data *symdata, *xndxdata;
- Elf_Scn * symscn = elf_getscn (elf, symt);
- symdata = elf_getdata (symscn, NULL);
- xndxdata = get_xndxdata (elf, symscn);
- if (symdata == NULL)
- INTERNAL_ERROR (fname);
-
- if (shdr->sh_entsize == 0)
- INTERNAL_ERROR (fname);
-
- size_t nrels = shdr->sh_size / shdr->sh_entsize;
- size_t next = 0;
- const bool is_rela = (shdr->sh_type == SHT_RELA);
- const unsigned int ei_data = ehdr->e_ident[EI_DATA];
-
- for (size_t relidx = 0; relidx < nrels; ++relidx)
- {
- int rtype, symndx, offset, addend;
- union { GElf_Rela rela; GElf_Rel rel; } mem;
- void *rel_p; /* Pointer to either rela or rel above */
-
- if (is_rela)
- {
- GElf_Rela *r = gelf_getrela (reldata, relidx, &mem.rela);
- if (r == NULL)
- INTERNAL_ERROR (fname);
- offset = r->r_offset;
- addend = r->r_addend;
- rtype = GELF_R_TYPE (r->r_info);
- symndx = GELF_R_SYM (r->r_info);
- rel_p = r;
- }
- else
- {
- GElf_Rel *r = gelf_getrel (reldata, relidx, &mem.rel);
- if (r == NULL)
- INTERNAL_ERROR (fname);
- offset = r->r_offset;
- addend = 0;
- rtype = GELF_R_TYPE (r->r_info);
- symndx = GELF_R_SYM (r->r_info);
- rel_p = r;
- }
-
- /* R_*_NONE relocs can always just be removed. */
- if (rtype == 0)
- continue;
-
- /* We only do simple absolute relocations. */
- int addsub = 0;
- Elf_Type type = ebl_reloc_simple_type (ebl, rtype, &addsub);
- if (type == ELF_T_NUM)
- goto relocate_failed;
-
- /* And only for relocations against other debug sections. */
- GElf_Sym sym_mem;
- Elf32_Word xndx;
- GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
- symndx, &sym_mem,
- &xndx);
- if (sym == NULL)
- INTERNAL_ERROR (fname);
- Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
- ? xndx : sym->st_shndx);
-
- bool dbg_scn = ebl_debugscn_p (ebl, secndx_name (elf, sec));
-
- if (!dbg_scn)
- goto relocate_failed;
-
- if (! relocate (elf, offset, addend,
- tdata, ei_data, fname, is_rela,
- sym, addsub, type))
- goto relocate_failed;
-
- continue; /* Next */
-
-relocate_failed:
- if (relidx != next)
- {
- int updated;
- if (is_rela)
- updated = gelf_update_rela (reldata, next, rel_p);
- else
- updated = gelf_update_rel (reldata, next, rel_p);
- if (updated == 0)
- INTERNAL_ERROR (fname);
- }
- ++next;
- }
-
- nrels = next;
- shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
- if (gelf_update_shdr (scn, shdr) == 0)
- INTERNAL_ERROR (fname);
-
- if (is_gnu_compressed)
- {
- if (elf_compress_gnu (tscn, 1, ELF_CHF_FORCE) != 1)
- INTERNAL_ERROR (fname);
- }
- else if (tcompress_type != 0)
- {
- if (elf_compress (tscn, tcompress_type, ELF_CHF_FORCE) != 1)
- INTERNAL_ERROR (fname);
- }
- }
- }
-}
-
static int
process_file (const char *fname)
{
@@ -839,7 +499,7 @@ process_file (const char *fname)
/* Processing for --reloc-debug-sections-only. */
static int
-handle_debug_relocs (Elf *elf, Ebl *ebl, Elf *new_elf,
+handle_debug_relocs (Elf *elf, Elf *new_elf,
GElf_Ehdr *ehdr, const char *fname, size_t shstrndx,
GElf_Off *last_offset, GElf_Xword *last_size)
{
@@ -910,8 +570,9 @@ handle_debug_relocs (Elf *elf, Ebl *ebl, Elf *new_elf,
return 1;
}
- /* Adjust the relocation sections. */
- remove_debug_relocations (ebl, new_elf, ehdr, fname, shstrndx);
+ /* Remove debug section relocations. */
+ if (dwelf_elf_remove_debug_relocations (new_elf) == -1)
+ INTERNAL_ERROR (fname);
/* Adjust the offsets of the non-allocated sections, so they come after
the allocated sections. */
@@ -1139,7 +800,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
if (reloc_debug_only)
{
- if (handle_debug_relocs (elf, ebl, newelf, ehdr, fname, shstrndx,
+ if (handle_debug_relocs (elf, newelf, ehdr, fname, shstrndx,
&lastsec_offset, &lastsec_size) != 0)
{
result = 1;
@@ -2457,7 +2118,10 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
zero based between the unallocated sections. */
if (debug_fname != NULL && removing_sections
&& reloc_debug && ehdr->e_type == ET_REL)
- remove_debug_relocations (ebl, debugelf, ehdr, fname, shstrndx);
+ {
+ if (dwelf_elf_remove_debug_relocations (debugelf) == -1)
+ INTERNAL_ERROR (fname);
+ }
/* Now that we have done all adjustments to the data,
we can actually write out the debug file. */
@@ -59,7 +59,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
get-units-invalid get-units-split attr-integrate-skel \
all-dwarf-ranges unit-info next_cfi \
elfcopy addsections xlate_notes elfrdwrnop \
- dwelf_elf_e_machine_string \
+ dwelf_elf_e_machine_string remove-relocs \
getphdrnum leb128 read_unaligned \
msg_tst system-elf-libelf-test system-elf-gelf-test \
nvidia_extended_linemap_libdw elf-print-reloc-syms \
@@ -204,6 +204,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
run-strip-version.sh run-xlate-note.sh \
run-readelf-discr.sh \
run-dwelf_elf_e_machine_string.sh \
+ run-remove-relocs.sh \
run-elfclassify.sh run-elfclassify-self.sh \
run-disasm-riscv64.sh \
run-pt_gnu_prop-tests.sh \
@@ -576,6 +577,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
run-readelf-discr.sh \
testfile-rng.debug.bz2 testfile-urng.debug.bz2 \
run-dwelf_elf_e_machine_string.sh \
+ run-remove-relocs.sh testfile-remove-relocs.bz2 \
run-elfclassify.sh run-elfclassify-self.sh \
run-disasm-riscv64.sh \
testfile-riscv64-dis1.o.bz2 testfile-riscv64-dis1.expect.bz2 \
@@ -856,6 +858,7 @@ debuginfod_build_id_find_LDADD = $(libelf) $(libdw)
xlate_notes_LDADD = $(libelf)
elfrdwrnop_LDADD = $(libelf)
dwelf_elf_e_machine_string_LDADD = $(libelf) $(libdw)
+remove_relocs_LDADD = $(libelf) $(libdw)
getphdrnum_LDADD = $(libelf) $(libdw)
leb128_LDADD = $(libelf) $(libdw)
read_unaligned_LDADD = $(libelf) $(libdw)
new file mode 100644
@@ -0,0 +1,38 @@
+/* Test program for dwelf_elf_remove_debug_relocs
+ Copyright (C) 2024 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dw)
+#include ELFUTILS_HEADER(dwelf)
+
+int main(int argc __attribute__ ((unused)), char **argv) {
+ Elf *elf;
+ elf_version (EV_CURRENT);
+ int fd = open (argv[1], O_RDWR);
+
+ elf = elf_begin (fd, ELF_C_RDWR, NULL);
+
+ dwelf_elf_remove_debug_relocations (elf);
+ elf_update (elf, ELF_C_WRITE);
+
+ elf_end (elf);
+ return 0;
+}
new file mode 100755
@@ -0,0 +1,54 @@
+#! /usr/bin/env bash
+# Test dwelf_elf_remove_debug_relocations
+# Copyright (C) 2024 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# = qq.c =
+# int add (int a, int b)
+# {
+# return a+b;
+# }
+#
+# int main()
+# {
+# return 0;
+# }
+
+# Using gcc (GCC) 14.2.1 20240801 (Red Hat 14.2.1-1)
+# gcc -g -c qq.c -o testfile-remove-relocs
+
+testfiles testfile-remove-relocs
+
+# Before debug relocations are removed some indices into string tables are
+# set to a default value of 0. This causes incorrect file and function
+# names to be displayed.
+testrun_compare ${abs_builddir}/allfcts testfile-remove-relocs <<\EOF
+qq.c/qq.c:6:GNU C17 14.2.1 20240801 (Red Hat 14.2.1-1) -mtune=generic -march=x86-64 -g
+qq.c/qq.c:1:add
+EOF
+
+# Remove debug relocations and write the changes to the testfile.
+testrun ${abs_builddir}/remove-relocs testfile-remove-relocs
+
+# Correct file and function names should now be displayed.
+testrun_compare ${abs_builddir}/allfcts testfile-remove-relocs <<\EOF
+/home/dichen/elfutils/tests/qq.c:6:main
+/home/dichen/elfutils/tests/qq.c:1:add
+EOF
+
+exit 0
new file mode 100644
GIT binary patch
literal 1088
zcmV-G1i$-2T4*^jL0KkKS)er3J^%yRfB*mg|Ni#(_5b_r(_;Vc|9gvQWE8{z0K`cE
zL_h*SU`)^hde?`qYcFQ@bAv@sQ&Ue-r>W{R^)pjVs2MQ;dTIaw01W|=pa1{>01W^&
zPfB_a%6e%(RMF`@G(Z3V02%-QXaE2J0ib9A05vd(6*r|D)X>l-(V*1Yn3`d!ko5*Y
z1`q*>gu-ahVh=<E)L=46O#{>hgHKQZX`sOxGynhwMu5;^0B8n)00070Q8Xq%Ddieu
z&@|8h^#e^b4F-ly02%;jXf$Zh8hU{B4^RmDELD`%=HnQFAq_A<j3g?~{TX(abYl{y
zO1yNEP?>*eHhohwHb?H%Q<GBlQVcCwZG(34Ly~gTMjxcY0w>?Jj5JcDh-nnrqZ0yV
zp?K}+M)t}&0TYBpCP4s>M`X-{9QKu}rm8^2{8G<rmvHntQK<$=uMS6i4`?@B-P_J<
z%m!V7IR&vcZUI6DR_)ea<^VH83TxYzrje;jiJ{to6lub^sHS+$i&s%SY>a9WfHFg1
z%;3?B4tGyKDx*gDKoITZ&l#gxiGagE0gi!*lLY8tvr_{Eh+xb?RW?#K>6!S>Hd-eY
zQF{5F4VH#rf@T<?h7U>{fCstIN<a=`5<-yfAS6g2&9~iHnZ%LgUyV;z;g8HZ7c4Bf
z6+13wG88W}oqsN~g*I*74l7Z<Xx#H=k_-p4KoS<UF}-<gg#_Y22#AQ8MV!P`q$WA9
zes-3rNEqL7i(ls}{fU_12fV0In@H)@l&M67dV~Z}Z>WYCAw-%-swAQUOoJIk)esR%
zCJPzH23@a#<pRjM1&>oMT86mdtp1}Z5NdFSDY9*X0TDQ5V3Fdk<T=hvnT!<l_G5=h
z%-*yfQ^-(!LIQ#VQ*WgDK6iW1?t!0L8u2hnt`Wc`UC17D1D^odErw%u#uEsk(jZ~o
zny^7bvOi*&jG>ri;1Lt4OhI(Qj!q8Sh~h>FOk`gNj!!JRhh&3AoRYz1W~`%uZbp(j
z`(a=?vs?t-7D9WEx*D>ns)3S3WRU}!zs#gkDn)mEW1m45Leqi7Mw0L+D9ZR7S?`rB
ztJuvHH;@uvof^{^)#`vM17&EEEvlNnxSo7Nkuo7}BkPlc)_^q~`oeSqs;6gRG$Vkg
z-0Y}YDo>PhS|Rb12AXW=fMvL^DBUv1JMdvp-3NODpvW%Fh(5%mW8x6j$@g_f4kR1I
zM>t4XEXyu)<|I_1Udd|=Z1_|C;@CxF5}ksfWMDpR<BP5mOf(?`J>U%%`P2@<N|A|K
zKxa)zY%>9&F2mTMKM_fwv*4f+A45<Y5g0ZUQUgKK6$XD|OQeV;B!LV&m=rP2elX5G
zSf?Gd(`-4Rwhvs*S^eOy;ozPTHEBaYHTZ&o0T@m2<x)DJ)3?L0dxM|D#4hBDaG@bU
GX{dalrP>4l
literal 0
HcmV?d00001
--
2.46.2