Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /* Generate assembler source containing symbol information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright 2002       by Kai Germaschewski
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * This software may be used and distributed according to the terms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * of the GNU General Public License, incorporated herein by reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Usage: nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *      Table compression uses all the unused char codes on the symbols and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *  maps these to the most used substrings (tokens). For instance, it might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *  map char code 0xF7 to represent "write_" and then in every symbol where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *  "write_" appears it can be replaced by 0xF7, saving 5 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *      The used codes themselves are also placed in the table so that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *  decompresion can work without "special cases".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *      Applied to kernel symbols, this usually produces a compression ratio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *  of about 50%.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define KSYM_NAME_LEN		128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) struct sym_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	unsigned long long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	unsigned int start_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	unsigned int percpu_absolute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	unsigned char sym[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) struct addr_range {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	const char *start_sym, *end_sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	unsigned long long start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static unsigned long long _text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static unsigned long long relative_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) static struct addr_range text_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	{ "_stext",     "_etext"     },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	{ "_sinittext", "_einittext" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define text_range_text     (&text_ranges[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define text_range_inittext (&text_ranges[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) static struct addr_range percpu_range = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	"__per_cpu_start", "__per_cpu_end", -1ULL, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) static struct sym_entry **table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static unsigned int table_size, table_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) static int all_symbols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) static int absolute_percpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static int base_relative;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static int token_profit[0x10000];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) /* the table that holds the result of the compression */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) static unsigned char best_table[256][2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) static unsigned char best_table_len[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) static void usage(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	fprintf(stderr, "Usage: kallsyms [--all-symbols] "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			"[--base-relative] < in.map > out.S\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) static char *sym_name(const struct sym_entry *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	return (char *)s->sym + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) static bool is_ignored_symbol(const char *name, char type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	/* Symbol names that exactly match to the following are ignored.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	static const char * const ignored_symbols[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		 * Symbols which vary between passes. Passes 1 and 2 must have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		 * identical symbol lists. The kallsyms_* symbols below are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		 * only added after pass 1, they would be included in pass 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		 * when --all-symbols is specified so exclude them to get a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		 * stable symbol list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		"kallsyms_addresses",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		"kallsyms_offsets",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		"kallsyms_relative_base",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		"kallsyms_num_syms",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		"kallsyms_names",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		"kallsyms_markers",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		"kallsyms_token_table",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		"kallsyms_token_index",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		/* Exclude linker generated symbols which vary between passes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		"_SDA_BASE_",		/* ppc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		"_SDA2_BASE_",		/* ppc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	/* Symbol names that begin with the following are ignored.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	static const char * const ignored_prefixes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		"$",			/* local symbols for ARM, MIPS, etc. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		".LASANPC",		/* s390 kasan local symbols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		"__crc_",		/* modversions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		"__efistub_",		/* arm64 EFI stub namespace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		"__kvm_nvhe_",		/* arm64 non-VHE KVM namespace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		"__AArch64ADRPThunk_",	/* arm64 lld */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		"__ARMV5PILongThunk_",	/* arm lld */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		"__ARMV7PILongThunk_",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		"__ThumbV7PILongThunk_",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		"__LA25Thunk_",		/* mips lld */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		"__microLA25Thunk_",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	/* Symbol names that end with the following are ignored.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	static const char * const ignored_suffixes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		"_from_arm",		/* arm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		"_from_thumb",		/* arm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		"_veneer",		/* arm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	/* Symbol names that contain the following are ignored.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	static const char * const ignored_matches[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		".long_branch.",	/* ppc stub */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		".plt_branch.",		/* ppc stub */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	const char * const *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	for (p = ignored_symbols; *p; p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		if (!strcmp(name, *p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	for (p = ignored_prefixes; *p; p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		if (!strncmp(name, *p, strlen(*p)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	for (p = ignored_suffixes; *p; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		int l = strlen(name) - strlen(*p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		if (l >= 0 && !strcmp(name + l, *p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 			return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	for (p = ignored_matches; *p; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		if (strstr(name, *p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	if (type == 'U' || type == 'u')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	/* exclude debugging symbols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	if (type == 'N' || type == 'n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	if (toupper(type) == 'A') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		/* Keep these useful absolute symbols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		if (strcmp(name, "__kernel_syscall_via_break") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		    strcmp(name, "__kernel_syscall_via_epc") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		    strcmp(name, "__kernel_sigtramp") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		    strcmp(name, "__gp"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static void check_symbol_range(const char *sym, unsigned long long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			       struct addr_range *ranges, int entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	struct addr_range *ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	for (i = 0; i < entries; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		ar = &ranges[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		if (strcmp(sym, ar->start_sym) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			ar->start = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		} else if (strcmp(sym, ar->end_sym) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 			ar->end = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static struct sym_entry *read_symbol(FILE *in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	char name[500], type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	unsigned long long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	struct sym_entry *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	rc = fscanf(in, "%llx %c %499s\n", &addr, &type, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	if (rc != 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		if (rc != EOF && fgets(name, 500, in) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			fprintf(stderr, "Read error or end of file.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	if (strlen(name) >= KSYM_NAME_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		fprintf(stderr, "Symbol %s too long for kallsyms (%zu >= %d).\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 				"Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			name, strlen(name), KSYM_NAME_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	if (strcmp(name, "_text") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		_text = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	/* Ignore most absolute/undefined (?) symbols. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	if (is_ignored_symbol(name, type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	check_symbol_range(name, addr, text_ranges, ARRAY_SIZE(text_ranges));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	check_symbol_range(name, addr, &percpu_range, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	/* include the type field in the symbol name, so that it gets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	 * compressed together */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	len = strlen(name) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	sym = malloc(sizeof(*sym) + len + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	if (!sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		fprintf(stderr, "kallsyms failure: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			"unable to allocate required amount of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	sym->addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	sym->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	sym->sym[0] = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	strcpy(sym_name(sym), name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	sym->percpu_absolute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	return sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static int symbol_in_range(const struct sym_entry *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 			   const struct addr_range *ranges, int entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	const struct addr_range *ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	for (i = 0; i < entries; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		ar = &ranges[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		if (s->addr >= ar->start && s->addr <= ar->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int symbol_valid(const struct sym_entry *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	const char *name = sym_name(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	/* if --all-symbols is not specified, then symbols outside the text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	 * and inittext sections are discarded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	if (!all_symbols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		if (symbol_in_range(s, text_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 				    ARRAY_SIZE(text_ranges)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		/* Corner case.  Discard any symbols with the same value as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		 * _etext _einittext; they can move between pass 1 and 2 when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		 * the kallsyms data are added.  If these symbols move then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		 * they may get dropped in pass 2, which breaks the kallsyms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		 * rules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		if ((s->addr == text_range_text->end &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		     strcmp(name, text_range_text->end_sym)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		    (s->addr == text_range_inittext->end &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		     strcmp(name, text_range_inittext->end_sym)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* remove all the invalid symbols from the table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static void shrink_table(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	unsigned int i, pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	for (i = 0; i < table_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		if (symbol_valid(table[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 			if (pos != i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 				table[pos] = table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 			pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 			free(table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	table_cnt = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	/* When valid symbol is not registered, exit to error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	if (!table_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		fprintf(stderr, "No valid symbol.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static void read_map(FILE *in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	struct sym_entry *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	while (!feof(in)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		sym = read_symbol(in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		if (!sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		sym->start_pos = table_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		if (table_cnt >= table_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 			table_size += 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 			table = realloc(table, sizeof(*table) * table_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 			if (!table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 				fprintf(stderr, "out of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 				exit (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		table[table_cnt++] = sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static void output_label(const char *label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	printf(".globl %s\n", label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	printf("\tALGN\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	printf("%s:\n", label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* Provide proper symbols relocatability by their '_text' relativeness. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static void output_address(unsigned long long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	if (_text <= addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		printf("\tPTR\t_text + %#llx\n", addr - _text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		printf("\tPTR\t_text - %#llx\n", _text - addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* uncompress a compressed symbol. When this function is called, the best table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)  * might still be compressed itself, so the function needs to be recursive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static int expand_symbol(const unsigned char *data, int len, char *result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	int c, rlen, total=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	while (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		c = *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		/* if the table holds a single char that is the same as the one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		 * we are looking for, then end the search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		if (best_table[c][0]==c && best_table_len[c]==1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			*result++ = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 			total++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			/* if not, recurse and expand */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			rlen = expand_symbol(best_table[c], best_table_len[c], result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			total += rlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 			result += rlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		data++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	*result=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int symbol_absolute(const struct sym_entry *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	return s->percpu_absolute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static void write_src(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	unsigned int i, k, off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	unsigned int best_idx[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	unsigned int *markers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	char buf[KSYM_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	printf("#include <asm/bitsperlong.h>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	printf("#if BITS_PER_LONG == 64\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	printf("#define PTR .quad\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	printf("#define ALGN .balign 8\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	printf("#else\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	printf("#define PTR .long\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	printf("#define ALGN .balign 4\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	printf("#endif\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	printf("\t.section .rodata, \"a\"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	if (!base_relative)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		output_label("kallsyms_addresses");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		output_label("kallsyms_offsets");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	for (i = 0; i < table_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		if (base_relative) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			 * Use the offset relative to the lowest value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 			 * encountered of all relative symbols, and emit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			 * non-relocatable fixed offsets that will be fixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 			 * up at runtime.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			long long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 			int overflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			if (!absolute_percpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 				offset = table[i]->addr - relative_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 				overflow = (offset < 0 || offset > UINT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 			} else if (symbol_absolute(table[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 				offset = table[i]->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 				overflow = (offset < 0 || offset > INT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 				offset = relative_base - table[i]->addr - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 				overflow = (offset < INT_MIN || offset >= 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 			if (overflow) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 				fprintf(stderr, "kallsyms failure: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 					"%s symbol value %#llx out of range in relative mode\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 					symbol_absolute(table[i]) ? "absolute" : "relative",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 					table[i]->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 				exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 			printf("\t.long\t%#x\n", (int)offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		} else if (!symbol_absolute(table[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 			output_address(table[i]->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 			printf("\tPTR\t%#llx\n", table[i]->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	if (base_relative) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		output_label("kallsyms_relative_base");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		output_address(relative_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	output_label("kallsyms_num_syms");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	printf("\t.long\t%u\n", table_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	/* table of offset markers, that give the offset in the compressed stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	 * every 256 symbols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	markers = malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	if (!markers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		fprintf(stderr, "kallsyms failure: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 			"unable to allocate required memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	output_label("kallsyms_names");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	for (i = 0; i < table_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		if ((i & 0xFF) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 			markers[i >> 8] = off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		printf("\t.byte 0x%02x", table[i]->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		for (k = 0; k < table[i]->len; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 			printf(", 0x%02x", table[i]->sym[k]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		off += table[i]->len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	output_label("kallsyms_markers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	for (i = 0; i < ((table_cnt + 255) >> 8); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		printf("\t.long\t%u\n", markers[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	free(markers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	output_label("kallsyms_token_table");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	for (i = 0; i < 256; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		best_idx[i] = off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		expand_symbol(best_table[i], best_table_len[i], buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		printf("\t.asciz\t\"%s\"\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		off += strlen(buf) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	output_label("kallsyms_token_index");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	for (i = 0; i < 256; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		printf("\t.short\t%d\n", best_idx[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* table lookup compression functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* count all the possible tokens in a symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static void learn_symbol(const unsigned char *symbol, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	for (i = 0; i < len - 1; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* decrease the count for all the possible tokens in a symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static void forget_symbol(const unsigned char *symbol, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	for (i = 0; i < len - 1; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /* do the initial token count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static void build_initial_tok_table(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	for (i = 0; i < table_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 		learn_symbol(table[i]->sym, table[i]->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static unsigned char *find_token(unsigned char *str, int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 				 const unsigned char *token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	for (i = 0; i < len - 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		if (str[i] == token[0] && str[i+1] == token[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 			return &str[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* replace a given token in all the valid symbols. Use the sampled symbols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)  * to update the counts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static void compress_symbols(const unsigned char *str, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	unsigned int i, len, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	unsigned char *p1, *p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	for (i = 0; i < table_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		len = table[i]->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		p1 = table[i]->sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		/* find the token on the symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		p2 = find_token(p1, len, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		if (!p2) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		/* decrease the counts for this symbol's tokens */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 		forget_symbol(table[i]->sym, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		size = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 			*p2 = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 			p2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 			size -= (p2 - p1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 			memmove(p2, p2 + 1, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 			p1 = p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 			len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 			if (size < 2) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 			/* find the token on the symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 			p2 = find_token(p1, size, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 		} while (p2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		table[i]->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 		/* increase the counts for this symbol's new tokens */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 		learn_symbol(table[i]->sym, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* search the token with the maximum profit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static int find_best_token(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	int i, best, bestprofit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	bestprofit=-10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	best = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	for (i = 0; i < 0x10000; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		if (token_profit[i] > bestprofit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 			best = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			bestprofit = token_profit[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	return best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* this is the core of the algorithm: calculate the "best" table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static void optimize_result(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	int i, best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	/* using the '\0' symbol last allows compress_symbols to use standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	 * fast string functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	for (i = 255; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		/* if this table slot is empty (it is not used by an actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		 * original char code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		if (!best_table_len[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 			/* find the token with the best profit value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 			best = find_best_token();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 			if (token_profit[best] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 			/* place it in the "best" table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 			best_table_len[i] = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 			best_table[i][0] = best & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 			best_table[i][1] = (best >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 			/* replace this token in all the valid symbols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 			compress_symbols(best_table[i], i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* start by placing the symbols that are actually used on the table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static void insert_real_symbols_in_table(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	unsigned int i, j, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	for (i = 0; i < table_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		for (j = 0; j < table[i]->len; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 			c = table[i]->sym[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 			best_table[c][0]=c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 			best_table_len[c]=1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static void optimize_token_table(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	build_initial_tok_table();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	insert_real_symbols_in_table();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	optimize_result();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* guess for "linker script provide" symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static int may_be_linker_script_provide_symbol(const struct sym_entry *se)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	const char *symbol = sym_name(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	int len = se->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	if (len < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	if (symbol[0] != '_' || symbol[1] != '_')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	/* __start_XXXXX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	if (!memcmp(symbol + 2, "start_", 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	/* __stop_XXXXX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	if (!memcmp(symbol + 2, "stop_", 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	/* __end_XXXXX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	if (!memcmp(symbol + 2, "end_", 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	/* __XXXXX_start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	if (!memcmp(symbol + len - 6, "_start", 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	/* __XXXXX_end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	if (!memcmp(symbol + len - 4, "_end", 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) static int compare_symbols(const void *a, const void *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	const struct sym_entry *sa = *(const struct sym_entry **)a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	const struct sym_entry *sb = *(const struct sym_entry **)b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	int wa, wb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	/* sort by address first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	if (sa->addr > sb->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	if (sa->addr < sb->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	/* sort by "weakness" type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	wa = (sa->sym[0] == 'w') || (sa->sym[0] == 'W');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	wb = (sb->sym[0] == 'w') || (sb->sym[0] == 'W');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	if (wa != wb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 		return wa - wb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	/* sort by "linker script provide" type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	wa = may_be_linker_script_provide_symbol(sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	wb = may_be_linker_script_provide_symbol(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	if (wa != wb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 		return wa - wb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	/* sort by the number of prefix underscores */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	wa = strspn(sym_name(sa), "_");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	wb = strspn(sym_name(sb), "_");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	if (wa != wb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 		return wa - wb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	/* sort by initial order, so that other symbols are left undisturbed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	return sa->start_pos - sb->start_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static void sort_symbols(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	qsort(table, table_cnt, sizeof(table[0]), compare_symbols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static void make_percpus_absolute(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	for (i = 0; i < table_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 		if (symbol_in_range(table[i], &percpu_range, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 			 * Keep the 'A' override for percpu symbols to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 			 * ensure consistent behavior compared to older
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 			 * versions of this tool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 			table[i]->sym[0] = 'A';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 			table[i]->percpu_absolute = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* find the minimum non-absolute symbol address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static void record_relative_base(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	for (i = 0; i < table_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 		if (!symbol_absolute(table[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 			 * The table is sorted by address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 			 * Take the first non-absolute symbol value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 			relative_base = table[i]->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	if (argc >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 		for (i = 1; i < argc; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 			if(strcmp(argv[i], "--all-symbols") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 				all_symbols = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 			else if (strcmp(argv[i], "--absolute-percpu") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 				absolute_percpu = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 			else if (strcmp(argv[i], "--base-relative") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 				base_relative = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 				usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 	} else if (argc != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 		usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 	read_map(stdin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 	shrink_table();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 	if (absolute_percpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 		make_percpus_absolute();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 	sort_symbols();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 	if (base_relative)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 		record_relative_base();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 	optimize_token_table();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	write_src();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }