[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] symbols: arrange to know where functions end
commit d3b637fba31b9ea5c43d830d67b558a849b615cc Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Mon Sep 1 11:08:29 2025 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Mon Sep 1 13:07:01 2025 +0200 symbols: arrange to know where functions end When determining the symbol for a given address (e.g. for the %pS logging format specifier), so far the size of a symbol (function) was assumed to be everything until the next symbol. There may be gaps though, which would better be recognizable in output (often suggesting something odd is going on). Insert "fake" end symbols in the address table, accompanied by zero- length type/name entries (to keep lookup reasonably close to how it was). Note however that this, with GNU binutils prior to 2.45, won't work for xen.efi: The linker loses function sizes (they're not part of a normal symbol table entry), and hence nm has no way of reporting them. The address table growth is quite significant on x86 release builds (due to functions being aligned to 16-byte boundaries), though: Its size almost doubles. Requested-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Jason Andryuk <jason.andryuk@xxxxxxx> --- xen/common/symbols.c | 41 +++++++++++++++++++++++++++---- xen/tools/symbols.c | 68 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 92 insertions(+), 17 deletions(-) diff --git a/xen/common/symbols.c b/xen/common/symbols.c index 500d726325..0d8cc25ab0 100644 --- a/xen/common/symbols.c +++ b/xen/common/symbols.c @@ -116,6 +116,13 @@ const char *symbols_lookup(unsigned long addr, else high = mid; } + /* If we hit an END symbol, move to the previous (real) one. */ + if (!symbols_names[get_symbol_offset(low)]) { + ASSERT(low); + symbol_end = symbols_address(low); + --low; + } + /* search for the first aliased symbol. Aliased symbols are symbols with the same address */ while (low && symbols_address(low - 1) == symbols_address(low)) @@ -124,11 +131,13 @@ const char *symbols_lookup(unsigned long addr, /* Grab name */ symbols_expand_symbol(get_symbol_offset(low), namebuf); - /* Search for next non-aliased symbol */ - for (i = low + 1; i < symbols_num_addrs; i++) { - if (symbols_address(i) > symbols_address(low)) { - symbol_end = symbols_address(i); - break; + if (!symbol_end) { + /* Search for next non-aliased symbol */ + for (i = low + 1; i < symbols_num_addrs; i++) { + if (symbols_address(i) > symbols_address(low)) { + symbol_end = symbols_address(i); + break; + } } } @@ -170,6 +179,7 @@ int xensyms_read(uint32_t *symnum, char *type, return -ERANGE; if ( *symnum == symbols_num_addrs ) { + no_symbol: /* No more symbols */ name[0] = '\0'; return 0; @@ -183,10 +193,31 @@ int xensyms_read(uint32_t *symnum, char *type, /* Non-sequential access */ next_offset = get_symbol_offset(*symnum); + /* + * If we're at an END symbol, skip to the next (real) one. This can + * happen if the caller ignores the *symnum output from an earlier + * iteration (Linux'es /proc/xen/xensyms handling does as of 6.14-rc). + */ + if ( !symbols_names[next_offset] ) + { + ++next_offset; + if ( ++*symnum == symbols_num_addrs ) + goto no_symbol; + } + *type = symbols_get_symbol_type(next_offset); next_offset = symbols_expand_symbol(next_offset, name); *address = symbols_address(*symnum); + /* If next one is an END symbol, skip it. */ + if ( !symbols_names[next_offset] ) + { + ++next_offset; + /* Make sure not to increment past symbols_num_addrs below. */ + if ( *symnum + 1 < symbols_num_addrs ) + ++*symnum; + } + next_symbol = ++*symnum; spin_unlock(&symbols_mutex); diff --git a/xen/tools/symbols.c b/xen/tools/symbols.c index d2d5e1bc83..d20e51a31c 100644 --- a/xen/tools/symbols.c +++ b/xen/tools/symbols.c @@ -38,6 +38,7 @@ struct sym_entry { unsigned long long addr; + unsigned long size; unsigned int len; unsigned char *sym; char *orig_symbol; @@ -87,6 +88,8 @@ static int read_symbol(FILE *in, struct sym_entry *s) static char *filename; int rc = -1; + s->size = 0; + switch (input_format) { case fmt_bsd: rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str); @@ -96,8 +99,12 @@ static int read_symbol(FILE *in, struct sym_entry *s) /* nothing */; rc = fscanf(in, "%499[^ |] |%llx | %c |", str, &s->addr, &stype); - if (rc == 3 && fscanf(in, " %19[^ |] |", type) != 1) - *type = '\0'; + if (rc == 3) { + if(fscanf(in, " %19[^ |] |", type) != 1) + *type = '\0'; + else if(fscanf(in, "%lx |", &s->size) != 1) + s->size = 0; + } break; } if (rc != 3) { @@ -287,9 +294,18 @@ static int compare_name_orig(const void *p1, const void *p2) return rc; } +/* Determine whether the symbol at address table @idx wants a fake END + * symbol (address only) emitted as well. */ +static bool want_symbol_end(unsigned int idx) +{ + return table[idx].size && + (idx + 1 == table_cnt || + table[idx].addr + table[idx].size < table[idx + 1].addr); +} + static void write_src(void) { - unsigned int i, k, off; + unsigned int i, k, off, ends; unsigned int best_idx[256]; unsigned int *markers; char buf[KSYM_NAME_LEN+1]; @@ -318,24 +334,42 @@ static void write_src(void) printf("#else\n"); output_label("symbols_offsets"); printf("#endif\n"); - for (i = 0; i < table_cnt; i++) { + for (i = 0, ends = 0; i < table_cnt; i++) { printf("\tPTR\t%#llx - SYMBOLS_ORIGIN\n", table[i].addr); + + table[i].addr_idx = i + ends; + + if (!want_symbol_end(i)) { + /* If there's another symbol at the same address, + * propagate this symbol's size if the next one has + * no size, or if the next one's size is larger. */ + if (table[i].size && + i + 1 < table_cnt && + table[i + 1].addr == table[i].addr && + (!table[i + 1].size || + table[i + 1].size > table[i].size)) + table[i + 1].size = table[i].size; + continue; + } + + ++ends; + printf("\tPTR\t%#llx - SYMBOLS_ORIGIN\n", + table[i].addr + table[i].size); } printf("\n"); output_label("symbols_num_addrs"); - printf("\t.long\t%d\n", table_cnt); + printf("\t.long\t%d\n", table_cnt + ends); printf("\n"); /* table of offset markers, that give the offset in the compressed stream * every 256 symbols */ - markers = (unsigned int *) malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256)); + markers = malloc(sizeof(*markers) * ((table_cnt + ends + 255) >> 8)); output_label("symbols_names"); - off = 0; - for (i = 0; i < table_cnt; i++) { - if ((i & 0xFF) == 0) - markers[i >> 8] = off; + for (i = 0, off = 0, ends = 0; i < table_cnt; i++) { + if (((i + ends) & 0xFF) == 0) + markers[(i + ends) >> 8] = off; printf("\t.byte 0x%02x", table[i].len); for (k = 0; k < table[i].len; k++) @@ -344,11 +378,22 @@ static void write_src(void) table[i].stream_offset = off; off += table[i].len + 1; + + if (!want_symbol_end(i)) + continue; + + /* END symbols have no name or type. */ + ++ends; + if (((i + ends) & 0xFF) == 0) + markers[(i + ends) >> 8] = off; + + printf("\t.byte 0\n"); + ++off; } printf("\n"); output_label("symbols_markers"); - for (i = 0; i < ((table_cnt + 255) >> 8); i++) + for (i = 0; i < ((table_cnt + ends + 255) >> 8); i++) printf("\t.long\t%d\n", markers[i]); printf("\n"); @@ -450,7 +495,6 @@ static void compress_symbols(unsigned char *str, int idx) 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; -- generated by git-patchbot for /home/xen/git/xen.git#staging
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |