Skip to content

Commit f756bb7

Browse files
committed
Get macOS JIT compiled frames working
Still need support for object files.
1 parent b73353d commit f756bb7

11 files changed

Lines changed: 878 additions & 5 deletions

File tree

src/binary/mach-o.cpp

Lines changed: 346 additions & 1 deletion
Large diffs are not rendered by default.

src/binary/mach-o.hpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,48 @@ namespace detail {
4242
std::string name;
4343
};
4444

45+
struct object_relocation {
46+
std::uint32_t address;
47+
std::uint32_t symbolnum;
48+
std::uint8_t pcrel;
49+
std::uint8_t length;
50+
std::uint8_t external;
51+
std::uint8_t type;
52+
};
53+
54+
struct object_symbol {
55+
std::uint8_t type;
56+
std::uint8_t sect;
57+
std::uint16_t desc;
58+
uint64_t value;
59+
std::string name;
60+
};
61+
62+
struct object_section {
63+
std::string name;
64+
std::string segment_name;
65+
std::uint32_t flags;
66+
uint64_t addr;
67+
std::uint32_t offset;
68+
uint64_t size;
69+
std::uint32_t align;
70+
std::uint32_t reloff;
71+
std::uint32_t nreloc;
72+
std::vector<char> data;
73+
std::vector<object_relocation> relocations;
74+
};
75+
76+
struct object_data {
77+
bool is_little_endian;
78+
bool is_64_bit;
79+
std::uint32_t filetype;
80+
cpu_type_t cpu_type;
81+
cpu_subtype_t cpu_subtype;
82+
std::size_t size;
83+
std::vector<object_section> sections;
84+
std::vector<object_symbol> symbols;
85+
};
86+
4587
// map from object file to a vector of symbols to resolve
4688
using debug_map = std::unordered_map<std::string, std::vector<debug_map_entry>>;
4789

@@ -114,6 +156,7 @@ namespace detail {
114156
Result<debug_map, internal_error> get_debug_map();
115157

116158
Result<const std::vector<symbol_entry>&, internal_error> symbol_table();
159+
Result<object_data, internal_error> get_object_data();
117160

118161
optional<std::string> lookup_symbol(frame_ptr pc);
119162

@@ -128,6 +171,8 @@ namespace detail {
128171

129172
template<std::size_t Bits>
130173
Result<segment_command_64, internal_error> load_segment_command(std::uint32_t offset) const;
174+
template<std::size_t Bits>
175+
Result<section_64, internal_error> load_section(std::uint32_t offset) const;
131176

132177
Result<symtab_command, internal_error> load_symbol_table_command(std::uint32_t offset) const;
133178

src/jit/jit_objects.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "cpptrace/forward.hpp"
44
#include "utils/error.hpp"
5+
#include "logging.hpp"
56
#include "utils/optional.hpp"
67
#include "utils/span.hpp"
78
#include "binary/elf.hpp"
@@ -11,6 +12,7 @@
1112
#endif
1213

1314
#include <algorithm>
15+
#include <cstdint>
1416
#include <iostream>
1517
#include <fstream>
1618
#include <map>
@@ -46,8 +48,10 @@ namespace detail {
4648

4749
public:
4850
void add_jit_object(cbspan object) {
51+
log::debug("jit add_jit_object start: ptr={} size={}", reinterpret_cast<std::uintptr_t>(object.data()), object.size());
4952
auto object_res = jit_object_type::open(object);
5053
if(object_res.is_error()) {
54+
log::warn("jit add_jit_object: failed to parse object ptr={} size={}", reinterpret_cast<std::uintptr_t>(object.data()), object.size());
5155
if(!should_absorb_trace_exceptions()) {
5256
object_res.drop_error();
5357
}
@@ -61,11 +65,17 @@ namespace detail {
6165
#endif
6266
};
6367
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
64-
#if IS_LINUX
68+
#if IS_LINUX || IS_APPLE
6569
auto dwarf_object_res = entry.object->get_object_data();
6670
if(dwarf_object_res) {
6771
entry.dwarf_resolver = libdwarf::make_dwarf_resolver(std::move(dwarf_object_res).unwrap_value());
72+
log::debug(
73+
"jit add_jit_object: created in-memory dwarf resolver ptr={} resolver={}",
74+
reinterpret_cast<std::uintptr_t>(object.data()),
75+
reinterpret_cast<std::uintptr_t>(entry.dwarf_resolver.get())
76+
);
6877
} else if(!should_absorb_trace_exceptions()) {
78+
log::warn("jit add_jit_object: failed to build in-memory dwarf object ptr={}", reinterpret_cast<std::uintptr_t>(object.data()));
6979
dwarf_object_res.drop_error();
7080
}
7181
#endif
@@ -74,13 +84,16 @@ namespace detail {
7484
auto* object_file = objects.back().object.get();
7585
auto ranges_res = object_file->get_pc_ranges();
7686
if(ranges_res.is_error()) {
87+
log::warn("jit add_jit_object: failed to extract pc ranges ptr={}", reinterpret_cast<std::uintptr_t>(object.data()));
7788
if(!should_absorb_trace_exceptions()) {
7889
ranges_res.drop_error();
7990
}
8091
return;
8192
}
8293
auto& ranges = ranges_res.unwrap_value();
94+
log::debug("jit add_jit_object: ptr={} extracted {} pc ranges", reinterpret_cast<std::uintptr_t>(object.data()), ranges.size());
8395
for(auto range : ranges) {
96+
log::debug("jit add_jit_object: range [{}, {})", range.low, range.high);
8497
range_entry entry{
8598
range.low,
8699
range.high,
@@ -116,6 +129,7 @@ namespace detail {
116129
}
117130

118131
optional<jit_object_lookup_result> lookup(frame_ptr pc) const {
132+
log::debug("jit lookup: pc={} range_count={}", pc, range_list.size());
119133
auto it = first_less_than_or_equal(
120134
range_list.begin(),
121135
range_list.end(),
@@ -125,10 +139,23 @@ namespace detail {
125139
}
126140
);
127141
if(it == range_list.end()) {
142+
log::debug("jit lookup: miss, no candidate range for pc={}", pc);
128143
return nullopt;
129144
}
130145
ASSERT(pc >= it->low);
131146
if(pc < it->high) {
147+
log::debug(
148+
"jit lookup: hit pc={} in [{}, {}) object_ptr={} dwarf_resolver={}",
149+
pc,
150+
it->low,
151+
it->high,
152+
reinterpret_cast<std::uintptr_t>(it->object_start),
153+
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
154+
reinterpret_cast<std::uintptr_t>(it->dwarf_resolver)
155+
#else
156+
0
157+
#endif
158+
);
132159
return jit_object_lookup_result{
133160
*it->object,
134161
it->low
@@ -137,6 +164,7 @@ namespace detail {
137164
#endif
138165
};
139166
} else {
167+
log::debug("jit lookup: miss, candidate range [{}, {}) does not contain pc={}", it->low, it->high, pc);
140168
return nullopt;
141169
}
142170
}

0 commit comments

Comments
 (0)