VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

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