ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
emu_elf.h File Reference

ELF32 image services for the board emulator (load / symbols / vectors). More...

#include <stddef.h>
#include <stdint.h>
#include <unicorn/unicorn.h>
#include "ra8_attributes.h"
Include dependency graph for emu_elf.h:
This graph shows which files directly or indirectly include this file:

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.

Detailed Description

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.

Since
0.1.0

Definition in file emu_elf.h.

Typedef Documentation

◆ elf_exec_segment_fn

typedef bool(* elf_exec_segment_fn) (const elf_exec_segment_t *seg, void *ctx)

Per-segment callback for elf_foreach_exec_segment.

Parameters
[in]segSegment to scan.
[in]ctxOpaque pointer forwarded from the caller.
Returns
True to keep walking, false to stop early (e.g. a site cap was hit).
Since
0.1.0

Definition at line 255 of file emu_elf.h.

◆ emu_elf_string_fn

typedef bool(* emu_elf_string_fn) (const char *bytes, size_t length, void *ctx)

Callback receiving one non-empty chunk of an ELF string.

Definition at line 335 of file emu_elf.h.

◆ emu_elf_symbol_fn

typedef bool(* emu_elf_symbol_fn) (const emu_elf_symbol_t *symbol, void *ctx)

Callback invoked for each bounds-checked ELF symbol entry.

Definition at line 315 of file emu_elf.h.

Enumeration Type Documentation

◆ emu_elf_io_status_t

enum emu_elf_io_status_t : uint8_t

Status for bounded raw-descriptor ELF source operations.

Enumerator
k_emu_elf_io_ok 

The complete operation succeeded.

k_emu_elf_io_invalid 

A pointer, descriptor, range, or path was bad.

k_emu_elf_io_capacity 

Caller scratch is smaller than required.

k_emu_elf_io_eof 

The source ended during an exact read.

k_emu_elf_io_error 

A host operation failed.

Definition at line 74 of file emu_elf.h.

◆ emu_elf_layout_t

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).

Invariant
Values match the ELF32 object-file format; they are file-format facts, not tunables.
See also
load_elf() Walks program headers using these offsets.
elf_sym_addr() Walks section headers / .symtab using these offsets.
Since
0.1.0
Enumerator
k_elf_ehdr_size 

ELF32 file-header size.

k_elf_em_arm 

e_machine == EM_ARM.

k_elf_e_machine_off 

e_machine in the file header.

k_elf_e_phoff_off 

e_phoff in the file header.

k_elf_e_phentsize_off 

e_phentsize in the file header.

k_elf_e_phnum_off 

e_phnum in the file header.

k_elf_ph_offset_off 

p_offset in a program header.

k_elf_ph_vaddr_off 

p_vaddr (VMA) in a program header.

k_elf_ph_paddr_off 

p_paddr in a program header.

k_elf_ph_filesz_off 

p_filesz in a program header.

k_elf_ph_flags_off 

p_flags in a program header.

k_elf_pf_x 

PF_X: segment is executable.

k_elf_pt_load 

p_type == PT_LOAD.

k_elf_shentsize_min 

ELF32 section-header entry size.

k_elf_sh_size_off 

sh_size in a section header.

k_elf_sh_link_off 

sh_link in a section header.

k_elf_sh_entsize_off 

sh_entsize in a section header.

k_elf_sym_info_off 

st_info in a symbol-table entry.

k_elf_st_type_mask 

Low nibble of st_info is the type.

Definition at line 51 of file emu_elf.h.

Function Documentation

◆ elf_foreach_exec_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.

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.

Parameters
[in]elfOpen source; every read is bounded by its captured length.
[in]fnCallback invoked per executable segment.
[in,out]ctxOpaque pointer forwarded to fn.
Returns
The number of segments handed to fn.
Return values
0The image is too short, the header table is truncated, or the image carries no executable PT_LOAD segment.
Precondition
elf remains open for the complete walk.
fn is non-NULL.
Postcondition
No read touches a byte at or beyond elf->length.
The walk stops early once fn returns false.
Note
Independent source instances may be walked concurrently.
See also
div0_seam_install() Scans for UDIV/SDIV sites.
long_shift_seam_install() Scans for LSLL/LSRL/ASRL sites.
Since
0.1.0

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().

◆ elf_foreach_load_segment()

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.

Parameters
[in]elfOpen immutable ELF source.
[in]fnCallback invoked for each segment.
[in,out]ctxOpaque callback context.
Returns
Number of load segments handed to fn.
Return values
0The header is malformed or no load segment was delivered.
Precondition
elf remains open for the complete walk.
fn is non-null.
Postcondition
No segment range crosses the source length.
Iteration stops when fn returns false.
Note
Segment descriptors borrow only the source context, never file bytes.
Since
0.1.0

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().

◆ elf_foreach_symbol()

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.

Parameters
[in]elfOpen immutable ELF source.
[in]fnCallback invoked for each decoded entry.
[in,out]ctxOpaque callback context.
Returns
Number of symbol entries handed to fn.
Return values
0The table is malformed or no symbol was delivered.
Precondition
elf remains open for the complete walk.
fn is non-null.
Postcondition
Malformed tables are skipped without out-of-range reads.
Iteration stops when fn returns false.
Note
Uses only bounded stack views and retains no source pointers.
Since
0.1.0

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().

◆ elf_string_foreach()

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.

Parameters
[in]elfOpen immutable ELF source.
[in]offsetAbsolute first string byte.
[in]fnChunk consumer.
[in,out]ctxOpaque callback context.
Returns
True only when a terminating NUL was found and every callback accepted.
Return values
trueA terminating NUL was found and every callback accepted.
falseA read failed, no NUL was found, or the callback stopped.
Precondition
elf remains open through the stream.
fn is non-null.
Postcondition
No callback chunk contains the terminating NUL.
No read crosses elf->length.
Note
The callback must consume each transient chunk before returning.
Since
0.1.0

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().

◆ elf_sym_addr()

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.

Parameters
[in]elfOpen immutable ELF source.
[in]nameNUL-terminated symbol name to find.
[out]size_outIf non-NULL, receives the symbol's st_size (0 if absent).
Returns
Even (Thumb-cleared) symbol address, or 0 if not found.
Return values
0Symbol not present, or the image carries no symbol table.
Precondition
elf remains open throughout the bounded symbol walk.
name is NUL-terminated.
Postcondition
On a hit, size_out (when non-NULL) holds the symbol size.
The source and its descriptor cursor are unmodified.
Note
Not thread-safe; ra8_emulator is single-threaded.
See also
elf_vector_base() The segment-level companion lookup.
Since
0.1.0

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().

◆ elf_vector_base()

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.

Parameters
[in]elfOpen ELF source (little-endian ELF32 ARM).
Returns
Lowest executable PT_LOAD p_vaddr, or 0 if none / the header is bad.
Return values
0No executable PT_LOAD segment, or a truncated header table.
Precondition
elf remains open throughout the bounded header walk.
The program-header table lies within elf->length.
Postcondition
The return value is the VMA of some executable PT_LOAD segment, or 0.
Note
Not thread-safe; ra8_emulator is single-threaded.
See also
elf_sym_addr() The symbol-level companion lookup.
Since
0.1.0
Postcondition
Ownership of caller-supplied storage is unchanged.

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().

◆ load_elf()

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.

Parameters
[in,out]ucUnicorn engine whose memory receives the segments.
[in]elfOpen immutable ELF source.
Returns
0 on success, -1 on a malformed image or a failed memory write.
Return values
0At least one PT_LOAD segment was written.
-1Not a 32-bit ARM ELF, or a segment write failed, or no segment was loadable.
Precondition
uc has every segment's target region mapped.
elf remains open for the complete segment walk.
Postcondition
On success, every non-empty PT_LOAD segment is resident at its LMA.
On failure, a diagnostic has been printed to injected error sink.
Note
Not thread-safe; call during single-threaded setup or a warm reboot.
See also
priv_emu_elf_source_open() Acquires the source this consumes.
Since
0.1.0

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().

◆ 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.

Parameters
[in,out]ucUnicorn engine to reboot (kept alive).
[in]elfOpen firmware source whose segments are re-loaded.
[in]traceWhether –trace is active (forwarded to the models).
Returns
The reset-vector PC to resume the run loop from (Thumb bit set).
Return values
0The image re-load failed; the caller must end the run.
Precondition
The same elf loaded successfully at startup and remains open.
The engine is idle (between chunks).
Postcondition
On success the core state matches a fresh boot of the image.
Note
Not thread-safe; the emulator is single-threaded host-side.
See also
load_elf() Performs the segment re-write.
Since
0.1.0
Postcondition
Ownership of caller-supplied storage is unchanged.

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().