1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
From 59d4b8c48e5040af7e02b34eb26ea602ec82a38e Mon Sep 17 00:00:00 2001
From: James Cowgill <james410@cowgill.org.uk>
Date: Mon, 5 Jan 2015 15:17:02 +0000
Subject: [PATCH 3/3] Add mips n64 relocation format hack
MIPSEL N64 ELF files use a slightly different format for storing relocation
entries which is incompatible with the normal R_SYM / R_INFO macros.
To workaround this, we rearrange the bytes in the relocation's r_info field
when reading and writing the relocations.
This patch also ensures that strip.c sets the correct value of e_machine
before manipulating relocations so that these changes take effect.
Signed-off-by: James Cowgill <james410@cowgill.org.uk>
---
libelf/gelf_getrel.c | 25 +++++++++++++++++++++++--
libelf/gelf_getrela.c | 25 +++++++++++++++++++++++--
libelf/gelf_update_rel.c | 20 +++++++++++++++++++-
libelf/gelf_update_rela.c | 20 +++++++++++++++++++-
src/strip.c | 17 +++++++++++++++++
5 files changed, 101 insertions(+), 6 deletions(-)
Index: elfutils-0.175/libelf/gelf_getrel.c
===================================================================
--- elfutils-0.175.orig/libelf/gelf_getrel.c
+++ elfutils-0.175/libelf/gelf_getrel.c
@@ -36,6 +36,7 @@
#include "libelfP.h"
+#define EF_MIPS_ABI 0x0000F000
GElf_Rel *
gelf_getrel (Elf_Data *data, int ndx, GElf_Rel *dst)
@@ -89,8 +90,28 @@ gelf_getrel (Elf_Data *data, int ndx, GE
result = NULL;
}
else
- result = memcpy (dst, &((Elf64_Rel *) data_scn->d.d_buf)[ndx],
- sizeof (Elf64_Rel));
+ {
+ GElf_Ehdr hdr;
+ result = memcpy (dst, &((Elf64_Rel *) data_scn->d.d_buf)[ndx],
+ sizeof (Elf64_Rel));
+
+ if (gelf_getehdr(scn->elf, &hdr) != NULL &&
+ hdr.e_ident[EI_DATA] == ELFDATA2LSB &&
+ hdr.e_machine == EM_MIPS &&
+ (hdr.e_flags & EF_MIPS_ABI) == 0)
+ {
+ /*
+ * The relocation format is mangled on MIPSEL N64
+ * We'll adjust it so at least R_SYM will work on it
+ */
+ GElf_Xword r_info = dst->r_info;
+ dst->r_info = (r_info << 32) |
+ ((r_info >> 8) & 0xFF000000) |
+ ((r_info >> 24) & 0x00FF0000) |
+ ((r_info >> 40) & 0x0000FF00) |
+ ((r_info >> 56) & 0x000000FF);
+ }
+ }
}
rwlock_unlock (scn->elf->lock);
Index: elfutils-0.175/libelf/gelf_getrela.c
===================================================================
--- elfutils-0.175.orig/libelf/gelf_getrela.c
+++ elfutils-0.175/libelf/gelf_getrela.c
@@ -36,6 +36,7 @@
#include "libelfP.h"
+#define EF_MIPS_ABI 0x0000F000
GElf_Rela *
gelf_getrela (Elf_Data *data, int ndx, GElf_Rela *dst)
@@ -90,8 +91,28 @@ gelf_getrela (Elf_Data *data, int ndx, G
result = NULL;
}
else
- result = memcpy (dst, &((Elf64_Rela *) data_scn->d.d_buf)[ndx],
- sizeof (Elf64_Rela));
+ {
+ GElf_Ehdr hdr;
+ result = memcpy (dst, &((Elf64_Rela *) data_scn->d.d_buf)[ndx],
+ sizeof (Elf64_Rela));
+
+ if (gelf_getehdr(scn->elf, &hdr) != NULL &&
+ hdr.e_ident[EI_DATA] == ELFDATA2LSB &&
+ hdr.e_machine == EM_MIPS &&
+ (hdr.e_flags & EF_MIPS_ABI) == 0)
+ {
+ /*
+ * The relocation format is mangled on MIPSEL N64
+ * We'll adjust it so at least R_SYM will work on it
+ */
+ GElf_Xword r_info = dst->r_info;
+ dst->r_info = (r_info << 32) |
+ ((r_info >> 8) & 0xFF000000) |
+ ((r_info >> 24) & 0x00FF0000) |
+ ((r_info >> 40) & 0x0000FF00) |
+ ((r_info >> 56) & 0x000000FF);
+ }
+ }
}
rwlock_unlock (scn->elf->lock);
Index: elfutils-0.175/libelf/gelf_update_rel.c
===================================================================
--- elfutils-0.175.orig/libelf/gelf_update_rel.c
+++ elfutils-0.175/libelf/gelf_update_rel.c
@@ -36,6 +36,7 @@
#include "libelfP.h"
+#define EF_MIPS_ABI 0x0000F000
int
gelf_update_rel (Elf_Data *dst, int ndx, GElf_Rel *src)
@@ -86,6 +87,9 @@ gelf_update_rel (Elf_Data *dst, int ndx,
}
else
{
+ GElf_Ehdr hdr;
+ GElf_Rel value = *src;
+
/* Check whether we have to resize the data buffer. */
if (INVALID_NDX (ndx, Elf64_Rel, &data_scn->d))
{
@@ -93,7 +97,21 @@ gelf_update_rel (Elf_Data *dst, int ndx,
goto out;
}
- ((Elf64_Rel *) data_scn->d.d_buf)[ndx] = *src;
+ if (gelf_getehdr(scn->elf, &hdr) != NULL &&
+ hdr.e_ident[EI_DATA] == ELFDATA2LSB &&
+ hdr.e_machine == EM_MIPS &&
+ (hdr.e_flags & EF_MIPS_ABI) == 0)
+ {
+ /* Undo the MIPSEL N64 hack from gelf_getrel */
+ GElf_Xword r_info = value.r_info;
+ value.r_info = (r_info >> 32) |
+ ((r_info << 8) & 0x000000FF00000000) |
+ ((r_info << 24) & 0x0000FF0000000000) |
+ ((r_info << 40) & 0x00FF000000000000) |
+ ((r_info << 56) & 0xFF00000000000000);
+ }
+
+ ((Elf64_Rel *) data_scn->d.d_buf)[ndx] = value;
}
result = 1;
Index: elfutils-0.175/libelf/gelf_update_rela.c
===================================================================
--- elfutils-0.175.orig/libelf/gelf_update_rela.c
+++ elfutils-0.175/libelf/gelf_update_rela.c
@@ -36,6 +36,7 @@
#include "libelfP.h"
+#define EF_MIPS_ABI 0x0000F000
int
gelf_update_rela (Elf_Data *dst, int ndx, GElf_Rela *src)
@@ -89,6 +90,9 @@ gelf_update_rela (Elf_Data *dst, int ndx
}
else
{
+ GElf_Ehdr hdr;
+ GElf_Rela value = *src;
+
/* Check whether we have to resize the data buffer. */
if (INVALID_NDX (ndx, Elf64_Rela, &data_scn->d))
{
@@ -96,7 +100,21 @@ gelf_update_rela (Elf_Data *dst, int ndx
goto out;
}
- ((Elf64_Rela *) data_scn->d.d_buf)[ndx] = *src;
+ if (gelf_getehdr(scn->elf, &hdr) != NULL &&
+ hdr.e_ident[EI_DATA] == ELFDATA2LSB &&
+ hdr.e_machine == EM_MIPS &&
+ (hdr.e_flags & EF_MIPS_ABI) == 0)
+ {
+ /* Undo the MIPSEL N64 hack from gelf_getrel */
+ GElf_Xword r_info = value.r_info;
+ value.r_info = (r_info >> 32) |
+ ((r_info << 8) & 0x000000FF00000000) |
+ ((r_info << 24) & 0x0000FF0000000000) |
+ ((r_info << 40) & 0x00FF000000000000) |
+ ((r_info << 56) & 0xFF00000000000000);
+ }
+
+ ((Elf64_Rela *) data_scn->d.d_buf)[ndx] = value;
}
result = 1;
Index: elfutils-0.175/src/strip.c
===================================================================
--- elfutils-0.175.orig/src/strip.c
+++ elfutils-0.175/src/strip.c
@@ -1062,6 +1062,23 @@ handle_elf (int fd, Elf *elf, const char
goto fail;
}
+ /* Copy identity part of the ELF header now */
+ newehdr = gelf_getehdr (newelf, &newehdr_mem);
+ if (newehdr == NULL)
+ INTERNAL_ERROR (fname);
+
+ memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
+ newehdr->e_type = ehdr->e_type;
+ newehdr->e_machine = ehdr->e_machine;
+ newehdr->e_version = ehdr->e_version;
+
+ if (gelf_update_ehdr (newelf, newehdr) == 0)
+ {
+ error (0, 0, gettext ("%s: error while creating ELF header: %s"),
+ fname, elf_errmsg (-1));
+ return 1;
+ }
+
/* Copy over the old program header if needed. */
if (phnum > 0)
{
|