feat add dispatcher

This commit is contained in:
tqcq
2024-04-07 02:42:12 +00:00
parent 7807eecc08
commit cc7d131d95
32 changed files with 7240 additions and 133 deletions

View File

@@ -2,6 +2,7 @@
#include "sled/lang/attributes.h"
#ifdef _WIN32
namespace sled {
void
InitializeSymbolizer(const char *argv0)
{}
@@ -11,6 +12,7 @@ Symbolize(const void *pc, char *out, int out_size)
{
return false;
}
}// namespace sled
#elif defined(__APPLE__)
#include "symbolize_darwin.inc"
#elif defined(__linux__)

View File

@@ -1,140 +1,61 @@
#include <array>
#include <cxxabi.h>
#include <dlfcn.h>
#include <elf.h>
#include <errno.h>
#include "sled/log/log.h"
#include <dwarf++.hh>
#include <elf++.hh>
#include <fcntl.h>
#include <link.h>
#include <sled/log/log.h>
#include <sled/strings/utils.h>
#include <sstream>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
namespace sled {
static constexpr char kTag[] = "symbolizer";
static char *g_exe = nullptr;
static const uint64_t
GetHex(const char *start, const char *end)
{
uint64_t hex = 0;
for (const char *p = start; p < end; ++p) {
int ch = *p;
if (ch >= '0' && ch <= '9') {
hex = hex * 16 + (ch - '0');
} else if (ch >= 'a' && ch <= 'f') {
hex = hex * 16 + (ch - 'a' + 10);
} else if (ch >= 'A' && ch <= 'F') {
hex = hex * 16 + (ch - 'A' + 10);
} else {
break;
}
}
return hex;
}
static const uint64_t
GetHex(const std::string &str)
{
return GetHex(str.c_str(), str.c_str() + str.size());
}
struct ObjFile {
ObjFile() : filename(nullptr), start_addr(nullptr), end_addr(nullptr), offset(0), fd(-1), elf_type(-1)
{
memset(&elf_header, 0, sizeof(elf_header));
memset(phdrs.data(), 0, sizeof(ElfW(Phdr)) * phdrs.size());
}
char *filename;
const void *start_addr;
const void *end_addr;
uint64_t offset;
int fd;
int elf_type;
ElfW(Ehdr) elf_header;
std::array<ElfW(Phdr), 16> phdrs;
};
std::string
ReadFullFile(int fd)
{
std::stringstream ss;
char buf[4096];
ssize_t n;
while ((n = read(fd, buf, sizeof(buf))) > 0) { ss.write(buf, n); }
return ss.str();
}
bool
ReadAddrMap()
{
char maps_path[80];
snprintf(maps_path, sizeof(maps_path), "/proc/self/task/%d/maps", getpid());
int maps_fd;
do {
maps_fd = open(maps_path, O_RDONLY);
} while (maps_fd < 0 && errno == EINTR);
if (maps_fd < 0) {
LOGE(kTag, "open {} failed, {}", maps_path, strerror(errno));
return false;
}
std::string full_file = ReadFullFile(maps_fd);
auto lines = sled::StrSplit(full_file, "\n");
// maps start_addr-end_addr permission offset dev inode pathname
for (const auto &line : lines) {
auto fields = sled::StrSplit(line, " \n\t", true);
if (fields.size() < 6) { continue; }
auto addrs = sled::StrSplit(fields[0], "-", false);
uint64_t start_addr = GetHex(addrs[0]);
uint64_t end_addr = GetHex(addrs[1]);
uint64_t offset = GetHex(fields[2]);
LOGD(kTag, "addr: {}-{} {} {} {}", start_addr, end_addr, offset, fields[1], fields[5]);
}
return true;
}
class Symbolizer {};
static elf::elf *g_elf = nullptr;
static dwarf::dwarf *g_dwarf = nullptr;
void
InitializeSymbolizer(const char *argv0)
{
if (g_exe) {
free(g_exe);
g_exe = nullptr;
}
if (g_elf) { return; }
int self_fd = open(argv0, O_RDONLY);
if (self_fd < 0) { return; }
g_elf = new elf::elf(elf::create_mmap_loader(self_fd));
g_dwarf = new dwarf::dwarf(dwarf::elf::create_loader(*g_elf));
}
if (argv0 && argv0[0] != '\0') { g_exe = strdup(argv0); }
static bool
FindPC(dwarf::taddr pc)
{
return false;
}
bool
Symbolize(const void *pc, char *out, int out_size)
{
Dl_info info;
if (!dladdr(pc, &info)) { return false; }
if (info.dli_fname && out_size > 0) {
strncpy(out, info.dli_fname, out_size);
if (!g_elf || !g_dwarf) { return false; }
if (out_size <= 0) { return false; }
out[0] = '\0';
const auto end_pos = static_cast<size_t>(out_size) - 1;
if (out[end_pos] != '\0') {
// add ...
out[end_pos] = '\0';
}
union {
const void *void_pc;
dwarf::taddr pc_addr;
} u;
u.void_pc = pc;
bool found = false;
for (auto &cu : g_dwarf->compilation_units()) {
try {
if (dwarf::die_pc_range(cu.root()).contains(u.pc_addr)) {
auto &lt = cu.get_line_table();
auto iter = lt.find_address(u.pc_addr);
if (iter == lt.end()) {
return false;
} else {
LOGD("found line {}", iter->get_description());
}
found = true;
break;
}
} catch (...) {}
}
return true;
return found;
}
}// namespace sled

View File

@@ -64,7 +64,7 @@ void_cast(TRet (TClass::*mem_func)(Args...))
}
// TODO: Support Linux
#if defined(__APPLE__)
// #if defined(__APPLE__)
TEST_SUITE("Symbolize")
{
TEST_CASE("Trivial Function")
@@ -87,7 +87,8 @@ TEST_SUITE("Symbolize")
CHECK_EQ(doctest::String("Class::StaticFunc()"), TrySymbolize(void_cast(&Class::StaticFunc)));
}
}
#endif
// #endif
int
main(int argc, char *argv[])

View File

@@ -0,0 +1,59 @@
#ifndef SLED_EXP_DESIGN_PATTERNS_DISPATCHER_H
#define SLED_EXP_DESIGN_PATTERNS_DISPATCHER_H
#include "sled/synchronization/mutex.h"
#include <memory>
#include <set>
namespace sled {
namespace experimental {
template<typename T>
class Dispatcher {
public:
enum class DispatchResult { kHandled, kNotFound };
struct Handler {
virtual ~Handler() = default;
virtual bool HandleMessage(const T &) = 0;
virtual bool OnMessage(T &&) = 0;
};
virtual ~Dispatcher() = default;
void AddHandler(std::shared_ptr<Handler> handler)
{
if (!handler) { return; }
// sled::MutexLock lock(&mutex_);
sled::SharedMutexWriteLock lock(&rwlock_);
handlers_.insert(handler);
}
void RemoveHandler(std::shared_ptr<Handler> handler)
{
if (!handler) { return; }
// sled::MutexLock lock(&mutex_);
sled::SharedMutexWriteLock lock(&rwlock_);
handlers_.erase(handler);
}
DispatchResult Dispatch(const T &message)
{
// sled::MutexLock lock(&mutex_);
sled::SharedMutexReadLock lock(&rwlock_);
for (auto &handler : handlers_) {
if (handler->HandleMessage(message)) { return DispatchResult::kHandled; }
}
return DispatchResult::kNotFound;
}
private:
std::set<std::shared_ptr<Handler>> handlers_;
sled::SharedMutex rwlock_;
// sled::Mutex mutex_;
};
}// namespace experimental
}// namespace sled
#endif// SLED_EXP_DESIGN_PATTERNS_DISPATCHER_H

View File

@@ -4,6 +4,7 @@
extern "C" int
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
if (size > 15) { return 1; }
auto uri_or = sled::URI::ParseURI(std::string(reinterpret_cast<const char *>(data), size));
if (!uri_or.ok()) { return 0; }
auto uri = std::move(uri_or.value());