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