#include #include #include #include #include #include #include #include #include #include "elfconfig.h" #if KERNEL_ELFCLASS == ELFCLASS32 #define Elf_Ehdr Elf32_Ehdr #define Elf_Shdr Elf32_Shdr #define Elf_Sym Elf32_Sym #define Elf_Addr Elf32_Addr #define Elf_Section Elf32_Section #define ELF_ST_BIND ELF32_ST_BIND #define ELF_ST_TYPE ELF32_ST_TYPE #define Elf_Rel Elf32_Rel #define Elf_Rela Elf32_Rela #define ELF_R_SYM ELF32_R_SYM #define ELF_R_TYPE ELF32_R_TYPE /* It needs to match sizeof within kernel * as defined in include/linux/module.h */ #define ksym_t uint32_t #define kstr_t uint32_t #define ksym_hash_t uint32_t #else #define Elf_Ehdr Elf64_Ehdr #define Elf_Shdr Elf64_Shdr #define Elf_Sym Elf64_Sym #define Elf_Addr Elf64_Addr #define Elf_Section Elf64_Section #define ELF_ST_BIND ELF64_ST_BIND #define ELF_ST_TYPE ELF64_ST_TYPE #define Elf_Rel Elf64_Rel #define Elf_Rela Elf64_Rela #define ELF_R_SYM ELF64_R_SYM #define ELF_R_TYPE ELF64_R_TYPE /* It needs to match sizeof within kernel * as defined in include/linux/module.h */ #define ksym_t uint64_t #define kstr_t uint64_t #define ksym_hash_t uint64_t #endif /* The 64-bit MIPS ELF ABI uses an unusual reloc format. */ typedef struct { Elf32_Word r_sym; /* Symbol index */ unsigned char r_ssym; /* Special symbol for 2nd relocation */ unsigned char r_type3; /* 3rd relocation type */ unsigned char r_type2; /* 2nd relocation type */ unsigned char r_type1; /* 1st relocation type */ } _Elf64_Mips_R_Info; typedef union { Elf64_Xword r_info_number; _Elf64_Mips_R_Info r_info_fields; } _Elf64_Mips_R_Info_union; #define ELF64_MIPS_R_SYM(i) \ ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) #define ELF64_MIPS_R_TYPE(i) \ ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1) #if KERNEL_ELFDATA != HOST_ELFDATA static inline void __endian(const void *src, void *dest, unsigned int size) { unsigned int i; for (i = 0; i < size; i++) ((unsigned char *)dest)[i] = ((unsigned char *)src)[size - i - 1]; } #define TO_NATIVE(x) \ ({ \ typeof(x) __x; \ __endian(&(x), &(__x), sizeof(__x)); \ __x; \ }) #else /* endianness matches */ #define TO_NATIVE(x) (x) #endif #define GET_KSTRING(__ksym, __offset) (unsigned char *)(__ksym->name + __offset) /* We have no more than 5 kernel symbol tables __ksymtab __ksymtab_gpl __ksymtab_unused __ksymtab_unused_gpl __ksymtab_gpl_future */ enum ksymtab_type { KSYMTAB = 0, KSYMTAB_GPL, KSYMTAB_UNUSED, KSYMTAB_UNUSED_GPL, KSYMTAB_GPL_FUTURE, KSYMTAB_ALL, }; /* * This maps the ELF hash table * The entries in the .hash table always have a size of 32 bits. */ struct elf_htable { uint32_t nbucket; uint32_t nchain; uint32_t *elf_buckets; uint32_t *chains; }; /* as defined in include/linux/module.h */ struct kernel_symbol { ksym_t value; kstr_t name; ksym_hash_t hash_value; }; struct kernel_symtab { const char *name; struct kernel_symbol *start; struct kernel_symbol *stop; Elf_Section sec; }; struct elf_info { unsigned long size; Elf_Ehdr *hdr; Elf_Shdr *sechdrs; Elf_Sym *symtab_start; Elf_Sym *symtab_stop; long kstr_offset; unsigned long base_addr; struct { ksym_hash_t *start; ksym_hash_t *stop; } undef_hash; struct kernel_symtab ksym_tables[KSYMTAB_ALL]; Elf_Section markers_strings_sec; const char *strtab; const char *kstrings; char *modinfo; unsigned int modinfo_len; }; /* from elflib.c */ void fatal(const char *fmt, ...); void warn(const char *fmt, ...); void merror(const char *fmt, ...); ksym_hash_t gnu_hash(const unsigned char *name); void *grab_file(const char *filename, unsigned long *size); void release_file(void *file, unsigned long size); int parse_elf(struct elf_info *info, const char *filename); int parse_writable_elf(struct elf_info *info, const char *filename); void parse_elf_finish(struct elf_info *info);