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