Skip to content

Commit

Permalink
feat(symbol resolution): implement kallsyms support
Browse files Browse the repository at this point in the history
lo2s is currently not able to resolve the symbols from instruction
pointers coming from the kernel.

I have implemented in this PR support for parsing kallsyms to alleviate
this.

/proc/kallsyms is a file which records the addresses of symbols inside
the running kernel.

One issue is that it only reports the location, not the size of symbols.
I simply assume that a symbol ends at the start of the next symbol and
the last symbol in the kernel ending at the highest address.
  • Loading branch information
cvonelm committed Oct 21, 2024
1 parent b044d65 commit 632ada6
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
79 changes: 79 additions & 0 deletions include/lo2s/mmap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <deque>
#include <map>
#include <mutex>
#include <regex>
#include <sstream>
#include <stdexcept>

Expand Down Expand Up @@ -140,6 +141,84 @@ class BfdRadareBinary : public Binary
#endif // HAVE_RADARE
};

class Kallsyms : public Binary
{
public:
Kallsyms() : Binary("kernel")
{
std::map<Address, std::string> entries;
std::ifstream ksyms_file("/proc/kallsyms");

std::regex ksym_regex("([0-9a-f]+) (?:t|T) ([^[:space:]]+)");
std::smatch ksym_match;

std::string line;

// Emplacing into entries map takes care of sorting symbols by address
while (getline(ksyms_file, line))
{
if (std::regex_match(line, ksym_match, ksym_regex))
{
std::string sym_str = ksym_match[2];
uint64_t sym_addr = stoull(ksym_match[1], nullptr, 16);
entries.emplace(std::piecewise_construct, std::forward_as_tuple(sym_addr),
std::forward_as_tuple(sym_str));
}
}

std::string sym_str = "";
Address prev = 0;

for (auto& entry : entries)
{
if (prev != 0 && prev != entry.first)
{
kallsyms_.emplace(std::piecewise_construct,
std::forward_as_tuple(prev, entry.first),
std::forward_as_tuple(sym_str));
}
else
{
start_ = entry.first.value();
}
sym_str = entry.second;
prev = entry.first;
}

if (sym_str != "")
{
kallsyms_.emplace(std::piecewise_construct,
std::forward_as_tuple(prev, Address((uint64_t)-1)),
std::forward_as_tuple(sym_str));
}
}

static Kallsyms& cache()
{
static Kallsyms k;
return k;
}

uint64_t start()
{
return start_;
}

virtual std::string lookup_instruction(Address) override
{
throw std::domain_error("Unknown instruction.");
}

virtual LineInfo lookup_line_info(Address addr) override
{
return LineInfo::for_function("kernel", kallsyms_.at(addr + start_).c_str(), 1, "");
}

private:
std::map<Range, std::string> kallsyms_;
uint64_t start_;
};

struct RecordMmapType
{
// BAD things happen if you try this
Expand Down
5 changes: 5 additions & 0 deletions src/mmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ MemoryMap::MemoryMap()

MemoryMap::MemoryMap(Process process, bool read_initial)
{
Binary* kall = &Kallsyms::cache();
map_.emplace(std::piecewise_construct,
std::forward_as_tuple(Kallsyms::cache().start(), (uint64_t)-1),
std::forward_as_tuple(Kallsyms::cache().start(), (uint64_t)-1, 0, *kall));

if (!read_initial)
{
return;
Expand Down

0 comments on commit 632ada6

Please sign in to comment.