|
@@ -22,6 +22,7 @@
|
|
|
#include <stdlib.h>
|
|
|
#include <string.h>
|
|
|
#include <ctype.h>
|
|
|
+#include <limits.h>
|
|
|
|
|
|
#ifndef ARRAY_SIZE
|
|
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
|
@@ -43,6 +44,7 @@ struct addr_range {
|
|
|
};
|
|
|
|
|
|
static unsigned long long _text;
|
|
|
+static unsigned long long relative_base;
|
|
|
static struct addr_range text_ranges[] = {
|
|
|
{ "_stext", "_etext" },
|
|
|
{ "_sinittext", "_einittext" },
|
|
@@ -62,6 +64,7 @@ static int all_symbols = 0;
|
|
|
static int absolute_percpu = 0;
|
|
|
static char symbol_prefix_char = '\0';
|
|
|
static unsigned long long kernel_start_addr = 0;
|
|
|
+static int base_relative = 0;
|
|
|
|
|
|
int token_profit[0x10000];
|
|
|
|
|
@@ -75,7 +78,7 @@ static void usage(void)
|
|
|
fprintf(stderr, "Usage: kallsyms [--all-symbols] "
|
|
|
"[--symbol-prefix=<prefix char>] "
|
|
|
"[--page-offset=<CONFIG_PAGE_OFFSET>] "
|
|
|
- "< in.map > out.S\n");
|
|
|
+ "[--base-relative] < in.map > out.S\n");
|
|
|
exit(1);
|
|
|
}
|
|
|
|
|
@@ -205,6 +208,8 @@ static int symbol_valid(struct sym_entry *s)
|
|
|
*/
|
|
|
static char *special_symbols[] = {
|
|
|
"kallsyms_addresses",
|
|
|
+ "kallsyms_offsets",
|
|
|
+ "kallsyms_relative_base",
|
|
|
"kallsyms_num_syms",
|
|
|
"kallsyms_names",
|
|
|
"kallsyms_markers",
|
|
@@ -349,16 +354,48 @@ static void write_src(void)
|
|
|
|
|
|
printf("\t.section .rodata, \"a\"\n");
|
|
|
|
|
|
- /* Provide proper symbols relocatability by their '_text'
|
|
|
- * relativeness. The symbol names cannot be used to construct
|
|
|
- * normal symbol references as the list of symbols contains
|
|
|
- * symbols that are declared static and are private to their
|
|
|
- * .o files. This prevents .tmp_kallsyms.o or any other
|
|
|
- * object from referencing them.
|
|
|
+ /* Provide proper symbols relocatability by their relativeness
|
|
|
+ * to a fixed anchor point in the runtime image, either '_text'
|
|
|
+ * for absolute address tables, in which case the linker will
|
|
|
+ * emit the final addresses at build time. Otherwise, use the
|
|
|
+ * offset relative to the lowest value encountered of all relative
|
|
|
+ * symbols, and emit non-relocatable fixed offsets that will be fixed
|
|
|
+ * up at runtime.
|
|
|
+ *
|
|
|
+ * The symbol names cannot be used to construct normal symbol
|
|
|
+ * references as the list of symbols contains symbols that are
|
|
|
+ * declared static and are private to their .o files. This prevents
|
|
|
+ * .tmp_kallsyms.o or any other object from referencing them.
|
|
|
*/
|
|
|
- output_label("kallsyms_addresses");
|
|
|
+ if (!base_relative)
|
|
|
+ output_label("kallsyms_addresses");
|
|
|
+ else
|
|
|
+ output_label("kallsyms_offsets");
|
|
|
+
|
|
|
for (i = 0; i < table_cnt; i++) {
|
|
|
- if (!symbol_absolute(&table[i])) {
|
|
|
+ if (base_relative) {
|
|
|
+ long long offset;
|
|
|
+ int overflow;
|
|
|
+
|
|
|
+ if (!absolute_percpu) {
|
|
|
+ offset = table[i].addr - relative_base;
|
|
|
+ overflow = (offset < 0 || offset > UINT_MAX);
|
|
|
+ } else if (symbol_absolute(&table[i])) {
|
|
|
+ offset = table[i].addr;
|
|
|
+ overflow = (offset < 0 || offset > INT_MAX);
|
|
|
+ } else {
|
|
|
+ offset = relative_base - table[i].addr - 1;
|
|
|
+ overflow = (offset < INT_MIN || offset >= 0);
|
|
|
+ }
|
|
|
+ if (overflow) {
|
|
|
+ fprintf(stderr, "kallsyms failure: "
|
|
|
+ "%s symbol value %#llx out of range in relative mode\n",
|
|
|
+ symbol_absolute(&table[i]) ? "absolute" : "relative",
|
|
|
+ table[i].addr);
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ }
|
|
|
+ printf("\t.long\t%#x\n", (int)offset);
|
|
|
+ } else if (!symbol_absolute(&table[i])) {
|
|
|
if (_text <= table[i].addr)
|
|
|
printf("\tPTR\t_text + %#llx\n",
|
|
|
table[i].addr - _text);
|
|
@@ -371,6 +408,12 @@ static void write_src(void)
|
|
|
}
|
|
|
printf("\n");
|
|
|
|
|
|
+ if (base_relative) {
|
|
|
+ output_label("kallsyms_relative_base");
|
|
|
+ printf("\tPTR\t_text - %#llx\n", _text - relative_base);
|
|
|
+ printf("\n");
|
|
|
+ }
|
|
|
+
|
|
|
output_label("kallsyms_num_syms");
|
|
|
printf("\tPTR\t%d\n", table_cnt);
|
|
|
printf("\n");
|
|
@@ -695,6 +738,18 @@ static void make_percpus_absolute(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* find the minimum non-absolute symbol address */
|
|
|
+static void record_relative_base(void)
|
|
|
+{
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ relative_base = -1ULL;
|
|
|
+ for (i = 0; i < table_cnt; i++)
|
|
|
+ if (!symbol_absolute(&table[i]) &&
|
|
|
+ table[i].addr < relative_base)
|
|
|
+ relative_base = table[i].addr;
|
|
|
+}
|
|
|
+
|
|
|
int main(int argc, char **argv)
|
|
|
{
|
|
|
if (argc >= 2) {
|
|
@@ -713,7 +768,9 @@ int main(int argc, char **argv)
|
|
|
} else if (strncmp(argv[i], "--page-offset=", 14) == 0) {
|
|
|
const char *p = &argv[i][14];
|
|
|
kernel_start_addr = strtoull(p, NULL, 16);
|
|
|
- } else
|
|
|
+ } else if (strcmp(argv[i], "--base-relative") == 0)
|
|
|
+ base_relative = 1;
|
|
|
+ else
|
|
|
usage();
|
|
|
}
|
|
|
} else if (argc != 1)
|
|
@@ -722,6 +779,8 @@ int main(int argc, char **argv)
|
|
|
read_map(stdin);
|
|
|
if (absolute_percpu)
|
|
|
make_percpus_absolute();
|
|
|
+ if (base_relative)
|
|
|
+ record_relative_base();
|
|
|
sort_symbols();
|
|
|
optimize_token_table();
|
|
|
write_src();
|