Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
debug_info.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <utility>
4#include <vector>
5#include <cstdint>
6#include <cstddef>
7#include <algorithm>
8
9namespace sysio::vm {
10
11struct null_debug_info {
13 void on_code_start(const void* compiled_base, const void* wasm_code_start) {}
14 void on_function_start(const void* code_addr, const void* wasm_addr) {}
15 void on_instr_start(const void* code_addr, const void* wasm_addr) {}
16 void on_code_end(const void* code_addr, const void* wasm_addr) {}
17 void set(const null_debug_info&) {}
18 void relocate(const void*) {}
19};
20
21// Maps a contiguous region of code to offsets onto the code section of the original wasm.
22class profile_instr_map {
23 struct addr_entry {
24 uint32_t offset;
25 uint32_t wasm_addr;
26 };
27
28public:
29
30 struct builder {
31 void on_code_start(const void* compiled_base, const void* wasm_code_start) {
32 code_base = compiled_base;
33 wasm_base = wasm_code_start;
34 }
35 void on_function_start(const void* code_addr, const void* wasm_addr) {
36 data.push_back({
37 static_cast<std::uint32_t>(reinterpret_cast<const char*>(code_addr) - reinterpret_cast<const char*>(code_base)),
38 static_cast<std::uint32_t>(reinterpret_cast<const char*>(wasm_addr) - reinterpret_cast<const char*>(wasm_base))
39 });
40 }
41 void on_instr_start(const void* code_addr, const void* wasm_addr) {
42 data.push_back({
43 static_cast<std::uint32_t>(reinterpret_cast<const char*>(code_addr) - reinterpret_cast<const char*>(code_base)),
44 static_cast<std::uint32_t>(reinterpret_cast<const char*>(wasm_addr) - reinterpret_cast<const char*>(wasm_base))
45 });
46 }
47 void on_code_end(const void* code_addr, const void* wasm_addr) {
48 code_end = code_addr;
49 }
50
51 const void* code_base = nullptr;
52 const void* wasm_base = nullptr;
53 const void* code_end = nullptr;
54 std::vector<addr_entry> data;
55 };
56
57 void set(builder&& b) {
58 data = std::move(b.data);
59 std::sort(data.begin(), data.end(), [](const addr_entry& lhs, const addr_entry& rhs){ return lhs.offset < rhs.offset; });
60 base_address = b.code_base;
61 code_size = reinterpret_cast<const char*>(b.code_end) - reinterpret_cast<const char*>(base_address);
62 offset_to_addr = data.data();
63 offset_to_addr_len = data.size();
64 }
65
66 profile_instr_map() = default;
69
70 // Indicate that the executable code was moved/copied/mmapped/etc to another location
71 void relocate(const void* new_base) { base_address = new_base; }
72
73 // Cannot use most of the standard library as the STL is not async-signal-safe
74 std::uint32_t translate(const void* pc) const {
75 std::size_t diff = (reinterpret_cast<const char*>(pc) - reinterpret_cast<const char*>(base_address)); // negative values wrap
76 if(diff >= code_size || diff < offset_to_addr[0].offset) return 0xFFFFFFFFu;
77 std::uint32_t offset = diff;
78
79 // Loop invariant: offset_to_addr[lower].offset <= offset < offset_to_addr[upper].offset
80 std::size_t lower = 0, upper = offset_to_addr_len;
81 while(upper - lower > 1) {
82 std::size_t mid = lower + (upper - lower) / 2;
83 if(offset_to_addr[mid].offset <= offset) {
84 lower = mid;
85 } else {
86 upper = mid;
87 }
88 }
89
90 return offset_to_addr[lower].wasm_addr;
91 }
92private:
93 const void* base_address = nullptr;
94 std::size_t code_size = 0;
95
96 addr_entry* offset_to_addr = nullptr;
97 std::size_t offset_to_addr_len = 0;
98
99 std::vector<addr_entry> data;
100};
101
102}
profile_instr_map & operator=(const profile_instr_map &)=delete
void relocate(const void *new_base)
profile_instr_map(const profile_instr_map &)=delete
std::uint32_t translate(const void *pc) const
void diff(const std::string &a, const std::string &b)
Definition jmp.cpp:18
unsigned int uint32_t
Definition stdint.h:126
void relocate(const void *)
void on_instr_start(const void *code_addr, const void *wasm_addr)
void on_function_start(const void *code_addr, const void *wasm_addr)
void on_code_start(const void *compiled_base, const void *wasm_code_start)
void on_code_end(const void *code_addr, const void *wasm_addr)
void set(const null_debug_info &)
void on_code_end(const void *code_addr, const void *wasm_addr)
void on_instr_start(const void *code_addr, const void *wasm_addr)
void on_code_start(const void *compiled_base, const void *wasm_code_start)
std::vector< addr_entry > data
void on_function_start(const void *code_addr, const void *wasm_addr)