scripts: gen_kobject_list.py cleanup

Un-do the changes made to the code when this was separated out
to elf_helper.py.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2020-03-12 12:44:36 -07:00 committed by Andrew Boie
commit b42fe9c764

View file

@ -122,6 +122,30 @@ def subsystem_to_enum(subsys):
scr = os.path.basename(sys.argv[0]) scr = os.path.basename(sys.argv[0])
def debug(text):
if not args.verbose:
return
sys.stdout.write(scr + ": " + text + "\n")
def error(text):
sys.exit("%s ERROR: %s" % (scr, text))
def debug_die(die, text):
lp_header = die.dwarfinfo.line_program_for_CU(die.cu).header
files = lp_header["file_entry"]
includes = lp_header["include_directory"]
fileinfo = files[die.attributes["DW_AT_decl_file"].value - 1]
filename = fileinfo.name.decode("utf-8")
filedir = includes[fileinfo.dir_index - 1].decode("utf-8")
path = os.path.join(filedir, filename)
lineno = die.attributes["DW_AT_decl_line"].value
debug(str(die))
debug("File '%s', line %d:" % (path, lineno))
debug(" %s" % text)
# -- ELF processing # -- ELF processing
DW_OP_addr = 0x3 DW_OP_addr = 0x3
@ -135,8 +159,6 @@ stack_counter = 0
# Global type environment. Populated by pass 1. # Global type environment. Populated by pass 1.
type_env = {} type_env = {}
extern_env = {} extern_env = {}
elh_kobjects = {}
elh_subsystems = {}
class KobjectInstance: class KobjectInstance:
def __init__(self, type_obj, addr): def __init__(self, type_obj, addr):
@ -373,9 +395,9 @@ def analyze_die_struct(die):
if not size: if not size:
return return
if name in elh_kobjects: if name in kobjects:
type_env[offset] = KobjectType(offset, name, size) type_env[offset] = KobjectType(offset, name, size)
elif name in elh_subsystems: elif name in subsystems:
type_env[offset] = KobjectType(offset, name, size, api=True) type_env[offset] = KobjectType(offset, name, size, api=True)
else: else:
at = AggregateType(offset, name, size) at = AggregateType(offset, name, size)
@ -474,40 +496,14 @@ def device_get_api_addr(elf, addr):
return addr_deref(elf, addr + offset) return addr_deref(elf, addr + offset)
def get_filename_lineno(die): def find_kobjects(elf, syms):
lp_header = die.dwarfinfo.line_program_for_CU(die.cu).header if not elf.has_dwarf_info():
files = lp_header["file_entry"]
includes = lp_header["include_directory"]
fileinfo = files[die.attributes["DW_AT_decl_file"].value - 1]
filename = fileinfo.name.decode("utf-8")
filedir = includes[fileinfo.dir_index - 1].decode("utf-8")
path = os.path.join(filedir, filename)
lineno = die.attributes["DW_AT_decl_line"].value
return (path, lineno)
class ElfHelper:
def __init__(self, filename, verbose, kobjs, subs):
self.verbose = verbose
self.fp = open(filename, "rb")
self.elf = ELFFile(self.fp)
self.little_endian = self.elf.little_endian
global elh_kobjects
global elh_subsystems
elh_kobjects = kobjs
elh_subsystems = subs
def find_kobjects(self, syms):
if not self.elf.has_dwarf_info():
sys.exit("ELF file has no DWARF information") sys.exit("ELF file has no DWARF information")
app_smem_start = syms["_app_smem_start"] app_smem_start = syms["_app_smem_start"]
app_smem_end = syms["_app_smem_end"] app_smem_end = syms["_app_smem_end"]
di = self.elf.get_dwarf_info() di = elf.get_dwarf_info()
variables = [] variables = []
@ -564,18 +560,15 @@ class ElfHelper:
continue continue
if "DW_AT_location" not in die.attributes: if "DW_AT_location" not in die.attributes:
self.debug_die( debug_die(die,
die, "No location information for object '%s'; possibly stack allocated"
"No location information for object '%s'; possibly" % name)
" stack allocated" % name)
continue continue
loc = die.attributes["DW_AT_location"] loc = die.attributes["DW_AT_location"]
if loc.form != "DW_FORM_exprloc" and \ if loc.form != "DW_FORM_exprloc" and \
loc.form != "DW_FORM_block1": loc.form != "DW_FORM_block1":
self.debug_die( debug_die(die, "kernel object '%s' unexpected location format" %
die,
"kernel object '%s' unexpected location format" %
name) name)
continue continue
@ -584,11 +577,9 @@ class ElfHelper:
# Check if frame pointer offset DW_OP_fbreg # Check if frame pointer offset DW_OP_fbreg
if opcode == DW_OP_fbreg: if opcode == DW_OP_fbreg:
self.debug_die(die, "kernel object '%s' found on stack" % debug_die(die, "kernel object '%s' found on stack" % name)
name)
else: else:
self.debug_die( debug_die(die,
die,
"kernel object '%s' unexpected exprloc opcode %s" % "kernel object '%s' unexpected exprloc opcode %s" %
(name, hex(opcode))) (name, hex(opcode)))
continue continue
@ -604,7 +595,7 @@ class ElfHelper:
objs = type_obj.get_kobjects(addr) objs = type_obj.get_kobjects(addr)
all_objs.update(objs) all_objs.update(objs)
self.debug("symbol '%s' at %s contains %d object(s)" debug("symbol '%s' at %s contains %d object(s)"
% (name, hex(addr), len(objs))) % (name, hex(addr), len(objs)))
# Step 4: objs is a dictionary mapping variable memory addresses to # Step 4: objs is a dictionary mapping variable memory addresses to
@ -618,10 +609,9 @@ class ElfHelper:
if ko.type_obj.api: if ko.type_obj.api:
continue continue
_, user_ram_allowed = elh_kobjects[ko.type_obj.name] _, user_ram_allowed = kobjects[ko.type_obj.name]
if not user_ram_allowed and app_smem_start <= addr < app_smem_end: if not user_ram_allowed and app_smem_start <= addr < app_smem_end:
self.debug_die(die, debug_die(die, "object '%s' found in invalid location %s"
"object '%s' found in invalid location %s"
% (name, hex(addr))) % (name, hex(addr)))
continue continue
@ -633,13 +623,13 @@ class ElfHelper:
# Device struct. Need to get the address of its API struct, # Device struct. Need to get the address of its API struct,
# if it has one. # if it has one.
apiaddr = device_get_api_addr(self.elf, addr) apiaddr = device_get_api_addr(elf, addr)
if apiaddr not in all_objs: if apiaddr not in all_objs:
if apiaddr == 0: if apiaddr == 0:
self.debug("device instance at 0x%x has no associated subsystem" debug("device instance at 0x%x has no associated subsystem"
% addr) % addr)
else: else:
self.debug("device instance at 0x%x has unknown API 0x%x" debug("device instance at 0x%x has unknown API 0x%x"
% (addr, apiaddr)) % (addr, apiaddr))
# API struct does not correspond to a known subsystem, skip it # API struct does not correspond to a known subsystem, skip it
continue continue
@ -648,7 +638,7 @@ class ElfHelper:
ko.type_name = subsystem_to_enum(apiobj.type_obj.name) ko.type_name = subsystem_to_enum(apiobj.type_obj.name)
ret[addr] = ko ret[addr] = ko
self.debug("found %d kernel object instances total" % len(ret)) debug("found %d kernel object instances total" % len(ret))
# 1. Before python 3.7 dict order is not guaranteed. With Python # 1. Before python 3.7 dict order is not guaranteed. With Python
# 3.5 it doesn't seem random with *integer* keys but can't # 3.5 it doesn't seem random with *integer* keys but can't
@ -658,45 +648,14 @@ class ElfHelper:
# 3. Sorting memory address looks good. # 3. Sorting memory address looks good.
return OrderedDict(sorted(ret.items())) return OrderedDict(sorted(ret.items()))
def get_symbols(self): def get_symbols(elf):
for section in self.elf.iter_sections(): for section in elf.iter_sections():
if isinstance(section, SymbolTableSection): if isinstance(section, SymbolTableSection):
return {sym.name: sym.entry.st_value return {sym.name: sym.entry.st_value
for sym in section.iter_symbols()} for sym in section.iter_symbols()}
raise LookupError("Could not find symbol table") raise LookupError("Could not find symbol table")
def debug(self, text):
if not self.verbose:
return
sys.stdout.write(scr + ": " + text + "\n")
@staticmethod
def error(text):
sys.exit("%s ERROR: %s" % (scr, text))
def debug_die(self, die, text):
fn, ln = get_filename_lineno(die)
self.debug(str(die))
self.debug("File '%s', line %d:" % (fn, ln))
self.debug(" %s" % text)
@staticmethod
def get_thread_counter():
return thread_counter
@staticmethod
def get_sys_mutex_counter():
return sys_mutex_counter
@staticmethod
def get_futex_counter():
return futex_counter
@staticmethod
def get_stack_counter():
return stack_counter
# -- GPERF generation logic # -- GPERF generation logic
@ -745,25 +704,23 @@ void z_object_wordlist_foreach(_wordlist_cb_func_t func, void *context)
""" """
def write_gperf_table(fp, eh, objs, static_begin, static_end): def write_gperf_table(fp, syms, objs, little_endian, static_begin, static_end):
syms = eh.get_symbols()
fp.write(header) fp.write(header)
num_mutexes = eh.get_sys_mutex_counter() if sys_mutex_counter != 0:
if num_mutexes != 0: fp.write("static struct k_mutex kernel_mutexes[%d] = {\n"
fp.write("static struct k_mutex kernel_mutexes[%d] = {\n" % num_mutexes) % sys_mutex_counter)
for i in range(num_mutexes): for i in range(sys_mutex_counter):
fp.write("_K_MUTEX_INITIALIZER(kernel_mutexes[%d])" % i) fp.write("_K_MUTEX_INITIALIZER(kernel_mutexes[%d])" % i)
if i != num_mutexes - 1: if i != sys_mutex_counter - 1:
fp.write(", ") fp.write(", ")
fp.write("};\n") fp.write("};\n")
num_futex = eh.get_futex_counter() if futex_counter != 0:
if num_futex != 0: fp.write("static struct z_futex_data futex_data[%d] = {\n"
fp.write("static struct z_futex_data futex_data[%d] = {\n" % num_futex) % futex_counter)
for i in range(num_futex): for i in range(futex_counter):
fp.write("Z_FUTEX_DATA_INITIALIZER(futex_data[%d])" % i) fp.write("Z_FUTEX_DATA_INITIALIZER(futex_data[%d])" % i)
if i != num_futex - 1: if i != futex_counter - 1:
fp.write(", ") fp.write(", ")
fp.write("};\n") fp.write("};\n")
@ -775,15 +732,14 @@ def write_gperf_table(fp, eh, objs, static_begin, static_end):
if "CONFIG_GEN_PRIV_STACKS" in syms: if "CONFIG_GEN_PRIV_STACKS" in syms:
metadata_names["K_OBJ_THREAD_STACK_ELEMENT"] = "stack_data" metadata_names["K_OBJ_THREAD_STACK_ELEMENT"] = "stack_data"
num_stack = eh.get_stack_counter() if stack_counter != 0:
if num_stack != 0:
fp.write("static u8_t Z_GENERIC_SECTION(.priv_stacks.noinit) " fp.write("static u8_t Z_GENERIC_SECTION(.priv_stacks.noinit) "
" __aligned(Z_PRIVILEGE_STACK_ALIGN)" " __aligned(Z_PRIVILEGE_STACK_ALIGN)"
" priv_stacks[%d][CONFIG_PRIVILEGED_STACK_SIZE];\n" " priv_stacks[%d][CONFIG_PRIVILEGED_STACK_SIZE];\n"
% num_stack); % stack_counter)
fp.write("static struct z_stack_data stack_data[%d] = {\n" fp.write("static struct z_stack_data stack_data[%d] = {\n"
% num_stack) % stack_counter)
counter = 0 counter = 0
for _, ko in objs.items(): for _, ko in objs.items():
if ko.type_name != "K_OBJ_THREAD_STACK_ELEMENT": if ko.type_name != "K_OBJ_THREAD_STACK_ELEMENT":
@ -797,7 +753,7 @@ def write_gperf_table(fp, eh, objs, static_begin, static_end):
ko.data = "&stack_data[%d]" % counter ko.data = "&stack_data[%d]" % counter
fp.write("\t{ %d, (u8_t *)(&priv_stacks[%d]) }" fp.write("\t{ %d, (u8_t *)(&priv_stacks[%d]) }"
% (size, counter)) % (size, counter))
if counter != (num_stack - 1): if counter != (stack_counter - 1):
fp.write(",") fp.write(",")
fp.write("\n") fp.write("\n")
counter += 1 counter += 1
@ -826,7 +782,7 @@ def write_gperf_table(fp, eh, objs, static_begin, static_end):
else: else:
format_code = "I" format_code = "I"
if eh.little_endian: if little_endian:
endian = "<" endian = "<"
else: else:
endian = ">" endian = ">"
@ -945,7 +901,7 @@ def write_kobj_size_output(fp):
dep, _ = obj_info dep, _ = obj_info
# device handled by default case. Stacks are not currently handled, # device handled by default case. Stacks are not currently handled,
# if they eventually are it will be a special case. # if they eventually are it will be a special case.
if kobj in {"device", "z_thread_stack_element"}: if kobj in {"device", STACK_TYPE}:
continue continue
if dep: if dep:
@ -1007,22 +963,21 @@ def main():
if args.gperf_output: if args.gperf_output:
assert args.kernel, "--kernel ELF required for --gperf-output" assert args.kernel, "--kernel ELF required for --gperf-output"
eh = ElfHelper(args.kernel, args.verbose, kobjects, subsystems) elf = ELFFile(open(args.kernel, "rb"))
syms = eh.get_symbols() syms = get_symbols(elf)
max_threads = syms["CONFIG_MAX_THREAD_BYTES"] * 8 max_threads = syms["CONFIG_MAX_THREAD_BYTES"] * 8
objs = eh.find_kobjects(syms) objs = find_kobjects(elf, syms)
if not objs: if not objs:
sys.stderr.write("WARNING: zero kobject found in %s\n" sys.stderr.write("WARNING: zero kobject found in %s\n"
% args.kernel) % args.kernel)
thread_counter = eh.get_thread_counter()
if thread_counter > max_threads: if thread_counter > max_threads:
sys.exit("Too many thread objects ({})\n" sys.exit("Too many thread objects ({})\n"
"Increase CONFIG_MAX_THREAD_BYTES to {}" "Increase CONFIG_MAX_THREAD_BYTES to {}"
.format(thread_counter, -(-thread_counter // 8))) .format(thread_counter, -(-thread_counter // 8)))
with open(args.gperf_output, "w") as fp: with open(args.gperf_output, "w") as fp:
write_gperf_table(fp, eh, objs, write_gperf_table(fp, syms, objs, elf.little_endian,
syms["_static_kernel_objects_begin"], syms["_static_kernel_objects_begin"],
syms["_static_kernel_objects_end"]) syms["_static_kernel_objects_end"])