feat symbolize support mac
This commit is contained in:
parent
f97c1b7e0b
commit
c96cb23a3d
131
'
131
'
@ -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
|
@ -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
|
||||
|
2091
src/sled/debugging/demangle.cc
Normal file
2091
src/sled/debugging/demangle.cc
Normal file
File diff suppressed because it is too large
Load Diff
11
src/sled/debugging/demangle.h
Normal file
11
src/sled/debugging/demangle.h
Normal 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
|
0
src/sled/debugging/demangle_test.cc
Normal file
0
src/sled/debugging/demangle_test.cc
Normal 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
|
||||
|
@ -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
|
||||
|
83
src/sled/debugging/symbolize_darwin.inc
Normal file
83
src/sled/debugging/symbolize_darwin.inc
Normal 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
|
@ -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[])
|
||||
|
Loading…
Reference in New Issue
Block a user