quic/qbox
Loading...
Searching...
No Matches
loader.h
1/*
2 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 * Author: GreenSocs 2022
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#ifndef _GREENSOCS_BASE_COMPONENTS_LOADER_H
9#define _GREENSOCS_BASE_COMPONENTS_LOADER_H
10
11#include <fstream>
12
13#include <cci_configuration>
14#include <systemc>
15#include <tlm>
16#include <tlm_utils/simple_initiator_socket.h>
17#include <scp/report.h>
18#include <module_factory_registery.h>
19#include <ports/target-signal-socket.h>
20#include <tlm_sockets_buswidth.h>
21
22#include "onmethod.h"
23
24#include <cinttypes>
25#include <fcntl.h>
26#include <libelf.h>
27#include <list>
28#include <string>
29#include <unistd.h>
30#include <vector>
31#include <limits>
32#include <zip.h>
33
34#ifndef _WIN32
35#include <fcntl.h>
36#include <sys/mman.h>
37#include <sys/stat.h>
38#endif
39
40#define BINFILE_READ_CHUNK_SIZE (1024 * 1024)
41
42namespace gs {
43
52/* simple class to load csv file*/
53class CSVRow
54{
55public:
56 std::string operator[](std::size_t index) const
57 {
58 return std::string(&m_line[m_data[index] + 1], m_data[index + 1] - (m_data[index] + 1));
59 }
60 std::size_t size() const { return m_data.size() - 1; }
61 void readNextRow(std::istream& str)
62 {
63 std::getline(str, m_line);
64
65 m_data.clear();
66 m_data.emplace_back(-1);
67 std::string::size_type pos = 0;
68 while ((pos = m_line.find(',', pos)) != std::string::npos) {
69 m_data.emplace_back(pos);
70 ++pos;
71 }
72 // This checks for a trailing comma with no data after it.
73 pos = m_line.size();
74 m_data.emplace_back(pos);
75 }
76
77private:
78 std::string m_line;
79 std::vector<int> m_data;
80};
81
82static std::istream& operator>>(std::istream& str, CSVRow& data)
83{
84 data.readNextRow(str);
85 return str;
86}
87
88template <unsigned int BUSWIDTH = DEFAULT_TLM_BUSWIDTH>
89class loader : public sc_core::sc_module
90{
91 SCP_LOGGER();
92 cci::cci_broker_handle m_broker;
93
94 template <typename MODULE, typename TYPES = tlm::tlm_base_protocol_types>
95 class simple_initiator_socket_zero
96 : public tlm_utils::simple_initiator_socket_b<MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND>
97 {
98 using typename tlm_utils::simple_initiator_socket_b<MODULE, BUSWIDTH, TYPES,
99 sc_core::SC_ZERO_OR_MORE_BOUND>::base_target_socket_type;
100 typedef tlm_utils::simple_initiator_socket_b<MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
101
102 public:
103 simple_initiator_socket_zero(const char* name): socket_b(name) {}
104 };
105
106public:
109 onMethodHelper m_onMethod;
110
111private:
112 uint64_t m_address = 0;
113
114 std::function<void(const uint8_t* data, uint64_t offset, uint64_t len)> write_cb;
115 bool m_use_callback = false;
116
117 std::list<std::string> sc_cci_children(sc_core::sc_module_name name)
118 {
119 std::list<std::string> children;
120 int l = strlen(name) + 1;
121 auto uncon = m_broker.get_unconsumed_preset_values([&name](const std::pair<std::string, cci::cci_value>& iv) {
122 return iv.first.find(std::string(name) + ".") == 0;
123 });
124 for (auto p : uncon) {
125 children.push_back(p.first.substr(l, p.first.find(".", l) - l));
126 }
127 children.sort();
128 children.unique();
129 return children;
130 }
131
132 void send(uint64_t addr, uint8_t* data, uint64_t len)
133 {
134 if (m_use_callback) {
135 write_cb(data, addr, len);
136 } else {
137 tlm::tlm_generic_payload trans;
138
139 trans.set_command(tlm::TLM_WRITE_COMMAND);
140 trans.set_address(addr);
141 trans.set_data_ptr(data);
142 trans.set_data_length(len);
143 trans.set_streaming_width(len);
144 trans.set_byte_enable_length(0);
145 if (initiator_socket->transport_dbg(trans) != len) {
146 SCP_FATAL(()) << name() << " : Error loading data to memory @ "
147 << "0x" << std::hex << addr;
148 }
149 }
150 }
151
152 template <typename T>
153 T cci_get(std::string name)
154 {
155 return gs::cci_get<T>(m_broker, name);
156 }
157
158 uint32_t byte_swap32(uint32_t in)
159 {
161 out = in & 0xff;
162 in >>= 8;
163 out <<= 8;
164 out |= in & 0xff;
165 in >>= 8;
166 out <<= 8;
167 out |= in & 0xff;
168 in >>= 8;
169 out <<= 8;
170 out |= in & 0xff;
171 in >>= 8;
172 return out;
173 }
174
175public:
176 loader(sc_core::sc_module_name name)
177 : m_broker(cci::cci_get_broker())
178 , initiator_socket("initiator_socket") //, [&](std::string s) -> void { register_boundto(s); })
179 , reset("reset")
180 {
181 SCP_TRACE(())("default constructor");
182 // Respect the single function call semantics,
183 // but ensure execution happens on the main SystemC thread, not on a light weight process,
184 // as the loader uses a lot of stack
185 reset.register_value_changed_cb([&](bool value) { m_onMethod.run([&]() { doreset(value); }); });
186 }
187 void doreset(bool value)
188 {
189 SCP_WARN(())("Reset");
190 if (value) {
191 end_of_elaboration();
192 }
193 }
194 loader(sc_core::sc_module_name name, std::function<void(const uint8_t* data, uint64_t offset, uint64_t len)> _write)
195 : m_broker(cci::cci_get_broker())
196 , initiator_socket("initiator_socket") //, [&](std::string s) -> void { register_boundto(s); })
197 , reset("reset")
198 , write_cb(_write)
199 {
200 SCP_TRACE(())("constructor with callback");
201 m_use_callback = true;
202 reset.register_value_changed_cb([&](bool value) { m_onMethod.run([&]() { doreset(value); }); });
203 }
204
205 ~loader() {}
206
207protected:
208 void load(std::string name)
209 {
210 bool read = false;
211 if (m_broker.has_preset_value(name + ".elf_file")) {
212 if (m_use_callback) {
213 SCP_WARN(()) << "elf file loading into local memory will interpret addresses "
214 "relative to the memory - probably not what you want?";
215 }
216 std::string file = gs::cci_get<std::string>(m_broker, name + ".elf_file");
217 elf_load(file);
218 read = true;
219 } else {
220 uint64_t addr = 0;
221 if (m_use_callback) {
222 addr = gs::cci_get<uint64_t>(m_broker, name + ".offset");
223 } else {
224 addr = gs::cci_get<uint64_t>(m_broker, name + ".address");
225 }
226 std::string file;
227 if (gs::cci_get<std::string>(m_broker, name + ".bin_file", file)) {
228 uint64_t file_offset = 0, file_data_len = std::numeric_limits<uint64_t>::max();
229 if (!((gs::cci_get<uint64_t>(m_broker, name + ".bin_file_offset", file_offset) &&
230 gs::cci_get<uint64_t>(m_broker, name + ".bin_file_size", file_data_len)))) {
231 struct stat file_stat;
232 if (stat(file.c_str(), &file_stat) < 0) {
233 SCP_FATAL(()) << "can't stat file " << file;
234 }
235 file_data_len = file_stat.st_size;
236 file_offset = 0;
237 }
238 SCP_INFO(()) << "Loading binary file: " << file << " starting at offset: " << file_offset
239 << " with size: " << file_data_len << " to addr: " << addr;
241 read = true;
242 }
243 if (gs::cci_get<std::string>(m_broker, name + ".zip_archive", file)) {
245 if (!((gs::cci_get<uint64_t>(m_broker, name + ".archived_file_offset", file_offset) &&
246 gs::cci_get<uint64_t>(m_broker, name + ".archived_file_size", file_data_len)))) {
247 // can't stat file size here, as the actual file inside archive is accessed inside zip_file_load()
248 file_data_len = 0;
249 file_offset = 0;
250 }
251 std::string archived_file_name;
252 if (!gs::cci_get<std::string>(m_broker, name + ".archived_file_name", archived_file_name))
254 SCP_INFO(()) << "Loading " << archived_file_name << " from zip file: " << file
255 << " starting at offset: " << file_offset << " to addr: " << addr;
256 zip_file_load(nullptr, file, addr, archived_file_name, file_offset, file_data_len);
257 read = true;
258 }
259 if (gs::cci_get<std::string>(m_broker, name + ".csv_file", file)) {
260 std::string addr_str = gs::cci_get<std::string>(m_broker, name + ".addr_str");
261 std::string val_str = gs::cci_get<std::string>(m_broker, name + ".value_str");
262 bool byte_swap = false;
263 byte_swap = gs::cci_get<bool>(m_broker, name + ".byte_swap", byte_swap);
264 SCP_INFO(())("Loading csv file {}, ({}) to {:#x}", file, (name + ".csv_file"), addr);
265 csv_load(file, addr, addr_str, val_str, byte_swap);
266 read = true;
267 }
268 std::string param;
269 if (gs::cci_get<std::string>(m_broker, name + ".param", param)) {
270 cci::cci_param_typed_handle<std::string> data(m_broker.get_param_handle(param));
271 if (!data.is_valid()) {
272 SCP_FATAL(()) << "Unable to find valid source param '" << param << "' for '" << name << "'";
273 }
274 SCP_INFO(())("Loading string parameter {} to {:#x}", param, addr);
275 str_load(data.get_value(), addr);
276 read = true;
277 }
278 if (sc_cci_children((name + ".data").c_str()).size()) {
279 bool byte_swap = false;
280 gs::cci_get<bool>(m_broker, name + ".byte_swap", byte_swap);
281 SCP_INFO(())("Loading config data to {:#x}", addr);
282 data_load(name + ".data", addr, byte_swap);
283 read = true;
284 }
285 }
286 if (!read) {
287 SCP_FATAL(()) << "Unknown loader type: '" << name << "'";
288 }
289 }
290 void end_of_elaboration()
291 {
292 int i = 0;
293 auto children = sc_cci_children(name());
294 for (std::string s : children) {
295 if (std::count_if(s.begin(), s.end(), [](unsigned char c) { return std::isdigit(c); })) {
296 load(std::string(name()) + "." + s);
297 i++;
298 }
299 }
300 if (i == 0 && children.size() > 0) {
301 load(name());
302 }
303 }
304
305public:
313 void file_load(std::string filename, uint64_t addr, uint64_t file_offset = 0,
314 uint64_t file_data_len = std::numeric_limits<uint64_t>::max())
315 {
316 std::ifstream fin(filename, std::ios::in | std::ios::binary);
317 if (!fin.good()) {
318 SCP_FATAL(()) << "Memory::load(): error file not found (" << filename << ")";
319 }
321 uint64_t read_len = 0;
322 fin.seekg(file_offset, std::ios::beg);
323 uint8_t buffer[BINFILE_READ_CHUNK_SIZE];
324 uint64_t c = 0;
325 while (!fin.eof() && (rem_len > 0)) {
326 read_len = std::min(rem_len, static_cast<uint64_t>(BINFILE_READ_CHUNK_SIZE));
327 fin.read(reinterpret_cast<char*>(&buffer[0]), read_len);
328 size_t r = fin.gcount();
329 send(addr + c, buffer, r);
330 c += r;
331 rem_len = ((rem_len >= r) ? rem_len - r : 0);
332 }
333 fin.close();
334 }
335
336 /*
337 - p_archive: pointer to a zip_t struct if the zip archive is opened outside this function.
338 - archive_name: the name of the zip archive.
339 - file_name: name of the file to be extracted from archive_name.
340 */
341 void zip_file_load(zip_t* p_archive, const std::string& archive_name, uint64_t addr,
342 const std::string& file_name = "", uint64_t file_offset = 0, uint64_t file_data_len = 0,
343 bool is_compressed = false, const std::string& uncompressed_file_name = "")
344 {
345 if (archive_name.empty()) SCP_FATAL(()) << "Missing zip archive name!";
347 if (!z_archive) {
348 z_archive = zip_open(archive_name.c_str(), 0, nullptr);
349 if (!z_archive) SCP_FATAL(()) << "Can't open zip archive: " << archive_name;
350 }
352 if (num_entries < 0)
353 SCP_FATAL(()) << "Can't get the number of the entries in zip archive: " << archive_name
354 << " may be the archive file is corrupted!";
355 if (num_entries == 0) SCP_FATAL(()) << "There is no files in the zip archive: " << archive_name;
357 if (num_entries > 1) {
358 if (file_name.empty())
359 SCP_FATAL(()) << "many files exist in zip arcive: " << archive_name
360 << " but file name is not specified";
361 if (zip_stat(z_archive, file_name.c_str(), ZIP_FL_NOCASE, &z_stat) < 0)
362 SCP_FATAL(()) << "Can't find any file named: " << file_name << " in the zip archive: " << archive_name;
363 } else { // num of entries = 1
365 SCP_FATAL(()) << "Can't get status os the file inside zip archive: " << archive_name;
366 }
368 if (!is_compressed) {
369 std::vector<uint8_t> bin_info(z_stat.size);
371 SCP_DEBUG(()) << "load data from zip archive " << archive_name << " to addr: 0x" << std::hex << addr
372 << " len: 0x" << std::hex << used_data_len;
373 send(addr, reinterpret_cast<uint8_t*>(&bin_info[0]) + file_offset, used_data_len);
374 } else {
375 std::vector<uint8_t> compressed_file_data(z_stat.size);
376 zip_read_file(z_archive, file_name, z_stat, compressed_file_data, 0, z_stat.size);
378 zip_source_buffer_create(reinterpret_cast<uint8_t*>(&compressed_file_data[0]), z_stat.size, 0, nullptr),
379 ZIP_RDONLY, nullptr);
380 if (!f_archive) SCP_FATAL(()) << "Can't open zip archive: " << file_name;
382 if (f_num_entries != 1)
383 SCP_FATAL(()) << "Compressed file: " << file_name << " in: " << archive_name << " is corrupted!";
386 SCP_FATAL(()) << "Can't find any file named: " << uncompressed_file_name
387 << " in the zip archive: " << file_name << " extracted from: " << archive_name;
388 std::vector<uint8_t> bin_info(f_stat.size);
390 SCP_DEBUG(()) << "load data from zip archive " << file_name << " to addr: 0x" << std::hex << addr
391 << " len: 0x" << std::hex << used_data_len;
392 send(addr, reinterpret_cast<uint8_t*>(&bin_info[0]) + file_offset, used_data_len);
393 }
394 }
395
396 zip_int64_t zip_read_file(zip_t* z_archive, const std::string& archive_name, const zip_stat_t& z_stat,
397 std::vector<uint8_t>& data, uint64_t file_offset, uint64_t file_data_len)
398 {
399 uint8_t* bin_info_t = &data[0];
401 if (!fd) SCP_FATAL(()) << "Can't open file: " << z_stat.name << "in zip archive: " << archive_name;
403 if (file_data_len == 0)
405 else if ((file_offset < z_stat.size) && ((file_data_len + file_offset) > z_stat.size))
407 else if (file_offset > z_stat.size)
408 SCP_FATAL(()) << "file offset (" << file_offset << " )is bigger than the size (" << z_stat.size << ") of "
409 << z_stat.name << "in zip archive: " << archive_name;
410 else
412
414 while (rem > 0) {
415 read_bytes_num = zip_fread(fd, reinterpret_cast<uint8_t*>(bin_info_t), rem);
416 if (read_bytes_num < 0) {
417 SCP_FATAL(()) << "Can't read " << used_file_data_len << " from " << z_stat.name
418 << " in zip archive: " << archive_name;
419 }
422 }
423 zip_fclose(fd);
424 return used_file_data_len;
425 }
426
427 void csv_load(std::string filename, uint64_t offset, std::string addr_str, std::string value_str, bool byte_swap)
428 {
429 std::ifstream file(filename);
430
431 CSVRow row;
432 if (!(file >> row)) {
433 SCP_FATAL(()) << "Unable to find " << filename;
434 }
435 int addr_i = -1;
436 int value_i = -1;
437 for (std::size_t i = 0; i < row.size(); i++) {
438 if (row[i] == addr_str) {
439 addr_i = i;
440 }
441 if (row[i] == value_str) {
442 value_i = i;
443 }
444 }
445 if (addr_i == -1 || value_i == -1) {
446 SCP_FATAL(()) << "Unable to find " << filename;
447 }
448 std::size_t min_field_count = std::max(addr_i, value_i);
449 while (file >> row) {
450 if (row.size() <= min_field_count) {
451 continue;
452 }
453 const std::string addr = std::string(row[addr_i]);
454 uint64_t value = std::stoll(std::string(row[value_i]), nullptr, 0);
455 if (byte_swap) value = byte_swap32(value);
456 uint64_t addr_p = std::stoll(addr, nullptr, 0) + offset;
457 send(addr_p, (uint8_t*)(&value), sizeof(value));
458 }
459 }
460
461private:
462 // it makes no sense to expose this function, you could only sensibly use it from a config
463 // anyway
464 void data_load(std::string param, uint64_t addr, bool byte_swap)
465 {
466 for (std::string s : sc_cci_children(param.c_str())) {
467 if (std::count_if(s.begin(), s.end(), [](unsigned char c) { return std::isdigit(c); })) {
468 union {
469 uint32_t d;
470 uint8_t b[sizeof(uint32_t)];
471 } data;
472 data.d = gs::cci_get<uint32_t>(m_broker, param + "." + std::string(s));
473 if (byte_swap) {
474 data.d = byte_swap32(data.d);
475 }
476 send(addr + (stoi(s) * 0x4), &(data.b[0]), 4);
477 } else {
478 SCP_FATAL(()) << "unknown format for parameter load";
479 break;
480 }
481 }
482 }
483
484public:
485 void str_load(std::string data, uint64_t addr)
486 {
487 send(addr, reinterpret_cast<uint8_t*>(const_cast<char*>(data.c_str())), data.length());
488 }
489
490 void ptr_load(uint8_t* data, uint64_t addr, uint64_t len) { send(addr, data, len); }
491
492 void elf_load(const std::string& path)
493 {
494 elf_reader(path, [&](uint64_t addr, uint8_t* data, uint64_t len) -> void { send(addr, data, len); });
495 }
496
497 /* Elf reader helper class */
498private:
499 /* elf loading */
500 typedef enum _endianess {
501 ENDIAN_UNKNOWN = 0,
502 ENDIAN_LITTLE = 1,
503 ENDIAN_BIG = 2,
504 } endianess;
505
506 struct elf_segment {
507 const uint64_t virt;
508 const uint64_t phys;
509 const uint64_t size;
510 const uint64_t filesz;
511 const uint64_t offset;
512 const bool r, w, x;
513 };
514
515 class elf_reader
516 {
517 private:
518 std::vector<struct elf_segment> m_segments;
519
520 std::function<void(uint64_t, uint8_t*, uint64_t)> m_send;
521
522 std::string m_filename;
523 int m_fd;
524 uint64_t m_entry;
525 uint64_t m_machine;
526 endianess m_endian;
527
528 public:
529 uint64_t entry() const { return m_entry; }
530 uint64_t machine() const { return m_machine; }
531
532 endianess endian() const { return m_endian; }
533 bool is_little_endian() const { return m_endian == ENDIAN_LITTLE; }
534 bool is_big_endian() const { return m_endian == ENDIAN_BIG; }
535
536 const char* filename() const { return m_filename.c_str(); }
537
538 const std::vector<elf_segment>& segments() const { return m_segments; }
539
540 elf_reader(const elf_reader&) = delete;
541
543 typedef Elf32_Ehdr Elf_Ehdr;
544 typedef Elf32_Phdr Elf_Phdr;
545 typedef Elf32_Shdr Elf_Shdr;
546 typedef Elf32_Sym Elf_Sym;
547
548 static Elf_Ehdr* elf_getehdr(Elf* elf) { return elf32_getehdr(elf); }
549
550 static Elf_Phdr* elf_getphdr(Elf* elf) { return elf32_getphdr(elf); }
551
552 static Elf_Shdr* elf_getshdr(Elf_Scn* scn) { return elf32_getshdr(scn); }
553 };
554
556 typedef Elf64_Ehdr Elf_Ehdr;
557 typedef Elf64_Phdr Elf_Phdr;
558 typedef Elf64_Shdr Elf_Shdr;
559 typedef Elf64_Sym Elf_Sym;
560
561 static Elf_Ehdr* elf_getehdr(Elf* elf) { return elf64_getehdr(elf); }
562
563 static Elf_Phdr* elf_getphdr(Elf* elf) { return elf64_getphdr(elf); }
564
565 static Elf_Shdr* elf_getshdr(Elf_Scn* scn) { return elf64_getshdr(scn); }
566 };
567
568 static endianess elf_endianess(Elf* elf)
569 {
570 const char* ident = elf_getident(elf, nullptr);
571 if (ident == nullptr) return ENDIAN_UNKNOWN;
572
573 switch (ident[EI_DATA]) {
574 case ELFDATA2LSB:
575 return ENDIAN_LITTLE;
576 case ELFDATA2MSB:
577 return ENDIAN_BIG;
578 default:
579 return ENDIAN_UNKNOWN;
580 }
581 }
582
583 template <typename T>
584 static std::vector<elf_segment> elf_segments(Elf* elf)
585 {
586 size_t count = 0;
587 int err = elf_getphdrnum(elf, &count);
588 if (err) SCP_FATAL("elf_reader") << "elf_begin failed: " << elf_errmsg(err);
589
590 std::vector<elf_segment> segments;
591 typename T::Elf_Phdr* hdr = T::elf_getphdr(elf);
592 for (uint64_t i = 0; i < count; i++, hdr++) {
593 if (hdr->p_type == PT_LOAD) {
594 bool r = hdr->p_flags & PF_R;
595 bool w = hdr->p_flags & PF_W;
596 bool x = hdr->p_flags & PF_X;
597 segments.push_back(
598 { hdr->p_vaddr, hdr->p_paddr, hdr->p_memsz, hdr->p_filesz, hdr->p_offset, r, w, x });
599 }
600 }
601
602 return segments;
603 }
604
605 template <typename T, typename ELF>
606 void read_sections(ELF* elf)
607 {
608 Elf_Scn* scn = nullptr;
609 while ((scn = elf_nextscn(elf, scn)) != nullptr) {
610 typename T::Elf_Shdr* shdr = T::elf_getshdr(scn);
611 if (shdr->sh_type != SHT_SYMTAB) continue;
612
613 Elf_Data* data = elf_getdata(scn, nullptr);
614 size_t num_symbols = shdr->sh_size / shdr->sh_entsize;
615 typename T::Elf_Sym* syms = (typename T::Elf_Sym*)(data->d_buf);
616
617 for (size_t i = 0; i < num_symbols; i++) {
618 if (syms[i].st_size == 0) continue;
619
620 char* name = elf_strptr(elf, shdr->sh_link, syms[i].st_name);
621 if (name == nullptr || strlen(name) == 0) continue;
622 }
623 }
624 }
625
626 uint64_t to_phys(uint64_t virt) const
627 {
628 for (auto& seg : m_segments) {
629 if ((virt >= seg.virt) && virt < (seg.virt + seg.size)) return seg.phys + virt - seg.virt;
630 }
631
632 return virt;
633 }
634
635 elf_reader(const std::string& path, std::function<void(uint64_t, uint8_t*, uint64_t)> _send)
636 : m_send(_send), m_filename(path), m_fd(-1), m_entry(0), m_machine(0), m_endian(ENDIAN_UNKNOWN)
637 {
638 if (elf_version(EV_CURRENT) == EV_NONE) SCP_FATAL("elf_reader") << "failed to read libelf version";
639
640 m_fd = open(filename(), O_RDONLY, 0);
641 if (m_fd < 0) SCP_FATAL("elf_reader") << "cannot open elf file " << filename();
642
643 Elf* elf = elf_begin(m_fd, ELF_C_READ, nullptr);
644 if (elf == nullptr) SCP_FATAL("elf_reader") << "error reading " << filename() << " : " << elf_errmsg(-1);
645
646 if (elf_kind(elf) != ELF_K_ELF) SCP_FATAL("elf_reader") << "ELF version error in " << filename();
647
650 if (ehdr32) {
651 m_entry = ehdr32->e_entry;
652 m_machine = ehdr32->e_machine;
653 m_endian = elf_endianess(elf);
654 m_segments = elf_segments<elf32_traits>(elf);
656 }
657
658 if (ehdr64) {
659 m_entry = ehdr64->e_entry;
660 m_machine = ehdr64->e_machine;
661 m_endian = elf_endianess(elf);
662 m_segments = elf_segments<elf64_traits>(elf);
664 }
665
666 elf_end(elf);
667
668 for (auto s : m_segments) {
669 read_segment(s);
670 }
671 }
672
673 ~elf_reader()
674 {
675 if (m_fd >= 0) close(m_fd);
676 }
677
678 uint64_t read_segment(const elf_segment& segment)
679 {
680 if (m_fd < 0) SCP_FATAL("elf_reader") << "ELF file '" << filename() << "' not open";
681
682 if (lseek(m_fd, segment.offset, SEEK_SET) != (ssize_t)segment.offset)
683 SCP_FATAL("elf_reader") << "cannot seek within ELF file " << filename();
684
685 uint8_t buff[1024];
686 size_t sz = segment.filesz;
687 size_t offset = 0;
688 while (sz) {
689 int s = read(m_fd, buff, (sz < sizeof(buff) ? sz : sizeof(buff)));
690 sz -= s;
691 if (!s) {
692 SCP_FATAL("elf_reader") << "cannot read ELF file " << filename();
693 exit(0);
694 }
695 m_send(segment.phys + offset, buff, s);
696 offset += s;
697 }
698 if (lseek(m_fd, 0, SEEK_SET) != 0) SCP_FATAL("elf_reader") << "cannot seek within ELF file " << filename();
699
700 return segment.size;
701 }
702 };
703};
704} // namespace gs
705
706extern "C" void module_register();
707#endif
Definition target.h:160
Definition loader.h:54
Definition loader.h:90
void file_load(std::string filename, uint64_t addr, uint64_t file_offset=0, uint64_t file_data_len=std::numeric_limits< uint64_t >::max())
This function reads a file into memory and can be used to load an image.
Definition loader.h:313
Definition onmethod.h:14
Tool which reads a Lua configuration file and sets parameters.
Definition biflow.cc:10