11da177e4SLinus Torvalds #include <stdio.h> 21da177e4SLinus Torvalds #include <stdlib.h> 31da177e4SLinus Torvalds #include <stdarg.h> 41da177e4SLinus Torvalds #include <string.h> 51da177e4SLinus Torvalds #include <sys/types.h> 61da177e4SLinus Torvalds #include <sys/stat.h> 71da177e4SLinus Torvalds #include <sys/mman.h> 81da177e4SLinus Torvalds #include <fcntl.h> 91da177e4SLinus Torvalds #include <unistd.h> 101da177e4SLinus Torvalds #include <elf.h> 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds #include "elfconfig.h" 131da177e4SLinus Torvalds 143c0561e0SPavel Fedin /* On BSD-alike OSes elf.h defines these according to host's word size */ 153c0561e0SPavel Fedin #undef ELF_ST_BIND 163c0561e0SPavel Fedin #undef ELF_ST_TYPE 173c0561e0SPavel Fedin #undef ELF_R_SYM 183c0561e0SPavel Fedin #undef ELF_R_TYPE 193c0561e0SPavel Fedin 201da177e4SLinus Torvalds #if KERNEL_ELFCLASS == ELFCLASS32 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #define Elf_Ehdr Elf32_Ehdr 231da177e4SLinus Torvalds #define Elf_Shdr Elf32_Shdr 241da177e4SLinus Torvalds #define Elf_Sym Elf32_Sym 25b39927cfSSam Ravnborg #define Elf_Addr Elf32_Addr 269ad21c3fSSam Ravnborg #define Elf_Sword Elf64_Sword 274f4c4ee1SSam Ravnborg #define Elf_Section Elf32_Half 281da177e4SLinus Torvalds #define ELF_ST_BIND ELF32_ST_BIND 291da177e4SLinus Torvalds #define ELF_ST_TYPE ELF32_ST_TYPE 301da177e4SLinus Torvalds 312c1a51f3SAtsushi Nemoto #define Elf_Rel Elf32_Rel 32b39927cfSSam Ravnborg #define Elf_Rela Elf32_Rela 33b39927cfSSam Ravnborg #define ELF_R_SYM ELF32_R_SYM 34b39927cfSSam Ravnborg #define ELF_R_TYPE ELF32_R_TYPE 351da177e4SLinus Torvalds #else 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds #define Elf_Ehdr Elf64_Ehdr 381da177e4SLinus Torvalds #define Elf_Shdr Elf64_Shdr 391da177e4SLinus Torvalds #define Elf_Sym Elf64_Sym 40b39927cfSSam Ravnborg #define Elf_Addr Elf64_Addr 419ad21c3fSSam Ravnborg #define Elf_Sword Elf64_Sxword 424f4c4ee1SSam Ravnborg #define Elf_Section Elf64_Half 431da177e4SLinus Torvalds #define ELF_ST_BIND ELF64_ST_BIND 441da177e4SLinus Torvalds #define ELF_ST_TYPE ELF64_ST_TYPE 451da177e4SLinus Torvalds 462c1a51f3SAtsushi Nemoto #define Elf_Rel Elf64_Rel 47b39927cfSSam Ravnborg #define Elf_Rela Elf64_Rela 48b39927cfSSam Ravnborg #define ELF_R_SYM ELF64_R_SYM 49b39927cfSSam Ravnborg #define ELF_R_TYPE ELF64_R_TYPE 501da177e4SLinus Torvalds #endif 511da177e4SLinus Torvalds 52eae07ac6SAtsushi Nemoto /* The 64-bit MIPS ELF ABI uses an unusual reloc format. */ 53eae07ac6SAtsushi Nemoto typedef struct 54eae07ac6SAtsushi Nemoto { 55eae07ac6SAtsushi Nemoto Elf32_Word r_sym; /* Symbol index */ 56eae07ac6SAtsushi Nemoto unsigned char r_ssym; /* Special symbol for 2nd relocation */ 57eae07ac6SAtsushi Nemoto unsigned char r_type3; /* 3rd relocation type */ 58eae07ac6SAtsushi Nemoto unsigned char r_type2; /* 2nd relocation type */ 59eae07ac6SAtsushi Nemoto unsigned char r_type1; /* 1st relocation type */ 60eae07ac6SAtsushi Nemoto } _Elf64_Mips_R_Info; 61eae07ac6SAtsushi Nemoto 62eae07ac6SAtsushi Nemoto typedef union 63eae07ac6SAtsushi Nemoto { 64eae07ac6SAtsushi Nemoto Elf64_Xword r_info_number; 65eae07ac6SAtsushi Nemoto _Elf64_Mips_R_Info r_info_fields; 66eae07ac6SAtsushi Nemoto } _Elf64_Mips_R_Info_union; 67eae07ac6SAtsushi Nemoto 68eae07ac6SAtsushi Nemoto #define ELF64_MIPS_R_SYM(i) \ 69eae07ac6SAtsushi Nemoto ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) 70eae07ac6SAtsushi Nemoto 71ae4ac123SAtsushi Nemoto #define ELF64_MIPS_R_TYPE(i) \ 72ae4ac123SAtsushi Nemoto ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1) 73ae4ac123SAtsushi Nemoto 741da177e4SLinus Torvalds #if KERNEL_ELFDATA != HOST_ELFDATA 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds static inline void __endian(const void *src, void *dest, unsigned int size) 771da177e4SLinus Torvalds { 781da177e4SLinus Torvalds unsigned int i; 791da177e4SLinus Torvalds for (i = 0; i < size; i++) 801da177e4SLinus Torvalds ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; 811da177e4SLinus Torvalds } 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds #define TO_NATIVE(x) \ 841da177e4SLinus Torvalds ({ \ 851da177e4SLinus Torvalds typeof(x) __x; \ 861da177e4SLinus Torvalds __endian(&(x), &(__x), sizeof(__x)); \ 871da177e4SLinus Torvalds __x; \ 881da177e4SLinus Torvalds }) 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds #else /* endianness matches */ 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds #define TO_NATIVE(x) (x) 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds #endif 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds #define NOFAIL(ptr) do_nofail((ptr), #ptr) 971da177e4SLinus Torvalds void *do_nofail(void *ptr, const char *expr); 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds struct buffer { 1001da177e4SLinus Torvalds char *p; 1011da177e4SLinus Torvalds int pos; 1021da177e4SLinus Torvalds int size; 1031da177e4SLinus Torvalds }; 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds void __attribute__((format(printf, 2, 3))) 1061da177e4SLinus Torvalds buf_printf(struct buffer *buf, const char *fmt, ...); 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds void 1091da177e4SLinus Torvalds buf_write(struct buffer *buf, const char *s, int len); 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds struct module { 1121da177e4SLinus Torvalds struct module *next; 1131da177e4SLinus Torvalds const char *name; 114b817f6feSSam Ravnborg int gpl_compatible; 1151da177e4SLinus Torvalds struct symbol *unres; 1161da177e4SLinus Torvalds int seen; 1171da177e4SLinus Torvalds int skip; 1181da177e4SLinus Torvalds int has_init; 1191da177e4SLinus Torvalds int has_cleanup; 1201da177e4SLinus Torvalds struct buffer dev_table_buf; 1211da177e4SLinus Torvalds char srcversion[25]; 122258f7426SFrank Rowand int is_dot_o; 1231da177e4SLinus Torvalds }; 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds struct elf_info { 1261da177e4SLinus Torvalds unsigned long size; 1271da177e4SLinus Torvalds Elf_Ehdr *hdr; 1281da177e4SLinus Torvalds Elf_Shdr *sechdrs; 1291da177e4SLinus Torvalds Elf_Sym *symtab_start; 1301da177e4SLinus Torvalds Elf_Sym *symtab_stop; 131bd5cbcedSRam Pai Elf_Section export_sec; 132c96fca21SSam Ravnborg Elf_Section export_unused_sec; 133bd5cbcedSRam Pai Elf_Section export_gpl_sec; 134c96fca21SSam Ravnborg Elf_Section export_unused_gpl_sec; 135bd5cbcedSRam Pai Elf_Section export_gpl_future_sec; 1367d02b490SAndi Kleen char *strtab; 1371da177e4SLinus Torvalds char *modinfo; 1381da177e4SLinus Torvalds unsigned int modinfo_len; 1391ce53adfSDenys Vlasenko 1401ce53adfSDenys Vlasenko /* support for 32bit section numbers */ 1411ce53adfSDenys Vlasenko 1421ce53adfSDenys Vlasenko unsigned int num_sections; /* max_secindex + 1 */ 1431ce53adfSDenys Vlasenko unsigned int secindex_strings; 1441ce53adfSDenys Vlasenko /* if Nth symbol table entry has .st_shndx = SHN_XINDEX, 1451ce53adfSDenys Vlasenko * take shndx from symtab_shndx_start[N] instead */ 1461ce53adfSDenys Vlasenko Elf32_Word *symtab_shndx_start; 1471ce53adfSDenys Vlasenko Elf32_Word *symtab_shndx_stop; 1481da177e4SLinus Torvalds }; 1491da177e4SLinus Torvalds 1501ce53adfSDenys Vlasenko static inline int is_shndx_special(unsigned int i) 1511ce53adfSDenys Vlasenko { 1521ce53adfSDenys Vlasenko return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; 1531ce53adfSDenys Vlasenko } 1541ce53adfSDenys Vlasenko 1556845756bSAnders Kaseorg /* 1566845756bSAnders Kaseorg * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of 1576845756bSAnders Kaseorg * the way to -256..-1, to avoid conflicting with real section 1586845756bSAnders Kaseorg * indices. 1591ce53adfSDenys Vlasenko */ 1606845756bSAnders Kaseorg #define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1)) 1611ce53adfSDenys Vlasenko 1621ce53adfSDenys Vlasenko /* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ 1631ce53adfSDenys Vlasenko static inline unsigned int get_secindex(const struct elf_info *info, 1641ce53adfSDenys Vlasenko const Elf_Sym *sym) 1651ce53adfSDenys Vlasenko { 1666845756bSAnders Kaseorg if (is_shndx_special(sym->st_shndx)) 1676845756bSAnders Kaseorg return SPECIAL(sym->st_shndx); 1681ce53adfSDenys Vlasenko if (sym->st_shndx != SHN_XINDEX) 1691ce53adfSDenys Vlasenko return sym->st_shndx; 1706845756bSAnders Kaseorg return info->symtab_shndx_start[sym - info->symtab_start]; 1711ce53adfSDenys Vlasenko } 1721ce53adfSDenys Vlasenko 173cb80514dSSam Ravnborg /* file2alias.c */ 1744ce6efedSSam Ravnborg extern unsigned int cross_build; 1751da177e4SLinus Torvalds void handle_moddevtable(struct module *mod, struct elf_info *info, 1761da177e4SLinus Torvalds Elf_Sym *sym, const char *symname); 1771da177e4SLinus Torvalds void add_moddevtable(struct buffer *buf, struct module *mod); 1781da177e4SLinus Torvalds 179cb80514dSSam Ravnborg /* sumversion.c */ 1801da177e4SLinus Torvalds void maybe_frob_rcs_version(const char *modfilename, 1811da177e4SLinus Torvalds char *version, 1821da177e4SLinus Torvalds void *modinfo, 1831da177e4SLinus Torvalds unsigned long modinfo_offset); 1841da177e4SLinus Torvalds void get_src_version(const char *modname, char sum[], unsigned sumlen); 1851da177e4SLinus Torvalds 186cb80514dSSam Ravnborg /* from modpost.c */ 1871da177e4SLinus Torvalds void *grab_file(const char *filename, unsigned long *size); 1881da177e4SLinus Torvalds char* get_next_line(unsigned long *pos, void *file, unsigned long size); 1891da177e4SLinus Torvalds void release_file(void *file, unsigned long size); 190cb80514dSSam Ravnborg 191cb80514dSSam Ravnborg void fatal(const char *fmt, ...); 192cb80514dSSam Ravnborg void warn(const char *fmt, ...); 1932a116659SMatthew Wilcox void merror(const char *fmt, ...); 194