162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#include <stdbool.h> 362306a36Sopenharmony_ci#include <stdio.h> 462306a36Sopenharmony_ci#include <stdlib.h> 562306a36Sopenharmony_ci#include <stdarg.h> 662306a36Sopenharmony_ci#include <string.h> 762306a36Sopenharmony_ci#include <sys/types.h> 862306a36Sopenharmony_ci#include <sys/stat.h> 962306a36Sopenharmony_ci#include <sys/mman.h> 1062306a36Sopenharmony_ci#include <fcntl.h> 1162306a36Sopenharmony_ci#include <unistd.h> 1262306a36Sopenharmony_ci#include <elf.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "list.h" 1562306a36Sopenharmony_ci#include "elfconfig.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* On BSD-alike OSes elf.h defines these according to host's word size */ 1862306a36Sopenharmony_ci#undef ELF_ST_BIND 1962306a36Sopenharmony_ci#undef ELF_ST_TYPE 2062306a36Sopenharmony_ci#undef ELF_R_SYM 2162306a36Sopenharmony_ci#undef ELF_R_TYPE 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#if KERNEL_ELFCLASS == ELFCLASS32 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define Elf_Ehdr Elf32_Ehdr 2662306a36Sopenharmony_ci#define Elf_Shdr Elf32_Shdr 2762306a36Sopenharmony_ci#define Elf_Sym Elf32_Sym 2862306a36Sopenharmony_ci#define Elf_Addr Elf32_Addr 2962306a36Sopenharmony_ci#define Elf_Section Elf32_Half 3062306a36Sopenharmony_ci#define ELF_ST_BIND ELF32_ST_BIND 3162306a36Sopenharmony_ci#define ELF_ST_TYPE ELF32_ST_TYPE 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define Elf_Rel Elf32_Rel 3462306a36Sopenharmony_ci#define Elf_Rela Elf32_Rela 3562306a36Sopenharmony_ci#define ELF_R_SYM ELF32_R_SYM 3662306a36Sopenharmony_ci#define ELF_R_TYPE ELF32_R_TYPE 3762306a36Sopenharmony_ci#else 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define Elf_Ehdr Elf64_Ehdr 4062306a36Sopenharmony_ci#define Elf_Shdr Elf64_Shdr 4162306a36Sopenharmony_ci#define Elf_Sym Elf64_Sym 4262306a36Sopenharmony_ci#define Elf_Addr Elf64_Addr 4362306a36Sopenharmony_ci#define Elf_Section Elf64_Half 4462306a36Sopenharmony_ci#define ELF_ST_BIND ELF64_ST_BIND 4562306a36Sopenharmony_ci#define ELF_ST_TYPE ELF64_ST_TYPE 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define Elf_Rel Elf64_Rel 4862306a36Sopenharmony_ci#define Elf_Rela Elf64_Rela 4962306a36Sopenharmony_ci#define ELF_R_SYM ELF64_R_SYM 5062306a36Sopenharmony_ci#define ELF_R_TYPE ELF64_R_TYPE 5162306a36Sopenharmony_ci#endif 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#if KERNEL_ELFDATA != HOST_ELFDATA 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic inline void __endian(const void *src, void *dest, unsigned int size) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci unsigned int i; 5862306a36Sopenharmony_ci for (i = 0; i < size; i++) 5962306a36Sopenharmony_ci ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define TO_NATIVE(x) \ 6362306a36Sopenharmony_ci({ \ 6462306a36Sopenharmony_ci typeof(x) __x; \ 6562306a36Sopenharmony_ci __endian(&(x), &(__x), sizeof(__x)); \ 6662306a36Sopenharmony_ci __x; \ 6762306a36Sopenharmony_ci}) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci#else /* endianness matches */ 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define TO_NATIVE(x) (x) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#endif 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#define NOFAIL(ptr) do_nofail((ptr), #ptr) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_civoid *do_nofail(void *ptr, const char *expr); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistruct buffer { 8262306a36Sopenharmony_ci char *p; 8362306a36Sopenharmony_ci int pos; 8462306a36Sopenharmony_ci int size; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_civoid __attribute__((format(printf, 2, 3))) 8862306a36Sopenharmony_cibuf_printf(struct buffer *buf, const char *fmt, ...); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_civoid 9162306a36Sopenharmony_cibuf_write(struct buffer *buf, const char *s, int len); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistruct module { 9462306a36Sopenharmony_ci struct list_head list; 9562306a36Sopenharmony_ci struct list_head exported_symbols; 9662306a36Sopenharmony_ci struct list_head unresolved_symbols; 9762306a36Sopenharmony_ci bool is_gpl_compatible; 9862306a36Sopenharmony_ci bool from_dump; /* true if module was loaded from *.symvers */ 9962306a36Sopenharmony_ci bool is_vmlinux; 10062306a36Sopenharmony_ci bool seen; 10162306a36Sopenharmony_ci bool has_init; 10262306a36Sopenharmony_ci bool has_cleanup; 10362306a36Sopenharmony_ci struct buffer dev_table_buf; 10462306a36Sopenharmony_ci char srcversion[25]; 10562306a36Sopenharmony_ci // Missing namespace dependencies 10662306a36Sopenharmony_ci struct list_head missing_namespaces; 10762306a36Sopenharmony_ci // Actual imported namespaces 10862306a36Sopenharmony_ci struct list_head imported_namespaces; 10962306a36Sopenharmony_ci char name[]; 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistruct elf_info { 11362306a36Sopenharmony_ci size_t size; 11462306a36Sopenharmony_ci Elf_Ehdr *hdr; 11562306a36Sopenharmony_ci Elf_Shdr *sechdrs; 11662306a36Sopenharmony_ci Elf_Sym *symtab_start; 11762306a36Sopenharmony_ci Elf_Sym *symtab_stop; 11862306a36Sopenharmony_ci unsigned int export_symbol_secndx; /* .export_symbol section */ 11962306a36Sopenharmony_ci char *strtab; 12062306a36Sopenharmony_ci char *modinfo; 12162306a36Sopenharmony_ci unsigned int modinfo_len; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* support for 32bit section numbers */ 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci unsigned int num_sections; /* max_secindex + 1 */ 12662306a36Sopenharmony_ci unsigned int secindex_strings; 12762306a36Sopenharmony_ci /* if Nth symbol table entry has .st_shndx = SHN_XINDEX, 12862306a36Sopenharmony_ci * take shndx from symtab_shndx_start[N] instead */ 12962306a36Sopenharmony_ci Elf32_Word *symtab_shndx_start; 13062306a36Sopenharmony_ci Elf32_Word *symtab_shndx_stop; 13162306a36Sopenharmony_ci}; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ 13462306a36Sopenharmony_cistatic inline unsigned int get_secindex(const struct elf_info *info, 13562306a36Sopenharmony_ci const Elf_Sym *sym) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci unsigned int index = sym->st_shndx; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci /* 14062306a36Sopenharmony_ci * Elf{32,64}_Sym::st_shndx is 2 byte. Big section numbers are available 14162306a36Sopenharmony_ci * in the .symtab_shndx section. 14262306a36Sopenharmony_ci */ 14362306a36Sopenharmony_ci if (index == SHN_XINDEX) 14462306a36Sopenharmony_ci return info->symtab_shndx_start[sym - info->symtab_start]; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* 14762306a36Sopenharmony_ci * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of 14862306a36Sopenharmony_ci * the way to UINT_MAX-255..UINT_MAX, to avoid conflicting with real 14962306a36Sopenharmony_ci * section indices. 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci if (index >= SHN_LORESERVE && index <= SHN_HIRESERVE) 15262306a36Sopenharmony_ci return index - SHN_HIRESERVE - 1; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci return index; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci/* file2alias.c */ 15862306a36Sopenharmony_civoid handle_moddevtable(struct module *mod, struct elf_info *info, 15962306a36Sopenharmony_ci Elf_Sym *sym, const char *symname); 16062306a36Sopenharmony_civoid add_moddevtable(struct buffer *buf, struct module *mod); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/* sumversion.c */ 16362306a36Sopenharmony_civoid get_src_version(const char *modname, char sum[], unsigned sumlen); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/* from modpost.c */ 16662306a36Sopenharmony_cichar *read_text_file(const char *filename); 16762306a36Sopenharmony_cichar *get_line(char **stringp); 16862306a36Sopenharmony_civoid *sym_get_data(const struct elf_info *info, const Elf_Sym *sym); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cienum loglevel { 17162306a36Sopenharmony_ci LOG_WARN, 17262306a36Sopenharmony_ci LOG_ERROR, 17362306a36Sopenharmony_ci LOG_FATAL 17462306a36Sopenharmony_ci}; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_civoid modpost_log(enum loglevel loglevel, const char *fmt, ...); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/* 17962306a36Sopenharmony_ci * warn - show the given message, then let modpost continue running, still 18062306a36Sopenharmony_ci * allowing modpost to exit successfully. This should be used when 18162306a36Sopenharmony_ci * we still allow to generate vmlinux and modules. 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * error - show the given message, then let modpost continue running, but fail 18462306a36Sopenharmony_ci * in the end. This should be used when we should stop building vmlinux 18562306a36Sopenharmony_ci * or modules, but we can continue running modpost to catch as many 18662306a36Sopenharmony_ci * issues as possible. 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * fatal - show the given message, and bail out immediately. This should be 18962306a36Sopenharmony_ci * used when there is no point to continue running modpost. 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args) 19262306a36Sopenharmony_ci#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args) 19362306a36Sopenharmony_ci#define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args) 194