Skip to content

Commit

Permalink
Optimizing stack trace in macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
gammasoft71 committed Oct 25, 2024
1 parent 2175056 commit bda8928
Showing 1 changed file with 39 additions and 24 deletions.
63 changes: 39 additions & 24 deletions src/xtd.core.native.macos/src/xtd/native/macos/stack_trace.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#define __XTD_CORE_NATIVE_LIBRARY__
#include <xtd/native/stack_trace>
#include "../../../../include/xtd/native/macos/shell_execute.h"
#include "../../../../include/xtd/native/macos/strings.h"
#undef __XTD_CORE_NATIVE_LIBRARY__
#include <execinfo.h>
#include <dlfcn.h>
Expand All @@ -22,27 +23,33 @@
free(demangled);
return result;
}
std::tuple<std::string, size_t, std::string> get_frame_from_address(void* address) {

std::vector<std::tuple<std::string, size_t, std::string>> get_frames_from_addresses(const std::vector<void*>& addresses) {
auto ss = std::stringstream {};
ss << "atos -p " << getpid() << " " << address;
auto frame_string = xtd::native::macos::shell_execute::run(ss.str());
if (frame_string.empty() || frame_string.size() < 2) return {};
frame_string.erase(frame_string.begin() + frame_string.size() - 2, frame_string.end());
auto method = std::string {};
if (frame_string.find(" (in") != frame_string.npos) {
method = frame_string.substr(0, frame_string.find(" (in"));
frame_string.erase(frame_string.begin(), frame_string.begin() + frame_string.find(" (in") + 4);
frame_string.erase(frame_string.begin(), frame_string.begin() + frame_string.find(") (") + 3);
ss << "atos -p " << getpid() << " ";
for (auto adress : addresses)
ss << adress << " ";
auto frame_strings = xtd::native::macos::strings::split(xtd::native::macos::shell_execute::run(ss.str()), {'\n'});
auto frames = std::vector<std::tuple<std::string, size_t, std::string>> {};
for (auto frame_string : frame_strings) {
if (frame_string.size() < 2) continue;;
frame_string.erase(frame_string.begin() + frame_string.size() - 1, frame_string.end());
auto method = std::string {};
if (frame_string.find(" (in") != frame_string.npos) {
method = frame_string.substr(0, frame_string.find(" (in"));
frame_string.erase(frame_string.begin(), frame_string.begin() + frame_string.find(" (in") + 4);
frame_string.erase(frame_string.begin(), frame_string.begin() + frame_string.find(") (") + 3);
}
auto file_name = std::string {};
auto line = size_t {0};
if (frame_string.find(":") != frame_string.npos) {
file_name = frame_string.substr(0, frame_string.find(":"));
frame_string.erase(frame_string.begin(), frame_string.begin() + frame_string.find(":") + 1);
line = std::stoi(frame_string);
}
frames.emplace_back(file_name, line, method);
}
auto file_name = std::string {};
auto line = size_t {0};
if (frame_string.find(":") != frame_string.npos) {
file_name = frame_string.substr(0, frame_string.find(":"));
frame_string.erase(frame_string.begin(), frame_string.begin() + frame_string.find(":") + 1);
line = std::stoi(frame_string);
}
return {file_name, line, method};
return frames;
}
}

Expand All @@ -57,16 +64,24 @@
auto traces = std::vector<void*> {};
traces.resize(max_frames);
auto nb_frames = static_cast<size_t>(backtrace(traces.data(), static_cast<int>(max_frames)));
traces.resize(nb_frames);

if (need_file_info) {
auto simple_frames = get_frames_from_addresses(traces);
for (auto index = skip_frames + native_offset; index < simple_frames.size(); ++index) {
auto dl_info = Dl_info {};
if (!dladdr(traces[index], &dl_info) || !dl_info.dli_sname) continue;
if (demangle_string(dl_info.dli_sname) == std::string("start")) break;
frames.push_back(std::make_tuple(std::get<0>(simple_frames[index]), std::get<1>(simple_frames[index]), 0, std::get<2>(simple_frames[index]), reinterpret_cast<size_t>(dl_info.dli_saddr) - reinterpret_cast<size_t>(dl_info.dli_fbase)));
}
return frames;
}

for (auto index = skip_frames + native_offset; index < nb_frames; ++index) {
auto dl_info = Dl_info {};
if (!dladdr(traces[index], &dl_info) || !dl_info.dli_sname) continue;
if (demangle_string(dl_info.dli_sname) == std::string("start")) break;
if (!need_file_info) frames.push_back(std::make_tuple("", 0, 0, demangle_string(dl_info.dli_sname), 0));
else {
auto [file_name, line, method] = get_frame_from_address(traces[index]);
frames.push_back(std::make_tuple(file_name, line, 0, method, reinterpret_cast<size_t>(dl_info.dli_saddr) - reinterpret_cast<size_t>(dl_info.dli_fbase)));
}
frames.push_back(std::make_tuple("", 0, 0, demangle_string(dl_info.dli_sname), 0));
}
return frames;
}

0 comments on commit bda8928

Please sign in to comment.