SimpleKernel 1.17.0
Loading...
Searching...
No Matches
kernel_elf.hpp
Go to the documentation of this file.
1
5#pragma once
6
7#include <elf.h>
8#include <etl/singleton.h>
9
10#include <cassert>
11#include <cstddef>
12#include <cstdint>
13#include <cstring>
14#include <span>
15
16#include "expected.hpp"
17#include "kernel_log.hpp"
18
22class KernelElf {
23 public:
25 std::span<Elf64_Sym> symtab{};
27 uint8_t* strtab{nullptr};
28
33 [[nodiscard]] auto GetElfSize() const -> size_t { return elf_.size(); }
34
37
42 explicit KernelElf(uint64_t elf_addr) {
43 assert(elf_addr != 0U && "elf_addr is null");
44
45 elf_ = std::span<uint8_t>(reinterpret_cast<uint8_t*>(elf_addr), EI_NIDENT);
46
47 // 检查 elf 头数据
48 CheckElfIdentity().or_else([](Error err) -> Expected<void> {
49 klog::Err("KernelElf NOT valid ELF file: {}", err.message());
50 while (true) {
52 }
53 return {};
54 });
55
56 ehdr_ = *reinterpret_cast<const Elf64_Ehdr*>(elf_.data());
57
58 // 重新计算 elf 大小
59 size_t max_size = EI_NIDENT;
60 if (ehdr_.e_phoff != 0) {
61 size_t ph_end = ehdr_.e_phoff + ehdr_.e_phnum * ehdr_.e_phentsize;
62 if (ph_end > max_size) {
63 max_size = ph_end;
64 }
65 }
66 if (ehdr_.e_shoff != 0) {
67 size_t sh_end = ehdr_.e_shoff + ehdr_.e_shnum * ehdr_.e_shentsize;
68 if (sh_end > max_size) {
69 max_size = sh_end;
70 }
71 const auto* shdrs =
72 reinterpret_cast<const Elf64_Shdr*>(elf_.data() + ehdr_.e_shoff);
73 for (int i = 0; i < ehdr_.e_shnum; ++i) {
74 size_t section_end = shdrs[i].sh_offset + shdrs[i].sh_size;
75 if (section_end > max_size) {
76 max_size = section_end;
77 }
78 }
79 }
80 elf_ = std::span<uint8_t>(reinterpret_cast<uint8_t*>(elf_addr), max_size);
81
82 phdr_ = std::span<Elf64_Phdr>(
83 reinterpret_cast<Elf64_Phdr*>(elf_.data() + ehdr_.e_phoff),
84 ehdr_.e_phnum);
85
86 shdr_ = std::span<Elf64_Shdr>(
87 reinterpret_cast<Elf64_Shdr*>(elf_.data() + ehdr_.e_shoff),
88 ehdr_.e_shnum);
89
90 const auto* shstrtab = reinterpret_cast<const char*>(elf_.data()) +
91 shdr_[ehdr_.e_shstrndx].sh_offset;
92 for (auto shdr : shdr_) {
93 if (strcmp(shstrtab + shdr.sh_name, ".symtab") == 0) {
94 symtab = std::span<Elf64_Sym>(
95 reinterpret_cast<Elf64_Sym*>(elf_.data() + shdr.sh_offset),
96 (shdr.sh_size / sizeof(Elf64_Sym)));
97 } else if (strcmp(shstrtab + shdr.sh_name, ".strtab") == 0) {
98 strtab = elf_.data() + shdr.sh_offset;
99 }
100 }
101 }
102
103 KernelElf() = default;
104 KernelElf(const KernelElf&) = default;
105 KernelElf(KernelElf&&) = default;
106 auto operator=(const KernelElf&) -> KernelElf& = default;
107 auto operator=(KernelElf&&) -> KernelElf& = default;
108 ~KernelElf() = default;
110
111 protected:
114 std::span<uint8_t> elf_{};
115 Elf64_Ehdr ehdr_{};
116 std::span<Elf64_Phdr> phdr_{};
117 std::span<Elf64_Shdr> shdr_{};
119
124 [[nodiscard]] auto CheckElfIdentity() const -> Expected<void> {
125 return CheckElfMagic().and_then([this]() { return CheckElfClass(); });
126 }
127
128 private:
132 [[nodiscard]] auto CheckElfMagic() const -> Expected<void> {
133 if ((elf_[EI_MAG0] != ELFMAG0) || (elf_[EI_MAG1] != ELFMAG1) ||
134 (elf_[EI_MAG2] != ELFMAG2) || (elf_[EI_MAG3] != ELFMAG3)) {
135 return std::unexpected(Error(ErrorCode::kElfInvalidMagic));
136 }
137 return {};
138 }
139
143 [[nodiscard]] auto CheckElfClass() const -> Expected<void> {
144 if (elf_[EI_CLASS] == ELFCLASS32) {
145 return std::unexpected(Error(ErrorCode::kElfUnsupported32Bit));
146 }
147 if (elf_[EI_CLASS] != ELFCLASS64) {
148 return std::unexpected(Error(ErrorCode::kElfInvalidClass));
149 }
150 return {};
151 }
152};
153
154using KernelElfSingleton = etl::singleton<KernelElf>;
ELF 文件相关
auto CheckElfClass() const -> Expected< void >
KernelElf(const KernelElf &)=default
auto CheckElfMagic() const -> Expected< void >
std::span< uint8_t > elf_
auto operator=(KernelElf &&) -> KernelElf &=default
~KernelElf()=default
auto GetElfSize() const -> size_t
获取 elf 文件大小
std::span< Elf64_Shdr > shdr_
uint8_t * strtab
字符串表
std::span< Elf64_Phdr > phdr_
Elf64_Ehdr ehdr_
KernelElf(KernelElf &&)=default
auto CheckElfIdentity() const -> Expected< void >
auto operator=(const KernelElf &) -> KernelElf &=default
KernelElf()=default
KernelElf(uint64_t elf_addr)
构造函数
std::span< Elf64_Sym > symtab
符号表
@ kElfUnsupported32Bit
@ kElfInvalidMagic
@ kElfInvalidClass
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
etl::singleton< KernelElf > KernelElfSingleton
void Pause()
Definition cpu_io.h:20
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
#define strcmp
错误类型,用于 std::expected
Definition expected.hpp:343
constexpr auto message() const -> const char *
Definition expected.hpp:358