|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
ELF32 image services for the board emulator (load / symbols / vectors). More...
Go to the source code of this file.
Data Structures | |
| struct | emu_elf_io_result_t |
| Exact result for source open and bounded view acquisition. More... | |
| struct | emu_elf_source_t |
| One independently owned immutable raw-descriptor ELF source. More... | |
| struct | emu_elf_view_t |
| Transient view into caller-owned bounded scratch. More... | |
| struct | elf_exec_segment_t |
| One executable PT_LOAD segment, already bounds-checked against the image. More... | |
| struct | emu_elf_symbol_t |
| One bounds-checked symbol-table entry plus its string offset. More... | |
Typedefs | |
| typedef bool(* | elf_exec_segment_fn) (const elf_exec_segment_t *seg, void *ctx) |
| Per-segment callback for elf_foreach_exec_segment. | |
| typedef bool(* | emu_elf_symbol_fn) (const emu_elf_symbol_t *symbol, void *ctx) |
| Callback invoked for each bounds-checked ELF symbol entry. | |
| typedef bool(* | emu_elf_string_fn) (const char *bytes, size_t length, void *ctx) |
| Callback receiving one non-empty chunk of an ELF string. | |
Enumerations | |
| enum | emu_elf_layout_t : uint32_t { k_elf_ehdr_size = 52U , k_elf_em_arm = 40U , k_elf_e_machine_off = 18U , k_elf_e_phoff_off = 28U , k_elf_e_phentsize_off = 42U , k_elf_e_phnum_off = 44U , k_elf_ph_offset_off = 4U , k_elf_ph_vaddr_off = 8U , k_elf_ph_paddr_off = 12U , k_elf_ph_filesz_off = 16U , k_elf_ph_flags_off = 24U , k_elf_pf_x = 1U , k_elf_pt_load = 1U , k_elf_shentsize_min = 40U , k_elf_sh_size_off = 20U , k_elf_sh_link_off = 24U , k_elf_sh_entsize_off = 36U , k_elf_sym_info_off = 12U , k_elf_st_type_mask = 0x0FU } |
| ELF32 file-layout constants (header sizes and field byte offsets). More... | |
| enum | emu_elf_io_status_t : uint8_t { k_emu_elf_io_ok = 0U , k_emu_elf_io_invalid , k_emu_elf_io_capacity , k_emu_elf_io_eof , k_emu_elf_io_error } |
| Status for bounded raw-descriptor ELF source operations. More... | |
Functions | |
| int | load_elf (uc_engine *uc, const emu_elf_source_t *elf) |
| Load ELF32 PT_LOAD segments into emulated memory at their LMA. | |
| uint32_t | elf_vector_base (const emu_elf_source_t *elf) |
| Vector-table base of an ELF: lowest executable PT_LOAD VMA. | |
| uint32_t | elf_sym_addr (const emu_elf_source_t *elf, const char *name, uint32_t *size_out) |
| Resolve a function symbol's entry address from the ELF .symtab. | |
| uint32_t | warm_reboot (uc_engine *uc, const emu_elf_source_t *elf, bool trace) |
| Warm-reboot the firmware: re-run from the reset vector in place. | |
| uint32_t | elf_foreach_load_segment (const emu_elf_source_t *elf, elf_exec_segment_fn fn, void *ctx) |
| Walk every non-empty, bounds-checked PT_LOAD segment. | |
| uint32_t | elf_foreach_exec_segment (const emu_elf_source_t *elf, elf_exec_segment_fn fn, void *ctx) |
| Walk every executable PT_LOAD segment of an ELF32 image. | |
| uint32_t | elf_foreach_symbol (const emu_elf_source_t *elf, emu_elf_symbol_fn fn, void *ctx) |
| Walk every symbol in every usable SHT_SYMTAB section. | |
| bool | elf_string_foreach (const emu_elf_source_t *elf, uint64_t offset, emu_elf_string_fn fn, void *ctx) |
| Stream one NUL-terminated ELF string through bounded stack chunks. | |
ELF32 image services for the board emulator (load / symbols / vectors).
The emulator's view of a firmware image: retain an immutable raw descriptor, stream PT_LOAD segments into Unicorn memory at their LMA, resolve symbols from the .symtab (for the seam installers, --dump-sym and --stop-sym), and derive the vector-table base of an image (for the TrustZone Non-Secure world switch). The raw ELF32 field offsets live here too so every scanner (MVE / long-shift / div-0 seam installs, the profiler's symbol collection) parses program and section headers with one shared set of named constants.
Split out of the ra8_emulator main translation unit; the behaviour is the emulator's original ELF handling, moved verbatim.
Definition in file emu_elf.h.
| typedef bool(* elf_exec_segment_fn) (const elf_exec_segment_t *seg, void *ctx) |
Per-segment callback for elf_foreach_exec_segment.
| [in] | seg | Segment to scan. |
| [in] | ctx | Opaque pointer forwarded from the caller. |
| typedef bool(* emu_elf_string_fn) (const char *bytes, size_t length, void *ctx) |
| typedef bool(* emu_elf_symbol_fn) (const emu_elf_symbol_t *symbol, void *ctx) |
| enum emu_elf_io_status_t : uint8_t |
Status for bounded raw-descriptor ELF source operations.
| enum emu_elf_layout_t : uint32_t |
ELF32 file-layout constants (header sizes and field byte offsets).
Named offsets into the little-endian ELF32 file header, program headers, section headers, and symbol-table entries, as fixed by the System V ABI. Shared by the segment loader, the symbol resolver, and every image scanner that walks executable PT_LOAD segments (seam installers, profiler).
| uint32_t elf_foreach_exec_segment | ( | const emu_elf_source_t * | elf, |
| elf_exec_segment_fn | fn, | ||
| void * | ctx ) |
Walk every executable PT_LOAD segment of an ELF32 image.
Decodes the program-header table once, skips any segment that is not a non-empty executable PT_LOAD or that would run past the end of the image, and invokes fn for each survivor. Factored out because the seam installers and the profiler each need exactly this walk; duplicating it left the same twenty statements of bounds-checking in several functions, where a fix to one copy would silently miss the others.
| [in] | elf | Open source; every read is bounded by its captured length. |
| [in] | fn | Callback invoked per executable segment. |
| [in,out] | ctx | Opaque pointer forwarded to fn. |
fn. | 0 | The image is too short, the header table is truncated, or the image carries no executable PT_LOAD segment. |
elf remains open for the complete walk. fn is non-NULL. fn returns false.Definition at line 265 of file emu_elf.c.
References emu_elf_program_table_t::count, elf_exec_segment_t::flags, internal_load_segment(), internal_program_table(), and k_elf_pf_x.
Referenced by div0_seam_install(), elf_vector_base(), and long_shift_seam_install().
| uint32_t elf_foreach_load_segment | ( | const emu_elf_source_t * | elf, |
| elf_exec_segment_fn | fn, | ||
| void * | ctx ) |
Walk every non-empty, bounds-checked PT_LOAD segment.
Decodes each usable load header and publishes only source offsets.
| [in] | elf | Open immutable ELF source. |
| [in] | fn | Callback invoked for each segment. |
| [in,out] | ctx | Opaque callback context. |
fn. | 0 | The header is malformed or no load segment was delivered. |
elf remains open for the complete walk. fn is non-null. fn returns false. Definition at line 172 of file emu_elf.c.
References emu_elf_program_table_t::count, internal_load_segment(), and internal_program_table().
Referenced by internal_cpu1_image_present(), and load_elf().
| uint32_t elf_foreach_symbol | ( | const emu_elf_source_t * | elf, |
| emu_elf_symbol_fn | fn, | ||
| void * | ctx ) |
Walk every symbol in every usable SHT_SYMTAB section.
Decodes bounded entries and retains only absolute name offsets.
| [in] | elf | Open immutable ELF source. |
| [in] | fn | Callback invoked for each decoded entry. |
| [in,out] | ctx | Opaque callback context. |
fn. | 0 | The table is malformed or no symbol was delivered. |
elf remains open for the complete walk. fn is non-null. fn returns false. Definition at line 274 of file emu_elf_symbols.c.
References emu_elf_section_table_t::count, internal_section_read(), internal_section_table(), internal_symbol_table(), internal_symbol_walk(), and k_elf_shentsize_min.
Referenced by elf_sym_addr(), and prof_load().
| bool elf_string_foreach | ( | const emu_elf_source_t * | elf, |
| uint64_t | offset, | ||
| emu_elf_string_fn | fn, | ||
| void * | ctx ) |
Stream one NUL-terminated ELF string through bounded stack chunks.
Reads at most 256 bytes per step and never retains source bytes.
| [in] | elf | Open immutable ELF source. |
| [in] | offset | Absolute first string byte. |
| [in] | fn | Chunk consumer. |
| [in,out] | ctx | Opaque callback context. |
| true | A terminating NUL was found and every callback accepted. |
| false | A read failed, no NUL was found, or the callback stopped. |
elf remains open through the stream. fn is non-null. Definition at line 298 of file emu_elf_symbols.c.
References internal_symbol_read(), k_elf_string_chunk, emu_elf_source_t::length, and memchr().
Referenced by internal_lookup_symbol(), and internal_prof_name().
| uint32_t elf_sym_addr | ( | const emu_elf_source_t * | elf, |
| const char * | name, | ||
| uint32_t * | size_out ) |
Resolve a function symbol's entry address from the ELF .symtab.
Walks the ELF32 section headers for the SHT_SYMTAB table and its linked string table, then matches name and returns its st_value with the Thumb bit cleared (so it can be used as a UC_HOOK_CODE address). Used by the seam installers to shim first-party firmware APIs and by the --dump-sym / --stop-sym probes. Returns 0 if the symbol (or a symbol table) is absent.
| [in] | elf | Open immutable ELF source. |
| [in] | name | NUL-terminated symbol name to find. |
| [out] | size_out | If non-NULL, receives the symbol's st_size (0 if absent). |
| 0 | Symbol not present, or the image carries no symbol table. |
elf remains open throughout the bounded symbol walk. name is NUL-terminated. size_out (when non-NULL) holds the symbol size. Definition at line 401 of file emu_elf_symbols.c.
References emu_elf_lookup_t::address, elf_foreach_symbol(), internal_lookup_symbol(), emu_elf_source_t::length, emu_elf_lookup_t::size, and strlen().
Referenced by emu_tz_install(), emu_tz_patch_cmse(), eth_seam_hook(), fast_sd_seam_install(), internal_main_resolve_symbols(), sym_trace_install(), and usbh_seam_install().
| uint32_t elf_vector_base | ( | const emu_elf_source_t * | elf | ) |
Vector-table base of an ELF: lowest executable PT_LOAD VMA.
Walks the program headers and returns the lowest p_vaddr among non-empty, executable (PF_X) PT_LOAD segments. On Cortex-M the vector table is linked at the start of the executable text region, so this is the image's vector base: 0x32100000 for the RAM-resident NS layout (a single RWE segment runs from the NS_SRAM2 alias) and 0x90000000 for the OSPI-XIP layout (the R-E segment executes in place from the flash window). The executable filter is essential for XIP: that image also carries a writable .data segment whose VMA is 0x32100000 (its initialisers live in flash, copied to RAM at NS startup) – lower than the vectors – so a plain minimum-VMA scan would wrongly pick the RAM alias. ra8_emulator feeds the result to the TrustZone NS vector-base tracking so the BLXNS world switch reads the NS MSP/reset from wherever the loaded image placed them.
| [in] | elf | Open ELF source (little-endian ELF32 ARM). |
| 0 | No executable PT_LOAD segment, or a truncated header table. |
elf remains open throughout the bounded header walk. Definition at line 320 of file emu_elf.c.
References emu_elf_vector_ctx_t::base, elf_foreach_exec_segment(), emu_elf_vector_ctx_t::found, and internal_vector_segment().
Referenced by internal_main_load_ns().
| int load_elf | ( | uc_engine * | uc, |
| const emu_elf_source_t * | elf ) |
Load ELF32 PT_LOAD segments into emulated memory at their LMA.
Validates the ELF magic, class (ELFCLASS32) and machine (EM_ARM), then walks the program headers and writes each non-empty PT_LOAD segment's file bytes to its physical load address (p_paddr) in uc memory – exactly what a flash programmer does with the image. One loaded ... @ ... injected error sink line is emitted per segment. .bss is untouched (the firmware's own Reset_Handler zeroes it), matching real boot.
| [in,out] | uc | Unicorn engine whose memory receives the segments. |
| [in] | elf | Open immutable ELF source. |
| 0 | At least one PT_LOAD segment was written. |
| -1 | Not a 32-bit ARM ELF, or a segment write failed, or no segment was loadable. |
uc has every segment's target region mapped. elf remains open for the complete segment walk. Definition at line 248 of file emu_elf.c.
References elf_foreach_load_segment(), emu_elf_load_ctx_t::failed, internal_program_table(), internal_stream_segment(), k_elf_em_arm, emu_elf_load_ctx_t::loaded, and priv_emu_io_errf().
Referenced by internal_cpu1_engine_init(), internal_main_load_ns(), internal_main_load_primary(), and warm_reboot().
| uint32_t warm_reboot | ( | uc_engine * | uc, |
| const emu_elf_source_t * | elf, | ||
| bool | trace ) |
Warm-reboot the firmware: re-run from the reset vector in place.
Mirrors a Cortex-M reset without tearing down the Unicorn engine. Restores the code image and the .data initial values by re-writing the ELF's PT_LOAD segments (the firmware's own Reset_Handler then re-zeroes .bss and re-copies .data), re-reads SP/PC from the vector table, resets the peripheral models (the reset-cause RSTSRn and the VBATT backup domain deliberately survive their reset hooks, so the reboot cause and battery-backed state persist), and clears the host-side exception / scheduler bookkeeping so the next boot starts clean. The installed Unicorn hooks persist across this, so they are NOT re-added, and one-shot CLI input (–keys / –input / –usb-in) is NOT re-injected.
| [in,out] | uc | Unicorn engine to reboot (kept alive). |
| [in] | elf | Open firmware source whose segments are re-loaded. |
| [in] | trace | Whether –trace is active (forwarded to the models). |
| 0 | The image re-load failed; the caller must end the run. |
elf loaded successfully at startup and remains open. Definition at line 24 of file emu_elf_reboot.c.
References board_console_reset(), board_net_init(), board_periph_init(), emu_console_reset(), emu_div0_clear_fault(), emu_div0_disarm(), emu_exc_reset(), emu_mem_read(), emu_memmap_mram_base(), emu_mpu_clear_fault(), emu_view_reset_console(), k_xpsr_t_bit, load_elf(), and priv_emu_io_errf().
Referenced by internal_run_loop_prologue(), and internal_run_loop_run_chunk().