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 |
Andrew Boie | c78c5e6 | 2019-03-11 14:45:43 -0700 | [diff] [blame] | 6 | """ |
| 7 | Script to generate gperf tables of kernel object metadata |
| 8 | |
| 9 | User mode threads making system calls reference kernel objects by memory |
| 10 | address, as the kernel/driver APIs in Zephyr are the same for both user |
| 11 | and supervisor contexts. It is necessary for the kernel to be able to |
| 12 | validate accesses to kernel objects to make the following assertions: |
| 13 | |
| 14 | - That the memory address points to a kernel object |
| 15 | |
| 16 | - The kernel object is of the expected type for the API being invoked |
| 17 | |
| 18 | - The kernel object is of the expected initialization state |
| 19 | |
| 20 | - The calling thread has sufficient permissions on the object |
| 21 | |
David B. Kinder | 17299f0 | 2019-05-31 15:39:39 -0700 | [diff] [blame] | 22 | For more details see the :ref:`kernelobjects` section in the documentation. |
Marc Herbert | 4a10eea | 2019-04-16 15:39:45 -0700 | [diff] [blame] | 23 | |
Andrew Boie | c78c5e6 | 2019-03-11 14:45:43 -0700 | [diff] [blame] | 24 | The zephyr build generates an intermediate ELF binary, zephyr_prebuilt.elf, |
| 25 | which this script scans looking for kernel objects by examining the DWARF |
| 26 | debug information to look for instances of data structures that are considered |
| 27 | kernel objects. For device drivers, the API struct pointer populated at build |
| 28 | time is also examined to disambiguate between various device driver instances |
| 29 | since they are all 'struct device'. |
| 30 | |
Marc Herbert | 4a10eea | 2019-04-16 15:39:45 -0700 | [diff] [blame] | 31 | This script can generate five different output files: |
Andrew Boie | c78c5e6 | 2019-03-11 14:45:43 -0700 | [diff] [blame] | 32 | |
| 33 | - A gperf script to generate the hash table mapping kernel object memory |
| 34 | addresses to kernel object metadata, used to track permissions, |
| 35 | object type, initialization state, and any object-specific data. |
| 36 | |
| 37 | - A header file containing generated macros for validating driver instances |
| 38 | inside the system call handlers for the driver subsystem APIs. |
| 39 | |
Marc Herbert | 4a10eea | 2019-04-16 15:39:45 -0700 | [diff] [blame] | 40 | - A code fragment included by kernel.h with one enum constant for |
| 41 | each kernel object type and each driver instance. |
Andrew Boie | c78c5e6 | 2019-03-11 14:45:43 -0700 | [diff] [blame] | 42 | |
Marc Herbert | 4a10eea | 2019-04-16 15:39:45 -0700 | [diff] [blame] | 43 | - The inner cases of a switch/case C statement, included by |
| 44 | kernel/userspace.c, mapping the kernel object types and driver |
| 45 | instances to their human-readable representation in the |
Andrew Boie | c78c5e6 | 2019-03-11 14:45:43 -0700 | [diff] [blame] | 46 | otype_to_str() function. |
| 47 | |
Marc Herbert | 4a10eea | 2019-04-16 15:39:45 -0700 | [diff] [blame] | 48 | - The inner cases of a switch/case C statement, included by |
| 49 | kernel/userspace.c, mapping kernel object types to their sizes. |
| 50 | This is used for allocating instances of them at runtime |
| 51 | (CONFIG_DYNAMIC_OBJECTS) in the obj_size_get() function. |
Andrew Boie | c78c5e6 | 2019-03-11 14:45:43 -0700 | [diff] [blame] | 52 | """ |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 53 | |
| 54 | import sys |
| 55 | import argparse |
Daniel Leung | e58b654 | 2018-08-08 11:23:16 -0700 | [diff] [blame] | 56 | import math |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 57 | import os |
| 58 | import struct |
Andrew Boie | f20efcf | 2018-05-23 10:57:39 -0700 | [diff] [blame] | 59 | from elf_helper import ElfHelper, kobject_to_enum |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 60 | |
Marc Herbert | f78288b | 2019-03-05 14:31:44 -0800 | [diff] [blame] | 61 | from collections import OrderedDict |
| 62 | |
Andrew Boie | 09c22cc | 2018-06-27 10:25:45 -0700 | [diff] [blame] | 63 | # Keys in this dictionary are structs which should be recognized as kernel |
Andrew Boie | c235e16 | 2019-03-27 14:27:24 -0700 | [diff] [blame] | 64 | # objects. Values are a tuple: |
| 65 | # |
| 66 | # - The first item is None, or the name of a Kconfig that |
| 67 | # indicates the presence of this object's definition in case it is not |
| 68 | # available in all configurations. |
| 69 | # |
| 70 | # - The second item is a boolean indicating whether it is permissible for |
| 71 | # the object to be located in user-accessible memory. |
Andrew Boie | 09c22cc | 2018-06-27 10:25:45 -0700 | [diff] [blame] | 72 | |
Marc Herbert | f78288b | 2019-03-05 14:31:44 -0800 | [diff] [blame] | 73 | # Regular dictionaries are ordered only with Python 3.6 and |
| 74 | # above. Good summary and pointers to official documents at: |
| 75 | # https://stackoverflow.com/questions/39980323/are-dictionaries-ordered-in-python-3-6 |
Ulf Magnusson | 0d39a10 | 2019-09-06 11:13:19 +0200 | [diff] [blame] | 76 | kobjects = OrderedDict([ |
Andrew Boie | c235e16 | 2019-03-27 14:27:24 -0700 | [diff] [blame] | 77 | ("k_mem_slab", (None, False)), |
| 78 | ("k_msgq", (None, False)), |
| 79 | ("k_mutex", (None, False)), |
| 80 | ("k_pipe", (None, False)), |
| 81 | ("k_queue", (None, False)), |
| 82 | ("k_poll_signal", (None, False)), |
| 83 | ("k_sem", (None, False)), |
| 84 | ("k_stack", (None, False)), |
| 85 | ("k_thread", (None, False)), |
| 86 | ("k_timer", (None, False)), |
| 87 | ("_k_thread_stack_element", (None, False)), |
Andrew Boie | c235e16 | 2019-03-27 14:27:24 -0700 | [diff] [blame] | 88 | ("device", (None, False)), |
Wentong Wu | 5611e92 | 2019-06-20 23:51:27 +0800 | [diff] [blame] | 89 | ("sys_mutex", (None, True)), |
| 90 | ("k_futex", (None, True)) |
Marc Herbert | f78288b | 2019-03-05 14:31:44 -0800 | [diff] [blame] | 91 | ]) |
| 92 | |
| 93 | |
Andrew Boie | 5bd891d | 2017-09-27 12:59:28 -0700 | [diff] [blame] | 94 | |
| 95 | subsystems = [ |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 96 | "adc_driver_api", |
| 97 | "aio_cmp_driver_api", |
| 98 | "counter_driver_api", |
| 99 | "crypto_driver_api", |
Andrew Boie | ce6c8f3 | 2018-02-09 13:58:37 -0800 | [diff] [blame] | 100 | "dma_driver_api", |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 101 | "flash_driver_api", |
| 102 | "gpio_driver_api", |
| 103 | "i2c_driver_api", |
| 104 | "i2s_driver_api", |
| 105 | "ipm_driver_api", |
Manivannan Sadhasivam | 26babfc | 2018-05-03 23:46:58 +0530 | [diff] [blame] | 106 | "led_driver_api", |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 107 | "pinmux_driver_api", |
| 108 | "pwm_driver_api", |
| 109 | "entropy_driver_api", |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 110 | "sensor_driver_api", |
| 111 | "spi_driver_api", |
| 112 | "uart_driver_api", |
Alexander Wachter | 8757e78 | 2019-02-07 17:57:43 +0100 | [diff] [blame] | 113 | "can_driver_api", |
Jukka Rissanen | c9aaab7 | 2019-05-27 16:01:49 +0800 | [diff] [blame] | 114 | "ptp_clock_driver_api", |
Henrik Brix Andersen | a2a7b77 | 2019-10-20 21:22:03 +0200 | [diff] [blame] | 115 | "eeprom_driver_api", |
Andrew Boie | 13b8b41 | 2019-12-16 12:15:45 -0800 | [diff] [blame] | 116 | "wdt_driver_api", |
Andrew Boie | 5bd891d | 2017-09-27 12:59:28 -0700 | [diff] [blame] | 117 | |
Andrew Boie | 6f92809 | 2019-04-23 13:06:59 -0700 | [diff] [blame] | 118 | # Fake 'sample driver' subsystem, used by tests/samples |
| 119 | "sample_driver_api" |
| 120 | ] |
Andrew Boie | 5bd891d | 2017-09-27 12:59:28 -0700 | [diff] [blame] | 121 | |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 122 | header = """%compare-lengths |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 123 | %define lookup-function-name z_object_lookup |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 124 | %language=ANSI-C |
Andrew Boie | 47f8fd1 | 2017-10-05 11:11:02 -0700 | [diff] [blame] | 125 | %global-table |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 126 | %struct-type |
| 127 | %{ |
| 128 | #include <kernel.h> |
Andrew Boie | 31bdfc0 | 2017-11-08 16:38:03 -0800 | [diff] [blame] | 129 | #include <toolchain.h> |
Andrew Boie | 47f8fd1 | 2017-10-05 11:11:02 -0700 | [diff] [blame] | 130 | #include <syscall_handler.h> |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 131 | #include <string.h> |
| 132 | %} |
| 133 | struct _k_object; |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 134 | """ |
| 135 | |
Andy Gross | 6042ae9 | 2018-01-22 14:26:49 -0600 | [diff] [blame] | 136 | # Different versions of gperf have different prototypes for the lookup |
| 137 | # function, best to implement the wrapper here. The pointer value itself is |
| 138 | # 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] | 139 | # NULL-terminated. |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 140 | footer = """%% |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 141 | struct _k_object *z_object_gperf_find(void *obj) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 142 | { |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 143 | return z_object_lookup((const char *)obj, sizeof(void *)); |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 144 | } |
Andrew Boie | 47f8fd1 | 2017-10-05 11:11:02 -0700 | [diff] [blame] | 145 | |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 146 | void z_object_gperf_wordlist_foreach(_wordlist_cb_func_t func, void *context) |
Andrew Boie | 47f8fd1 | 2017-10-05 11:11:02 -0700 | [diff] [blame] | 147 | { |
| 148 | int i; |
| 149 | |
| 150 | for (i = MIN_HASH_VALUE; i <= MAX_HASH_VALUE; i++) { |
Flavio Ceolin | 4218d5f | 2018-09-17 09:39:51 -0700 | [diff] [blame] | 151 | if (wordlist[i].name != NULL) { |
Andrew Boie | 47f8fd1 | 2017-10-05 11:11:02 -0700 | [diff] [blame] | 152 | func(&wordlist[i], context); |
| 153 | } |
| 154 | } |
| 155 | } |
Andrew Boie | 31bdfc0 | 2017-11-08 16:38:03 -0800 | [diff] [blame] | 156 | |
| 157 | #ifndef CONFIG_DYNAMIC_OBJECTS |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 158 | struct _k_object *z_object_find(void *obj) |
| 159 | ALIAS_OF(z_object_gperf_find); |
Andrew Boie | 31bdfc0 | 2017-11-08 16:38:03 -0800 | [diff] [blame] | 160 | |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 161 | void z_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) |
| 162 | ALIAS_OF(z_object_gperf_wordlist_foreach); |
Andrew Boie | 31bdfc0 | 2017-11-08 16:38:03 -0800 | [diff] [blame] | 163 | #endif |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 164 | """ |
| 165 | |
| 166 | |
Andy Gross | 6042ae9 | 2018-01-22 14:26:49 -0600 | [diff] [blame] | 167 | def write_gperf_table(fp, eh, objs, static_begin, static_end): |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 168 | fp.write(header) |
Andrew Boie | f083567 | 2019-03-27 15:44:52 -0700 | [diff] [blame] | 169 | num_mutexes = eh.get_sys_mutex_counter() |
Ulf Magnusson | 9d34356 | 2019-05-07 12:06:35 +0200 | [diff] [blame] | 170 | if num_mutexes != 0: |
Andrew Boie | f083567 | 2019-03-27 15:44:52 -0700 | [diff] [blame] | 171 | fp.write("static struct k_mutex kernel_mutexes[%d] = {\n" % num_mutexes) |
| 172 | for i in range(num_mutexes): |
| 173 | fp.write("_K_MUTEX_INITIALIZER(kernel_mutexes[%d])" % i) |
Ulf Magnusson | 9d34356 | 2019-05-07 12:06:35 +0200 | [diff] [blame] | 174 | if i != num_mutexes - 1: |
Andrew Boie | f083567 | 2019-03-27 15:44:52 -0700 | [diff] [blame] | 175 | fp.write(", ") |
| 176 | fp.write("};\n") |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 177 | |
Wentong Wu | 5611e92 | 2019-06-20 23:51:27 +0800 | [diff] [blame] | 178 | num_futex = eh.get_futex_counter() |
Ulf Magnusson | d4c851c | 2019-09-02 11:11:22 +0200 | [diff] [blame] | 179 | if num_futex != 0: |
Wentong Wu | 5611e92 | 2019-06-20 23:51:27 +0800 | [diff] [blame] | 180 | fp.write("static struct z_futex_data futex_data[%d] = {\n" % num_futex) |
| 181 | for i in range(num_futex): |
| 182 | fp.write("Z_FUTEX_DATA_INITIALIZER(futex_data[%d])" % i) |
Ulf Magnusson | d4c851c | 2019-09-02 11:11:22 +0200 | [diff] [blame] | 183 | if i != num_futex - 1: |
Wentong Wu | 5611e92 | 2019-06-20 23:51:27 +0800 | [diff] [blame] | 184 | fp.write(", ") |
| 185 | fp.write("};\n") |
| 186 | |
Andrew Boie | f083567 | 2019-03-27 15:44:52 -0700 | [diff] [blame] | 187 | fp.write("%%\n") |
Daniel Leung | e58b654 | 2018-08-08 11:23:16 -0700 | [diff] [blame] | 188 | # Setup variables for mapping thread indexes |
| 189 | syms = eh.get_symbols() |
| 190 | thread_max_bytes = syms["CONFIG_MAX_THREAD_BYTES"] |
| 191 | thread_idx_map = {} |
| 192 | |
| 193 | for i in range(0, thread_max_bytes): |
| 194 | thread_idx_map[i] = 0xFF |
| 195 | |
Andrew Boie | bca15da | 2017-10-15 14:17:48 -0700 | [diff] [blame] | 196 | for obj_addr, ko in objs.items(): |
| 197 | obj_type = ko.type_name |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 198 | # pre-initialized objects fall within this memory range, they are |
| 199 | # either completely initialized at build time, or done automatically |
| 200 | # at boot during some PRE_KERNEL_* phase |
Ulf Magnusson | 3206e42 | 2019-09-03 15:05:01 +0200 | [diff] [blame] | 201 | initialized = static_begin <= obj_addr < static_end |
Andrew Boie | 7875707 | 2019-07-23 13:29:30 -0700 | [diff] [blame] | 202 | is_driver = obj_type.startswith("K_OBJ_DRIVER_") |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 203 | |
Andrew Boie | f290ab5 | 2019-11-18 17:06:13 -0800 | [diff] [blame] | 204 | if "CONFIG_64BIT" in syms: |
| 205 | format_code = "Q" |
| 206 | else: |
| 207 | format_code = "I" |
| 208 | |
| 209 | if eh.little_endian: |
| 210 | endian = "<" |
| 211 | else: |
| 212 | endian = ">" |
| 213 | |
| 214 | byte_str = struct.pack(endian + format_code, obj_addr) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 215 | fp.write("\"") |
| 216 | for byte in byte_str: |
| 217 | val = "\\x%02x" % byte |
| 218 | fp.write(val) |
| 219 | |
Andrew Boie | 7875707 | 2019-07-23 13:29:30 -0700 | [diff] [blame] | 220 | flags = "0" |
Ulf Magnusson | d4c851c | 2019-09-02 11:11:22 +0200 | [diff] [blame] | 221 | if initialized: |
Andrew Boie | 7875707 | 2019-07-23 13:29:30 -0700 | [diff] [blame] | 222 | flags += " | K_OBJ_FLAG_INITIALIZED" |
Ulf Magnusson | d4c851c | 2019-09-02 11:11:22 +0200 | [diff] [blame] | 223 | if is_driver: |
Andrew Boie | 7875707 | 2019-07-23 13:29:30 -0700 | [diff] [blame] | 224 | flags += " | K_OBJ_FLAG_DRIVER" |
| 225 | |
| 226 | fp.write("\", {}, %s, %s, %s\n" % (obj_type, flags, str(ko.data))) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 227 | |
Daniel Leung | e58b654 | 2018-08-08 11:23:16 -0700 | [diff] [blame] | 228 | if obj_type == "K_OBJ_THREAD": |
| 229 | idx = math.floor(ko.data / 8) |
| 230 | bit = ko.data % 8 |
| 231 | thread_idx_map[idx] = thread_idx_map[idx] & ~(2**bit) |
| 232 | |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 233 | fp.write(footer) |
| 234 | |
Daniel Leung | e58b654 | 2018-08-08 11:23:16 -0700 | [diff] [blame] | 235 | # Generate the array of already mapped thread indexes |
| 236 | fp.write('\n') |
Andrew Boie | 9b34ecd | 2020-01-08 17:37:11 -0800 | [diff] [blame] | 237 | fp.write('Z_GENERIC_SECTION(.kobject_data.data) ') |
Daniel Leung | e58b654 | 2018-08-08 11:23:16 -0700 | [diff] [blame] | 238 | fp.write('u8_t _thread_idx_map[%d] = {' % (thread_max_bytes)) |
| 239 | |
| 240 | for i in range(0, thread_max_bytes): |
| 241 | fp.write(' 0x%x, ' % (thread_idx_map[i])) |
| 242 | |
| 243 | fp.write('};\n') |
| 244 | |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 245 | |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 246 | driver_macro_tpl = """ |
Andrew Boie | 8345e5e | 2018-05-04 15:57:57 -0700 | [diff] [blame] | 247 | #define Z_SYSCALL_DRIVER_%(driver_upper)s(ptr, op) Z_SYSCALL_DRIVER_GEN(ptr, op, %(driver_lower)s, %(driver_upper)s) |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 248 | """ |
| 249 | |
Anas Nashif | 7a08b2b | 2018-09-16 14:54:44 -0500 | [diff] [blame] | 250 | |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 251 | def write_validation_output(fp): |
Flavio Ceolin | a7fffa9 | 2018-09-13 15:06:35 -0700 | [diff] [blame] | 252 | fp.write("#ifndef DRIVER_VALIDATION_GEN_H\n") |
| 253 | fp.write("#define DRIVER_VALIDATION_GEN_H\n") |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 254 | |
Andrew Boie | 8345e5e | 2018-05-04 15:57:57 -0700 | [diff] [blame] | 255 | fp.write("""#define Z_SYSCALL_DRIVER_GEN(ptr, op, driver_lower_case, driver_upper_case) \\ |
| 256 | (Z_SYSCALL_OBJ(ptr, K_OBJ_DRIVER_##driver_upper_case) || \\ |
| 257 | Z_SYSCALL_DRIVER_OP(ptr, driver_lower_case##_driver_api, op)) |
| 258 | """) |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 259 | |
| 260 | for subsystem in subsystems: |
| 261 | subsystem = subsystem.replace("_driver_api", "") |
| 262 | |
| 263 | fp.write(driver_macro_tpl % { |
| 264 | "driver_lower": subsystem.lower(), |
| 265 | "driver_upper": subsystem.upper(), |
| 266 | }) |
| 267 | |
Flavio Ceolin | a7fffa9 | 2018-09-13 15:06:35 -0700 | [diff] [blame] | 268 | fp.write("#endif /* DRIVER_VALIDATION_GEN_H */\n") |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 269 | |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 270 | |
| 271 | def write_kobj_types_output(fp): |
| 272 | fp.write("/* Core kernel objects */\n") |
Andrew Boie | c235e16 | 2019-03-27 14:27:24 -0700 | [diff] [blame] | 273 | for kobj, obj_info in kobjects.items(): |
| 274 | dep, _ = obj_info |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 275 | if kobj == "device": |
| 276 | continue |
| 277 | |
Andrew Boie | 09c22cc | 2018-06-27 10:25:45 -0700 | [diff] [blame] | 278 | if dep: |
| 279 | fp.write("#ifdef %s\n" % dep) |
| 280 | |
Andrew Boie | f20efcf | 2018-05-23 10:57:39 -0700 | [diff] [blame] | 281 | fp.write("%s,\n" % kobject_to_enum(kobj)) |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 282 | |
Andrew Boie | 09c22cc | 2018-06-27 10:25:45 -0700 | [diff] [blame] | 283 | if dep: |
| 284 | fp.write("#endif\n") |
| 285 | |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 286 | fp.write("/* Driver subsystems */\n") |
| 287 | for subsystem in subsystems: |
| 288 | subsystem = subsystem.replace("_driver_api", "").upper() |
| 289 | fp.write("K_OBJ_DRIVER_%s,\n" % subsystem) |
| 290 | |
| 291 | |
| 292 | def write_kobj_otype_output(fp): |
| 293 | fp.write("/* Core kernel objects */\n") |
Andrew Boie | c235e16 | 2019-03-27 14:27:24 -0700 | [diff] [blame] | 294 | for kobj, obj_info in kobjects.items(): |
| 295 | dep, _ = obj_info |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 296 | if kobj == "device": |
| 297 | continue |
| 298 | |
Andrew Boie | 09c22cc | 2018-06-27 10:25:45 -0700 | [diff] [blame] | 299 | if dep: |
| 300 | fp.write("#ifdef %s\n" % dep) |
| 301 | |
Anas Nashif | 7a08b2b | 2018-09-16 14:54:44 -0500 | [diff] [blame] | 302 | fp.write('case %s: ret = "%s"; break;\n' % |
| 303 | (kobject_to_enum(kobj), kobj)) |
Andrew Boie | 09c22cc | 2018-06-27 10:25:45 -0700 | [diff] [blame] | 304 | if dep: |
| 305 | fp.write("#endif\n") |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 306 | |
| 307 | fp.write("/* Driver subsystems */\n") |
| 308 | for subsystem in subsystems: |
| 309 | subsystem = subsystem.replace("_driver_api", "") |
Flavio Ceolin | 3259ac0 | 2018-09-11 13:14:21 -0700 | [diff] [blame] | 310 | fp.write('case K_OBJ_DRIVER_%s: ret = "%s driver"; break;\n' % ( |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 311 | subsystem.upper(), |
| 312 | subsystem |
| 313 | )) |
| 314 | |
Anas Nashif | 7a08b2b | 2018-09-16 14:54:44 -0500 | [diff] [blame] | 315 | |
Andrew Boie | 47fa8eb | 2018-05-16 10:11:17 -0700 | [diff] [blame] | 316 | def write_kobj_size_output(fp): |
| 317 | fp.write("/* Non device/stack objects */\n") |
Andrew Boie | c235e16 | 2019-03-27 14:27:24 -0700 | [diff] [blame] | 318 | for kobj, obj_info in kobjects.items(): |
| 319 | dep, _ = obj_info |
Andrew Boie | 47fa8eb | 2018-05-16 10:11:17 -0700 | [diff] [blame] | 320 | # device handled by default case. Stacks are not currently handled, |
| 321 | # if they eventually are it will be a special case. |
Ulf Magnusson | 3feb8f9 | 2019-09-03 14:25:26 +0200 | [diff] [blame] | 322 | if kobj in {"device", "_k_thread_stack_element"}: |
Andrew Boie | 47fa8eb | 2018-05-16 10:11:17 -0700 | [diff] [blame] | 323 | continue |
| 324 | |
Andrew Boie | 09c22cc | 2018-06-27 10:25:45 -0700 | [diff] [blame] | 325 | if dep: |
| 326 | fp.write("#ifdef %s\n" % dep) |
| 327 | |
Flavio Ceolin | 3259ac0 | 2018-09-11 13:14:21 -0700 | [diff] [blame] | 328 | fp.write('case %s: ret = sizeof(struct %s); break;\n' % |
Anas Nashif | 7a08b2b | 2018-09-16 14:54:44 -0500 | [diff] [blame] | 329 | (kobject_to_enum(kobj), kobj)) |
Andrew Boie | 09c22cc | 2018-06-27 10:25:45 -0700 | [diff] [blame] | 330 | if dep: |
| 331 | fp.write("#endif\n") |
| 332 | |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 333 | |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 334 | def parse_args(): |
| 335 | global args |
| 336 | |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 337 | parser = argparse.ArgumentParser( |
| 338 | description=__doc__, |
| 339 | formatter_class=argparse.RawDescriptionHelpFormatter) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 340 | |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 341 | parser.add_argument("-k", "--kernel", required=False, |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 342 | help="Input zephyr ELF binary") |
| 343 | parser.add_argument( |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 344 | "-g", "--gperf-output", required=False, |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 345 | help="Output list of kernel object addresses for gperf use") |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 346 | parser.add_argument( |
| 347 | "-V", "--validation-output", required=False, |
| 348 | help="Output driver validation macros") |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 349 | parser.add_argument( |
| 350 | "-K", "--kobj-types-output", required=False, |
Marc Herbert | 4a10eea | 2019-04-16 15:39:45 -0700 | [diff] [blame] | 351 | help="Output k_object enum constants") |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 352 | parser.add_argument( |
| 353 | "-S", "--kobj-otype-output", required=False, |
| 354 | help="Output case statements for otype_to_str()") |
Andrew Boie | 47fa8eb | 2018-05-16 10:11:17 -0700 | [diff] [blame] | 355 | parser.add_argument( |
| 356 | "-Z", "--kobj-size-output", required=False, |
| 357 | help="Output case statements for obj_size_get()") |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 358 | parser.add_argument("-v", "--verbose", action="store_true", |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 359 | help="Print extra debugging information") |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 360 | args = parser.parse_args() |
Sebastian Bøe | 4971d2a | 2017-12-28 17:34:50 +0100 | [diff] [blame] | 361 | if "VERBOSE" in os.environ: |
| 362 | args.verbose = 1 |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 363 | |
| 364 | |
| 365 | def main(): |
| 366 | parse_args() |
| 367 | |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 368 | if args.gperf_output: |
Marc Herbert | f78288b | 2019-03-05 14:31:44 -0800 | [diff] [blame] | 369 | assert args.kernel, "--kernel ELF required for --gperf-output" |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 370 | eh = ElfHelper(args.kernel, args.verbose, kobjects, subsystems) |
| 371 | syms = eh.get_symbols() |
| 372 | max_threads = syms["CONFIG_MAX_THREAD_BYTES"] * 8 |
| 373 | objs = eh.find_kobjects(syms) |
Marc Herbert | f78288b | 2019-03-05 14:31:44 -0800 | [diff] [blame] | 374 | if not objs: |
| 375 | sys.stderr.write("WARNING: zero kobject found in %s\n" |
| 376 | % args.kernel) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 377 | |
Anas Nashif | 7a08b2b | 2018-09-16 14:54:44 -0500 | [diff] [blame] | 378 | thread_counter = eh.get_thread_counter() |
| 379 | if thread_counter > max_threads: |
Ulf Magnusson | 50b9b12 | 2019-09-07 14:41:01 +0200 | [diff] [blame] | 380 | sys.exit("Too many thread objects ({})\n" |
| 381 | "Increase CONFIG_MAX_THREAD_BYTES to {}" |
| 382 | .format(thread_counter, -(-thread_counter // 8))) |
Andrew Boie | 818a96d | 2017-11-03 09:00:35 -0700 | [diff] [blame] | 383 | |
Leandro Pereira | c200367 | 2018-04-04 13:50:32 -0700 | [diff] [blame] | 384 | with open(args.gperf_output, "w") as fp: |
| 385 | write_gperf_table(fp, eh, objs, |
| 386 | syms["_static_kernel_objects_begin"], |
| 387 | syms["_static_kernel_objects_end"]) |
| 388 | |
| 389 | if args.validation_output: |
| 390 | with open(args.validation_output, "w") as fp: |
| 391 | write_validation_output(fp) |
Anas Nashif | 7256553 | 2017-12-12 08:19:25 -0500 | [diff] [blame] | 392 | |
Leandro Pereira | 39dc7d0 | 2018-04-05 13:59:33 -0700 | [diff] [blame] | 393 | if args.kobj_types_output: |
| 394 | with open(args.kobj_types_output, "w") as fp: |
| 395 | write_kobj_types_output(fp) |
| 396 | |
| 397 | if args.kobj_otype_output: |
| 398 | with open(args.kobj_otype_output, "w") as fp: |
| 399 | write_kobj_otype_output(fp) |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 400 | |
Andrew Boie | 47fa8eb | 2018-05-16 10:11:17 -0700 | [diff] [blame] | 401 | if args.kobj_size_output: |
| 402 | with open(args.kobj_size_output, "w") as fp: |
| 403 | write_kobj_size_output(fp) |
| 404 | |
Anas Nashif | 7a08b2b | 2018-09-16 14:54:44 -0500 | [diff] [blame] | 405 | |
Andrew Boie | 945af95 | 2017-08-22 13:15:23 -0700 | [diff] [blame] | 406 | if __name__ == "__main__": |
| 407 | main() |