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