1// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause 2/* 3 * Copyright 2013 Freescale Semiconductor, Inc. 4 * 5 * 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> 17#include "compiler.h" 18 19#ifndef EM_AARCH64 20#define EM_AARCH64 183 21#endif 22 23#ifndef R_AARCH64_RELATIVE 24#define R_AARCH64_RELATIVE 1027 25#endif 26 27#ifndef EM_M68K 28#define EM_M68K 4 29#endif 30 31#ifndef R_68K_NONE 32#define R_68K_NONE 0 33#endif 34 35#ifndef R_68K_32 36#define R_68K_32 1 37#endif 38 39#ifndef R_68K_GLOB_DAT 40#define R_68K_GLOB_DAT 20 41#endif 42 43#ifndef R_68K_JMP_SLOT 44#define R_68K_JMP_SLOT 21 45#endif 46 47#ifndef R_68K_RELATIVE 48#define R_68K_RELATIVE 22 49#endif 50 51#ifndef EM_MICROBLAZE 52#define EM_MICROBLAZE 189 53#endif 54 55#ifndef R_MICROBLAZE_NONE 56#define R_MICROBLAZE_NONE 0 57#endif 58 59#ifndef R_MICROBLAZE_32 60#define R_MICROBLAZE_32 1 61#endif 62 63#ifndef R_MICROBLAZE_REL 64#define R_MICROBLAZE_REL 16 65#endif 66 67#ifndef R_MICROBLAZE_GLOB_DAT 68#define R_MICROBLAZE_GLOB_DAT 18 69#endif 70 71static int ei_class; 72static int ei_data; 73static int machine; 74 75static uint64_t rela_start, rela_end, text_base, dyn_start; 76 77static const bool debug_en; 78 79static void debug(const char *fmt, ...) 80{ 81 va_list args; 82 83 if (debug_en) { 84 va_start(args, fmt); 85 vprintf(fmt, args); 86 va_end(args); 87 } 88} 89 90static uint16_t elf16_to_cpu(uint16_t data) 91{ 92 if (ei_data == ELFDATA2LSB) 93 return le16_to_cpu(data); 94 95 return be16_to_cpu(data); 96} 97 98static uint32_t elf32_to_cpu(uint32_t data) 99{ 100 if (ei_data == ELFDATA2LSB) 101 return le32_to_cpu(data); 102 103 return be32_to_cpu(data); 104} 105 106static uint32_t cpu_to_elf32(uint32_t data) 107{ 108 if (ei_data == ELFDATA2LSB) 109 return cpu_to_le32(data); 110 111 return cpu_to_be32(data); 112} 113 114static bool supported_rela(Elf64_Rela *rela) 115{ 116 uint64_t mask = 0xffffffffULL; /* would be different on 32-bit */ 117 uint32_t type = rela->r_info & mask; 118 119 switch (type) { 120 case R_AARCH64_RELATIVE: 121 return true; 122 default: 123 fprintf(stderr, "warning: unsupported relocation type %" 124 PRIu32 " at %" PRIx64 "\n", 125 type, rela->r_offset); 126 127 return false; 128 } 129} 130 131static int decode_elf64(FILE *felf, char **argv) 132{ 133 size_t size; 134 Elf64_Ehdr header; 135 uint64_t section_header_base, section_header_size; 136 uint64_t sh_addr, sh_offset, sh_size; 137 Elf64_Half sh_index, sh_num; 138 Elf64_Shdr *sh_table; /* Elf symbol table */ 139 int ret, i; 140 char *sh_str; 141 142 debug("64bit version\n"); 143 144 /* Make sure we are at start */ 145 rewind(felf); 146 147 size = fread(&header, 1, sizeof(header), felf); 148 if (size != sizeof(header)) { 149 fclose(felf); 150 return 25; 151 } 152 153 machine = le16_to_cpu(header.e_machine); 154 debug("Machine\t%d\n", machine); 155 156 if (machine != EM_AARCH64) { 157 fprintf(stderr, "%s: Not supported machine type\n", argv[0]); 158 return 30; 159 } 160 161 text_base = le64_to_cpu(header.e_entry); 162 section_header_base = le64_to_cpu(header.e_shoff); 163 section_header_size = le16_to_cpu(header.e_shentsize) * 164 le16_to_cpu(header.e_shnum); 165 166 sh_table = malloc(section_header_size); 167 if (!sh_table) { 168 fprintf(stderr, "%s: Cannot allocate space for section header\n", 169 argv[0]); 170 fclose(felf); 171 return 26; 172 } 173 174 ret = fseek(felf, section_header_base, SEEK_SET); 175 if (ret) { 176 fprintf(stderr, "%s: Can't set pointer to section header: %x/%lx\n", 177 argv[0], ret, section_header_base); 178 free(sh_table); 179 fclose(felf); 180 return 26; 181 } 182 183 size = fread(sh_table, 1, section_header_size, felf); 184 if (size != section_header_size) { 185 fprintf(stderr, "%s: Can't read section header: %lx/%lx\n", 186 argv[0], size, section_header_size); 187 free(sh_table); 188 fclose(felf); 189 return 27; 190 } 191 192 sh_index = le16_to_cpu(header.e_shstrndx); 193 sh_size = le64_to_cpu(sh_table[sh_index].sh_size); 194 debug("e_shstrndx %x, sh_size %lx\n", sh_index, sh_size); 195 196 sh_str = malloc(sh_size); 197 if (!sh_str) { 198 fprintf(stderr, "malloc failed\n"); 199 free(sh_table); 200 fclose(felf); 201 return 28; 202 } 203 204 /* 205 * Specifies the byte offset from the beginning of the file 206 * to the first byte in the section. 207 */ 208 sh_offset = le64_to_cpu(sh_table[sh_index].sh_offset); 209 sh_num = le16_to_cpu(header.e_shnum); 210 211 ret = fseek(felf, sh_offset, SEEK_SET); 212 if (ret) { 213 fprintf(stderr, "Setting up sh_offset failed\n"); 214 free(sh_str); 215 free(sh_table); 216 fclose(felf); 217 return 29; 218 } 219 220 size = fread(sh_str, 1, sh_size, felf); 221 if (size != sh_size) { 222 fprintf(stderr, "%s: Can't read section: %lx/%lx\n", 223 argv[0], size, sh_size); 224 free(sh_str); 225 free(sh_table); 226 fclose(felf); 227 return 30; 228 } 229 230 for (i = 0; i < sh_num; i++) { 231 char *sh_name = sh_str + le32_to_cpu(sh_table[i].sh_name); 232 233 debug("%s\n", sh_name); 234 235 sh_addr = le64_to_cpu(sh_table[i].sh_addr); 236 sh_offset = le64_to_cpu(sh_table[i].sh_offset); 237 sh_size = le64_to_cpu(sh_table[i].sh_size); 238 239 if (!strcmp(".rela.dyn", sh_name)) { 240 debug("Found section\t\".rela_dyn\"\n"); 241 debug(" at addr\t0x%08x\n", sh_addr); 242 debug(" at offset\t0x%08x\n", sh_offset); 243 debug(" of size\t0x%08x\n", sh_size); 244 rela_start = sh_addr; 245 rela_end = rela_start + sh_size; 246 break; 247 } 248 } 249 250 /* Clean up */ 251 free(sh_str); 252 free(sh_table); 253 fclose(felf); 254 255 debug("text_base\t0x%08lx\n", text_base); 256 debug("rela_start\t0x%08lx\n", rela_start); 257 debug("rela_end\t0x%08lx\n", rela_end); 258 259 if (!rela_start) 260 return 1; 261 262 return 0; 263} 264 265static int decode_elf32(FILE *felf, char **argv) 266{ 267 size_t size; 268 Elf32_Ehdr header; 269 uint64_t section_header_base, section_header_size; 270 uint32_t sh_addr, sh_offset, sh_size; 271 Elf32_Half sh_index, sh_num; 272 Elf32_Shdr *sh_table; /* Elf symbol table */ 273 int ret, i; 274 char *sh_str; 275 276 debug("32bit version\n"); 277 278 /* Make sure we are at start */ 279 rewind(felf); 280 281 size = fread(&header, 1, sizeof(header), felf); 282 if (size != sizeof(header)) { 283 fclose(felf); 284 return 25; 285 } 286 287 machine = elf16_to_cpu(header.e_machine); 288 debug("Machine %d\n", machine); 289 290 if (machine != EM_MICROBLAZE && machine != EM_M68K) { 291 fprintf(stderr, "%s: Not supported machine type\n", argv[0]); 292 return 30; 293 } 294 295 text_base = elf32_to_cpu(header.e_entry); 296 /* 297 * M68K ELF entry point is MONITOR_BASE, not TEXT_BASE. 298 * TEXT_BASE is always MONITOR_BASE &~ 0x7ff, so clear 299 * those bits here. 300 */ 301 if (machine == EM_M68K) 302 text_base &= ~0x7ff; 303 304 section_header_base = elf32_to_cpu(header.e_shoff); 305 section_header_size = elf16_to_cpu(header.e_shentsize) * 306 elf16_to_cpu(header.e_shnum); 307 308 sh_table = malloc(section_header_size); 309 if (!sh_table) { 310 fprintf(stderr, "%s: Cannot allocate space for section header\n", 311 argv[0]); 312 fclose(felf); 313 return 26; 314 } 315 316 ret = fseek(felf, section_header_base, SEEK_SET); 317 if (ret) { 318 fprintf(stderr, "%s: Can't set pointer to section header: %x/%lx\n", 319 argv[0], ret, section_header_base); 320 free(sh_table); 321 fclose(felf); 322 return 26; 323 } 324 325 size = fread(sh_table, 1, section_header_size, felf); 326 if (size != section_header_size) { 327 fprintf(stderr, "%s: Can't read section header: %lx/%lx\n", 328 argv[0], size, section_header_size); 329 free(sh_table); 330 fclose(felf); 331 return 27; 332 } 333 334 sh_index = elf16_to_cpu(header.e_shstrndx); 335 sh_size = elf32_to_cpu(sh_table[sh_index].sh_size); 336 debug("e_shstrndx %x, sh_size %lx\n", sh_index, sh_size); 337 338 sh_str = malloc(sh_size); 339 if (!sh_str) { 340 fprintf(stderr, "malloc failed\n"); 341 free(sh_table); 342 fclose(felf); 343 return 28; 344 } 345 346 /* 347 * Specifies the byte offset from the beginning of the file 348 * to the first byte in the section. 349 */ 350 sh_offset = elf32_to_cpu(sh_table[sh_index].sh_offset); 351 sh_num = elf16_to_cpu(header.e_shnum); 352 353 ret = fseek(felf, sh_offset, SEEK_SET); 354 if (ret) { 355 fprintf(stderr, "Setting up sh_offset failed\n"); 356 free(sh_str); 357 free(sh_table); 358 fclose(felf); 359 return 29; 360 } 361 362 size = fread(sh_str, 1, sh_size, felf); 363 if (size != sh_size) { 364 fprintf(stderr, "%s: Can't read section: %lx/%x\n", 365 argv[0], size, sh_size); 366 free(sh_str); 367 free(sh_table); 368 fclose(felf); 369 return 30; 370 } 371 372 for (i = 0; i < sh_num; i++) { 373 char *sh_name = sh_str + elf32_to_cpu(sh_table[i].sh_name); 374 375 debug("%s\n", sh_name); 376 377 sh_addr = elf32_to_cpu(sh_table[i].sh_addr); 378 sh_offset = elf32_to_cpu(sh_table[i].sh_offset); 379 sh_size = elf32_to_cpu(sh_table[i].sh_size); 380 381 if (!strcmp(".rela.dyn", sh_name)) { 382 debug("Found section\t\".rela_dyn\"\n"); 383 debug(" at addr\t0x%08x\n", sh_addr); 384 debug(" at offset\t0x%08x\n", sh_offset); 385 debug(" of size\t0x%08x\n", sh_size); 386 rela_start = sh_addr; 387 rela_end = rela_start + sh_size; 388 } 389 if (!strcmp(".dynsym", sh_name)) { 390 debug("Found section\t\".dynsym\"\n"); 391 debug(" at addr\t0x%08x\n", sh_addr); 392 debug(" at offset\t0x%08x\n", sh_offset); 393 debug(" of size\t0x%08x\n", sh_size); 394 dyn_start = sh_addr; 395 } 396 } 397 398 /* Clean up */ 399 free(sh_str); 400 free(sh_table); 401 fclose(felf); 402 403 debug("text_base\t0x%08lx\n", text_base); 404 debug("rela_start\t0x%08lx\n", rela_start); 405 debug("rela_end\t0x%08lx\n", rela_end); 406 debug("dyn_start\t0x%08lx\n", dyn_start); 407 408 if (!rela_start) 409 return 1; 410 411 return 0; 412} 413 414static int decode_elf(char **argv) 415{ 416 FILE *felf; 417 size_t size; 418 unsigned char e_ident[EI_NIDENT]; 419 420 felf = fopen(argv[2], "r+b"); 421 if (!felf) { 422 fprintf(stderr, "%s: Cannot open %s: %s\n", 423 argv[0], argv[5], strerror(errno)); 424 return 2; 425 } 426 427 size = fread(e_ident, 1, EI_NIDENT, felf); 428 if (size != EI_NIDENT) { 429 fclose(felf); 430 return 25; 431 } 432 433 /* Check if this is really ELF file */ 434 if (e_ident[0] != 0x7f && 435 e_ident[1] != 'E' && 436 e_ident[2] != 'L' && 437 e_ident[3] != 'F') { 438 fclose(felf); 439 return 1; 440 } 441 442 ei_class = e_ident[4]; 443 debug("EI_CLASS(1=32bit, 2=64bit) %d\n", ei_class); 444 445 ei_data = e_ident[5]; 446 debug("EI_DATA(1=little endian, 2=big endian) %d\n", ei_data); 447 448 if (ei_class == 2) 449 return decode_elf64(felf, argv); 450 451 return decode_elf32(felf, argv); 452} 453 454static int rela_elf64(char **argv, FILE *f) 455{ 456 int i, num; 457 458 if ((rela_end - rela_start) % sizeof(Elf64_Rela)) { 459 fprintf(stderr, "%s: rela size isn't a multiple of Elf64_Rela\n", argv[0]); 460 return 3; 461 } 462 463 num = (rela_end - rela_start) / sizeof(Elf64_Rela); 464 465 for (i = 0; i < num; i++) { 466 Elf64_Rela rela, swrela; 467 uint64_t pos = rela_start + sizeof(Elf64_Rela) * i; 468 uint64_t addr; 469 470 if (fseek(f, pos, SEEK_SET) < 0) { 471 fprintf(stderr, "%s: %s: seek to %" PRIx64 472 " failed: %s\n", 473 argv[0], argv[1], pos, strerror(errno)); 474 } 475 476 if (fread(&rela, sizeof(rela), 1, f) != 1) { 477 fprintf(stderr, "%s: %s: read rela failed at %" 478 PRIx64 "\n", 479 argv[0], argv[1], pos); 480 return 4; 481 } 482 483 swrela.r_offset = le64_to_cpu(rela.r_offset); 484 swrela.r_info = le64_to_cpu(rela.r_info); 485 swrela.r_addend = le64_to_cpu(rela.r_addend); 486 487 if (!supported_rela(&swrela)) 488 continue; 489 490 debug("Rela %" PRIx64 " %" PRIu64 " %" PRIx64 "\n", 491 swrela.r_offset, swrela.r_info, swrela.r_addend); 492 493 if (swrela.r_offset < text_base) { 494 fprintf(stderr, "%s: %s: bad rela at %" PRIx64 "\n", 495 argv[0], argv[1], pos); 496 return 4; 497 } 498 499 addr = swrela.r_offset - text_base; 500 501 if (fseek(f, addr, SEEK_SET) < 0) { 502 fprintf(stderr, "%s: %s: seek to %" 503 PRIx64 " failed: %s\n", 504 argv[0], argv[1], addr, strerror(errno)); 505 } 506 507 if (fwrite(&rela.r_addend, sizeof(rela.r_addend), 1, f) != 1) { 508 fprintf(stderr, "%s: %s: write failed at %" PRIx64 "\n", 509 argv[0], argv[1], addr); 510 return 4; 511 } 512 } 513 514 return 0; 515} 516 517static bool supported_rela32(Elf32_Rela *rela, uint32_t *type) 518{ 519 uint32_t mask = 0xffULL; /* would be different on 32-bit */ 520 *type = rela->r_info & mask; 521 522 debug("Type:\t"); 523 524 if (machine == EM_M68K) { 525 switch (*type) { 526 case R_68K_32: 527 debug("R_68K_32\n"); 528 return true; 529 case R_68K_GLOB_DAT: 530 debug("R_68K_GLOB_DAT\n"); 531 return true; 532 case R_68K_JMP_SLOT: 533 debug("R_68K_JMP_SLOT\n"); 534 return true; 535 case R_68K_NONE: 536 debug("R_68K_NONE - ignoring - do nothing\n"); 537 return false; 538 case R_68K_RELATIVE: 539 debug("R_68K_RELATIVE\n"); 540 return true; 541 } 542 } else { 543 switch (*type) { 544 case R_MICROBLAZE_32: 545 debug("R_MICROBLAZE_32\n"); 546 return true; 547 case R_MICROBLAZE_GLOB_DAT: 548 debug("R_MICROBLAZE_GLOB_DAT\n"); 549 return true; 550 case R_MICROBLAZE_NONE: 551 debug("R_MICROBLAZE_NONE - ignoring - do nothing\n"); 552 return false; 553 case R_MICROBLAZE_REL: 554 debug("R_MICROBLAZE_REL\n"); 555 return true; 556 } 557 } 558 fprintf(stderr, "warning: unsupported relocation type %" 559 PRIu32 " at %" PRIx32 "\n", *type, rela->r_offset); 560 561 return false; 562} 563 564static int rela_elf32(char **argv, FILE *f) 565{ 566 int i, num, index; 567 uint32_t value, type; 568 569 if ((rela_end - rela_start) % sizeof(Elf32_Rela)) { 570 fprintf(stderr, "%s: rela size isn't a multiple of Elf32_Rela\n", argv[0]); 571 return 3; 572 } 573 574 num = (rela_end - rela_start) / sizeof(Elf32_Rela); 575 576 debug("Number of entries: %u\n", num); 577 578 for (i = 0; i < num; i++) { 579 Elf32_Rela rela, swrela; 580 Elf32_Sym symbols; 581 uint32_t pos = rela_start + sizeof(Elf32_Rela) * i; 582 uint32_t addr, pos_dyn; 583 584 debug("\nPosition:\t%d/0x%x\n", i, pos); 585 586 if (fseek(f, pos, SEEK_SET) < 0) { 587 fprintf(stderr, "%s: %s: seek to %" PRIx32 588 " failed: %s\n", 589 argv[0], argv[1], pos, strerror(errno)); 590 } 591 592 if (fread(&rela, sizeof(rela), 1, f) != 1) { 593 fprintf(stderr, "%s: %s: read rela failed at %" 594 PRIx32 "\n", 595 argv[0], argv[1], pos); 596 return 4; 597 } 598 599 debug("Rela:\toffset:\t%" PRIx32 " r_info:\t%" 600 PRIu32 " r_addend:\t%" PRIx32 "\n", 601 rela.r_offset, rela.r_info, rela.r_addend); 602 603 swrela.r_offset = elf32_to_cpu(rela.r_offset); 604 swrela.r_info = elf32_to_cpu(rela.r_info); 605 swrela.r_addend = elf32_to_cpu(rela.r_addend); 606 607 debug("SWRela:\toffset:\t%" PRIx32 " r_info:\t%" 608 PRIu32 " r_addend:\t%" PRIx32 "\n", 609 swrela.r_offset, swrela.r_info, swrela.r_addend); 610 611 if (!supported_rela32(&swrela, &type)) 612 continue; 613 614 if (swrela.r_offset < text_base) { 615 fprintf(stderr, "%s: %s: bad rela at %" PRIx32 "\n", 616 argv[0], argv[1], pos); 617 return 4; 618 } 619 620 addr = swrela.r_offset - text_base; 621 622 debug("Addr:\t0x%" PRIx32 "\n", addr); 623 624 if ((machine == EM_M68K && type == R_68K_RELATIVE) || 625 (machine == EM_MICROBLAZE && type == R_MICROBLAZE_REL)) { 626 if (fseek(f, addr, SEEK_SET) < 0) { 627 fprintf(stderr, "%s: %s: seek to %" 628 PRIx32 " failed: %s\n", 629 argv[0], argv[1], addr, strerror(errno)); 630 return 5; 631 } 632 633 debug("Write addend\n"); 634 635 if (fwrite(&rela.r_addend, sizeof(rela.r_addend), 1, f) != 1) { 636 fprintf(stderr, "%s: %s: write failed at %" PRIx32 "\n", 637 argv[0], argv[1], addr); 638 return 4; 639 } 640 } else if ((machine == EM_M68K && 641 (type == R_68K_32 || type == R_68K_GLOB_DAT || 642 type == R_68K_JMP_SLOT)) || 643 (machine == EM_MICROBLAZE && 644 (type == R_MICROBLAZE_32 || 645 type == R_MICROBLAZE_GLOB_DAT))) { 646 /* global symbols read it and add reloc offset */ 647 index = swrela.r_info >> 8; 648 pos_dyn = dyn_start + sizeof(Elf32_Sym) * index; 649 650 debug("Index:\t%d\n", index); 651 debug("Pos_dyn:\t0x%x\n", pos_dyn); 652 653 if (fseek(f, pos_dyn, SEEK_SET) < 0) { 654 fprintf(stderr, "%s: %s: seek to %" 655 PRIx32 " failed: %s\n", 656 argv[0], argv[1], pos_dyn, strerror(errno)); 657 return 5; 658 } 659 660 if (fread(&symbols, sizeof(symbols), 1, f) != 1) { 661 fprintf(stderr, "%s: %s: read symbols failed at %" 662 PRIx32 "\n", 663 argv[0], argv[1], pos_dyn); 664 return 4; 665 } 666 667 debug("Symbol description:\n"); 668 debug(" st_name:\t0x%x\n", elf32_to_cpu(symbols.st_name)); 669 debug(" st_value:\t0x%x\n", elf32_to_cpu(symbols.st_value)); 670 debug(" st_size:\t0x%x\n", elf32_to_cpu(symbols.st_size)); 671 672 value = swrela.r_addend + elf32_to_cpu(symbols.st_value); 673 674 debug("Value:\t0x%x\n", value); 675 676 value = cpu_to_elf32(value); 677 678 if (fseek(f, addr, SEEK_SET) < 0) { 679 fprintf(stderr, "%s: %s: seek to %" 680 PRIx32 " failed: %s\n", 681 argv[0], argv[1], addr, strerror(errno)); 682 return 5; 683 } 684 685 if (fwrite(&value, sizeof(rela.r_addend), 1, f) != 1) { 686 fprintf(stderr, "%s: %s: write failed at %" PRIx32 "\n", 687 argv[0], argv[1], addr); 688 return 4; 689 } 690 } else if (machine == EM_M68K && type == R_68K_NONE) { 691 debug("R_68K_NONE - skip\n"); 692 } else if (machine == EM_MICROBLAZE && type == R_MICROBLAZE_NONE) { 693 debug("R_MICROBLAZE_NONE - skip\n"); 694 } else { 695 fprintf(stderr, "warning: unsupported relocation type %" 696 PRIu32 " at %" PRIx32 "\n", 697 type, rela.r_offset); 698 } 699 } 700 701 return 0; 702} 703 704int main(int argc, char **argv) 705{ 706 FILE *f; 707 int ret; 708 uint64_t file_size; 709 710 if (argc != 3) { 711 fprintf(stderr, "Statically apply ELF rela relocations\n"); 712 fprintf(stderr, "Usage: %s <bin file> <u-boot ELF>\n", 713 argv[0]); 714 return 1; 715 } 716 717 ret = decode_elf(argv); 718 if (ret) { 719 fprintf(stderr, "ELF decoding failed\n"); 720 return ret; 721 } 722 723 if (rela_start > rela_end || rela_start < text_base) { 724 fprintf(stderr, "%s: bad rela bounds\n", argv[0]); 725 return 3; 726 } 727 728 rela_start -= text_base; 729 rela_end -= text_base; 730 dyn_start -= text_base; 731 732 f = fopen(argv[1], "r+b"); 733 if (!f) { 734 fprintf(stderr, "%s: Cannot open %s: %s\n", 735 argv[0], argv[1], strerror(errno)); 736 return 2; 737 } 738 739 fseek(f, 0, SEEK_END); 740 file_size = ftell(f); 741 rewind(f); 742 743 if (rela_end > file_size) { 744 // Most likely compiler inserted some section that didn't get 745 // objcopy-ed into the final binary 746 rela_end = file_size; 747 } 748 749 if (ei_class == 2) 750 ret = rela_elf64(argv, f); 751 else 752 ret = rela_elf32(argv, f); 753 754 if (fclose(f) < 0) { 755 fprintf(stderr, "%s: %s: close failed: %s\n", 756 argv[0], argv[1], strerror(errno)); 757 return 4; 758 } 759 760 return ret; 761} 762