1968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <stdio.h> 2968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <stdarg.h> 3968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <stdlib.h> 4968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <stdint.h> 5968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <string.h> 6968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <errno.h> 7968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <unistd.h> 8968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <elf.h> 9968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <byteswap.h> 10968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define USE_BSD 11968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <endian.h> 12873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin#include <regex.h> 1355f9709cd07c9d33e30b575ee1b3bfd0aeaa3760Matt Fleming#include <tools/le_byteshift.h> 14873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin 15873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvinstatic void die(char *fmt, ...); 16968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 17ca820181fc187af316a18b2700582663662c4012Robert P. J. Day#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 18968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic Elf32_Ehdr ehdr; 19968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic unsigned long reloc_count, reloc_idx; 20968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic unsigned long *relocs; 216520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic unsigned long reloc16_count, reloc16_idx; 226520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic unsigned long *relocs16; 23968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 24908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvinstruct section { 25908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin Elf32_Shdr shdr; 26908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *link; 27908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin Elf32_Sym *symtab; 28908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin Elf32_Rel *reltab; 29908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin char *strtab; 30908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin}; 31908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvinstatic struct section *secs; 32908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin 336520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinenum symtype { 346520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin S_ABS, 356520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin S_REL, 366520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin S_SEG, 376520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin S_LIN, 386520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin S_NSYMTYPES 396520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin}; 406520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 416520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic const char * const sym_regex_kernel[S_NSYMTYPES] = { 426a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal/* 436a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * Following symbols have been audited. There values are constant and do 446a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * not change if bzImage is loaded at a different physical address than 456a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * the address for which it has been compiled. Don't warn user about 466a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * absolute relocations present w.r.t these symbols. 476a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal */ 486520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin [S_ABS] = 49873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin "^(xen_irq_disable_direct_reloc$|" 50873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin "xen_save_fl_direct_reloc$|" 51873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin "VDSO|" 526520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin "__crc_)", 536a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal 54873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin/* 55873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin * These symbols are known to be relative, even if the linker marks them 56873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin * as absolute (typically defined outside any section in the linker script.) 57873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin */ 586520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin [S_REL] = 59a3e854d95a76862cd37937e0b0438f540536771aH. Peter Anvin "^(__init_(begin|end)|" 60a3e854d95a76862cd37937e0b0438f540536771aH. Peter Anvin "__x86_cpu_dev_(start|end)|" 61a3e854d95a76862cd37937e0b0438f540536771aH. Peter Anvin "(__parainstructions|__alt_instructions)(|_end)|" 62a3e854d95a76862cd37937e0b0438f540536771aH. Peter Anvin "(__iommu_table|__apicdrivers|__smp_locks)(|_end)|" 633c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__(start|end)_pci_.*|" 643c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__(start|end)_builtin_fw|" 653c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__(start|stop)___ksymtab(|_gpl|_unused|_unused_gpl|_gpl_future)|" 663c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__(start|stop)___kcrctab(|_gpl|_unused|_unused_gpl|_gpl_future)|" 673c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__(start|stop)___param|" 683c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__(start|stop)___modver|" 693c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__(start|stop)___bug_table|" 703c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__tracedata_(start|end)|" 713c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__(start|stop)_notes|" 723c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__end_rodata|" 733c47c685100285be39ff7e347f762480b448b956H. Peter Anvin "__initramfs_start|" 74c51ac8ac9a82d4883c9b62247cca98195da8cd63H. Peter Anvin "(jiffies|jiffies_64)|" 75a3e854d95a76862cd37937e0b0438f540536771aH. Peter Anvin "_end)$" 766520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin}; 776520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 786520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 796520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic const char * const sym_regex_realmode[S_NSYMTYPES] = { 806520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin/* 816520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin * These are 16-bit segment symbols when compiling 16-bit code. 826520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin */ 836520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin [S_SEG] = 846520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin "^real_mode_seg$", 856520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 866520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin/* 876520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin * These are offsets belonging to segments, as opposed to linear addresses, 886520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin * when compiling 16-bit code. 896520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin */ 906520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin [S_LIN] = 916520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin "^pa_", 926520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin}; 936520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 946520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic const char * const *sym_regex; 956520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 966520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic regex_t sym_regex_c[S_NSYMTYPES]; 976520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic int is_reloc(enum symtype type, const char *sym_name) 986a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal{ 996520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin return sym_regex[type] && 1006520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin !regexec(&sym_regex_c[type], sym_name, 0, NULL, 0); 101873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin} 1026a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal 1036520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic void regex_init(int use_real_mode) 104873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin{ 105873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin char errbuf[128]; 106873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin int err; 1076520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin int i; 108873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin 1096520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (use_real_mode) 1106520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin sym_regex = sym_regex_realmode; 1116520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin else 1126520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin sym_regex = sym_regex_kernel; 1136520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 1146520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin for (i = 0; i < S_NSYMTYPES; i++) { 1156520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (!sym_regex[i]) 1166520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin continue; 1176520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 1186520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin err = regcomp(&sym_regex_c[i], sym_regex[i], 1196520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin REG_EXTENDED|REG_NOSUB); 1206520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 1216520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (err) { 1226520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin regerror(err, &sym_regex_c[i], errbuf, sizeof errbuf); 1236520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin die("%s", errbuf); 1246520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } 125873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin } 1266a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal} 1276a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal 128968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void die(char *fmt, ...) 129968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 130968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman va_list ap; 131968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman va_start(ap, fmt); 132968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman vfprintf(stderr, fmt, ap); 133968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman va_end(ap); 134968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman exit(1); 135968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 136968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 137968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sym_type(unsigned type) 138968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 139968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman static const char *type_name[] = { 140968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define SYM_TYPE(X) [X] = #X 141968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_TYPE(STT_NOTYPE), 142968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_TYPE(STT_OBJECT), 143968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_TYPE(STT_FUNC), 144968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_TYPE(STT_SECTION), 145968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_TYPE(STT_FILE), 146968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_TYPE(STT_COMMON), 147968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_TYPE(STT_TLS), 148968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#undef SYM_TYPE 149968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman }; 150968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *name = "unknown sym type name"; 151ca820181fc187af316a18b2700582663662c4012Robert P. J. Day if (type < ARRAY_SIZE(type_name)) { 152968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = type_name[type]; 153968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 154968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return name; 155968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 156968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 157968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sym_bind(unsigned bind) 158968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 159968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman static const char *bind_name[] = { 160968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define SYM_BIND(X) [X] = #X 161968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_BIND(STB_LOCAL), 162968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_BIND(STB_GLOBAL), 163968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_BIND(STB_WEAK), 164968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#undef SYM_BIND 165968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman }; 166968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *name = "unknown sym bind name"; 167ca820181fc187af316a18b2700582663662c4012Robert P. J. Day if (bind < ARRAY_SIZE(bind_name)) { 168968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = bind_name[bind]; 169968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 170968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return name; 171968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 172968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 173968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sym_visibility(unsigned visibility) 174968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 175968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman static const char *visibility_name[] = { 176968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define SYM_VISIBILITY(X) [X] = #X 177968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_VISIBILITY(STV_DEFAULT), 178968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_VISIBILITY(STV_INTERNAL), 179968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_VISIBILITY(STV_HIDDEN), 180968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman SYM_VISIBILITY(STV_PROTECTED), 181968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#undef SYM_VISIBILITY 182968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman }; 183968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *name = "unknown sym visibility name"; 184ca820181fc187af316a18b2700582663662c4012Robert P. J. Day if (visibility < ARRAY_SIZE(visibility_name)) { 185968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = visibility_name[visibility]; 186968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 187968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return name; 188968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 189968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 190968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *rel_type(unsigned type) 191968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 192968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman static const char *type_name[] = { 193968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define REL_TYPE(X) [X] = #X 194968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_NONE), 195968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_32), 196968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_PC32), 197968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_GOT32), 198968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_PLT32), 199968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_COPY), 200968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_GLOB_DAT), 201968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_JMP_SLOT), 202968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_RELATIVE), 203968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_GOTOFF), 204968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman REL_TYPE(R_386_GOTPC), 2056520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin REL_TYPE(R_386_8), 2066520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin REL_TYPE(R_386_PC8), 2076520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin REL_TYPE(R_386_16), 2086520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin REL_TYPE(R_386_PC16), 209968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#undef REL_TYPE 210968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman }; 211968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *name = "unknown type rel type name"; 212873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin if (type < ARRAY_SIZE(type_name) && type_name[type]) { 213968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = type_name[type]; 214968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 215968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return name; 216968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 217968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 218968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sec_name(unsigned shndx) 219968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 220968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *sec_strtab; 221968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *name; 222908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec_strtab = secs[ehdr.e_shstrndx].strtab; 223968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = "<noname>"; 224968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (shndx < ehdr.e_shnum) { 225908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin name = sec_strtab + secs[shndx].shdr.sh_name; 226968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 227968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman else if (shndx == SHN_ABS) { 228968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = "ABSOLUTE"; 229968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 230968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman else if (shndx == SHN_COMMON) { 231968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = "COMMON"; 232968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 233968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return name; 234968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 235968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 236968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) 237968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 238968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *name; 239968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = "<noname>"; 240968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (sym->st_name) { 241968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = sym_strtab + sym->st_name; 242968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 243968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman else { 2446520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin name = sec_name(sym->st_shndx); 245968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 246968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return name; 247968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 248968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 249968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 250968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 25113da9e200fe4740b02cd51e07ab454627e228920Linus Torvalds#if BYTE_ORDER == LITTLE_ENDIAN 252968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define le16_to_cpu(val) (val) 253968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define le32_to_cpu(val) (val) 254968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#endif 25513da9e200fe4740b02cd51e07ab454627e228920Linus Torvalds#if BYTE_ORDER == BIG_ENDIAN 256968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define le16_to_cpu(val) bswap_16(val) 257968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define le32_to_cpu(val) bswap_32(val) 258968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#endif 259968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 260968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic uint16_t elf16_to_cpu(uint16_t val) 261968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 262968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return le16_to_cpu(val); 263968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 264968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 265968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic uint32_t elf32_to_cpu(uint32_t val) 266968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 267968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return le32_to_cpu(val); 268968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 269968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 270968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_ehdr(FILE *fp) 271968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 272968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) { 273968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Cannot read ELF header: %s\n", 274968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman strerror(errno)); 275968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 2768bd1796dedd50abd7553afbe6113bd97cc88390fCyrill Gorcunov if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) { 277968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("No ELF magic\n"); 278968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 279968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { 280968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Not a 32 bit executable\n"); 281968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 282968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) { 283968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Not a LSB ELF executable\n"); 284968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 285968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) { 286968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Unknown ELF version\n"); 287968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 288968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman /* Convert the fields to native endian */ 289968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_type = elf16_to_cpu(ehdr.e_type); 290968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_machine = elf16_to_cpu(ehdr.e_machine); 291968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_version = elf32_to_cpu(ehdr.e_version); 292968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_entry = elf32_to_cpu(ehdr.e_entry); 293968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_phoff = elf32_to_cpu(ehdr.e_phoff); 294968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_shoff = elf32_to_cpu(ehdr.e_shoff); 295968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_flags = elf32_to_cpu(ehdr.e_flags); 296968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_ehsize = elf16_to_cpu(ehdr.e_ehsize); 297968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize); 298968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_phnum = elf16_to_cpu(ehdr.e_phnum); 299968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize); 300968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_shnum = elf16_to_cpu(ehdr.e_shnum); 301968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_shstrndx = elf16_to_cpu(ehdr.e_shstrndx); 302968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 303968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) { 304968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Unsupported ELF header type\n"); 305968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 306968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (ehdr.e_machine != EM_386) { 307968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Not for x86\n"); 308968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 309968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (ehdr.e_version != EV_CURRENT) { 310968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Unknown ELF version\n"); 311968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 312968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) { 313968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Bad Elf header size\n"); 314968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 315968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) { 316968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Bad program header entry\n"); 317968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 318968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) { 319968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Bad section header entry\n"); 320968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 321968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (ehdr.e_shstrndx >= ehdr.e_shnum) { 322968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("String table index out of bounds\n"); 323968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 324968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 325968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 326968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_shdrs(FILE *fp) 327968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 328968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int i; 329908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin Elf32_Shdr shdr; 330908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin 331908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin secs = calloc(ehdr.e_shnum, sizeof(struct section)); 332908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (!secs) { 333908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin die("Unable to allocate %d section headers\n", 334908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin ehdr.e_shnum); 335968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 336968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) { 337968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Seek to %d failed: %s\n", 338968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman ehdr.e_shoff, strerror(errno)); 339968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 340908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (i = 0; i < ehdr.e_shnum; i++) { 341908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *sec = &secs[i]; 342908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (fread(&shdr, sizeof shdr, 1, fp) != 1) 343908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin die("Cannot read ELF section headers %d/%d: %s\n", 344908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin i, ehdr.e_shnum, strerror(errno)); 345908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_name = elf32_to_cpu(shdr.sh_name); 346908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_type = elf32_to_cpu(shdr.sh_type); 347908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_flags = elf32_to_cpu(shdr.sh_flags); 348908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_addr = elf32_to_cpu(shdr.sh_addr); 349908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_offset = elf32_to_cpu(shdr.sh_offset); 350908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_size = elf32_to_cpu(shdr.sh_size); 351908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_link = elf32_to_cpu(shdr.sh_link); 352908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_info = elf32_to_cpu(shdr.sh_info); 353908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign); 354908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_entsize = elf32_to_cpu(shdr.sh_entsize); 355908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (sec->shdr.sh_link < ehdr.e_shnum) 356908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->link = &secs[sec->shdr.sh_link]; 357968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 358968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 359968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 360968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 361968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_strtabs(FILE *fp) 362968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 363968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int i; 364908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (i = 0; i < ehdr.e_shnum; i++) { 365908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *sec = &secs[i]; 366908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (sec->shdr.sh_type != SHT_STRTAB) { 367968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 368968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 369908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->strtab = malloc(sec->shdr.sh_size); 370908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (!sec->strtab) { 371968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("malloc of %d bytes for strtab failed\n", 372908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_size); 373968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 374908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { 375968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Seek to %d failed: %s\n", 376908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_offset, strerror(errno)); 377968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 378908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) 379908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin != sec->shdr.sh_size) { 380968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Cannot read symbol table: %s\n", 381968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman strerror(errno)); 382968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 383968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 384968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 385968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 386968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_symtabs(FILE *fp) 387968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 388968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int i,j; 389908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (i = 0; i < ehdr.e_shnum; i++) { 390908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *sec = &secs[i]; 391908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (sec->shdr.sh_type != SHT_SYMTAB) { 392968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 393968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 394908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->symtab = malloc(sec->shdr.sh_size); 395908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (!sec->symtab) { 396968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("malloc of %d bytes for symtab failed\n", 397908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_size); 398968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 399908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { 400968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Seek to %d failed: %s\n", 401908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_offset, strerror(errno)); 402968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 403908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) 404908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin != sec->shdr.sh_size) { 405968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Cannot read symbol table: %s\n", 406968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman strerror(errno)); 407968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 408908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { 409908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin Elf32_Sym *sym = &sec->symtab[j]; 410908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sym->st_name = elf32_to_cpu(sym->st_name); 411908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sym->st_value = elf32_to_cpu(sym->st_value); 412908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sym->st_size = elf32_to_cpu(sym->st_size); 413908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sym->st_shndx = elf16_to_cpu(sym->st_shndx); 414968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 415968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 416968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 417968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 418968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 419968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_relocs(FILE *fp) 420968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 421968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int i,j; 422908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (i = 0; i < ehdr.e_shnum; i++) { 423908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *sec = &secs[i]; 424908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (sec->shdr.sh_type != SHT_REL) { 425968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 426968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 427908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->reltab = malloc(sec->shdr.sh_size); 428908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (!sec->reltab) { 429968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("malloc of %d bytes for relocs failed\n", 430908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_size); 431968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 432908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { 433968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Seek to %d failed: %s\n", 434908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec->shdr.sh_offset, strerror(errno)); 435968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 436908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (fread(sec->reltab, 1, sec->shdr.sh_size, fp) 437908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin != sec->shdr.sh_size) { 438968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Cannot read symbol table: %s\n", 439968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman strerror(errno)); 440968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 441908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { 442908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin Elf32_Rel *rel = &sec->reltab[j]; 443908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin rel->r_offset = elf32_to_cpu(rel->r_offset); 444908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin rel->r_info = elf32_to_cpu(rel->r_info); 445968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 446968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 447968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 448968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 449968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 450968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void print_absolute_symbols(void) 451968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 452968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int i; 453968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman printf("Absolute symbols\n"); 454968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman printf(" Num: Value Size Type Bind Visibility Name\n"); 455908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (i = 0; i < ehdr.e_shnum; i++) { 456908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *sec = &secs[i]; 457968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman char *sym_strtab; 458968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int j; 459908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin 460908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (sec->shdr.sh_type != SHT_SYMTAB) { 461968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 462968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 463908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sym_strtab = sec->link->strtab; 464908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { 465968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman Elf32_Sym *sym; 466968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *name; 467908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sym = &sec->symtab[j]; 468968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = sym_name(sym_strtab, sym); 469968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (sym->st_shndx != SHN_ABS) { 470968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 471968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 472968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman printf("%5d %08x %5d %10s %10s %12s %s\n", 473968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman j, sym->st_value, sym->st_size, 474968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman sym_type(ELF32_ST_TYPE(sym->st_info)), 475968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman sym_bind(ELF32_ST_BIND(sym->st_info)), 476968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)), 477968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name); 478968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 479968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 480968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman printf("\n"); 481968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 482968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 483968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void print_absolute_relocs(void) 484968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 4856a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal int i, printed = 0; 4866a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal 487908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (i = 0; i < ehdr.e_shnum; i++) { 488908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *sec = &secs[i]; 489908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *sec_applies, *sec_symtab; 490968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman char *sym_strtab; 491968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman Elf32_Sym *sh_symtab; 492968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int j; 493908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (sec->shdr.sh_type != SHT_REL) { 494968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 495968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 496908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec_symtab = sec->link; 497908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec_applies = &secs[sec->shdr.sh_info]; 498908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { 499968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 500968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 501908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sh_symtab = sec_symtab->symtab; 502908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sym_strtab = sec_symtab->link->strtab; 503908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { 504968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman Elf32_Rel *rel; 505968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman Elf32_Sym *sym; 506968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *name; 507908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin rel = &sec->reltab[j]; 508968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; 509968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name = sym_name(sym_strtab, sym); 510968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (sym->st_shndx != SHN_ABS) { 511968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 512968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 5136a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal 5146a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal /* Absolute symbols are not relocated if bzImage is 5156a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * loaded at a non-compiled address. Display a warning 5166a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * to user at compile time about the absolute 5176a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * relocations present. 5186a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * 5196a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * User need to audit the code to make sure 5206a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * some symbols which should have been section 5216a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * relative have not become absolute because of some 5226a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * linker optimization or wrong programming usage. 5236a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * 5246a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * Before warning check if this absolute symbol 5256a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * relocation is harmless. 5266a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal */ 5276520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (is_reloc(S_ABS, name) || is_reloc(S_REL, name)) 5286a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal continue; 5296a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal 5306a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal if (!printed) { 5316a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal printf("WARNING: Absolute relocations" 5326a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal " present\n"); 5336a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal printf("Offset Info Type Sym.Value " 5346a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal "Sym.Name\n"); 5356a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal printed = 1; 5366a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal } 5376a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal 538968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman printf("%08x %08x %10s %08x %s\n", 539968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman rel->r_offset, 540968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman rel->r_info, 541968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman rel_type(ELF32_R_TYPE(rel->r_info)), 542968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman sym->st_value, 543968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman name); 544968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 545968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 5466a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal 5476a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal if (printed) 5486a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal printf("\n"); 549968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 550968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 5516520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym), 5526520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin int use_real_mode) 553968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 554968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int i; 555968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman /* Walk through the relocations */ 556908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (i = 0; i < ehdr.e_shnum; i++) { 557968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman char *sym_strtab; 558968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman Elf32_Sym *sh_symtab; 559908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *sec_applies, *sec_symtab; 560968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int j; 561908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin struct section *sec = &secs[i]; 562908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin 563908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (sec->shdr.sh_type != SHT_REL) { 564968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 565968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 566908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec_symtab = sec->link; 567908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sec_applies = &secs[sec->shdr.sh_info]; 568908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { 569968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 570968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 571908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin sh_symtab = sec_symtab->symtab; 572cc65f1ec192dc54de57483194502e9fa00934c39H. Peter Anvin sym_strtab = sec_symtab->link->strtab; 573908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { 574968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman Elf32_Rel *rel; 575968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman Elf32_Sym *sym; 576968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman unsigned r_type; 5776520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin const char *symname; 57824ab82bd9bf18f3efc69a131d73577940941e1b7H. Peter Anvin int shn_abs; 57924ab82bd9bf18f3efc69a131d73577940941e1b7H. Peter Anvin 580908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin rel = &sec->reltab[j]; 581968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; 582968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman r_type = ELF32_R_TYPE(rel->r_info); 5836520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 58424ab82bd9bf18f3efc69a131d73577940941e1b7H. Peter Anvin shn_abs = sym->st_shndx == SHN_ABS; 58524ab82bd9bf18f3efc69a131d73577940941e1b7H. Peter Anvin 586873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin switch (r_type) { 587873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin case R_386_NONE: 588873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin case R_386_PC32: 5896520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin case R_386_PC16: 5906520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin case R_386_PC8: 59146176b4f6bac19454b7b5c35f68594b85850a600Tejun Heo /* 59246176b4f6bac19454b7b5c35f68594b85850a600Tejun Heo * NONE can be ignored and and PC relative 59346176b4f6bac19454b7b5c35f68594b85850a600Tejun Heo * relocations don't need to be adjusted. 59446176b4f6bac19454b7b5c35f68594b85850a600Tejun Heo */ 595873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin break; 5966520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 5976520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin case R_386_16: 5986520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin symname = sym_name(sym_strtab, sym); 5996520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (!use_real_mode) 6006520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin goto bad; 60124ab82bd9bf18f3efc69a131d73577940941e1b7H. Peter Anvin if (shn_abs) { 6026520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (is_reloc(S_ABS, symname)) 6036520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin break; 6046520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin else if (!is_reloc(S_SEG, symname)) 6056520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin goto bad; 6066520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } else { 6076520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (is_reloc(S_LIN, symname)) 6086520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin goto bad; 6096520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin else 6106520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin break; 6116520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } 6126520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin visit(rel, sym); 6136520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin break; 6146520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 615873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin case R_386_32: 6166520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin symname = sym_name(sym_strtab, sym); 61724ab82bd9bf18f3efc69a131d73577940941e1b7H. Peter Anvin if (shn_abs) { 6186520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (is_reloc(S_ABS, symname)) 6196520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin break; 6206520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin else if (!is_reloc(S_REL, symname)) 6216520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin goto bad; 6226520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } else { 6236520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (use_real_mode && 6246520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin !is_reloc(S_LIN, symname)) 6256520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin break; 6266520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } 627968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman visit(rel, sym); 628873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin break; 629873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin default: 630873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin die("Unsupported relocation type: %s (%d)\n", 631873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin rel_type(r_type), r_type); 632873b5271f878a11729fb4602c6ce967d0ff81119H. Peter Anvin break; 6336520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin bad: 6346520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin symname = sym_name(sym_strtab, sym); 63524ab82bd9bf18f3efc69a131d73577940941e1b7H. Peter Anvin die("Invalid %s %s relocation: %s\n", 63624ab82bd9bf18f3efc69a131d73577940941e1b7H. Peter Anvin shn_abs ? "absolute" : "relative", 6376520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin rel_type(r_type), symname); 638968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 639968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 640968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 641968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 642968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 643968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) 644968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 6456520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (ELF32_R_TYPE(rel->r_info) == R_386_16) 6466520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin reloc16_count++; 6476520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin else 6486520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin reloc_count++; 649968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 650968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 651968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) 652968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 653968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman /* Remember the address that needs to be adjusted. */ 6546520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (ELF32_R_TYPE(rel->r_info) == R_386_16) 6556520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin relocs16[reloc16_idx++] = rel->r_offset; 6566520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin else 6576520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin relocs[reloc_idx++] = rel->r_offset; 658968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 659968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 660968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic int cmp_relocs(const void *va, const void *vb) 661968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 662968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const unsigned long *a, *b; 663968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman a = va; b = vb; 664968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return (*a == *b)? 0 : (*a > *b)? 1 : -1; 665968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 666968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 6676520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic int write32(unsigned int v, FILE *f) 6686520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin{ 6696520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin unsigned char buf[4]; 6706520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 6716520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin put_unaligned_le32(v, buf); 6726520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin return fwrite(buf, 1, 4, f) == 4 ? 0 : -1; 6736520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin} 6746520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 6756520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvinstatic void emit_relocs(int as_text, int use_real_mode) 676968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 677968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int i; 678968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman /* Count how many relocations I have and allocate space for them. */ 679968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman reloc_count = 0; 6806520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin walk_relocs(count_reloc, use_real_mode); 681968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman relocs = malloc(reloc_count * sizeof(relocs[0])); 682968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (!relocs) { 683968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("malloc of %d entries for relocs failed\n", 684968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman reloc_count); 685968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 6866520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 6876520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin relocs16 = malloc(reloc16_count * sizeof(relocs[0])); 6886520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (!relocs16) { 6896520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin die("malloc of %d entries for relocs16 failed\n", 6906520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin reloc16_count); 6916520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } 692968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman /* Collect up the relocations */ 693968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman reloc_idx = 0; 6946520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin walk_relocs(collect_reloc, use_real_mode); 6956520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 6966520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (reloc16_count && !use_real_mode) 6976520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin die("Segment relocations found but --realmode not specified\n"); 698968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 699968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman /* Order the relocations for more efficient processing */ 700968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); 7016520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin qsort(relocs16, reloc16_count, sizeof(relocs16[0]), cmp_relocs); 702968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 703968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman /* Print the relocations */ 704968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (as_text) { 705968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman /* Print the relocations in a form suitable that 706968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman * gas will like. 707968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman */ 708968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman printf(".section \".data.reloc\",\"a\"\n"); 709968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman printf(".balign 4\n"); 7106520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (use_real_mode) { 7116520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin printf("\t.long %lu\n", reloc16_count); 7126520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin for (i = 0; i < reloc16_count; i++) 7136520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin printf("\t.long 0x%08lx\n", relocs16[i]); 7146520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin printf("\t.long %lu\n", reloc_count); 7156520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin for (i = 0; i < reloc_count; i++) { 7166520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin printf("\t.long 0x%08lx\n", relocs[i]); 7176520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } 7186520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } else { 7196520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin /* Print a stop */ 7206520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin printf("\t.long 0x%08lx\n", (unsigned long)0); 7216520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin for (i = 0; i < reloc_count; i++) { 7226520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin printf("\t.long 0x%08lx\n", relocs[i]); 7236520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } 724968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 7256520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 726968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman printf("\n"); 727968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 728968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman else { 7296520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (use_real_mode) { 7306520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin write32(reloc16_count, stdout); 7316520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin for (i = 0; i < reloc16_count; i++) 7326520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin write32(relocs16[i], stdout); 7336520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin write32(reloc_count, stdout); 7346520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 7356520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin /* Now print each relocation */ 7366520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin for (i = 0; i < reloc_count; i++) 7376520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin write32(relocs[i], stdout); 7386520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } else { 7396520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin /* Print a stop */ 7406520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin write32(0, stdout); 7416520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin 7426520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin /* Now print each relocation */ 7436520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin for (i = 0; i < reloc_count; i++) { 7446520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin write32(relocs[i], stdout); 7456520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } 746968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 747968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 748968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 749968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 750968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void usage(void) 751968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 7526520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); 753968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 754968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 755968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanint main(int argc, char **argv) 756968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{ 7576a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal int show_absolute_syms, show_absolute_relocs; 7586520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin int as_text, use_real_mode; 759968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman const char *fname; 760968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman FILE *fp; 761968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman int i; 762968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman 7636a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal show_absolute_syms = 0; 7646a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal show_absolute_relocs = 0; 765968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman as_text = 0; 7666520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin use_real_mode = 0; 767968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman fname = NULL; 768908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin for (i = 1; i < argc; i++) { 769968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman char *arg = argv[i]; 770968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (*arg == '-') { 7716520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (strcmp(arg, "--abs-syms") == 0) { 7726a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal show_absolute_syms = 1; 7736a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal continue; 7746a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal } 7756520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (strcmp(arg, "--abs-relocs") == 0) { 7766a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal show_absolute_relocs = 1; 777968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 778968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 7796520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (strcmp(arg, "--text") == 0) { 780968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman as_text = 1; 781968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 782968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 7836520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin if (strcmp(arg, "--realmode") == 0) { 7846520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin use_real_mode = 1; 7856520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin continue; 7866520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin } 787968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 788968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman else if (!fname) { 789968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman fname = arg; 790968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman continue; 791968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 792968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman usage(); 793968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 794968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (!fname) { 795968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman usage(); 796968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 7976520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin regex_init(use_real_mode); 798968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman fp = fopen(fname, "r"); 799968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman if (!fp) { 800968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman die("Cannot open %s: %s\n", 801968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman fname, strerror(errno)); 802968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 803968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman read_ehdr(fp); 804968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman read_shdrs(fp); 805968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman read_strtabs(fp); 806968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman read_symtabs(fp); 807968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman read_relocs(fp); 8086a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal if (show_absolute_syms) { 809968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman print_absolute_symbols(); 8106a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal return 0; 8116a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal } 8126a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal if (show_absolute_relocs) { 813968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman print_absolute_relocs(); 814968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return 0; 815968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman } 8166520fe5564acf07ade7b18a1272db1184835c487H. Peter Anvin emit_relocs(as_text, use_real_mode); 817968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman return 0; 818968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman} 819