23typedef enum : uint32_t {
52 return (uint16_t)((uint16_t)bytes[0] | ((uint16_t)bytes[1] << 8U));
70 return (uint32_t)bytes[0] | ((uint32_t)bytes[1] << 8U) | ((uint32_t)bytes[2] << 16U) |
96 if (
priv_emu_elf_read(source, 0U,
sizeof(bytes), bytes,
sizeof(bytes), &view).status !=
114 const uint64_t table_bytes = (uint64_t)decoded.
entry_size * decoded.
count;
149 const uint64_t entry = (uint64_t)table->
offset + ((uint64_t)index * table->
entry_size);
150 if (
priv_emu_elf_read(source, entry,
sizeof(bytes), bytes,
sizeof(bytes), &view).status !=
157 if ((type != (uint32_t)
k_elf_pt_load) || (filesz == 0U) || ((uint64_t)offset > source->
length) ||
158 ((uint64_t)filesz > (source->
length - offset))) {
174 if ((elf ==
nullptr) || (fn ==
nullptr)) {
178 uint16_t machine = 0U;
182 uint32_t visited = 0U;
183 for (uint16_t index = 0U; index < table.
count; index++) {
189 if (!fn(&segment, ctx)) {
223 while (done < segment->filesz) {
224 const uint32_t remain = segment->
filesz - done;
225 const size_t chunk = (remain <
sizeof(scratch)) ? (
size_t)remain :
sizeof(scratch);
228 (uint64_t)segment->
offset + done,
241 done += (uint32_t)chunk;
251 uint16_t machine = 0U;
253 if ((machine == 0U) || (machine == (uint16_t)
k_elf_em_arm)) {
267 if ((elf ==
nullptr) || (fn ==
nullptr)) {
271 uint16_t machine = 0U;
275 uint32_t visited = 0U;
276 for (uint16_t index = 0U; index < table.
count; index++) {
283 if (!fn(&segment, ctx)) {
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.
emu_elf_stream_limit_t
Bounded parser and PT_LOAD transfer dimensions.
@ k_elf_data_offset
ELF identification data-byte offset.
@ k_elf_stream_scratch
Maximum transient segment bytes.
@ k_elf_word_high_shift
Shift of byte three in a word.
@ k_elf_program_header_min
ELF32 program-header bytes consumed.
static bool internal_vector_segment(const elf_exec_segment_t *segment, void *opaque)
Fold one executable segment into the lowest-VMA accumulator.
static bool internal_load_segment(const emu_elf_source_t *source, const emu_elf_program_table_t *table, uint16_t index, elf_exec_segment_t *segment)
Decode one bounds-checked PT_LOAD entry.
static uint16_t internal_u16(const uint8_t *bytes)
Decode one little-endian 16-bit ELF field.
static bool internal_program_table(const emu_elf_source_t *source, emu_elf_program_table_t *table, uint16_t *machine)
Read and validate the ELF32 ARM header and program-table geometry.
static uint32_t internal_u32(const uint8_t *bytes)
Decode one little-endian 32-bit ELF field.
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.
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.
static bool internal_stream_segment(const elf_exec_segment_t *segment, void *opaque)
Stream one PT_LOAD segment into Unicorn in bounded chunks.
ELF32 image services for the board emulator (load / symbols / vectors).
bool(* elf_exec_segment_fn)(const elf_exec_segment_t *seg, void *ctx)
Per-segment callback for elf_foreach_exec_segment.
@ k_elf_pf_x
PF_X: segment is executable.
@ k_elf_em_arm
e_machine == EM_ARM.
@ k_elf_ph_paddr_off
p_paddr in a program header.
@ k_elf_ph_flags_off
p_flags in a program header.
@ k_elf_e_machine_off
e_machine in the file header.
@ k_elf_ph_vaddr_off
p_vaddr (VMA) in a program header.
@ k_elf_e_phentsize_off
e_phentsize in the file header.
@ k_elf_e_phoff_off
e_phoff in the file header.
@ k_elf_e_phnum_off
e_phnum in the file header.
@ k_elf_ph_filesz_off
p_filesz in a program header.
@ k_elf_ehdr_size
ELF32 file-header size.
@ k_elf_ph_offset_off
p_offset in a program header.
@ k_elf_pt_load
p_type == PT_LOAD.
@ k_emu_elf_io_ok
The complete operation succeeded.
Private raw-descriptor ELF source operations.
emu_elf_io_result_t priv_emu_elf_read(const emu_elf_source_t *source, uint64_t offset, size_t required_bytes, void *scratch, size_t supplied_bytes, emu_elf_view_t *view)
Read one exact source range into caller-owned bounded scratch.
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
Central first-party Unicorn memory access seam.
uc_err emu_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t count)
Write guest memory through the central access seam.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
One executable PT_LOAD segment, already bounds-checked against the image.
uint32_t offset
Segment file offset.
uint32_t filesz
Segment file byte count.
const emu_elf_source_t * source
Open source owning segment bytes.
uint32_t paddr
Segment physical load address.
uint32_t vaddr
Segment virtual address.
uint32_t flags
ELF program-header flags.
Exact result for source open and bounded view acquisition.
emu_elf_io_status_t status
Semantic completion status.
Context for streaming PT_LOAD bytes into one Unicorn engine.
uc_engine * uc
Destination engine.
uint32_t loaded
Completely transferred segments.
bool failed
Sticky read/write failure.
Decoded program-header table geometry.
uint16_t count
Program-header entry count.
uint32_t offset
First program-header file offset.
uint16_t entry_size
Bytes per program-header entry.
One independently owned immutable raw-descriptor ELF source.
uint64_t length
Stat-derived parsing bound.
Accumulator for the lowest executable segment VMA.
uint32_t base
Current lowest VMA.
bool found
Whether any segment was seen.
Transient view into caller-owned bounded scratch.
const uint8_t * bytes
Scratch containing the exact source bytes.