Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # |
| 3 | # Copyright (c) 2017 Intel Corporation |
| 4 | # |
| 5 | # SPDX-License-Identifier: Apache-2.0 |
| 6 | |
| 7 | import sys |
| 8 | import argparse |
| 9 | import pprint |
| 10 | import os |
| 11 | import struct |
Andy Gross | 6042ae9 | 2018-01-22 14:26:49 -0600 | [diff] [blame] | 12 | from elf_helper import ElfHelper |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 13 | |
Andrew Boie | 5bd891d | 2017-09-27 12:59:28 -0700 | [diff] [blame] | 14 | kobjects = [ |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 15 | "k_alert", |
| 16 | "k_msgq", |
| 17 | "k_mutex", |
| 18 | "k_pipe", |
| 19 | "k_sem", |
| 20 | "k_stack", |
| 21 | "k_thread", |
| 22 | "k_timer", |
| 23 | "_k_thread_stack_element", |
| 24 | "device" |
| 25 | ] |
Andrew Boie | 5bd891d | 2017-09-27 12:59:28 -0700 | [diff] [blame] | 26 | |
| 27 | subsystems = [ |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 28 | "adc_driver_api", |
| 29 | "aio_cmp_driver_api", |
| 30 | "counter_driver_api", |
| 31 | "crypto_driver_api", |
Andrew Boie | ce6c8f3 | 2018-02-09 13:58:37 -0800 | [diff] [blame] | 32 | "dma_driver_api", |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 33 | "flash_driver_api", |
| 34 | "gpio_driver_api", |
| 35 | "i2c_driver_api", |
| 36 | "i2s_driver_api", |
| 37 | "ipm_driver_api", |
| 38 | "pinmux_driver_api", |
| 39 | "pwm_driver_api", |
| 40 | "entropy_driver_api", |
| 41 | "rtc_driver_api", |
| 42 | "sensor_driver_api", |
| 43 | "spi_driver_api", |
| 44 | "uart_driver_api", |
| 45 | ] |
Andrew Boie | 5bd891d | 2017-09-27 12:59:28 -0700 | [diff] [blame] | 46 | |
| 47 | |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 48 | header = """%compare-lengths |
| 49 | %define lookup-function-name _k_object_lookup |
| 50 | %language=ANSI-C |
Andrew Boie | 47f8fd1 | 2017-10-05 11:11:02 -0700 | [diff] [blame] | 51 | %global-table |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 52 | %struct-type |
| 53 | %{ |
| 54 | #include <kernel.h> |
Andrew Boie | 47f8fd1 | 2017-10-05 11:11:02 -0700 | [diff] [blame] | 55 | #include <syscall_handler.h> |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 56 | #include <string.h> |
| 57 | %} |
| 58 | struct _k_object; |
| 59 | %% |
| 60 | """ |
| 61 | |
| 62 | |
Andy Gross | 6042ae9 | 2018-01-22 14:26:49 -0600 | [diff] [blame] | 63 | # Different versions of gperf have different prototypes for the lookup |
| 64 | # function, best to implement the wrapper here. The pointer value itself is |
| 65 | # turned into a string, we told gperf to expect binary strings that are not |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 66 | # NULL-terminated. |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 67 | footer = """%% |
| 68 | struct _k_object *_k_object_find(void *obj) |
| 69 | { |
| 70 | return _k_object_lookup((const char *)obj, sizeof(void *)); |
| 71 | } |
Andrew Boie | 47f8fd1 | 2017-10-05 11:11:02 -0700 | [diff] [blame] | 72 | |
| 73 | void _k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) |
| 74 | { |
| 75 | int i; |
| 76 | |
| 77 | for (i = MIN_HASH_VALUE; i <= MAX_HASH_VALUE; i++) { |
| 78 | if (wordlist[i].name) { |
| 79 | func(&wordlist[i], context); |
| 80 | } |
| 81 | } |
| 82 | } |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 83 | """ |
| 84 | |
| 85 | |
Andy Gross | 6042ae9 | 2018-01-22 14:26:49 -0600 | [diff] [blame] | 86 | def write_gperf_table(fp, eh, objs, static_begin, static_end): |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 87 | fp.write(header) |
| 88 | |
Andrew Boie | bca15da | 2017-10-15 14:17:48 -0700 | [diff] [blame] | 89 | for obj_addr, ko in objs.items(): |
| 90 | obj_type = ko.type_name |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 91 | # pre-initialized objects fall within this memory range, they are |
| 92 | # either completely initialized at build time, or done automatically |
| 93 | # at boot during some PRE_KERNEL_* phase |
| 94 | initialized = obj_addr >= static_begin and obj_addr < static_end |
| 95 | |
Andy Gross | 6042ae9 | 2018-01-22 14:26:49 -0600 | [diff] [blame] | 96 | byte_str = struct.pack("<I" if eh.little_endian else ">I", obj_addr) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 97 | fp.write("\"") |
| 98 | for byte in byte_str: |
| 99 | val = "\\x%02x" % byte |
| 100 | fp.write(val) |
| 101 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 102 | fp.write( |
| 103 | "\",{},%s,%s,%d\n" % |
| 104 | (obj_type, |
| 105 | "K_OBJ_FLAG_INITIALIZED" if initialized else "0", |
| 106 | ko.data)) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 107 | |
| 108 | fp.write(footer) |
| 109 | |
| 110 | |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 111 | def parse_args(): |
| 112 | global args |
| 113 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 114 | parser = argparse.ArgumentParser( |
| 115 | description=__doc__, |
| 116 | formatter_class=argparse.RawDescriptionHelpFormatter) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 117 | |
| 118 | parser.add_argument("-k", "--kernel", required=True, |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 119 | help="Input zephyr ELF binary") |
| 120 | parser.add_argument( |
| 121 | "-o", "--output", required=True, |
| 122 | help="Output list of kernel object addresses for gperf use") |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 123 | parser.add_argument("-v", "--verbose", action="store_true", |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 124 | help="Print extra debugging information") |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 125 | args = parser.parse_args() |
Sebastian Bøe | 4971d2a | 2017-12-28 17:34:50 +0100 | [diff] [blame] | 126 | if "VERBOSE" in os.environ: |
| 127 | args.verbose = 1 |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 128 | |
| 129 | |
| 130 | def main(): |
| 131 | parse_args() |
| 132 | |
Andy Gross | 6042ae9 | 2018-01-22 14:26:49 -0600 | [diff] [blame] | 133 | eh = ElfHelper(args.kernel, args.verbose, kobjects, subsystems) |
| 134 | syms = eh.get_symbols() |
| 135 | max_threads = syms["CONFIG_MAX_THREAD_BYTES"] * 8 |
| 136 | objs = eh.find_kobjects(syms) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 137 | |
Andy Gross | 6042ae9 | 2018-01-22 14:26:49 -0600 | [diff] [blame] | 138 | if eh.get_thread_counter() > max_threads: |
Andrew Boie | 818a96d | 2017-11-03 09:00:35 -0700 | [diff] [blame] | 139 | sys.stderr.write("Too many thread objects (%d)\n" % thread_counter) |
| 140 | sys.stderr.write("Increase CONFIG_MAX_THREAD_BYTES to %d\n", |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 141 | -(-thread_counter // 8)) |
Andrew Boie | 818a96d | 2017-11-03 09:00:35 -0700 | [diff] [blame] | 142 | sys.exit(1) |
| 143 | |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 144 | with open(args.output, "w") as fp: |
Andy Gross | 6042ae9 | 2018-01-22 14:26:49 -0600 | [diff] [blame] | 145 | write_gperf_table(fp, eh, objs, syms["_static_kernel_objects_begin"], |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 146 | syms["_static_kernel_objects_end"]) |
| 147 | |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 148 | |
| 149 | if __name__ == "__main__": |
| 150 | main() |