1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
258e01fcaSMasahiro Yamada #include <stdbool.h>
31da177e4SLinus Torvalds #include <stdio.h>
41da177e4SLinus Torvalds #include <stdlib.h>
51da177e4SLinus Torvalds #include <stdarg.h>
61da177e4SLinus Torvalds #include <string.h>
71da177e4SLinus Torvalds #include <sys/types.h>
81da177e4SLinus Torvalds #include <sys/stat.h>
91da177e4SLinus Torvalds #include <sys/mman.h>
101da177e4SLinus Torvalds #include <fcntl.h>
111da177e4SLinus Torvalds #include <unistd.h>
121da177e4SLinus Torvalds #include <elf.h>
13*2bc92c61SJack Brennen #include "../../include/linux/module_symbol.h"
141da177e4SLinus Torvalds
15325eba05SMasahiro Yamada #include "list.h"
161da177e4SLinus Torvalds #include "elfconfig.h"
171da177e4SLinus Torvalds
183c0561e0SPavel Fedin /* On BSD-alike OSes elf.h defines these according to host's word size */
193c0561e0SPavel Fedin #undef ELF_ST_BIND
203c0561e0SPavel Fedin #undef ELF_ST_TYPE
213c0561e0SPavel Fedin #undef ELF_R_SYM
223c0561e0SPavel Fedin #undef ELF_R_TYPE
233c0561e0SPavel Fedin
241da177e4SLinus Torvalds #if KERNEL_ELFCLASS == ELFCLASS32
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds #define Elf_Ehdr Elf32_Ehdr
271da177e4SLinus Torvalds #define Elf_Shdr Elf32_Shdr
281da177e4SLinus Torvalds #define Elf_Sym Elf32_Sym
29b39927cfSSam Ravnborg #define Elf_Addr Elf32_Addr
304f4c4ee1SSam Ravnborg #define Elf_Section Elf32_Half
311da177e4SLinus Torvalds #define ELF_ST_BIND ELF32_ST_BIND
321da177e4SLinus Torvalds #define ELF_ST_TYPE ELF32_ST_TYPE
331da177e4SLinus Torvalds
342c1a51f3SAtsushi Nemoto #define Elf_Rel Elf32_Rel
35b39927cfSSam Ravnborg #define Elf_Rela Elf32_Rela
36b39927cfSSam Ravnborg #define ELF_R_SYM ELF32_R_SYM
37b39927cfSSam Ravnborg #define ELF_R_TYPE ELF32_R_TYPE
381da177e4SLinus Torvalds #else
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds #define Elf_Ehdr Elf64_Ehdr
411da177e4SLinus Torvalds #define Elf_Shdr Elf64_Shdr
421da177e4SLinus Torvalds #define Elf_Sym Elf64_Sym
43b39927cfSSam Ravnborg #define Elf_Addr Elf64_Addr
444f4c4ee1SSam Ravnborg #define Elf_Section Elf64_Half
451da177e4SLinus Torvalds #define ELF_ST_BIND ELF64_ST_BIND
461da177e4SLinus Torvalds #define ELF_ST_TYPE ELF64_ST_TYPE
471da177e4SLinus Torvalds
482c1a51f3SAtsushi Nemoto #define Elf_Rel Elf64_Rel
49b39927cfSSam Ravnborg #define Elf_Rela Elf64_Rela
50b39927cfSSam Ravnborg #define ELF_R_SYM ELF64_R_SYM
51b39927cfSSam Ravnborg #define ELF_R_TYPE ELF64_R_TYPE
521da177e4SLinus Torvalds #endif
531da177e4SLinus Torvalds
541da177e4SLinus Torvalds #if KERNEL_ELFDATA != HOST_ELFDATA
551da177e4SLinus Torvalds
__endian(const void * src,void * dest,unsigned int size)561da177e4SLinus Torvalds static inline void __endian(const void *src, void *dest, unsigned int size)
571da177e4SLinus Torvalds {
581da177e4SLinus Torvalds unsigned int i;
591da177e4SLinus Torvalds for (i = 0; i < size; i++)
601da177e4SLinus Torvalds ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1];
611da177e4SLinus Torvalds }
621da177e4SLinus Torvalds
631da177e4SLinus Torvalds #define TO_NATIVE(x) \
641da177e4SLinus Torvalds ({ \
651da177e4SLinus Torvalds typeof(x) __x; \
661da177e4SLinus Torvalds __endian(&(x), &(__x), sizeof(__x)); \
671da177e4SLinus Torvalds __x; \
681da177e4SLinus Torvalds })
691da177e4SLinus Torvalds
701da177e4SLinus Torvalds #else /* endianness matches */
711da177e4SLinus Torvalds
721da177e4SLinus Torvalds #define TO_NATIVE(x) (x)
731da177e4SLinus Torvalds
741da177e4SLinus Torvalds #endif
751da177e4SLinus Torvalds
761da177e4SLinus Torvalds #define NOFAIL(ptr) do_nofail((ptr), #ptr)
77c5c468dcSMasahiro Yamada
78c5c468dcSMasahiro Yamada #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
79c5c468dcSMasahiro Yamada
801da177e4SLinus Torvalds void *do_nofail(void *ptr, const char *expr);
811da177e4SLinus Torvalds
821da177e4SLinus Torvalds struct buffer {
831da177e4SLinus Torvalds char *p;
841da177e4SLinus Torvalds int pos;
851da177e4SLinus Torvalds int size;
861da177e4SLinus Torvalds };
871da177e4SLinus Torvalds
881da177e4SLinus Torvalds void __attribute__((format(printf, 2, 3)))
891da177e4SLinus Torvalds buf_printf(struct buffer *buf, const char *fmt, ...);
901da177e4SLinus Torvalds
911da177e4SLinus Torvalds void
921da177e4SLinus Torvalds buf_write(struct buffer *buf, const char *s, int len);
931da177e4SLinus Torvalds
941da177e4SLinus Torvalds struct module {
95325eba05SMasahiro Yamada struct list_head list;
96f841536eSMasahiro Yamada struct list_head exported_symbols;
978a69152bSMasahiro Yamada struct list_head unresolved_symbols;
985066743eSMasahiro Yamada bool is_gpl_compatible;
9958e01fcaSMasahiro Yamada bool from_dump; /* true if module was loaded from *.symvers */
10058e01fcaSMasahiro Yamada bool is_vmlinux;
10158e01fcaSMasahiro Yamada bool seen;
10258e01fcaSMasahiro Yamada bool has_init;
10358e01fcaSMasahiro Yamada bool has_cleanup;
1041da177e4SLinus Torvalds struct buffer dev_table_buf;
1051da177e4SLinus Torvalds char srcversion[25];
106bbc55bdeSMasahiro Yamada // Missing namespace dependencies
107ab489d60SMasahiro Yamada struct list_head missing_namespaces;
108cb9b55d2SMatthias Maennich // Actual imported namespaces
109ab489d60SMasahiro Yamada struct list_head imported_namespaces;
110a82f794cSMasahiro Yamada char name[];
1111da177e4SLinus Torvalds };
1121da177e4SLinus Torvalds
1131da177e4SLinus Torvalds struct elf_info {
1143b09efc4SMasahiro Yamada size_t size;
1151da177e4SLinus Torvalds Elf_Ehdr *hdr;
1161da177e4SLinus Torvalds Elf_Shdr *sechdrs;
1171da177e4SLinus Torvalds Elf_Sym *symtab_start;
1181da177e4SLinus Torvalds Elf_Sym *symtab_stop;
119ddb5cdbaSMasahiro Yamada unsigned int export_symbol_secndx; /* .export_symbol section */
1207d02b490SAndi Kleen char *strtab;
1211da177e4SLinus Torvalds char *modinfo;
1221da177e4SLinus Torvalds unsigned int modinfo_len;
1231ce53adfSDenys Vlasenko
1241ce53adfSDenys Vlasenko /* support for 32bit section numbers */
1251ce53adfSDenys Vlasenko
1261ce53adfSDenys Vlasenko unsigned int num_sections; /* max_secindex + 1 */
1271ce53adfSDenys Vlasenko unsigned int secindex_strings;
1281ce53adfSDenys Vlasenko /* if Nth symbol table entry has .st_shndx = SHN_XINDEX,
1291ce53adfSDenys Vlasenko * take shndx from symtab_shndx_start[N] instead */
1301ce53adfSDenys Vlasenko Elf32_Word *symtab_shndx_start;
1311ce53adfSDenys Vlasenko Elf32_Word *symtab_shndx_stop;
132*2bc92c61SJack Brennen
133*2bc92c61SJack Brennen struct symsearch *symsearch;
1341da177e4SLinus Torvalds };
1351da177e4SLinus Torvalds
1361ce53adfSDenys Vlasenko /* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
get_secindex(const struct elf_info * info,const Elf_Sym * sym)1371ce53adfSDenys Vlasenko static inline unsigned int get_secindex(const struct elf_info *info,
1381ce53adfSDenys Vlasenko const Elf_Sym *sym)
1391ce53adfSDenys Vlasenko {
14036b0f0deSMasahiro Yamada unsigned int index = sym->st_shndx;
14136b0f0deSMasahiro Yamada
14236b0f0deSMasahiro Yamada /*
14336b0f0deSMasahiro Yamada * Elf{32,64}_Sym::st_shndx is 2 byte. Big section numbers are available
14436b0f0deSMasahiro Yamada * in the .symtab_shndx section.
14536b0f0deSMasahiro Yamada */
14636b0f0deSMasahiro Yamada if (index == SHN_XINDEX)
1476845756bSAnders Kaseorg return info->symtab_shndx_start[sym - info->symtab_start];
14836b0f0deSMasahiro Yamada
14936b0f0deSMasahiro Yamada /*
15036b0f0deSMasahiro Yamada * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
15136b0f0deSMasahiro Yamada * the way to UINT_MAX-255..UINT_MAX, to avoid conflicting with real
15236b0f0deSMasahiro Yamada * section indices.
15336b0f0deSMasahiro Yamada */
15436b0f0deSMasahiro Yamada if (index >= SHN_LORESERVE && index <= SHN_HIRESERVE)
15536b0f0deSMasahiro Yamada return index - SHN_HIRESERVE - 1;
15636b0f0deSMasahiro Yamada
15736b0f0deSMasahiro Yamada return index;
1581ce53adfSDenys Vlasenko }
1591ce53adfSDenys Vlasenko
160*2bc92c61SJack Brennen /*
161*2bc92c61SJack Brennen * If there's no name there, ignore it; likewise, ignore it if it's
162*2bc92c61SJack Brennen * one of the magic symbols emitted used by current tools.
163*2bc92c61SJack Brennen *
164*2bc92c61SJack Brennen * Internal symbols created by tools should be ignored by modpost.
165*2bc92c61SJack Brennen */
is_valid_name(struct elf_info * elf,Elf_Sym * sym)166*2bc92c61SJack Brennen static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
167*2bc92c61SJack Brennen {
168*2bc92c61SJack Brennen const char *name = elf->strtab + sym->st_name;
169*2bc92c61SJack Brennen
170*2bc92c61SJack Brennen if (!name || !strlen(name))
171*2bc92c61SJack Brennen return 0;
172*2bc92c61SJack Brennen return !is_mapping_symbol(name);
173*2bc92c61SJack Brennen }
174*2bc92c61SJack Brennen
175*2bc92c61SJack Brennen /* symsearch.c */
176*2bc92c61SJack Brennen void symsearch_init(struct elf_info *elf);
177*2bc92c61SJack Brennen void symsearch_finish(struct elf_info *elf);
178*2bc92c61SJack Brennen Elf_Sym *symsearch_find_nearest(struct elf_info *elf, Elf_Addr addr,
179*2bc92c61SJack Brennen unsigned int secndx, bool allow_negative,
180*2bc92c61SJack Brennen Elf_Addr min_distance);
181*2bc92c61SJack Brennen
182cb80514dSSam Ravnborg /* file2alias.c */
1831da177e4SLinus Torvalds void handle_moddevtable(struct module *mod, struct elf_info *info,
1841da177e4SLinus Torvalds Elf_Sym *sym, const char *symname);
1851da177e4SLinus Torvalds void add_moddevtable(struct buffer *buf, struct module *mod);
1861da177e4SLinus Torvalds
187cb80514dSSam Ravnborg /* sumversion.c */
1881da177e4SLinus Torvalds void get_src_version(const char *modname, char sum[], unsigned sumlen);
1891da177e4SLinus Torvalds
190cb80514dSSam Ravnborg /* from modpost.c */
191ac5100f5SMasahiro Yamada char *read_text_file(const char *filename);
192ac5100f5SMasahiro Yamada char *get_line(char **stringp);
193abe864b8SMasahiro Yamada void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym);
194cb80514dSSam Ravnborg
19593c95e52SJessica Yu enum loglevel {
19693c95e52SJessica Yu LOG_WARN,
19793c95e52SJessica Yu LOG_ERROR,
19893c95e52SJessica Yu LOG_FATAL
19993c95e52SJessica Yu };
20093c95e52SJessica Yu
20193c95e52SJessica Yu void modpost_log(enum loglevel loglevel, const char *fmt, ...);
20293c95e52SJessica Yu
2030fd3fbadSMasahiro Yamada /*
2040fd3fbadSMasahiro Yamada * warn - show the given message, then let modpost continue running, still
2050fd3fbadSMasahiro Yamada * allowing modpost to exit successfully. This should be used when
2060fd3fbadSMasahiro Yamada * we still allow to generate vmlinux and modules.
2070fd3fbadSMasahiro Yamada *
2080fd3fbadSMasahiro Yamada * error - show the given message, then let modpost continue running, but fail
2090fd3fbadSMasahiro Yamada * in the end. This should be used when we should stop building vmlinux
2100fd3fbadSMasahiro Yamada * or modules, but we can continue running modpost to catch as many
2110fd3fbadSMasahiro Yamada * issues as possible.
2120fd3fbadSMasahiro Yamada *
2130fd3fbadSMasahiro Yamada * fatal - show the given message, and bail out immediately. This should be
2140fd3fbadSMasahiro Yamada * used when there is no point to continue running modpost.
2150fd3fbadSMasahiro Yamada */
21693c95e52SJessica Yu #define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
217bc72d723SMasahiro Yamada #define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
21893c95e52SJessica Yu #define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args)
219