Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
addr2line.cpp
Go to the documentation of this file.
1#include <sysio/vm/backend.hpp>
2#include <iostream>
3#include <iomanip>
4#include <cctype>
5
8 void on_code_start(const void* compiled_base, const void* wasm_code_start) {
9 wasm_base = wasm_code_start;
10 }
11 void on_function_start(const void* code_addr, const void* wasm_addr) {
12 function_offsets.push_back(static_cast<std::uint32_t>(reinterpret_cast<const char*>(wasm_addr) - reinterpret_cast<const char*>(wasm_base)));
13 }
14 void on_instr_start(const void* code_addr, const void* wasm_addr) {}
15 void on_code_end(const void* code_addr, const void* wasm_addr) {}
16 void set(nm_debug_info&& other) { *this = std::move(other); }
17 void relocate(const void*) {}
18
19 uint32_t get_function(std::uint32_t addr) {
20 auto pos = std::lower_bound(function_offsets.begin(), function_offsets.end(), addr + 1);
21 if(pos == function_offsets.begin()) return 0;
22 return (pos - function_offsets.begin()) - 1;
23 }
24
25 const void* wasm_base;
26 std::vector<uint32_t> function_offsets;
27};
28
30 if(mod.names && mod.names->function_names) {
31 for(uint32_t i = 0; i < mod.names->function_names->size(); ++i) {
32 if((*mod.names->function_names)[i].idx == idx) {
33 return &(*mod.names->function_names)[i].name;
34 }
35 }
36 }
37 for(uint32_t i = 0; i < mod.exports.size(); ++i) {
38 if(mod.exports[i].index == idx && mod.exports[i].kind == sysio::vm::Function) {
39 return &mod.exports[i].field_str;
40 }
41 }
42 return nullptr;
43}
44
45struct nm_options {
46 static constexpr bool parse_custom_section_name = true;
47};
48
49bool starts_with(std::string_view arg, std::string_view prefix) {
50 return arg.substr(0, prefix.size()) == prefix;
51}
52
53int main(int argc, const char** argv) {
54 bool print_addresses = false;
55 bool print_functions = false;
56 bool pretty = false;
57 std::vector<std::string> addresses;
58 std::string filename = "a.out";
59 for(int i = 1; i < argc; ++i) {
60 std::string arg = argv[i];
61 if(arg == "-h" || arg == "--help") {
62 std::cerr << "Usage: " << argv[0] << " [-h] [-a] [-C] [-e wasm] [-f] [-s] [-i] [-p] address..." << std::endl;
63 return 0;
64 } else if(arg == "-a" || arg == "--addresses") {
65 print_addresses = true;
66 } else if(arg == "-C" || starts_with(arg, "--demangle=")) {
67 // Ignore requests to demangle
68 } else if(arg == "-e") {
69 if(++i < argc) {
70 filename = argv[i];
71 } else {
72 std::cerr << "Missing argument to -e" << std::endl;
73 return 2;
74 }
75 } else if(starts_with(arg, "--exe=")) {
76 filename = arg.substr(6);
77 } else if(arg == "-f" || arg == "--functions") {
78 print_functions = true;
79 } else if(arg == "-s" || arg == "--basenames") {
80 // No effect without filenames
81 } else if(arg == "-i" || arg == "--inlines") {
82 // No effect without source information
83 } else if(arg == "-p" || arg == "--pretty-print") {
84 pretty = true;
85 } else if(arg[0] != '-') {
86 addresses.push_back(arg);
87 } else {
88 std::cerr << "unexpected argument: " << arg << std::endl;
89 return 2;
90 }
91 }
92
93 std::vector<std::string> function_names;
94
95 using namespace sysio::vm;
96 auto code = read_wasm(filename);
97 nm_debug_info info;
98 module mod;
100 parser.parse_module(code, mod, info);
101 {
102 for(std::size_t i = 0; i < info.function_offsets.size(); ++i) {
103 if(guarded_vector<uint8_t>* name = find_export_name(mod, i + mod.get_imported_functions_size())) {
104 function_names.push_back(std::string(reinterpret_cast<const char*>(name->raw()), name->size()));
105 } else {
106 function_names.push_back("fn" + std::to_string( i + mod.get_imported_functions_size()));
107 }
108 }
109 }
110
111 std::string_view sep = pretty ? " " : "\n";
112
113 auto print_one_address = [&](const std::string& addr) {
114 unsigned x = std::stoul(addr, nullptr, 16);
115 if(print_addresses) {
116 std::cout << std::showbase << std::hex << x << sep;
117 }
118 if(print_functions) {
119 std::cout << std::hex << function_names[info.get_function(x)] << sep;
120 }
121 std::cout << "??:0\n";
122 };
123
124 if(!addresses.empty()) {
125 for(const auto& addr : addresses) {
126 print_one_address(addr);
127 }
128 } else {
129 std::string addr;
130 while(std::cin >> addr) {
131 print_one_address(addr);
132 }
133 }
134}
sysio::vm::guarded_vector< uint8_t > * find_export_name(sysio::vm::module &mod, uint32_t idx)
Definition addr2line.cpp:29
bool starts_with(std::string_view arg, std::string_view prefix)
Definition addr2line.cpp:49
std::string name
module & parse_module(wasm_code &code, module &mod, DebugInfo &debug)
Definition parser.hpp:292
std::vector< uint8_t > read_wasm(const std::string &fname)
char ** argv
@ Function
Definition types.hpp:22
unsigned int uint32_t
Definition stdint.h:126
const void * wasm_base
Definition addr2line.cpp:25
void relocate(const void *)
Definition addr2line.cpp:17
uint32_t get_function(std::uint32_t addr)
Definition addr2line.cpp:19
void on_code_end(const void *code_addr, const void *wasm_addr)
Definition addr2line.cpp:15
std::vector< uint32_t > function_offsets
Definition addr2line.cpp:26
void on_instr_start(const void *code_addr, const void *wasm_addr)
Definition addr2line.cpp:14
void set(nm_debug_info &&other)
Definition addr2line.cpp:16
void on_function_start(const void *code_addr, const void *wasm_addr)
Definition addr2line.cpp:11
void on_code_start(const void *compiled_base, const void *wasm_code_start)
Definition addr2line.cpp:8
static constexpr bool parse_custom_section_name
Definition addr2line.cpp:46
Immutable except for fc::from_variant.
Definition name.hpp:43
guarded_vector< export_entry > exports
Definition types.hpp:175
name_section * names
Definition types.hpp:181
guarded_vector< name_assoc > * function_names
Definition types.hpp:162