Skip to content

Commit

Permalink
Replace BFD -> libelf, merge MMap class and ProcessInfo, split
Browse files Browse the repository at this point in the history
function and instruction resolution.

-> split function resolution and instruction resolution

-> integrate mmap code into ProcessInfo

The mmap code is not used outside of ProcessInfo and every function
in ProcessInfo was already a paper thin wrapper around something in Mmap

-> replace binutils/libbfd with elfutils/libdw/libelf

- API usable by human beings
- Actual documentation
- Has support for DWARF
  • Loading branch information
cvonelm committed Nov 7, 2024
1 parent e0101d5 commit f237e5d
Show file tree
Hide file tree
Showing 12 changed files with 717 additions and 494 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install binutils-dev libiberty-dev libsensors-dev
sudo apt-get install libelf-dev libdebuginfod-dev libdw-dev libsensors-dev
sudo pip install git-archive-all
- name: Cache OTF2
id: cache-otf2
Expand Down
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ if(NOT HAVE_PERF_RECORD_SWITCH)
message(FATAL_ERROR "lo2s requires support for perf context switch recording. Make sure that you are running on a kernel that support context_switch with perf_event_open")
endif()


# detect version of running kernel
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" LINUX_VERSION ${CMAKE_SYSTEM_VERSION})

Expand Down Expand Up @@ -206,6 +207,7 @@ set(SOURCE_FILES

src/config.cpp src/main.cpp src/monitor/process_monitor.cpp
src/platform.cpp
src/process_info.cpp
src/topology.cpp src/pipe.cpp src/dwarf_resolve.cpp
src/util.cpp
src/perf/util.cpp
Expand All @@ -232,6 +234,14 @@ target_link_libraries(lo2s
debuginfod
)

find_path(DEBUGINFOD_INCLUDE_DIRS elfutils/debuginfod.h
PATHS ENV C_INCLUDE_PATH ENV CPATH
PATH_SUFFIXES include)

if(DEBUGINFOD_INCLUDE_DIRS)
target_compile_definitions(lo2s PUBLIC HAVE_DEBUGINFOD)
endif()

# old glibc versions require -lrt for clock_gettime()
if(NOT CLOCK_GETTIME_FOUND)
if(CLOCK_GETTIME_FOUND_WITH_RT)
Expand Down
8 changes: 8 additions & 0 deletions include/lo2s/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ enum class MonitorType
CPU_SET
};

enum class DwarfUsage
{
NONE,
LOCAL,
FULL
};

struct Config
{
// General
Expand Down Expand Up @@ -102,6 +109,7 @@ struct Config
bool use_nvidia;
std::string cuda_injectionlib_path;
uint64_t nvidia_ringbuf_size;
DwarfUsage dwarf;
};

const Config& config();
Expand Down
43 changes: 43 additions & 0 deletions include/lo2s/dwarf_resolve.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once

#include <lo2s/address.hpp>
#include <lo2s/function_resolver.hpp>
#include <lo2s/line_info.hpp>

#include <map>
extern "C"
{
#include <elfutils/libdw.h>
#include <elfutils/libdwfl.h>
#include <fcntl.h>
#include <unistd.h>
}

namespace lo2s
{
class DwarfFunctionResolver : public FunctionResolver
{
public:
DwarfFunctionResolver(std::string name);

static FunctionResolver& cache(std::string name)
{
return StringCache<DwarfFunctionResolver>::instance()[name];
}

~DwarfFunctionResolver();
virtual LineInfo lookup_line_info(Address addr) override;

std::string name()
{
return name_;
}

private:
std::map<Range, LineInfo> cache_;
Dwfl_Callbacks cb;
Dwfl* dwfl_ = nullptr;
Dwfl_Module* mod_ = nullptr;
std::string name_;
};
} // namespace lo2s
130 changes: 130 additions & 0 deletions include/lo2s/function_resolver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* This file is part of the lo2s software.
* Linux OTF2 sampling
*
* Copyright (c) 2024,
* Technische Universitaet Dresden, Germany
*
* lo2s is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lo2s is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lo2s. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <lo2s/line_info.hpp>
#include <lo2s/util.hpp>

#include <string>

Check failure on line 27 in include/lo2s/function_resolver.hpp

View check run for this annotation

Code Style Turtle / Code Formatting Test

include/lo2s/function_resolver.hpp#L27

-#include <string>
#include <regex>

Check failure on line 28 in include/lo2s/function_resolver.hpp

View check run for this annotation

Code Style Turtle / Code Formatting Test

include/lo2s/function_resolver.hpp#L28

+#include <string>

namespace lo2s
{
class FunctionResolver
{
public:
FunctionResolver(const std::string& name) : name_(name)
{
}

static FunctionResolver& cache(const std::string& name)
{
return StringCache<FunctionResolver>::instance()[name];
}

virtual LineInfo lookup_line_info(Address)
{
return LineInfo::for_binary(name_);
}

std::string name()
{
return name_;
}

protected:
std::string name_;
};

class Kallsyms : public FunctionResolver
{
public:
Kallsyms() : FunctionResolver("[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 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_;
};
}

Check failure on line 130 in include/lo2s/function_resolver.hpp

View check run for this annotation

Code Style Turtle / Code Formatting Test

include/lo2s/function_resolver.hpp#L130

-} +} // namespace lo2s
72 changes: 72 additions & 0 deletions include/lo2s/instruction_resolver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* This file is part of the lo2s software.
* Linux OTF2 sampling
*
* Copyright (c) 2024,
* Technische Universitaet Dresden, Germany
*
* lo2s is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lo2s is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lo2s. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

Check failure on line 22 in include/lo2s/instruction_resolver.hpp

View check run for this annotation

Code Style Turtle / Code Formatting Test

include/lo2s/instruction_resolver.hpp#L22

-#pragma once +#pragma once

#include <lo2s/address.hpp>
#ifdef HAVE_RADARE
#include <lo2s/radare.hpp>
#endif
#include <lo2s/util.hpp>

#include <string>

Check failure on line 30 in include/lo2s/instruction_resolver.hpp

View check run for this annotation

Code Style Turtle / Code Formatting Test

include/lo2s/instruction_resolver.hpp#L30

+
namespace lo2s
{
class InstructionResolver
{
public:
InstructionResolver()
{
}

static InstructionResolver& cache()
{
static InstructionResolver ir;
return ir;
}

virtual std::string lookup_instruction(Address)
{
return "";
}
};
#ifdef HAVE_RADARE
class RadareInstructionResolver : public InstructionResolver
{
public:
RadareInstructionResolver(std::string name) : radare_(name)
{
}

static RadareInstructionResolver& cache(const std::string& name)
{
return StringCache<RadareInstructionResolver>::instance()[name];
}

virtual std::string lookup_instruction(Address ip)
{
return radare_.instruction(ip);
}

RadareResolver radare_;
};
#endif // HAVE_RADARE
} // namespace lo2s
Loading

0 comments on commit f237e5d

Please sign in to comment.