feat add dispatcher
This commit is contained in:
@@ -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__)
|
||||
|
||||
@@ -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 < = 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
|
||||
|
||||
@@ -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[])
|
||||
|
||||
59
src/sled/experimental/design_patterns/dispatcher.h
Normal file
59
src/sled/experimental/design_patterns/dispatcher.h
Normal 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
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user