extern const unsigned int symbols_num_syms;
extern const u8 symbols_names[];
+extern const struct symbol_offset symbols_sorted_offsets[];
+
extern const u8 symbols_token_table[];
extern const u16 symbols_token_index[];
unsigned long symbols_lookup_by_name(const char *symname)
{
char name[KSYM_NAME_LEN + 1];
+#ifdef CONFIG_FAST_SYMBOL_LOOKUP
+ unsigned long low, high;
+#else
uint32_t symnum = 0;
char type;
unsigned long addr;
int rc;
+#endif
if ( *symname == '\0' )
return 0;
+#ifdef CONFIG_FAST_SYMBOL_LOOKUP
+ low = 0;
+ high = symbols_num_syms;
+ while ( low < high )
+ {
+ unsigned long mid = low + ((high - low) / 2);
+ const struct symbol_offset *s;
+ int rc;
+
+ s = &symbols_sorted_offsets[mid];
+ (void)symbols_expand_symbol(s->stream, name);
+ /* Format is: [filename]#<symbol>. symbols_expand_symbol eats type.*/
+ rc = strcmp(symname, name);
+ if ( rc < 0 )
+ high = mid;
+ else if ( rc > 0 )
+ low = mid + 1;
+ else
+ return symbols_address(s->addr);
+ }
+#else
do {
rc = xensyms_read(&symnum, &type, &addr, name);
if ( rc )
} while ( name[0] != '\0' );
+#endif
return 0;
}
unsigned long long addr;
unsigned int len;
unsigned char *sym;
+ char *orig_symbol;
+ unsigned int addr_idx;
+ unsigned int stream_offset;
+ unsigned char type;
};
#define SYMBOL_NAME(s) ((char *)(s)->sym + 1)
static unsigned int table_size, table_cnt;
static unsigned long long _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
static int all_symbols = 0;
+static int sort_by_name = 0;
static char symbol_prefix_char = '\0';
static enum { fmt_bsd, fmt_sysv } input_format;
+static int compare_name(const void *p1, const void *p2);
int token_profit[0x10000];
*sym++ = '#';
}
strcpy(sym, str);
+ if (sort_by_name) {
+ s->orig_symbol = strdup(SYMBOL_NAME(s));
+ s->type = stype; /* As s->sym[0] ends mangled. */
+ }
s->sym[0] = stype;
-
rc = 0;
skip_tail:
return total;
}
+/* Sort by original (non mangled) symbol name, then type. */
+static int compare_name_orig(const void *p1, const void *p2)
+{
+ const struct sym_entry *sym1 = p1;
+ const struct sym_entry *sym2 = p2;
+ int rc;
+
+ rc = strcmp(sym1->orig_symbol, sym2->orig_symbol);
+
+ if (!rc)
+ rc = sym1->type - sym2->type;
+
+ return rc;
+}
+
static void write_src(void)
{
unsigned int i, k, off;
printf(", 0x%02x", table[i].sym[k]);
printf("\n");
+ table[i].stream_offset = off;
off += table[i].len + 1;
}
printf("\n");
printf("\t.long\t%d\n", markers[i]);
printf("\n");
- free(markers);
output_label("symbols_token_table");
off = 0;
for (i = 0; i < 256; i++)
printf("\t.short\t%d\n", best_idx[i]);
printf("\n");
+
+ if (!sort_by_name) {
+ free(markers);
+ return;
+ }
+
+ /* Sorted by original symbol names and type. */
+ qsort(table, table_cnt, sizeof(*table), compare_name_orig);
+
+ output_label("symbols_sorted_offsets");
+ /* A fixed sized array with two entries: offset in the
+ * compressed stream (for symbol name), and offset in
+ * symbols_addresses (or symbols_offset). */
+ for (i = 0; i < table_cnt; i++) {
+ printf("\t.long %u, %u\n", table[i].stream_offset, table[i].addr_idx);
+ }
+ printf("\n");
+
+ free(markers);
}
len = table[i].len;
p1 = table[i].sym;
+ table[i].addr_idx = i;
/* find the token on the symbol */
p2 = memmem_pvt(p1, len, str, 2);
if (!p2) continue;
input_format = fmt_sysv;
else if (strcmp(argv[i], "--sort") == 0)
unsorted = true;
+ else if (strcmp(argv[i], "--sort-by-name") == 0)
+ sort_by_name = 1;
else if (strcmp(argv[i], "--warn-dup") == 0)
warn_dup = true;
else