18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* This is included from relocs_32/64.c */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#define ElfW(type) _ElfW(ELF_BITS, type) 58c2ecf20Sopenharmony_ci#define _ElfW(bits, type) __ElfW(bits, type) 68c2ecf20Sopenharmony_ci#define __ElfW(bits, type) Elf##bits##_##type 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define Elf_Addr ElfW(Addr) 98c2ecf20Sopenharmony_ci#define Elf_Ehdr ElfW(Ehdr) 108c2ecf20Sopenharmony_ci#define Elf_Phdr ElfW(Phdr) 118c2ecf20Sopenharmony_ci#define Elf_Shdr ElfW(Shdr) 128c2ecf20Sopenharmony_ci#define Elf_Sym ElfW(Sym) 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic Elf_Ehdr ehdr; 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistruct relocs { 178c2ecf20Sopenharmony_ci uint32_t *offset; 188c2ecf20Sopenharmony_ci unsigned long count; 198c2ecf20Sopenharmony_ci unsigned long size; 208c2ecf20Sopenharmony_ci}; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic struct relocs relocs; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct section { 258c2ecf20Sopenharmony_ci Elf_Shdr shdr; 268c2ecf20Sopenharmony_ci struct section *link; 278c2ecf20Sopenharmony_ci Elf_Sym *symtab; 288c2ecf20Sopenharmony_ci Elf_Rel *reltab; 298c2ecf20Sopenharmony_ci char *strtab; 308c2ecf20Sopenharmony_ci long shdr_offset; 318c2ecf20Sopenharmony_ci}; 328c2ecf20Sopenharmony_cistatic struct section *secs; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic const char * const regex_sym_kernel = { 358c2ecf20Sopenharmony_ci/* Symbols matching these regex's should never be relocated */ 368c2ecf20Sopenharmony_ci "^(__crc_)", 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic regex_t sym_regex_c; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic int regex_skip_reloc(const char *sym_name) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci return !regexec(&sym_regex_c, sym_name, 0, NULL, 0); 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic void regex_init(void) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci char errbuf[128]; 498c2ecf20Sopenharmony_ci int err; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci err = regcomp(&sym_regex_c, regex_sym_kernel, 528c2ecf20Sopenharmony_ci REG_EXTENDED|REG_NOSUB); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci if (err) { 558c2ecf20Sopenharmony_ci regerror(err, &sym_regex_c, errbuf, sizeof(errbuf)); 568c2ecf20Sopenharmony_ci die("%s", errbuf); 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic const char *rel_type(unsigned type) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci static const char * const type_name[] = { 638c2ecf20Sopenharmony_ci#define REL_TYPE(X)[X] = #X 648c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_NONE), 658c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_16), 668c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_32), 678c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_REL32), 688c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_26), 698c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_HI16), 708c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_LO16), 718c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_GPREL16), 728c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_LITERAL), 738c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_GOT16), 748c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_PC16), 758c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_CALL16), 768c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_GPREL32), 778c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_64), 788c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_HIGHER), 798c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_HIGHEST), 808c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_PC21_S2), 818c2ecf20Sopenharmony_ci REL_TYPE(R_MIPS_PC26_S2), 828c2ecf20Sopenharmony_ci#undef REL_TYPE 838c2ecf20Sopenharmony_ci }; 848c2ecf20Sopenharmony_ci const char *name = "unknown type rel type name"; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (type < ARRAY_SIZE(type_name) && type_name[type]) 878c2ecf20Sopenharmony_ci name = type_name[type]; 888c2ecf20Sopenharmony_ci return name; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic const char *sec_name(unsigned shndx) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci const char *sec_strtab; 948c2ecf20Sopenharmony_ci const char *name; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci sec_strtab = secs[ehdr.e_shstrndx].strtab; 978c2ecf20Sopenharmony_ci if (shndx < ehdr.e_shnum) 988c2ecf20Sopenharmony_ci name = sec_strtab + secs[shndx].shdr.sh_name; 998c2ecf20Sopenharmony_ci else if (shndx == SHN_ABS) 1008c2ecf20Sopenharmony_ci name = "ABSOLUTE"; 1018c2ecf20Sopenharmony_ci else if (shndx == SHN_COMMON) 1028c2ecf20Sopenharmony_ci name = "COMMON"; 1038c2ecf20Sopenharmony_ci else 1048c2ecf20Sopenharmony_ci name = "<noname>"; 1058c2ecf20Sopenharmony_ci return name; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic struct section *sec_lookup(const char *secname) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci int i; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci for (i = 0; i < ehdr.e_shnum; i++) 1138c2ecf20Sopenharmony_ci if (strcmp(secname, sec_name(i)) == 0) 1148c2ecf20Sopenharmony_ci return &secs[i]; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return NULL; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic const char *sym_name(const char *sym_strtab, Elf_Sym *sym) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci const char *name; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (sym->st_name) 1248c2ecf20Sopenharmony_ci name = sym_strtab + sym->st_name; 1258c2ecf20Sopenharmony_ci else 1268c2ecf20Sopenharmony_ci name = sec_name(sym->st_shndx); 1278c2ecf20Sopenharmony_ci return name; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci#if BYTE_ORDER == LITTLE_ENDIAN 1318c2ecf20Sopenharmony_ci#define le16_to_cpu(val) (val) 1328c2ecf20Sopenharmony_ci#define le32_to_cpu(val) (val) 1338c2ecf20Sopenharmony_ci#define le64_to_cpu(val) (val) 1348c2ecf20Sopenharmony_ci#define be16_to_cpu(val) bswap_16(val) 1358c2ecf20Sopenharmony_ci#define be32_to_cpu(val) bswap_32(val) 1368c2ecf20Sopenharmony_ci#define be64_to_cpu(val) bswap_64(val) 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci#define cpu_to_le16(val) (val) 1398c2ecf20Sopenharmony_ci#define cpu_to_le32(val) (val) 1408c2ecf20Sopenharmony_ci#define cpu_to_le64(val) (val) 1418c2ecf20Sopenharmony_ci#define cpu_to_be16(val) bswap_16(val) 1428c2ecf20Sopenharmony_ci#define cpu_to_be32(val) bswap_32(val) 1438c2ecf20Sopenharmony_ci#define cpu_to_be64(val) bswap_64(val) 1448c2ecf20Sopenharmony_ci#endif 1458c2ecf20Sopenharmony_ci#if BYTE_ORDER == BIG_ENDIAN 1468c2ecf20Sopenharmony_ci#define le16_to_cpu(val) bswap_16(val) 1478c2ecf20Sopenharmony_ci#define le32_to_cpu(val) bswap_32(val) 1488c2ecf20Sopenharmony_ci#define le64_to_cpu(val) bswap_64(val) 1498c2ecf20Sopenharmony_ci#define be16_to_cpu(val) (val) 1508c2ecf20Sopenharmony_ci#define be32_to_cpu(val) (val) 1518c2ecf20Sopenharmony_ci#define be64_to_cpu(val) (val) 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci#define cpu_to_le16(val) bswap_16(val) 1548c2ecf20Sopenharmony_ci#define cpu_to_le32(val) bswap_32(val) 1558c2ecf20Sopenharmony_ci#define cpu_to_le64(val) bswap_64(val) 1568c2ecf20Sopenharmony_ci#define cpu_to_be16(val) (val) 1578c2ecf20Sopenharmony_ci#define cpu_to_be32(val) (val) 1588c2ecf20Sopenharmony_ci#define cpu_to_be64(val) (val) 1598c2ecf20Sopenharmony_ci#endif 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic uint16_t elf16_to_cpu(uint16_t val) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 1648c2ecf20Sopenharmony_ci return le16_to_cpu(val); 1658c2ecf20Sopenharmony_ci else 1668c2ecf20Sopenharmony_ci return be16_to_cpu(val); 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic uint32_t elf32_to_cpu(uint32_t val) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 1728c2ecf20Sopenharmony_ci return le32_to_cpu(val); 1738c2ecf20Sopenharmony_ci else 1748c2ecf20Sopenharmony_ci return be32_to_cpu(val); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic uint32_t cpu_to_elf32(uint32_t val) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 1808c2ecf20Sopenharmony_ci return cpu_to_le32(val); 1818c2ecf20Sopenharmony_ci else 1828c2ecf20Sopenharmony_ci return cpu_to_be32(val); 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci#define elf_half_to_cpu(x) elf16_to_cpu(x) 1868c2ecf20Sopenharmony_ci#define elf_word_to_cpu(x) elf32_to_cpu(x) 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci#if ELF_BITS == 64 1898c2ecf20Sopenharmony_cistatic uint64_t elf64_to_cpu(uint64_t val) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 1928c2ecf20Sopenharmony_ci return le64_to_cpu(val); 1938c2ecf20Sopenharmony_ci else 1948c2ecf20Sopenharmony_ci return be64_to_cpu(val); 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci#define elf_addr_to_cpu(x) elf64_to_cpu(x) 1978c2ecf20Sopenharmony_ci#define elf_off_to_cpu(x) elf64_to_cpu(x) 1988c2ecf20Sopenharmony_ci#define elf_xword_to_cpu(x) elf64_to_cpu(x) 1998c2ecf20Sopenharmony_ci#else 2008c2ecf20Sopenharmony_ci#define elf_addr_to_cpu(x) elf32_to_cpu(x) 2018c2ecf20Sopenharmony_ci#define elf_off_to_cpu(x) elf32_to_cpu(x) 2028c2ecf20Sopenharmony_ci#define elf_xword_to_cpu(x) elf32_to_cpu(x) 2038c2ecf20Sopenharmony_ci#endif 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic void read_ehdr(FILE *fp) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) 2088c2ecf20Sopenharmony_ci die("Cannot read ELF header: %s\n", strerror(errno)); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) 2118c2ecf20Sopenharmony_ci die("No ELF magic\n"); 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (ehdr.e_ident[EI_CLASS] != ELF_CLASS) 2148c2ecf20Sopenharmony_ci die("Not a %d bit executable\n", ELF_BITS); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) && 2178c2ecf20Sopenharmony_ci (ehdr.e_ident[EI_DATA] != ELFDATA2MSB)) 2188c2ecf20Sopenharmony_ci die("Unknown ELF Endianness\n"); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) 2218c2ecf20Sopenharmony_ci die("Unknown ELF version\n"); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* Convert the fields to native endian */ 2248c2ecf20Sopenharmony_ci ehdr.e_type = elf_half_to_cpu(ehdr.e_type); 2258c2ecf20Sopenharmony_ci ehdr.e_machine = elf_half_to_cpu(ehdr.e_machine); 2268c2ecf20Sopenharmony_ci ehdr.e_version = elf_word_to_cpu(ehdr.e_version); 2278c2ecf20Sopenharmony_ci ehdr.e_entry = elf_addr_to_cpu(ehdr.e_entry); 2288c2ecf20Sopenharmony_ci ehdr.e_phoff = elf_off_to_cpu(ehdr.e_phoff); 2298c2ecf20Sopenharmony_ci ehdr.e_shoff = elf_off_to_cpu(ehdr.e_shoff); 2308c2ecf20Sopenharmony_ci ehdr.e_flags = elf_word_to_cpu(ehdr.e_flags); 2318c2ecf20Sopenharmony_ci ehdr.e_ehsize = elf_half_to_cpu(ehdr.e_ehsize); 2328c2ecf20Sopenharmony_ci ehdr.e_phentsize = elf_half_to_cpu(ehdr.e_phentsize); 2338c2ecf20Sopenharmony_ci ehdr.e_phnum = elf_half_to_cpu(ehdr.e_phnum); 2348c2ecf20Sopenharmony_ci ehdr.e_shentsize = elf_half_to_cpu(ehdr.e_shentsize); 2358c2ecf20Sopenharmony_ci ehdr.e_shnum = elf_half_to_cpu(ehdr.e_shnum); 2368c2ecf20Sopenharmony_ci ehdr.e_shstrndx = elf_half_to_cpu(ehdr.e_shstrndx); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) 2398c2ecf20Sopenharmony_ci die("Unsupported ELF header type\n"); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (ehdr.e_machine != ELF_MACHINE) 2428c2ecf20Sopenharmony_ci die("Not for %s\n", ELF_MACHINE_NAME); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci if (ehdr.e_version != EV_CURRENT) 2458c2ecf20Sopenharmony_ci die("Unknown ELF version\n"); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (ehdr.e_ehsize != sizeof(Elf_Ehdr)) 2488c2ecf20Sopenharmony_ci die("Bad Elf header size\n"); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (ehdr.e_phentsize != sizeof(Elf_Phdr)) 2518c2ecf20Sopenharmony_ci die("Bad program header entry\n"); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci if (ehdr.e_shentsize != sizeof(Elf_Shdr)) 2548c2ecf20Sopenharmony_ci die("Bad section header entry\n"); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci if (ehdr.e_shstrndx >= ehdr.e_shnum) 2578c2ecf20Sopenharmony_ci die("String table index out of bounds\n"); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic void read_shdrs(FILE *fp) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci int i; 2638c2ecf20Sopenharmony_ci Elf_Shdr shdr; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci secs = calloc(ehdr.e_shnum, sizeof(struct section)); 2668c2ecf20Sopenharmony_ci if (!secs) 2678c2ecf20Sopenharmony_ci die("Unable to allocate %d section headers\n", ehdr.e_shnum); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) 2708c2ecf20Sopenharmony_ci die("Seek to %d failed: %s\n", ehdr.e_shoff, strerror(errno)); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci for (i = 0; i < ehdr.e_shnum; i++) { 2738c2ecf20Sopenharmony_ci struct section *sec = &secs[i]; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci sec->shdr_offset = ftell(fp); 2768c2ecf20Sopenharmony_ci if (fread(&shdr, sizeof(shdr), 1, fp) != 1) 2778c2ecf20Sopenharmony_ci die("Cannot read ELF section headers %d/%d: %s\n", 2788c2ecf20Sopenharmony_ci i, ehdr.e_shnum, strerror(errno)); 2798c2ecf20Sopenharmony_ci sec->shdr.sh_name = elf_word_to_cpu(shdr.sh_name); 2808c2ecf20Sopenharmony_ci sec->shdr.sh_type = elf_word_to_cpu(shdr.sh_type); 2818c2ecf20Sopenharmony_ci sec->shdr.sh_flags = elf_xword_to_cpu(shdr.sh_flags); 2828c2ecf20Sopenharmony_ci sec->shdr.sh_addr = elf_addr_to_cpu(shdr.sh_addr); 2838c2ecf20Sopenharmony_ci sec->shdr.sh_offset = elf_off_to_cpu(shdr.sh_offset); 2848c2ecf20Sopenharmony_ci sec->shdr.sh_size = elf_xword_to_cpu(shdr.sh_size); 2858c2ecf20Sopenharmony_ci sec->shdr.sh_link = elf_word_to_cpu(shdr.sh_link); 2868c2ecf20Sopenharmony_ci sec->shdr.sh_info = elf_word_to_cpu(shdr.sh_info); 2878c2ecf20Sopenharmony_ci sec->shdr.sh_addralign = elf_xword_to_cpu(shdr.sh_addralign); 2888c2ecf20Sopenharmony_ci sec->shdr.sh_entsize = elf_xword_to_cpu(shdr.sh_entsize); 2898c2ecf20Sopenharmony_ci if (sec->shdr.sh_link < ehdr.e_shnum) 2908c2ecf20Sopenharmony_ci sec->link = &secs[sec->shdr.sh_link]; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic void read_strtabs(FILE *fp) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci int i; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci for (i = 0; i < ehdr.e_shnum; i++) { 2998c2ecf20Sopenharmony_ci struct section *sec = &secs[i]; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (sec->shdr.sh_type != SHT_STRTAB) 3028c2ecf20Sopenharmony_ci continue; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci sec->strtab = malloc(sec->shdr.sh_size); 3058c2ecf20Sopenharmony_ci if (!sec->strtab) 3068c2ecf20Sopenharmony_ci die("malloc of %d bytes for strtab failed\n", 3078c2ecf20Sopenharmony_ci sec->shdr.sh_size); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) 3108c2ecf20Sopenharmony_ci die("Seek to %d failed: %s\n", 3118c2ecf20Sopenharmony_ci sec->shdr.sh_offset, strerror(errno)); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) != 3148c2ecf20Sopenharmony_ci sec->shdr.sh_size) 3158c2ecf20Sopenharmony_ci die("Cannot read symbol table: %s\n", strerror(errno)); 3168c2ecf20Sopenharmony_ci } 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic void read_symtabs(FILE *fp) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci int i, j; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci for (i = 0; i < ehdr.e_shnum; i++) { 3248c2ecf20Sopenharmony_ci struct section *sec = &secs[i]; 3258c2ecf20Sopenharmony_ci if (sec->shdr.sh_type != SHT_SYMTAB) 3268c2ecf20Sopenharmony_ci continue; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci sec->symtab = malloc(sec->shdr.sh_size); 3298c2ecf20Sopenharmony_ci if (!sec->symtab) 3308c2ecf20Sopenharmony_ci die("malloc of %d bytes for symtab failed\n", 3318c2ecf20Sopenharmony_ci sec->shdr.sh_size); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) 3348c2ecf20Sopenharmony_ci die("Seek to %d failed: %s\n", 3358c2ecf20Sopenharmony_ci sec->shdr.sh_offset, strerror(errno)); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) != 3388c2ecf20Sopenharmony_ci sec->shdr.sh_size) 3398c2ecf20Sopenharmony_ci die("Cannot read symbol table: %s\n", strerror(errno)); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) { 3428c2ecf20Sopenharmony_ci Elf_Sym *sym = &sec->symtab[j]; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci sym->st_name = elf_word_to_cpu(sym->st_name); 3458c2ecf20Sopenharmony_ci sym->st_value = elf_addr_to_cpu(sym->st_value); 3468c2ecf20Sopenharmony_ci sym->st_size = elf_xword_to_cpu(sym->st_size); 3478c2ecf20Sopenharmony_ci sym->st_shndx = elf_half_to_cpu(sym->st_shndx); 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic void read_relocs(FILE *fp) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci static unsigned long base = 0; 3558c2ecf20Sopenharmony_ci int i, j; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci if (!base) { 3588c2ecf20Sopenharmony_ci struct section *sec = sec_lookup(".text"); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci if (!sec) 3618c2ecf20Sopenharmony_ci die("Could not find .text section\n"); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci base = sec->shdr.sh_addr; 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci for (i = 0; i < ehdr.e_shnum; i++) { 3678c2ecf20Sopenharmony_ci struct section *sec = &secs[i]; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci if (sec->shdr.sh_type != SHT_REL_TYPE) 3708c2ecf20Sopenharmony_ci continue; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci sec->reltab = malloc(sec->shdr.sh_size); 3738c2ecf20Sopenharmony_ci if (!sec->reltab) 3748c2ecf20Sopenharmony_ci die("malloc of %d bytes for relocs failed\n", 3758c2ecf20Sopenharmony_ci sec->shdr.sh_size); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) 3788c2ecf20Sopenharmony_ci die("Seek to %d failed: %s\n", 3798c2ecf20Sopenharmony_ci sec->shdr.sh_offset, strerror(errno)); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci if (fread(sec->reltab, 1, sec->shdr.sh_size, fp) != 3828c2ecf20Sopenharmony_ci sec->shdr.sh_size) 3838c2ecf20Sopenharmony_ci die("Cannot read symbol table: %s\n", strerror(errno)); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) { 3868c2ecf20Sopenharmony_ci Elf_Rel *rel = &sec->reltab[j]; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci rel->r_offset = elf_addr_to_cpu(rel->r_offset); 3898c2ecf20Sopenharmony_ci /* Set offset into kernel image */ 3908c2ecf20Sopenharmony_ci rel->r_offset -= base; 3918c2ecf20Sopenharmony_ci#if (ELF_BITS == 32) 3928c2ecf20Sopenharmony_ci rel->r_info = elf_xword_to_cpu(rel->r_info); 3938c2ecf20Sopenharmony_ci#else 3948c2ecf20Sopenharmony_ci /* Convert MIPS64 RELA format - only the symbol 3958c2ecf20Sopenharmony_ci * index needs converting to native endianness 3968c2ecf20Sopenharmony_ci */ 3978c2ecf20Sopenharmony_ci rel->r_info = rel->r_info; 3988c2ecf20Sopenharmony_ci ELF_R_SYM(rel->r_info) = elf32_to_cpu(ELF_R_SYM(rel->r_info)); 3998c2ecf20Sopenharmony_ci#endif 4008c2ecf20Sopenharmony_ci#if (SHT_REL_TYPE == SHT_RELA) 4018c2ecf20Sopenharmony_ci rel->r_addend = elf_xword_to_cpu(rel->r_addend); 4028c2ecf20Sopenharmony_ci#endif 4038c2ecf20Sopenharmony_ci } 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci} 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_cistatic void remove_relocs(FILE *fp) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci int i; 4108c2ecf20Sopenharmony_ci Elf_Shdr shdr; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci for (i = 0; i < ehdr.e_shnum; i++) { 4138c2ecf20Sopenharmony_ci struct section *sec = &secs[i]; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci if (sec->shdr.sh_type != SHT_REL_TYPE) 4168c2ecf20Sopenharmony_ci continue; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0) 4198c2ecf20Sopenharmony_ci die("Seek to %d failed: %s\n", 4208c2ecf20Sopenharmony_ci sec->shdr_offset, strerror(errno)); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci if (fread(&shdr, sizeof(shdr), 1, fp) != 1) 4238c2ecf20Sopenharmony_ci die("Cannot read ELF section headers %d/%d: %s\n", 4248c2ecf20Sopenharmony_ci i, ehdr.e_shnum, strerror(errno)); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci /* Set relocation section size to 0, effectively removing it. 4278c2ecf20Sopenharmony_ci * This is necessary due to lack of support for relocations 4288c2ecf20Sopenharmony_ci * in objcopy when creating 32bit elf from 64bit elf. 4298c2ecf20Sopenharmony_ci */ 4308c2ecf20Sopenharmony_ci shdr.sh_size = 0; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0) 4338c2ecf20Sopenharmony_ci die("Seek to %d failed: %s\n", 4348c2ecf20Sopenharmony_ci sec->shdr_offset, strerror(errno)); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if (fwrite(&shdr, sizeof(shdr), 1, fp) != 1) 4378c2ecf20Sopenharmony_ci die("Cannot write ELF section headers %d/%d: %s\n", 4388c2ecf20Sopenharmony_ci i, ehdr.e_shnum, strerror(errno)); 4398c2ecf20Sopenharmony_ci } 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistatic void add_reloc(struct relocs *r, uint32_t offset, unsigned type) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci /* Relocation representation in binary table: 4458c2ecf20Sopenharmony_ci * |76543210|76543210|76543210|76543210| 4468c2ecf20Sopenharmony_ci * | Type | offset from _text >> 2 | 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_ci offset >>= 2; 4498c2ecf20Sopenharmony_ci if (offset > 0x00FFFFFF) 4508c2ecf20Sopenharmony_ci die("Kernel image exceeds maximum size for relocation!\n"); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci offset = (offset & 0x00FFFFFF) | ((type & 0xFF) << 24); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci if (r->count == r->size) { 4558c2ecf20Sopenharmony_ci unsigned long newsize = r->size + 50000; 4568c2ecf20Sopenharmony_ci void *mem = realloc(r->offset, newsize * sizeof(r->offset[0])); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci if (!mem) 4598c2ecf20Sopenharmony_ci die("realloc failed\n"); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci r->offset = mem; 4628c2ecf20Sopenharmony_ci r->size = newsize; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci r->offset[r->count++] = offset; 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistatic void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel, 4688c2ecf20Sopenharmony_ci Elf_Sym *sym, const char *symname)) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci int i; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci /* Walk through the relocations */ 4738c2ecf20Sopenharmony_ci for (i = 0; i < ehdr.e_shnum; i++) { 4748c2ecf20Sopenharmony_ci char *sym_strtab; 4758c2ecf20Sopenharmony_ci Elf_Sym *sh_symtab; 4768c2ecf20Sopenharmony_ci struct section *sec_applies, *sec_symtab; 4778c2ecf20Sopenharmony_ci int j; 4788c2ecf20Sopenharmony_ci struct section *sec = &secs[i]; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci if (sec->shdr.sh_type != SHT_REL_TYPE) 4818c2ecf20Sopenharmony_ci continue; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci sec_symtab = sec->link; 4848c2ecf20Sopenharmony_ci sec_applies = &secs[sec->shdr.sh_info]; 4858c2ecf20Sopenharmony_ci if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) 4868c2ecf20Sopenharmony_ci continue; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci sh_symtab = sec_symtab->symtab; 4898c2ecf20Sopenharmony_ci sym_strtab = sec_symtab->link->strtab; 4908c2ecf20Sopenharmony_ci for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) { 4918c2ecf20Sopenharmony_ci Elf_Rel *rel = &sec->reltab[j]; 4928c2ecf20Sopenharmony_ci Elf_Sym *sym = &sh_symtab[ELF_R_SYM(rel->r_info)]; 4938c2ecf20Sopenharmony_ci const char *symname = sym_name(sym_strtab, sym); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci process(sec, rel, sym, symname); 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci} 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_cistatic int do_reloc(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, 5018c2ecf20Sopenharmony_ci const char *symname) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci unsigned r_type = ELF_R_TYPE(rel->r_info); 5048c2ecf20Sopenharmony_ci unsigned bind = ELF_ST_BIND(sym->st_info); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci if ((bind == STB_WEAK) && (sym->st_value == 0)) { 5078c2ecf20Sopenharmony_ci /* Don't relocate weak symbols without a target */ 5088c2ecf20Sopenharmony_ci return 0; 5098c2ecf20Sopenharmony_ci } 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci if (regex_skip_reloc(symname)) 5128c2ecf20Sopenharmony_ci return 0; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci switch (r_type) { 5158c2ecf20Sopenharmony_ci case R_MIPS_NONE: 5168c2ecf20Sopenharmony_ci case R_MIPS_REL32: 5178c2ecf20Sopenharmony_ci case R_MIPS_PC16: 5188c2ecf20Sopenharmony_ci case R_MIPS_PC21_S2: 5198c2ecf20Sopenharmony_ci case R_MIPS_PC26_S2: 5208c2ecf20Sopenharmony_ci /* 5218c2ecf20Sopenharmony_ci * NONE can be ignored and PC relative relocations don't 5228c2ecf20Sopenharmony_ci * need to be adjusted. 5238c2ecf20Sopenharmony_ci */ 5248c2ecf20Sopenharmony_ci case R_MIPS_HIGHEST: 5258c2ecf20Sopenharmony_ci case R_MIPS_HIGHER: 5268c2ecf20Sopenharmony_ci /* We support relocating within the same 4Gb segment only, 5278c2ecf20Sopenharmony_ci * thus leaving the top 32bits unchanged 5288c2ecf20Sopenharmony_ci */ 5298c2ecf20Sopenharmony_ci case R_MIPS_LO16: 5308c2ecf20Sopenharmony_ci /* We support relocating by 64k jumps only 5318c2ecf20Sopenharmony_ci * thus leaving the bottom 16bits unchanged 5328c2ecf20Sopenharmony_ci */ 5338c2ecf20Sopenharmony_ci break; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci case R_MIPS_64: 5368c2ecf20Sopenharmony_ci case R_MIPS_32: 5378c2ecf20Sopenharmony_ci case R_MIPS_26: 5388c2ecf20Sopenharmony_ci case R_MIPS_HI16: 5398c2ecf20Sopenharmony_ci add_reloc(&relocs, rel->r_offset, r_type); 5408c2ecf20Sopenharmony_ci break; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci default: 5438c2ecf20Sopenharmony_ci die("Unsupported relocation type: %s (%d)\n", 5448c2ecf20Sopenharmony_ci rel_type(r_type), r_type); 5458c2ecf20Sopenharmony_ci break; 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci return 0; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_cistatic int write_reloc_as_bin(uint32_t v, FILE *f) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci unsigned char buf[4]; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci v = cpu_to_elf32(v); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci memcpy(buf, &v, sizeof(uint32_t)); 5588c2ecf20Sopenharmony_ci return fwrite(buf, 1, 4, f); 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_cistatic int write_reloc_as_text(uint32_t v, FILE *f) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci int res; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci res = fprintf(f, "\t.long 0x%08"PRIx32"\n", v); 5668c2ecf20Sopenharmony_ci if (res < 0) 5678c2ecf20Sopenharmony_ci return res; 5688c2ecf20Sopenharmony_ci else 5698c2ecf20Sopenharmony_ci return sizeof(uint32_t); 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic void emit_relocs(int as_text, int as_bin, FILE *outf) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci int i; 5758c2ecf20Sopenharmony_ci int (*write_reloc)(uint32_t, FILE *) = write_reloc_as_bin; 5768c2ecf20Sopenharmony_ci int size = 0; 5778c2ecf20Sopenharmony_ci int size_reserved; 5788c2ecf20Sopenharmony_ci struct section *sec_reloc; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci sec_reloc = sec_lookup(".data.reloc"); 5818c2ecf20Sopenharmony_ci if (!sec_reloc) 5828c2ecf20Sopenharmony_ci die("Could not find relocation section\n"); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci size_reserved = sec_reloc->shdr.sh_size; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci /* Collect up the relocations */ 5878c2ecf20Sopenharmony_ci walk_relocs(do_reloc); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci /* Print the relocations */ 5908c2ecf20Sopenharmony_ci if (as_text) { 5918c2ecf20Sopenharmony_ci /* Print the relocations in a form suitable that 5928c2ecf20Sopenharmony_ci * gas will like. 5938c2ecf20Sopenharmony_ci */ 5948c2ecf20Sopenharmony_ci printf(".section \".data.reloc\",\"a\"\n"); 5958c2ecf20Sopenharmony_ci printf(".balign 4\n"); 5968c2ecf20Sopenharmony_ci /* Output text to stdout */ 5978c2ecf20Sopenharmony_ci write_reloc = write_reloc_as_text; 5988c2ecf20Sopenharmony_ci outf = stdout; 5998c2ecf20Sopenharmony_ci } else if (as_bin) { 6008c2ecf20Sopenharmony_ci /* Output raw binary to stdout */ 6018c2ecf20Sopenharmony_ci outf = stdout; 6028c2ecf20Sopenharmony_ci } else { 6038c2ecf20Sopenharmony_ci /* Seek to offset of the relocation section. 6048c2ecf20Sopenharmony_ci * Each relocation is then written into the 6058c2ecf20Sopenharmony_ci * vmlinux kernel image. 6068c2ecf20Sopenharmony_ci */ 6078c2ecf20Sopenharmony_ci if (fseek(outf, sec_reloc->shdr.sh_offset, SEEK_SET) < 0) { 6088c2ecf20Sopenharmony_ci die("Seek to %d failed: %s\n", 6098c2ecf20Sopenharmony_ci sec_reloc->shdr.sh_offset, strerror(errno)); 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci for (i = 0; i < relocs.count; i++) 6148c2ecf20Sopenharmony_ci size += write_reloc(relocs.offset[i], outf); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci /* Print a stop, but only if we've actually written some relocs */ 6178c2ecf20Sopenharmony_ci if (size) 6188c2ecf20Sopenharmony_ci size += write_reloc(0, outf); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci if (size > size_reserved) 6218c2ecf20Sopenharmony_ci /* Die, but suggest a value for CONFIG_RELOCATION_TABLE_SIZE 6228c2ecf20Sopenharmony_ci * which will fix this problem and allow a bit of headroom 6238c2ecf20Sopenharmony_ci * if more kernel features are enabled 6248c2ecf20Sopenharmony_ci */ 6258c2ecf20Sopenharmony_ci die("Relocations overflow available space!\n" \ 6268c2ecf20Sopenharmony_ci "Please adjust CONFIG_RELOCATION_TABLE_SIZE " \ 6278c2ecf20Sopenharmony_ci "to at least 0x%08x\n", (size + 0x1000) & ~0xFFF); 6288c2ecf20Sopenharmony_ci} 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci/* 6318c2ecf20Sopenharmony_ci * As an aid to debugging problems with different linkers 6328c2ecf20Sopenharmony_ci * print summary information about the relocs. 6338c2ecf20Sopenharmony_ci * Since different linkers tend to emit the sections in 6348c2ecf20Sopenharmony_ci * different orders we use the section names in the output. 6358c2ecf20Sopenharmony_ci */ 6368c2ecf20Sopenharmony_cistatic int do_reloc_info(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, 6378c2ecf20Sopenharmony_ci const char *symname) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci printf("%16s 0x%08x %16s %40s %16s\n", 6408c2ecf20Sopenharmony_ci sec_name(sec->shdr.sh_info), 6418c2ecf20Sopenharmony_ci (unsigned int)rel->r_offset, 6428c2ecf20Sopenharmony_ci rel_type(ELF_R_TYPE(rel->r_info)), 6438c2ecf20Sopenharmony_ci symname, 6448c2ecf20Sopenharmony_ci sec_name(sym->st_shndx)); 6458c2ecf20Sopenharmony_ci return 0; 6468c2ecf20Sopenharmony_ci} 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_cistatic void print_reloc_info(void) 6498c2ecf20Sopenharmony_ci{ 6508c2ecf20Sopenharmony_ci printf("%16s %10s %16s %40s %16s\n", 6518c2ecf20Sopenharmony_ci "reloc section", 6528c2ecf20Sopenharmony_ci "offset", 6538c2ecf20Sopenharmony_ci "reloc type", 6548c2ecf20Sopenharmony_ci "symbol", 6558c2ecf20Sopenharmony_ci "symbol section"); 6568c2ecf20Sopenharmony_ci walk_relocs(do_reloc_info); 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci#if ELF_BITS == 64 6608c2ecf20Sopenharmony_ci# define process process_64 6618c2ecf20Sopenharmony_ci#else 6628c2ecf20Sopenharmony_ci# define process process_32 6638c2ecf20Sopenharmony_ci#endif 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_civoid process(FILE *fp, int as_text, int as_bin, 6668c2ecf20Sopenharmony_ci int show_reloc_info, int keep_relocs) 6678c2ecf20Sopenharmony_ci{ 6688c2ecf20Sopenharmony_ci regex_init(); 6698c2ecf20Sopenharmony_ci read_ehdr(fp); 6708c2ecf20Sopenharmony_ci read_shdrs(fp); 6718c2ecf20Sopenharmony_ci read_strtabs(fp); 6728c2ecf20Sopenharmony_ci read_symtabs(fp); 6738c2ecf20Sopenharmony_ci read_relocs(fp); 6748c2ecf20Sopenharmony_ci if (show_reloc_info) { 6758c2ecf20Sopenharmony_ci print_reloc_info(); 6768c2ecf20Sopenharmony_ci return; 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci emit_relocs(as_text, as_bin, fp); 6798c2ecf20Sopenharmony_ci if (!keep_relocs) 6808c2ecf20Sopenharmony_ci remove_relocs(fp); 6818c2ecf20Sopenharmony_ci} 682