libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
elf_reader.h
1#pragma once
2
4#include "libmicroemu/types.h"
5#include <cstddef>
6#include <cstdint>
7#include <iostream>
8#include <iterator>
9
10namespace libmicroemu::internal {
11
12class NullBuffer : public std::streambuf {
13public:
14 int overflow(int c) { return c; }
15};
16
17static NullBuffer null_buffer;
18static std::istream null_stream(&null_buffer);
19
20// ELF Header Strukturen
21struct Elf32_Ehdr {
22 u8 e_ident[16]; // Magic number and other info
23 u16 e_type; // Object file type
24 u16 e_machine; // Architecture
25 u32 e_version; // Object file version
26 u32 e_entry; // Entry point virtual address
27 u32 e_phoff; // Program header table file offset
28 u32 e_shoff; // Section header table file offset
29 u32 e_flags; // Processor-specific flags
30 u16 e_ehsize; // ELF header size in bytes
31 u16 e_phentsize; // Program header table entry size
32 u16 e_phnum; // Program header table entry count
33 u16 e_shentsize; // Section header table entry size
34 u16 e_shnum; // Section header table entry count
35 u16 e_shstrndx; // Section header string table index
36};
37
38struct Elf32_Phdr {
39 u32 p_type; // Segment type
40 u32 p_offset; // Segment file offset
41 u32 p_vaddr; // Segment virtual address
42 u32 p_paddr; // Segment physical address
43 u32 p_filesz; // Segment size in file
44 u32 p_memsz; // Segment size in memory
45 u32 p_flags; // Segment flags
46 u32 p_align; // Segment alignment
47};
48
49// Segmenttypen für ELF-Dateien
50enum SegmentType {
51 PT_NULL = 0, // Program header table entry unused
52 PT_LOAD = 1, // Loadable program segment
53 PT_DYNAMIC = 2, // Dynamic linking information
54 PT_INTERP = 3, // Program interpreter
55 PT_NOTE = 4, // Auxiliary information
56 PT_PHDR = 6, // Entry for header table itself
57 PT_ARM_EXIDX = 0x70000001 // Exception unwind tables
58};
59
60// Flags für ELF-Segmente
61enum SegmentFlags {
62 PF_X = 1 << 0, // Execute
63 PF_W = 1 << 1, // Write
64 PF_R = 1 << 2 // Read
65};
66
67class ElfReader {
68public:
69 class SegmentIterator {
70 public:
71 using iterator_category = std::input_iterator_tag;
72 using value_type = Elf32_Phdr;
73 using difference_type = decltype(static_cast<int *>(nullptr) - static_cast<int *>(nullptr));
74 using pointer = const Elf32_Phdr *;
75 using reference = const Elf32_Phdr &;
76
77 SegmentIterator(std::istream *file, std::streamoff pos, std::size_t index, std::size_t count)
78 : stream_(file), pos_(pos), index_(index), count_(count), phdr_() {
79 if (index_ < count_) {
80 stream_->seekg(pos_ + index_ * static_cast<std::streamoff>(sizeof(Elf32_Phdr)),
81 std::ios::beg);
82 stream_->read(reinterpret_cast<char *>(&phdr_), sizeof(Elf32_Phdr));
83 }
84 }
85
86 reference operator*() const { return phdr_; }
87 pointer operator->() const { return &phdr_; }
88
89 SegmentIterator &operator++() {
90 if (++index_ < count_) {
91 stream_->seekg(pos_ + index_ * static_cast<std::streamoff>(sizeof(Elf32_Phdr)),
92 std::ios::beg);
93 stream_->read(reinterpret_cast<char *>(&phdr_), sizeof(Elf32_Phdr));
94 }
95 return *this;
96 }
97
98 SegmentIterator operator++(int) {
99 SegmentIterator tmp(*this);
100 ++(*this);
101 return tmp;
102 }
103
104 bool operator==(const SegmentIterator &other) const { return index_ == other.index_; }
105 bool operator!=(const SegmentIterator &other) const { return index_ != other.index_; }
106
107 private:
108 std::istream *stream_;
109 std::streamoff pos_;
110 std::size_t index_;
111 std::size_t count_;
112 Elf32_Phdr phdr_;
113 };
114
115 static Result<ElfReader> ReadElf(std::istream &stream) {
116 // Read ELF header
117 Elf32_Ehdr ehdr;
118 stream.read(reinterpret_cast<char *>(&ehdr), sizeof(ehdr));
119 if (!stream) {
120 // Failed to read ELF header.
121 return Err<ElfReader>(StatusCode::kElfWrongHeader);
122 }
123
124 // Check if it's a valid ELF file
125 if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E' || ehdr.e_ident[2] != 'L' ||
126 ehdr.e_ident[3] != 'F') {
127 // Not a valid ELF file."
128 return Err<ElfReader>(StatusCode::kElfNotValid);
129 }
130
131 // Check if it's a 32-bit ELF file
132 if (ehdr.e_ident[4] != 1) {
133 // Not a 32-bit ELF file.
134 return Err<ElfReader>(StatusCode::kElfNotValid);
135 }
136
137 // Store program header offset, count, and entry point
138 return Ok(ElfReader(stream, ehdr.e_phoff, ehdr.e_phnum, ehdr.e_entry));
139 }
140
141 ~ElfReader() {}
142
143 SegmentIterator begin() { return SegmentIterator(&stream_, phoff_, 0, phnum_); }
144 SegmentIterator end() { return SegmentIterator(&stream_, phoff_, phnum_, phnum_); }
145
146 u32 GetEntryPoint() const { return entry_point_; }
147
148 Result<void> GetSegmentData(const Elf32_Phdr &phdr, u8 *buffer, u32 buffer_size, u32 buffer_vadr,
149 u32 segment_vadr) {
150 if (buffer_size < phdr.p_filesz) {
151 // Buffer size is too small to hold the segment data.
152 return Err(StatusCode::kBufferTooSmall);
153 }
154 stream_.seekg(phdr.p_offset, std::ios::beg);
155 stream_.read(reinterpret_cast<char *>(buffer) + (segment_vadr - buffer_vadr), buffer_size);
156 if (!stream_.good()) {
157 return Err(StatusCode::kError);
158 }
159 return Ok();
160 }
161
162 // Default Constructor uses null stream
163 ElfReader() : stream_(null_stream), phoff_(0), phnum_(0), entry_point_(0) {};
164
165 ElfReader(std::istream &stream, std::streamoff phoff, std::size_t phnum, u32 entry_point)
166 : stream_(stream), phoff_(phoff), phnum_(phnum), entry_point_(entry_point) {}
167
168private:
169 std::istream &stream_;
170 std::streamoff phoff_;
171 std::size_t phnum_;
172 u32 entry_point_;
173};
174
175} // namespace libmicroemu::internal
Definition elf_reader.h:12
The libmicroemu::internal namespace contains all classes and functions of libmicroemu which are priva...
Definition bkpt_flags.h:6
@ kElfNotValid
ELF file is not valid.
Definition status_code.h:87
@ kBufferTooSmall
Provided buffer is too small.
Definition status_code.h:45
@ kElfWrongHeader
ELF file has a wrong header.
Definition status_code.h:90
@ kError
An unspecified error occurred.
Definition status_code.h:25
Contains the Result class which is used to return the result of a function.
Definition elf_reader.h:21
Definition elf_reader.h:38
Definition result.h:15