blob: fe8cd6bda983e3b74cde70926949600aec6737cb [file] [log] [blame]
Tom Rini8b0c8a12018-05-06 18:27:01 -04001// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause
Scott Wood49fa0592013-12-14 11:47:32 +08002/*
3 * Copyright 2013 Freescale Semiconductor, Inc.
4 *
Scott Wood49fa0592013-12-14 11:47:32 +08005 * 64-bit and little-endian target only until we need to support a different
6 * arch that needs this.
7 */
8
9#include <elf.h>
10#include <errno.h>
11#include <inttypes.h>
12#include <stdarg.h>
13#include <stdbool.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
Jonathan Gray9dd92042016-12-11 14:51:13 +110017#include "compiler.h"
Scott Wood49fa0592013-12-14 11:47:32 +080018
Michal Simek5a691912022-07-08 08:15:06 +020019#ifndef EM_AARCH64
20#define EM_AARCH64 183
21#endif
22
Scott Wood49fa0592013-12-14 11:47:32 +080023#ifndef R_AARCH64_RELATIVE
24#define R_AARCH64_RELATIVE 1027
25#endif
26
Michal Simek5a691912022-07-08 08:15:06 +020027#ifndef EM_MICROBLAZE
28#define EM_MICROBLAZE 189
29#endif
30
31#ifndef R_MICROBLAZE_NONE
32#define R_MICROBLAZE_NONE 0
33#endif
34
35#ifndef R_MICROBLAZE_32
36#define R_MICROBLAZE_32 1
37#endif
38
39#ifndef R_MICROBLAZE_REL
40#define R_MICROBLAZE_REL 16
41#endif
42
43#ifndef R_MICROBLAZE_GLOB_DAT
44#define R_MICROBLAZE_GLOB_DAT 18
45#endif
46
Michal Simekef320202022-06-24 14:14:59 +020047static int ei_class;
Ovidiu Panait6155b0b2023-03-11 19:38:35 +020048static int ei_data;
Michal Simekef320202022-06-24 14:14:59 +020049
Michal Simek4fad25f2022-06-24 14:15:00 +020050static uint64_t rela_start, rela_end, text_base, dyn_start;
Michal Simek6944cec2022-06-24 14:14:59 +020051
Scott Wood49fa0592013-12-14 11:47:32 +080052static const bool debug_en;
53
54static void debug(const char *fmt, ...)
55{
56 va_list args;
57
xypron.glpk@gmx.de5cdd5392017-05-03 22:40:11 +020058 if (debug_en) {
59 va_start(args, fmt);
Scott Wood49fa0592013-12-14 11:47:32 +080060 vprintf(fmt, args);
xypron.glpk@gmx.de5cdd5392017-05-03 22:40:11 +020061 va_end(args);
62 }
Scott Wood49fa0592013-12-14 11:47:32 +080063}
64
Ovidiu Panait6155b0b2023-03-11 19:38:35 +020065static uint16_t elf16_to_cpu(uint16_t data)
66{
67 if (ei_data == ELFDATA2LSB)
68 return le16_to_cpu(data);
69
70 return be16_to_cpu(data);
71}
72
73static uint32_t elf32_to_cpu(uint32_t data)
74{
75 if (ei_data == ELFDATA2LSB)
76 return le32_to_cpu(data);
77
78 return be32_to_cpu(data);
79}
80
Scott Wood49fa0592013-12-14 11:47:32 +080081static bool supported_rela(Elf64_Rela *rela)
82{
83 uint64_t mask = 0xffffffffULL; /* would be different on 32-bit */
84 uint32_t type = rela->r_info & mask;
85
86 switch (type) {
Scott Wood49fa0592013-12-14 11:47:32 +080087 case R_AARCH64_RELATIVE:
88 return true;
Scott Wood49fa0592013-12-14 11:47:32 +080089 default:
90 fprintf(stderr, "warning: unsupported relocation type %"
91 PRIu32 " at %" PRIx64 "\n",
92 type, rela->r_offset);
93
94 return false;
95 }
Michal Simekef320202022-06-24 14:14:59 +020096}
97
98static int decode_elf64(FILE *felf, char **argv)
99{
100 size_t size;
101 Elf64_Ehdr header;
Samuel Hollandd0517862022-07-15 01:40:25 -0500102 uint64_t section_header_base, section_header_size;
103 uint64_t sh_addr, sh_offset, sh_size;
104 Elf64_Half sh_index, sh_num;
Michal Simekef320202022-06-24 14:14:59 +0200105 Elf64_Shdr *sh_table; /* Elf symbol table */
106 int ret, i, machine;
107 char *sh_str;
108
109 debug("64bit version\n");
110
111 /* Make sure we are at start */
112 rewind(felf);
113
114 size = fread(&header, 1, sizeof(header), felf);
115 if (size != sizeof(header)) {
116 fclose(felf);
117 return 25;
118 }
119
Samuel Hollandd0517862022-07-15 01:40:25 -0500120 machine = le16_to_cpu(header.e_machine);
Michal Simekef320202022-06-24 14:14:59 +0200121 debug("Machine\t%d\n", machine);
122
Michal Simek97d50302022-06-24 14:15:00 +0200123 if (machine != EM_AARCH64) {
124 fprintf(stderr, "%s: Not supported machine type\n", argv[0]);
125 return 30;
126 }
127
Samuel Hollandd0517862022-07-15 01:40:25 -0500128 text_base = le64_to_cpu(header.e_entry);
129 section_header_base = le64_to_cpu(header.e_shoff);
130 section_header_size = le16_to_cpu(header.e_shentsize) *
131 le16_to_cpu(header.e_shnum);
Michal Simekef320202022-06-24 14:14:59 +0200132
133 sh_table = malloc(section_header_size);
134 if (!sh_table) {
135 fprintf(stderr, "%s: Cannot allocate space for section header\n",
136 argv[0]);
137 fclose(felf);
138 return 26;
139 }
140
141 ret = fseek(felf, section_header_base, SEEK_SET);
142 if (ret) {
143 fprintf(stderr, "%s: Can't set pointer to section header: %x/%lx\n",
144 argv[0], ret, section_header_base);
145 free(sh_table);
146 fclose(felf);
147 return 26;
148 }
149
150 size = fread(sh_table, 1, section_header_size, felf);
151 if (size != section_header_size) {
152 fprintf(stderr, "%s: Can't read section header: %lx/%lx\n",
153 argv[0], size, section_header_size);
154 free(sh_table);
155 fclose(felf);
156 return 27;
157 }
158
Samuel Hollandd0517862022-07-15 01:40:25 -0500159 sh_index = le16_to_cpu(header.e_shstrndx);
160 sh_size = le64_to_cpu(sh_table[sh_index].sh_size);
161 debug("e_shstrndx %x, sh_size %lx\n", sh_index, sh_size);
Michal Simekef320202022-06-24 14:14:59 +0200162
163 sh_str = malloc(sh_size);
164 if (!sh_str) {
165 fprintf(stderr, "malloc failed\n");
166 free(sh_table);
167 fclose(felf);
168 return 28;
169 }
170
171 /*
172 * Specifies the byte offset from the beginning of the file
173 * to the first byte in the section.
174 */
Samuel Hollandd0517862022-07-15 01:40:25 -0500175 sh_offset = le64_to_cpu(sh_table[sh_index].sh_offset);
176 sh_num = le16_to_cpu(header.e_shnum);
Michal Simekef320202022-06-24 14:14:59 +0200177
178 ret = fseek(felf, sh_offset, SEEK_SET);
179 if (ret) {
180 fprintf(stderr, "Setting up sh_offset failed\n");
181 free(sh_str);
182 free(sh_table);
183 fclose(felf);
184 return 29;
185 }
186
187 size = fread(sh_str, 1, sh_size, felf);
188 if (size != sh_size) {
189 fprintf(stderr, "%s: Can't read section: %lx/%lx\n",
190 argv[0], size, sh_size);
191 free(sh_str);
192 free(sh_table);
193 fclose(felf);
194 return 30;
195 }
196
Samuel Hollandd0517862022-07-15 01:40:25 -0500197 for (i = 0; i < sh_num; i++) {
198 char *sh_name = sh_str + le32_to_cpu(sh_table[i].sh_name);
199
200 debug("%s\n", sh_name);
201
202 sh_addr = le64_to_cpu(sh_table[i].sh_addr);
203 sh_offset = le64_to_cpu(sh_table[i].sh_offset);
204 sh_size = le64_to_cpu(sh_table[i].sh_size);
205
206 if (!strcmp(".rela.dyn", sh_name)) {
Michal Simekef320202022-06-24 14:14:59 +0200207 debug("Found section\t\".rela_dyn\"\n");
Samuel Hollandd0517862022-07-15 01:40:25 -0500208 debug(" at addr\t0x%08x\n", sh_addr);
209 debug(" at offset\t0x%08x\n", sh_offset);
210 debug(" of size\t0x%08x\n", sh_size);
211 rela_start = sh_addr;
212 rela_end = rela_start + sh_size;
Michal Simekef320202022-06-24 14:14:59 +0200213 break;
214 }
215 }
216
217 /* Clean up */
218 free(sh_str);
219 free(sh_table);
220 fclose(felf);
221
222 debug("text_base\t0x%08lx\n", text_base);
223 debug("rela_start\t0x%08lx\n", rela_start);
224 debug("rela_end\t0x%08lx\n", rela_end);
225
226 if (!rela_start)
227 return 1;
228
229 return 0;
Scott Wood49fa0592013-12-14 11:47:32 +0800230}
231
Michal Simek4fad25f2022-06-24 14:15:00 +0200232static int decode_elf32(FILE *felf, char **argv)
233{
234 size_t size;
235 Elf32_Ehdr header;
Samuel Hollandd0517862022-07-15 01:40:25 -0500236 uint64_t section_header_base, section_header_size;
237 uint32_t sh_addr, sh_offset, sh_size;
238 Elf32_Half sh_index, sh_num;
Michal Simek4fad25f2022-06-24 14:15:00 +0200239 Elf32_Shdr *sh_table; /* Elf symbol table */
240 int ret, i, machine;
241 char *sh_str;
242
243 debug("32bit version\n");
244
245 /* Make sure we are at start */
246 rewind(felf);
247
248 size = fread(&header, 1, sizeof(header), felf);
249 if (size != sizeof(header)) {
250 fclose(felf);
251 return 25;
252 }
253
Ovidiu Panaita4786c92023-03-11 19:38:36 +0200254 machine = elf16_to_cpu(header.e_machine);
Michal Simek4fad25f2022-06-24 14:15:00 +0200255 debug("Machine %d\n", machine);
256
257 if (machine != EM_MICROBLAZE) {
258 fprintf(stderr, "%s: Not supported machine type\n", argv[0]);
259 return 30;
260 }
261
Ovidiu Panaita4786c92023-03-11 19:38:36 +0200262 text_base = elf32_to_cpu(header.e_entry);
263 section_header_base = elf32_to_cpu(header.e_shoff);
264 section_header_size = elf16_to_cpu(header.e_shentsize) *
265 elf16_to_cpu(header.e_shnum);
Michal Simek4fad25f2022-06-24 14:15:00 +0200266
267 sh_table = malloc(section_header_size);
268 if (!sh_table) {
269 fprintf(stderr, "%s: Cannot allocate space for section header\n",
270 argv[0]);
271 fclose(felf);
272 return 26;
273 }
274
275 ret = fseek(felf, section_header_base, SEEK_SET);
276 if (ret) {
277 fprintf(stderr, "%s: Can't set pointer to section header: %x/%lx\n",
278 argv[0], ret, section_header_base);
279 free(sh_table);
280 fclose(felf);
281 return 26;
282 }
283
284 size = fread(sh_table, 1, section_header_size, felf);
285 if (size != section_header_size) {
286 fprintf(stderr, "%s: Can't read section header: %lx/%lx\n",
287 argv[0], size, section_header_size);
288 free(sh_table);
289 fclose(felf);
290 return 27;
291 }
292
Ovidiu Panaita4786c92023-03-11 19:38:36 +0200293 sh_index = elf16_to_cpu(header.e_shstrndx);
294 sh_size = elf32_to_cpu(sh_table[sh_index].sh_size);
Samuel Hollandd0517862022-07-15 01:40:25 -0500295 debug("e_shstrndx %x, sh_size %lx\n", sh_index, sh_size);
Michal Simek4fad25f2022-06-24 14:15:00 +0200296
297 sh_str = malloc(sh_size);
298 if (!sh_str) {
299 fprintf(stderr, "malloc failed\n");
300 free(sh_table);
301 fclose(felf);
302 return 28;
303 }
304
305 /*
306 * Specifies the byte offset from the beginning of the file
307 * to the first byte in the section.
308 */
Ovidiu Panaita4786c92023-03-11 19:38:36 +0200309 sh_offset = elf32_to_cpu(sh_table[sh_index].sh_offset);
310 sh_num = elf16_to_cpu(header.e_shnum);
Michal Simek4fad25f2022-06-24 14:15:00 +0200311
312 ret = fseek(felf, sh_offset, SEEK_SET);
313 if (ret) {
314 fprintf(stderr, "Setting up sh_offset failed\n");
315 free(sh_str);
316 free(sh_table);
317 fclose(felf);
318 return 29;
319 }
320
321 size = fread(sh_str, 1, sh_size, felf);
322 if (size != sh_size) {
Samuel Hollandd0517862022-07-15 01:40:25 -0500323 fprintf(stderr, "%s: Can't read section: %lx/%x\n",
Michal Simek4fad25f2022-06-24 14:15:00 +0200324 argv[0], size, sh_size);
325 free(sh_str);
326 free(sh_table);
327 fclose(felf);
328 return 30;
329 }
330
Samuel Hollandd0517862022-07-15 01:40:25 -0500331 for (i = 0; i < sh_num; i++) {
Ovidiu Panaita4786c92023-03-11 19:38:36 +0200332 char *sh_name = sh_str + elf32_to_cpu(sh_table[i].sh_name);
Samuel Hollandd0517862022-07-15 01:40:25 -0500333
334 debug("%s\n", sh_name);
335
Ovidiu Panaita4786c92023-03-11 19:38:36 +0200336 sh_addr = elf32_to_cpu(sh_table[i].sh_addr);
337 sh_offset = elf32_to_cpu(sh_table[i].sh_offset);
338 sh_size = elf32_to_cpu(sh_table[i].sh_size);
Samuel Hollandd0517862022-07-15 01:40:25 -0500339
340 if (!strcmp(".rela.dyn", sh_name)) {
Michal Simek4fad25f2022-06-24 14:15:00 +0200341 debug("Found section\t\".rela_dyn\"\n");
Samuel Hollandd0517862022-07-15 01:40:25 -0500342 debug(" at addr\t0x%08x\n", sh_addr);
343 debug(" at offset\t0x%08x\n", sh_offset);
344 debug(" of size\t0x%08x\n", sh_size);
345 rela_start = sh_addr;
346 rela_end = rela_start + sh_size;
Michal Simek4fad25f2022-06-24 14:15:00 +0200347 }
Samuel Hollandd0517862022-07-15 01:40:25 -0500348 if (!strcmp(".dynsym", sh_name)) {
Michal Simek4fad25f2022-06-24 14:15:00 +0200349 debug("Found section\t\".dynsym\"\n");
Samuel Hollandd0517862022-07-15 01:40:25 -0500350 debug(" at addr\t0x%08x\n", sh_addr);
351 debug(" at offset\t0x%08x\n", sh_offset);
352 debug(" of size\t0x%08x\n", sh_size);
353 dyn_start = sh_addr;
Michal Simek4fad25f2022-06-24 14:15:00 +0200354 }
355 }
356
357 /* Clean up */
358 free(sh_str);
359 free(sh_table);
360 fclose(felf);
361
362 debug("text_base\t0x%08lx\n", text_base);
363 debug("rela_start\t0x%08lx\n", rela_start);
364 debug("rela_end\t0x%08lx\n", rela_end);
365 debug("dyn_start\t0x%08lx\n", dyn_start);
366
367 if (!rela_start)
368 return 1;
369
370 return 0;
371}
372
Michal Simekef320202022-06-24 14:14:59 +0200373static int decode_elf(char **argv)
Scott Wood49fa0592013-12-14 11:47:32 +0800374{
Michal Simekef320202022-06-24 14:14:59 +0200375 FILE *felf;
376 size_t size;
377 unsigned char e_ident[EI_NIDENT];
378
379 felf = fopen(argv[2], "r+b");
380 if (!felf) {
381 fprintf(stderr, "%s: Cannot open %s: %s\n",
382 argv[0], argv[5], strerror(errno));
383 return 2;
384 }
385
386 size = fread(e_ident, 1, EI_NIDENT, felf);
387 if (size != EI_NIDENT) {
388 fclose(felf);
389 return 25;
390 }
391
392 /* Check if this is really ELF file */
393 if (e_ident[0] != 0x7f &&
394 e_ident[1] != 'E' &&
395 e_ident[2] != 'L' &&
396 e_ident[3] != 'F') {
397 fclose(felf);
398 return 1;
399 }
400
401 ei_class = e_ident[4];
402 debug("EI_CLASS(1=32bit, 2=64bit) %d\n", ei_class);
403
Ovidiu Panait6155b0b2023-03-11 19:38:35 +0200404 ei_data = e_ident[5];
405 debug("EI_DATA(1=little endian, 2=big endian) %d\n", ei_data);
406
Michal Simekef320202022-06-24 14:14:59 +0200407 if (ei_class == 2)
408 return decode_elf64(felf, argv);
409
Michal Simek4fad25f2022-06-24 14:15:00 +0200410 return decode_elf32(felf, argv);
Scott Wood49fa0592013-12-14 11:47:32 +0800411}
412
Michal Simekf9c28a12022-06-24 14:15:00 +0200413static int rela_elf64(char **argv, FILE *f)
Scott Wood49fa0592013-12-14 11:47:32 +0800414{
Michal Simekf9c28a12022-06-24 14:15:00 +0200415 int i, num;
Alistair Delva5321bfe2021-10-20 21:31:32 +0000416
417 if ((rela_end - rela_start) % sizeof(Elf64_Rela)) {
418 fprintf(stderr, "%s: rela size isn't a multiple of Elf64_Rela\n", argv[0]);
419 return 3;
420 }
421
Scott Wood49fa0592013-12-14 11:47:32 +0800422 num = (rela_end - rela_start) / sizeof(Elf64_Rela);
423
424 for (i = 0; i < num; i++) {
425 Elf64_Rela rela, swrela;
426 uint64_t pos = rela_start + sizeof(Elf64_Rela) * i;
427 uint64_t addr;
428
429 if (fseek(f, pos, SEEK_SET) < 0) {
430 fprintf(stderr, "%s: %s: seek to %" PRIx64
431 " failed: %s\n",
432 argv[0], argv[1], pos, strerror(errno));
433 }
434
435 if (fread(&rela, sizeof(rela), 1, f) != 1) {
436 fprintf(stderr, "%s: %s: read rela failed at %"
437 PRIx64 "\n",
438 argv[0], argv[1], pos);
439 return 4;
440 }
441
Samuel Hollandd0517862022-07-15 01:40:25 -0500442 swrela.r_offset = le64_to_cpu(rela.r_offset);
443 swrela.r_info = le64_to_cpu(rela.r_info);
444 swrela.r_addend = le64_to_cpu(rela.r_addend);
Scott Wood49fa0592013-12-14 11:47:32 +0800445
446 if (!supported_rela(&swrela))
447 continue;
448
449 debug("Rela %" PRIx64 " %" PRIu64 " %" PRIx64 "\n",
450 swrela.r_offset, swrela.r_info, swrela.r_addend);
451
452 if (swrela.r_offset < text_base) {
453 fprintf(stderr, "%s: %s: bad rela at %" PRIx64 "\n",
454 argv[0], argv[1], pos);
455 return 4;
456 }
457
458 addr = swrela.r_offset - text_base;
459
460 if (fseek(f, addr, SEEK_SET) < 0) {
461 fprintf(stderr, "%s: %s: seek to %"
462 PRIx64 " failed: %s\n",
463 argv[0], argv[1], addr, strerror(errno));
464 }
465
466 if (fwrite(&rela.r_addend, sizeof(rela.r_addend), 1, f) != 1) {
467 fprintf(stderr, "%s: %s: write failed at %" PRIx64 "\n",
468 argv[0], argv[1], addr);
469 return 4;
470 }
471 }
472
Michal Simekf9c28a12022-06-24 14:15:00 +0200473 return 0;
474}
475
Michal Simek39b2b6c2022-06-24 14:15:00 +0200476static bool supported_rela32(Elf32_Rela *rela, uint32_t *type)
477{
478 uint32_t mask = 0xffULL; /* would be different on 32-bit */
479 *type = rela->r_info & mask;
480
481 debug("Type:\t");
482
483 switch (*type) {
484 case R_MICROBLAZE_32:
485 debug("R_MICROBLAZE_32\n");
486 return true;
487 case R_MICROBLAZE_GLOB_DAT:
488 debug("R_MICROBLAZE_GLOB_DAT\n");
489 return true;
490 case R_MICROBLAZE_NONE:
491 debug("R_MICROBLAZE_NONE - ignoring - do nothing\n");
492 return false;
493 case R_MICROBLAZE_REL:
494 debug("R_MICROBLAZE_REL\n");
495 return true;
496 default:
497 fprintf(stderr, "warning: unsupported relocation type %"
498 PRIu32 " at %" PRIx32 "\n", *type, rela->r_offset);
499
500 return false;
501 }
502}
503
504static int rela_elf32(char **argv, FILE *f)
505{
506 int i, num, index;
507 uint32_t value, type;
508
509 if ((rela_end - rela_start) % sizeof(Elf32_Rela)) {
510 fprintf(stderr, "%s: rela size isn't a multiple of Elf32_Rela\n", argv[0]);
511 return 3;
512 }
513
514 num = (rela_end - rela_start) / sizeof(Elf32_Rela);
515
516 debug("Number of entries: %u\n", num);
517
518 for (i = 0; i < num; i++) {
519 Elf32_Rela rela, swrela;
520 Elf32_Sym symbols;
521 uint32_t pos = rela_start + sizeof(Elf32_Rela) * i;
522 uint32_t addr, pos_dyn;
523
524 debug("\nPossition:\t%d/0x%x\n", i, pos);
525
526 if (fseek(f, pos, SEEK_SET) < 0) {
527 fprintf(stderr, "%s: %s: seek to %" PRIx32
528 " failed: %s\n",
529 argv[0], argv[1], pos, strerror(errno));
530 }
531
532 if (fread(&rela, sizeof(rela), 1, f) != 1) {
533 fprintf(stderr, "%s: %s: read rela failed at %"
534 PRIx32 "\n",
535 argv[0], argv[1], pos);
536 return 4;
537 }
538
539 debug("Rela:\toffset:\t%" PRIx32 " r_info:\t%"
540 PRIu32 " r_addend:\t%" PRIx32 "\n",
541 rela.r_offset, rela.r_info, rela.r_addend);
542
Ovidiu Panaita4786c92023-03-11 19:38:36 +0200543 swrela.r_offset = elf32_to_cpu(rela.r_offset);
544 swrela.r_info = elf32_to_cpu(rela.r_info);
545 swrela.r_addend = elf32_to_cpu(rela.r_addend);
Michal Simek39b2b6c2022-06-24 14:15:00 +0200546
547 debug("SWRela:\toffset:\t%" PRIx32 " r_info:\t%"
548 PRIu32 " r_addend:\t%" PRIx32 "\n",
549 swrela.r_offset, swrela.r_info, swrela.r_addend);
550
551 if (!supported_rela32(&swrela, &type))
552 continue;
553
554 if (swrela.r_offset < text_base) {
555 fprintf(stderr, "%s: %s: bad rela at %" PRIx32 "\n",
556 argv[0], argv[1], pos);
557 return 4;
558 }
559
560 addr = swrela.r_offset - text_base;
561
562 debug("Addr:\t0x%" PRIx32 "\n", addr);
563
564 switch (type) {
565 case R_MICROBLAZE_REL:
566 if (fseek(f, addr, SEEK_SET) < 0) {
567 fprintf(stderr, "%s: %s: seek to %"
568 PRIx32 " failed: %s\n",
569 argv[0], argv[1], addr, strerror(errno));
570 return 5;
571 }
572
573 debug("Write addend\n");
574
575 if (fwrite(&rela.r_addend, sizeof(rela.r_addend), 1, f) != 1) {
576 fprintf(stderr, "%s: %s: write failed at %" PRIx32 "\n",
577 argv[0], argv[1], addr);
578 return 4;
579 }
580 break;
581 case R_MICROBLAZE_32:
582 case R_MICROBLAZE_GLOB_DAT:
583 /* global symbols read it and add reloc offset */
584 index = swrela.r_info >> 8;
585 pos_dyn = dyn_start + sizeof(Elf32_Sym) * index;
586
587 debug("Index:\t%d\n", index);
588 debug("Pos_dyn:\t0x%x\n", pos_dyn);
589
590 if (fseek(f, pos_dyn, SEEK_SET) < 0) {
591 fprintf(stderr, "%s: %s: seek to %"
592 PRIx32 " failed: %s\n",
593 argv[0], argv[1], pos_dyn, strerror(errno));
594 return 5;
595 }
596
597 if (fread(&symbols, sizeof(symbols), 1, f) != 1) {
598 fprintf(stderr, "%s: %s: read symbols failed at %"
599 PRIx32 "\n",
600 argv[0], argv[1], pos_dyn);
601 return 4;
602 }
603
604 debug("Symbol description:\n");
605 debug(" st_name:\t0x%x\n", symbols.st_name);
606 debug(" st_value:\t0x%x\n", symbols.st_value);
607 debug(" st_size:\t0x%x\n", symbols.st_size);
608
609 value = swrela.r_addend + symbols.st_value;
610
611 debug("Value:\t0x%x\n", value);
612
613 if (fseek(f, addr, SEEK_SET) < 0) {
614 fprintf(stderr, "%s: %s: seek to %"
615 PRIx32 " failed: %s\n",
616 argv[0], argv[1], addr, strerror(errno));
617 return 5;
618 }
619
620 if (fwrite(&value, sizeof(rela.r_addend), 1, f) != 1) {
621 fprintf(stderr, "%s: %s: write failed at %" PRIx32 "\n",
622 argv[0], argv[1], addr);
623 return 4;
624 }
625
626 break;
627 case R_MICROBLAZE_NONE:
628 debug("R_MICROBLAZE_NONE - skip\n");
629 break;
630 default:
631 fprintf(stderr, "warning: unsupported relocation type %"
632 PRIu32 " at %" PRIx32 "\n",
633 type, rela.r_offset);
634 }
635 }
636
637 return 0;
638}
639
Michal Simekf9c28a12022-06-24 14:15:00 +0200640int main(int argc, char **argv)
641{
642 FILE *f;
643 int ret;
644 uint64_t file_size;
645
646 if (argc != 3) {
647 fprintf(stderr, "Statically apply ELF rela relocations\n");
648 fprintf(stderr, "Usage: %s <bin file> <u-boot ELF>\n",
649 argv[0]);
650 return 1;
651 }
652
653 ret = decode_elf(argv);
654 if (ret) {
655 fprintf(stderr, "ELF decoding failed\n");
656 return ret;
657 }
658
659 if (rela_start > rela_end || rela_start < text_base) {
660 fprintf(stderr, "%s: bad rela bounds\n", argv[0]);
661 return 3;
662 }
663
664 rela_start -= text_base;
665 rela_end -= text_base;
Michal Simek4fad25f2022-06-24 14:15:00 +0200666 dyn_start -= text_base;
Michal Simekf9c28a12022-06-24 14:15:00 +0200667
668 f = fopen(argv[1], "r+b");
669 if (!f) {
670 fprintf(stderr, "%s: Cannot open %s: %s\n",
671 argv[0], argv[1], strerror(errno));
672 return 2;
673 }
674
675 fseek(f, 0, SEEK_END);
676 file_size = ftell(f);
677 rewind(f);
678
679 if (rela_end > file_size) {
680 // Most likely compiler inserted some section that didn't get
681 // objcopy-ed into the final binary
682 rela_end = file_size;
683 }
684
685 if (ei_class == 2)
686 ret = rela_elf64(argv, f);
Michal Simek39b2b6c2022-06-24 14:15:00 +0200687 else
688 ret = rela_elf32(argv, f);
Michal Simekf9c28a12022-06-24 14:15:00 +0200689
Scott Wood49fa0592013-12-14 11:47:32 +0800690 if (fclose(f) < 0) {
691 fprintf(stderr, "%s: %s: close failed: %s\n",
692 argv[0], argv[1], strerror(errno));
693 return 4;
694 }
695
Michal Simekf9c28a12022-06-24 14:15:00 +0200696 return ret;
Scott Wood49fa0592013-12-14 11:47:32 +0800697}