build: symtab: Add a dummy entry at the end for the binary search

The `symtab_find_symbol_name()` is using an adapted binary
search function to get the entry between 2 addresses, we need
to add a dummy entry at the end so that the search function
can remain simple and straightforward without doing
out-of-bound checks:

   20  \
       |
       |
   50  x
       |
       |
   90  x
    .  |
    .  |
    .  |
dummy  /

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
This commit is contained in:
Yong Cong Sin 2024-05-27 21:38:55 +08:00 committed by David Leach
commit f5934de8e5
2 changed files with 33 additions and 16 deletions

View file

@ -55,8 +55,9 @@ def parse_args():
class symtab_entry: class symtab_entry:
def __init__(self, addr, offset, name): def __init__(self, addr, size, offset, name):
self.addr = addr self.addr = addr
self.size = size
self.offset = offset self.offset = offset
self.name = name self.name = name
@ -90,11 +91,12 @@ def main():
for nsym, symbol in enumerate(symtab.iter_symbols()): # pylint: disable=unused-variable for nsym, symbol in enumerate(symtab.iter_symbols()): # pylint: disable=unused-variable
symbol_type = describe_symbol_type(symbol['st_info']['type']) symbol_type = describe_symbol_type(symbol['st_info']['type'])
symbol_addr = symbol['st_value'] symbol_addr = symbol['st_value']
symbol_size = symbol['st_size']
if symbol_type == 'FUNC' and symbol_addr != 0: if symbol_type == 'FUNC' and symbol_addr != 0:
symbol_name = sanitize_func_name(symbol.name) symbol_name = sanitize_func_name(symbol.name)
symtab_list.append(symtab_entry( symtab_list.append(symtab_entry(
symbol_addr, symbol_addr, symbol_name)) symbol_addr, symbol_addr, symbol_size, symbol_name))
log.debug('%6d: %s %.25s' % ( log.debug('%6d: %s %.25s' % (
i, i,
hex(symbol_addr), hex(symbol_addr),
@ -115,10 +117,21 @@ def main():
print("#include <zephyr/debug/symtab.h>", file=wf) print("#include <zephyr/debug/symtab.h>", file=wf)
print("", file=wf) print("", file=wf)
print( print(
f"const struct z_symtab_entry z_symtab_entries[{len(symtab_list)}] = {{", file=wf) f"const struct z_symtab_entry z_symtab_entries[{len(symtab_list) + 1}] = {{", file=wf)
for i, entry in enumerate(symtab_list): for i, entry in enumerate(symtab_list):
print( print(
f"\t[{i}] = {{.offset = {hex(entry.offset)}, .name = \"{entry.name}\"}}, /* {hex(entry.addr)} */", file=wf) f"\t/* ADDR: {hex(entry.addr)} SIZE: {hex(entry.size)} */", file=wf)
print(
f"\t[{i}] = {{.offset = {hex(entry.offset)}, .name = \"{entry.name}\"}},", file=wf)
# Append a dummy entry at the end to facilitate the binary search
if symtab_list[-1].size == 0:
dummy_offset = f"{hex(symtab_list[-1].offset)} + sizeof(uintptr_t)"
else:
dummy_offset = f"{hex(symtab_list[-1].offset + symtab_list[-1].size)}"
print("\t/* dummy entry */", file=wf)
print(
f"\t[{len(symtab_list)}] = {{.offset = {dummy_offset}, .name = \"?\"}},", file=wf)
print(f"}};\n", file=wf) print(f"}};\n", file=wf)
print(f"const struct symtab_info z_symtab = {{", file=wf) print(f"const struct symtab_info z_symtab = {{", file=wf)

View file

@ -5,6 +5,7 @@
*/ */
#include <string.h> #include <string.h>
#include <stdbool.h>
#include <zephyr/debug/symtab.h> #include <zephyr/debug/symtab.h>
@ -19,22 +20,25 @@ const char *const symtab_find_symbol_name(uintptr_t addr, uint32_t *offset)
{ {
const struct symtab_info *const symtab = symtab_get(); const struct symtab_info *const symtab = symtab_get();
const uint32_t symbol_offset = addr - symtab->start_addr; const uint32_t symbol_offset = addr - symtab->start_addr;
uint32_t left = 0, right = symtab->length - 1; uint32_t left = 0, right = symtab->length;
uint32_t ret_offset = 0; uint32_t ret_offset = 0;
const char *ret_name = "?"; const char *ret_name = "?";
while (left <= right) { /* No need to search if the address is out-of-bound */
uint32_t mid = left + (right - left) / 2; if (symbol_offset < symtab->entries[symtab->length].offset) {
while (left <= right) {
uint32_t mid = left + (right - left) / 2;
if ((symbol_offset >= symtab->entries[mid].offset) && if ((symbol_offset >= symtab->entries[mid].offset) &&
(symbol_offset < symtab->entries[mid + 1].offset)) { (symbol_offset < symtab->entries[mid + 1].offset)) {
ret_offset = symbol_offset - symtab->entries[mid].offset; ret_offset = symbol_offset - symtab->entries[mid].offset;
ret_name = symtab->entries[mid].name; ret_name = symtab->entries[mid].name;
break; break;
} else if (symbol_offset < symtab->entries[mid].offset) { } else if (symbol_offset < symtab->entries[mid].offset) {
right = mid - 1; right = mid - 1;
} else { } else {
left = mid + 1; left = mid + 1;
}
} }
} }