forked from jeremy-rifkin/cpptrace
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmach-o.hpp
More file actions
150 lines (108 loc) · 4.4 KB
/
Copy pathmach-o.hpp
File metadata and controls
150 lines (108 loc) · 4.4 KB
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#ifndef MACHO_HPP
#define MACHO_HPP
#include "utils/common.hpp"
#include "utils/utils.hpp"
#include "utils/span.hpp"
#include "utils/io/base_file.hpp"
#if IS_APPLE
#include <cstdint>
#include <limits>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <mach-o/arch.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
CPPTRACE_BEGIN_NAMESPACE
namespace detail {
bool file_is_mach_o(cstring_view object_path) noexcept;
struct load_command_entry {
std::uint32_t file_offset;
std::uint32_t cmd;
std::uint32_t cmdsize;
};
class mach_o {
public:
struct debug_map_entry {
uint64_t source_address;
uint64_t size;
std::string name;
};
struct symbol_entry {
uint64_t address;
std::string name;
};
// map from object file to a vector of symbols to resolve
using debug_map = std::unordered_map<std::string, std::vector<debug_map_entry>>;
private:
std::unique_ptr<base_file> file;
std::uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
std::uint32_t filetype;
std::uint32_t n_load_commands;
std::uint32_t sizeof_load_commands;
std::uint32_t flags;
std::size_t bits = 0; // 32 or 64 once load_mach is called
std::size_t load_base = 0;
std::size_t fat_index = std::numeric_limits<std::size_t>::max();
std::vector<load_command_entry> load_commands;
struct symtab_info_data {
symtab_command symtab;
optional<std::vector<char>> stringtab;
Result<const char*, internal_error> get_string(std::size_t index) const;
};
bool tried_to_load_symtab = false;
optional<symtab_info_data> symtab_info;
bool tried_to_load_symbols = false;
optional<std::vector<symbol_entry>> symbols;
mach_o(std::unique_ptr<base_file> file, std::uint32_t magic) : file(std::move(file)), magic(magic) {}
Result<monostate, internal_error> load();
static NODISCARD Result<mach_o, internal_error> open(std::unique_ptr<base_file> file);
public:
static NODISCARD Result<mach_o, internal_error> open(cstring_view object_path);
static NODISCARD Result<mach_o, internal_error> open(cbspan object);
mach_o(mach_o&&) = default;
~mach_o() = default;
Result<std::uintptr_t, internal_error> get_text_vmaddr();
std::size_t get_fat_index() const;
void print_segments() const;
struct pc_range {
frame_ptr low;
frame_ptr high; // not inclusive
};
// for in-memory JIT mach-o's
Result<std::vector<pc_range>, internal_error> get_pc_ranges();
Result<std::reference_wrapper<optional<symtab_info_data>>, internal_error> get_symtab_info();
void print_symbol_table_entry(
const nlist_64& entry,
const char* stringtab,
std::size_t stringsize,
std::size_t j
) const;
void print_symbol_table();
// produce information similar to dsymutil -dump-debug-map
Result<debug_map, internal_error> get_debug_map();
Result<const std::vector<symbol_entry>&, internal_error> symbol_table();
optional<std::string> lookup_symbol(frame_ptr pc);
// produce information similar to dsymutil -dump-debug-map
static void print_debug_map(const debug_map& debug_map);
private:
template<std::size_t Bits>
Result<monostate, internal_error> load_mach();
Result<monostate, internal_error> load_fat_mach();
template<std::size_t Bits>
Result<segment_command_64, internal_error> load_segment_command(std::uint32_t offset) const;
Result<symtab_command, internal_error> load_symbol_table_command(std::uint32_t offset) const;
template<std::size_t Bits>
Result<nlist_64, internal_error> load_symtab_entry(std::uint32_t symbol_base, std::size_t index) const;
Result<std::vector<char>, internal_error> load_string_table(std::uint32_t offset, std::uint32_t byte_count) const;
bool should_swap() const;
};
Result<bool, internal_error> macho_is_fat(cstring_view object_path);
NODISCARD Result<maybe_owned<mach_o>, internal_error> open_mach_o_cached(const std::string& object_path);
}
CPPTRACE_END_NAMESPACE
#endif
#endif