feat symbolize support mac

This commit is contained in:
tqcq 2024-03-30 19:36:02 +08:00
parent f97c1b7e0b
commit c96cb23a3d
9 changed files with 2227 additions and 147 deletions

131
'
View File

@ -1,131 +0,0 @@
#include "sled/strings/utils.h"
#include <sstream>
#include <string.h>
namespace sled {
char
ToLower(char c)
{
return ::tolower(c);
}
char
ToUpper(char c)
{
return ::toupper(c);
}
std::string
ToLower(const std::string &str)
{
std::stringstream ss;
for (auto &ch : str) { ss << ToLower(ch); }
return ss.str();
}
std::string
ToUpper(const std::string &str)
{
std::stringstream ss;
for (auto &ch : str) { ss << ToUpper(ch); }
return ss.str();
}
std::string
StrJoin(const std::vector<std::string> &strings, const std::string &delim, bool skip_empty)
{
if (strings.empty()) { return ""; }
std::stringstream ss;
size_t i = 0;
while (skip_empty && i < strings.size() && strings[i].empty()) { ++i; }
if (i < strings.size()) { ss << strings[i++]; }
for (; i < strings.size(); ++i) {
if (skip_empty && strings[i].empty()) { continue; }
ss << delim << strings[i];
}
return ss.str();
}
std::vector<std::string>
StrSplit(const std::string &str, const std::string &delim, bool skip_empty)
{
std::vector<std::string> result;
if (str.empty()) { return result; }
size_t start = 0;
size_t next_pos = str.find_first_of(delim, start);
while (next_pos != std::string::npos) {
if ((!skip_empty && next_pos == start) || next_pos > start) {
result.emplace_back(str.begin() + start, str.begin() + next_pos);
}
if (!skip_empty) {
start = next_pos + 1;
next_pos = str.find_first_of(delim, start);
} else {
start = str.find_first_not_of(delim, next_pos);
if (start == std::string::npos) {
// all remaining characters are delimiters
break;
}
next_pos = str.find_first_of(delim, start);
}
}
if (start < str.size()) { result.emplace_back(str.substr(start)); }
return result;
}
std::string
Trim(const std::string &str, const std::string &chars)
{
return TrimLeft(TrimRight(str, chars), chars);
}
std::string
TrimLeft(const std::string &str, const std::string &chars)
{
size_t start = str.find_first_not_of(chars);
return start == std::string::npos ? "" : str.substr(start);
}
std::string
TrimRight(const std::string &str, const std::string &chars)
{
size_t end = str.find_last_not_of(chars);
return end == std::string::npos ? "" : str.substr(0, end + 1);
}
bool
EndsWith(const std::string &str, const std::string &suffix)
{
return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
bool
StartsWith(const std::string &str, const std::string &prefix)
{
return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0;
}
bool
EndsWithIgnoreCase(const std::string &str, const std::string &suffix)
{
return EndsWith(ToLower(str), ToLower(suffix));
}
bool
StartsWithIgnoreCase(const std::string &str, const std::string &prefix)
{
return StartsWith(ToLower(str), ToLower(prefix));
}
bool
EqualsIgnoreCase(const std::string &lhs, const std::string &rhs)
{
return ToLower(lhs) == ToLower(rhs);
}
}// namespace sled

View File

@ -45,6 +45,7 @@ target_include_directories(sled PUBLIC src/ 3party/eigen 3party/inja
target_sources(
sled
PRIVATE src/sled/async/async.cc
src/sled/debugging/demangle.cc
src/sled/debugging/symbolize.cc
src/sled/filesystem/path.cc
src/sled/log/log.cc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
#ifndef SLED_DEBUGGING_DEMANGLE_H
#define SLED_DEBUGGING_DEMANGLE_H
#pragma once
#include <string>
namespace sled {
bool Demangle(const char *mangled, char *out, size_t out_size);
std::string DemangleString(const char *mangled);
}// namespace sled
#endif// SLED_DEBUGGING_DEMANGLE_H

View File

View File

@ -11,15 +11,7 @@ Symbolize(const void *pc, char *out, int out_size)
return false;
}
#elif defined(__APPLE__)
void
InitializeSymbolizer(const char *argv0)
{}
bool
Symbolize(const void *pc, char *out, int out_size)
{
return false;
}
#include "symbolize_darwin.inc"
#elif defined(__linux__)
#include "sled/debugging/symbolize_elf.inc"
#endif

View File

@ -5,6 +5,5 @@
namespace sled {
void InitializeSymbolizer(const char *argv0);
bool Symbolize(const void *pc, char *out, int out_size);
bool ReadAddrMap();
}// namespace sled
#endif// SLED_DEBUGGING_SYMBOLIZE_H

View File

@ -0,0 +1,83 @@
#include "sled/debugging/demangle.h"
#include <assert.h>
#include <cxxabi.h>
#include <execinfo.h>
#include <algorithm>
#include <string.h>
namespace sled {
namespace {
static std::string
GetSymbolString(const std::string &backtrace_line)
{
// Example Backtrace lines:
// 0 libimaging_shared.dylib 0x018c152a
// _ZNSt11_Deque_baseIN3nik7mediadb4PageESaIS2_EE17_M_initialize_mapEm + 3478
//
// or
// 0 libimaging_shared.dylib 0x0000000001895c39
// _ZN3nik4util19register_shared_ptrINS_3gpu7TextureEEEvPKvS5_ + 39
//
// or
// 0 mysterious_app 0x0124000120120009 main + 17
auto address_pos = backtrace_line.find(" 0x");
if (address_pos == std::string::npos) return std::string();
std::string symbol_view = backtrace_line.substr(address_pos + 1);
auto space_pos = symbol_view.find(" ");
if (space_pos == std::string::npos) return std::string();
symbol_view = symbol_view.substr(space_pos + 1);// to mangled symbol
auto plus_pos = symbol_view.find(" + ");
if (plus_pos == std::string::npos) return std::string();
symbol_view = symbol_view.substr(0, plus_pos);// strip remainng
return std::string(symbol_view);
}
}// namespace
void
InitializeSymbolizer(const char *argv0)
{}
bool
Symbolize(const void *pc, char *out, int out_size)
{
if (out_size <= 0 || pc == nullptr) {
out = nullptr;
return false;
}
// This allocates a char* array.
char **frame_strings = backtrace_symbols(const_cast<void **>(&pc), 1);
if (frame_strings == nullptr) return false;
std::string symbol = GetSymbolString(frame_strings[0]);
free(frame_strings);
char tmp_buf[1024];
if (Demangle(symbol.c_str(), tmp_buf, sizeof(tmp_buf))) {
size_t len = strlen(tmp_buf);
if (len + 1 <= static_cast<size_t>(out_size)) {// +1 for '\0'
assert(len < sizeof(tmp_buf));
memmove(out, tmp_buf, len + 1);
}
} else {
strncpy(out, symbol.c_str(), static_cast<size_t>(out_size));
}
if (out[out_size - 1] != '\0') {
// strncpy() does not '\0' terminate when it truncates.
static constexpr char kEllipsis[] = "...";
size_t ellipsis_size = std::min(sizeof(kEllipsis) - 1, static_cast<size_t>(out_size) - 1);
memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);
out[out_size - 1] = '\0';
}
return true;
}
}// namespace sled

View File

@ -6,6 +6,17 @@ void
TestFunc1()
{}
class Class {
public:
Class() {}
void MemberFunc1() {}
int MemberFunc2() { return 0; }
int MemberFunc3(int) { return 0; }
};
static char try_symbolize_buffer[4096];
static const char *
@ -26,13 +37,36 @@ TrySymbolize(void *pc)
return TrySymbolizeWithLimit(pc, 4096);
}
// TEST(Symbolize, base)
// {
// char buf[1024];
// EXPECT_EQ("TestFunc1", TrySymbolize((void *) &TestFunc1));
// }
template<typename TRet, typename... Args>
void *
void_cast(TRet (*fn)(Args...))
{
return reinterpret_cast<void *>(fn);
}
TEST(Symbolize, ReadAddrMap) { sled::ReadAddrMap(); }
template<typename TClass, typename TRet, typename... Args>
void *
void_cast(TRet (TClass::*mem_func)(Args...))
{
union {
void *void_casted;
TRet (TClass::*p)(Args...);
};
p = mem_func;
return void_casted;
}
TEST(Symbolize, base)
{
char buf[1024];
EXPECT_STREQ("TestFunc1()", TrySymbolize(void_cast(TestFunc1)));
EXPECT_STREQ("Class::MemberFunc1()", TrySymbolize(void_cast(&Class::MemberFunc1)));
EXPECT_STREQ("Class::MemberFunc2()", TrySymbolize(void_cast(&Class::MemberFunc2)));
EXPECT_STREQ("Class::MemberFunc3()", TrySymbolize(void_cast(&Class::MemberFunc3)));
EXPECT_STREQ("TrySymbolizeWithLimit()", TrySymbolize(void_cast(&TrySymbolizeWithLimit)));
}
int
main(int argc, char *argv[])