aboutsummaryrefslogtreecommitdiff
path: root/c_emulator/elf_loader.h
blob: 352397fbf5115cc3697b4ff28c55465ad4810f24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#pragma once

#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <string>

#include <elfio/elfio.hpp>

enum class Architecture {
  RV32,
  RV64,
};

class ELF {
public:
  // Open a RISC-V ELF file. Throws an exception if the file doesn't
  // exist or isn't a RISC-V ELF file.
  static ELF open(const std::string &filename);

  // Return the architecture (RV32/64).
  Architecture architecture() const;

  // Return the entry point (where execution should begin).
  uint64_t entry() const;

  using ElfWriteFn = std::function<void(
    uint64_t,        // address
    const uint8_t *, // data
    uint64_t         // length
  )>;

  // Call `writer()` to load all of the loadable sections into memory (or you
  // can do anything else with them).
  void load(ElfWriteFn writer) const;

  // Load and return the symbol table. It isn't cached - every time you call
  // this the entire symbol table is loaded from disk. Note only STT_FUNC,
  // STT_OBJECT, STT_COMMON and STT_NOTYPE symbols that are not SHN_UNDEF are
  // returned.
  std::map<std::string, uint64_t> symbols() const;

private:
  explicit ELF(std::unique_ptr<ELFIO::elfio> reader);

  // Unfortunately there's a bug in ELFIO which means we can't std::move() it,
  // so we have to put it in a unique_ptr.
  // https://github.com/serge1/ELFIO/issues/157
  std::unique_ptr<ELFIO::elfio> m_reader;
};