Skip to content
9 changes: 6 additions & 3 deletions include/base_frame_symbol_lookup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
#include "dso_symbol_lookup.hpp"
#include "symbol_table.hpp"

struct ddog_prof_ProfilesDictionary;

namespace ddprof {
class BaseFrameSymbolLookup {
public:
SymbolIdx_t get_or_insert(pid_t pid, SymbolTable &symbol_table,
DsoSymbolLookup &dso_symbol_lookup,
DsoHdr &dso_hdr);
DsoSymbolLookup &dso_symbol_lookup, DsoHdr &dso_hdr,
const ddog_prof_ProfilesDictionary *dict);

// Erase symbol lookup for this pid (warning symbols still exist)
void erase(pid_t pid) {
Expand All @@ -27,7 +29,8 @@ class BaseFrameSymbolLookup {
private:
SymbolIdx_t insert_bin_symbol(pid_t pid, SymbolTable &symbol_table,
DsoSymbolLookup &dso_symbol_lookup,
DsoHdr &dso_hdr);
DsoHdr &dso_hdr,
const ddog_prof_ProfilesDictionary *dict);
static const int k_nb_bin_lookups = 10;
struct PidSymbol {
explicit PidSymbol(SymbolIdx_t symb_idx) : _symb_idx(symb_idx) {}
Expand Down
5 changes: 4 additions & 1 deletion include/common_mapinfo_lookup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <string>
#include <unordered_map>

struct ddog_prof_ProfilesDictionary;

namespace ddprof {
// Generates virtual frames for common unhandled cases
class CommonMapInfoLookup {
Expand All @@ -21,7 +23,8 @@ class CommonMapInfoLookup {
};

SymbolIdx_t get_or_insert(MappingErrors lookup_case,
MapInfoTable &mapinfo_table);
MapInfoTable &mapinfo_table,
const ddog_prof_ProfilesDictionary *dict);

private:
std::unordered_map<MappingErrors, MapInfoIdx_t> _map;
Expand Down
6 changes: 4 additions & 2 deletions include/common_symbol_lookup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@

#include <unordered_map>

struct ddog_prof_ProfilesDictionary;

namespace ddprof {
// Generates virtual frames for common unhandled cases
class CommonSymbolLookup {
public:
SymbolIdx_t get_or_insert(SymbolErrors lookup_case,
SymbolTable &symbol_table);
SymbolIdx_t get_or_insert(SymbolErrors lookup_case, SymbolTable &symbol_table,
const ddog_prof_ProfilesDictionary *dict);

private:
std::unordered_map<SymbolErrors, SymbolIdx_t> _map;
Expand Down
51 changes: 38 additions & 13 deletions include/ddog_profiling_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,60 @@
#include "symbol.hpp"
#include "unwind_output.hpp"

#include "datadog/blazesym.h"
#include "datadog/common.h"
#include "datadog/profiling.h"

#include <string_view>

struct blaze_sym;

namespace ddprof {
inline ddog_CharSlice to_CharSlice(std::string_view str) {
return {.ptr = str.data(), .len = str.size()};
}

void write_function(const Symbol &symbol, ddog_prof_Function *ffi_func);
ddog_prof_StringId2 intern_string(const ddog_prof_ProfilesDictionary *dict,
std::string_view str);

std::string_view get_string(const ddog_prof_ProfilesDictionary *dict,
ddog_prof_StringId2 string_id);

std::string_view
get_location2_function_name(const ddog_prof_ProfilesDictionary *dict,
const ddog_prof_Location2 &loc);

void write_function(std::string_view demangled_name, std::string_view file_name,
ddog_prof_Function *ffi_func);
std::string_view
get_location2_mapping_filename(const ddog_prof_ProfilesDictionary *dict,
const ddog_prof_Location2 &loc);

void write_mapping(const MapInfo &mapinfo, ddog_prof_Mapping *ffi_mapping);
ddog_prof_FunctionId2
intern_function_ids(const ddog_prof_ProfilesDictionary *dict,
ddog_prof_StringId2 name_id, ddog_prof_StringId2 file_id,
ddog_prof_StringId2 system_name_id);

void write_location(const FunLoc &loc, const MapInfo &mapinfo,
const Symbol &symbol, ddog_prof_Location *ffi_location);
ddog_prof_FunctionId2 intern_function(const ddog_prof_ProfilesDictionary *dict,
std::string_view demangled_name,
std::string_view file_name,
std::string_view system_name = {});

void write_location(ProcessAddress_t ip_or_elf_addr,
std::string_view demangled_name, std::string_view file_name,
uint32_t lineno, const MapInfo &mapinfo,
ddog_prof_Location *ffi_location);
ddog_prof_MappingId2 intern_mapping(const ddog_prof_ProfilesDictionary *dict,
const MapInfo &mapinfo);

DDRes write_location_blaze(
Symbol make_symbol(std::string symname, const std::string &demangled_name,
uint32_t lineno, const std::string &srcpath,
const ddog_prof_ProfilesDictionary *dict);

void write_location2(const FunLoc &loc, const MapInfo &mapinfo,
const Symbol &symbol, ddog_prof_Location2 *ffi_location);

DDRes write_location2_blaze(
ElfAddress_t elf_addr,
ddprof::HeterogeneousLookupStringMap<std::string> &demangled_names,
const MapInfo &mapinfo, const blaze_sym &blaze_sym, unsigned &cur_loc,
std::span<ddog_prof_Location> locations_buff);
const ddog_prof_ProfilesDictionary *dict,
std::span<ddog_prof_Location2> locations_buff);

void write_location2_no_sym(ElfAddress_t ip, const MapInfo &mapinfo,
const ddog_prof_ProfilesDictionary *dict,
ddog_prof_Location2 *ffi_location);
} // namespace ddprof
11 changes: 8 additions & 3 deletions include/dso_symbol_lookup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,29 @@

#include <unordered_map>

struct ddog_prof_ProfilesDictionary;

namespace ddprof {

class DsoSymbolLookup {
public:
SymbolIdx_t get_or_insert(FileAddress_t normalized_addr, const Dso &dso,
SymbolTable &symbol_table,
const ddog_prof_ProfilesDictionary *dict,
std::string_view addr_type = "elf");

// only binary info
SymbolIdx_t get_or_insert(const Dso &dso, SymbolTable &symbol_table);
SymbolIdx_t get_or_insert(const Dso &dso, SymbolTable &symbol_table,
const ddog_prof_ProfilesDictionary *dict);

void stats_display() const;

private:
size_t get_size() const;

SymbolIdx_t get_or_insert_unhandled_type(const Dso &dso,
SymbolTable &symbol_table);
SymbolIdx_t
get_or_insert_unhandled_type(const Dso &dso, SymbolTable &symbol_table,
const ddog_prof_ProfilesDictionary *dict);
// map of maps --> the aim is to monitor usage of some maps and clear them
// together
// TODO : find efficient clear on symbol table before we do this
Expand Down
5 changes: 3 additions & 2 deletions include/mapinfo_lookup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
#include <unordered_map>

struct Dwfl_Module;
struct ddog_prof_ProfilesDictionary;

namespace ddprof {

class MapInfoLookup {
public:
MapInfoIdx_t get_or_insert(pid_t pid, MapInfoTable &mapinfo_table,
const Dso &dso,
std::optional<BuildIdStr> build_id);
const Dso &dso, std::optional<BuildIdStr> build_id,
const ddog_prof_ProfilesDictionary *dict);
void erase(pid_t pid) {
// table elements are not removed (TODO to gain memory usage)
_mapinfo_pidmap.erase(pid);
Expand Down
3 changes: 3 additions & 0 deletions include/mapinfo_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <string>
#include <vector>

struct ddog_prof_Mapping2;

namespace ddprof {
class MapInfo {
public:
Expand All @@ -26,6 +28,7 @@ class MapInfo {
Offset_t _offset{0};
std::string _sopath;
BuildIdStr _build_id;
ddog_prof_Mapping2 *_mapping_id{nullptr};
};

using MapInfoTable = std::vector<MapInfo>;
Expand Down
28 changes: 21 additions & 7 deletions include/pprof/ddprof_pprof.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,25 @@ class Symbolizer;
struct SymbolHdr;

struct DDProfPProf {
// Label key IDs are stored in the dictionary (process-scoped)
// They are initialized once when SymbolHdr is created
struct DictLabelKeyIds {
ddog_prof_StringId2 container_id{};
ddog_prof_StringId2 process_id{};
ddog_prof_StringId2 process_name{};
ddog_prof_StringId2 thread_id{};
ddog_prof_StringId2 thread_name{};
ddog_prof_StringId2 tracepoint_type{};
};

/* single profile gathering several value types */
ddog_prof_Profile _profile{};
unsigned _nb_values = 0;
Tags _tags;
// avoid re-creating strings for all pid numbers
std::unordered_map<pid_t, std::string> _pid_str;
// Dictionary label key IDs (set from SymbolHdr)
DictLabelKeyIds _dict_label_key_ids;
};

struct DDProfValuePack {
Expand All @@ -36,7 +49,8 @@ struct DDProfValuePack {
uint64_t timestamp;
};

DDRes pprof_create_profile(DDProfPProf *pprof, DDProfContext &ctx);
DDRes pprof_create_profile(DDProfPProf *pprof, DDProfContext &ctx,
const ddog_prof_ProfilesDictionaryHandle *dict);

/**
* Aggregate to the existing profile the provided unwinding output.
Expand All @@ -45,12 +59,12 @@ DDRes pprof_create_profile(DDProfPProf *pprof, DDProfContext &ctx);
* @param watcher_idx matches the registered order at profile creation
* @param pprof
*/
DDRes pprof_aggregate(const UnwindOutput *uw_output,
const SymbolHdr &symbol_hdr, const DDProfValuePack &pack,
const PerfWatcher *watcher,
const FileInfoVector &file_infos, bool show_samples,
EventAggregationModePos value_pos, Symbolizer *symbolizer,
DDProfPProf *pprof);
DDRes pprof_aggregate_interned_sample(
const UnwindOutput *uw_output, const SymbolHdr &symbol_hdr,
const DDProfValuePack &pack, const PerfWatcher *watcher,
const FileInfoVector &file_infos, bool show_samples,
EventAggregationModePos value_pos, Symbolizer *symbolizer,
DDProfPProf *pprof);

DDRes pprof_reset(DDProfPProf *pprof);

Expand Down
15 changes: 11 additions & 4 deletions include/runtime_symbol_lookup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <array>
#include <unordered_map>

struct ddog_prof_ProfilesDictionary;

namespace ddprof {

class RuntimeSymbolLookup {
Expand All @@ -30,10 +32,12 @@ class RuntimeSymbolLookup {

SymbolIdx_t get_or_insert_jitdump(pid_t pid, ProcessAddress_t pc,
SymbolTable &symbol_table,
const ddog_prof_ProfilesDictionary *dict,
std::string_view jitdump_path);

SymbolIdx_t get_or_insert(pid_t pid, ProcessAddress_t pc,
SymbolTable &symbol_table);
SymbolTable &symbol_table,
const ddog_prof_ProfilesDictionary *dict);

void erase(pid_t pid) { _pid_map.erase(pid); }

Expand Down Expand Up @@ -77,10 +81,12 @@ class RuntimeSymbolLookup {
// Symbols are cached with the process's address.
//
DDRes fill_from_jitdump(std::string_view jitdump_path, pid_t pid,
SymbolMap &symbol_map, SymbolTable &symbol_table);
SymbolMap &symbol_map, SymbolTable &symbol_table,
const ddog_prof_ProfilesDictionary *dict);

DDRes fill_from_perfmap(int pid, SymbolMap &symbol_map,
SymbolTable &symbol_table);
SymbolTable &symbol_table,
const ddog_prof_ProfilesDictionary *dict);

UniqueFile perfmaps_open(int pid, const char *path_to_perfmap);

Expand Down Expand Up @@ -111,7 +117,8 @@ class RuntimeSymbolLookup {
static bool insert_or_replace(std::string_view symbol,
ProcessAddress_t address, Offset_t code_size,
SymbolMap &symbol_map,
SymbolTable &symbol_table);
SymbolTable &symbol_table,
const ddog_prof_ProfilesDictionary *dict);

static constexpr std::array<const std::string_view, 1>
_ignored_symbols_start = {{
Expand Down
19 changes: 4 additions & 15 deletions include/symbol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "ddprof_defs.hpp"

#include <string>
struct ddog_prof_Function2;

// Symbol
// Information relating to a given location
Expand All @@ -17,21 +17,10 @@ class Symbol {
public:
Symbol() : _lineno(0) {}

// Warning : Generates some string copies (these are not rvalues)
Symbol(std::string symname, std::string demangled_name, uint32_t lineno,
std::string srcpath)
: _symname(std::move(symname)),
_demangled_name(std::move(demangled_name)), _lineno(lineno),
_srcpath(std::move(srcpath)) {}
Symbol(uint32_t lineno, ddog_prof_Function2 *function_id)
: _lineno(lineno), _function_id(function_id) {}

// OUTPUT OF ADDRINFO
std::string _symname;

// DEMANGLING CACHE
std::string _demangled_name;

// OUTPUT OF LINE INFO
uint32_t _lineno;
std::string _srcpath;
ddog_prof_Function2 *_function_id{nullptr};
};
} // namespace ddprof
32 changes: 30 additions & 2 deletions include/symbol_hdr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,49 @@
#include "runtime_symbol_lookup.hpp"

#include <cstdlib>
#include <memory>

// Forward declarations for libdatadog types (must be at global scope)
struct ddog_prof_ProfilesDictionary;
using ddog_prof_ProfilesDictionaryHandle = ddog_prof_ProfilesDictionary *;

namespace ddprof {

struct ProfilesDictionaryDeleter {
void operator()(ddog_prof_ProfilesDictionaryHandle *handle) const;
};

using ProfilesDictionaryPtr =
std::unique_ptr<ddog_prof_ProfilesDictionaryHandle,
ProfilesDictionaryDeleter>;

struct SymbolHdr {
explicit SymbolHdr(std::string_view path_to_proc = "")
: _runtime_symbol_lookup(path_to_proc) {}
explicit SymbolHdr(std::string_view path_to_proc = "");
~SymbolHdr() = default;

SymbolHdr(const SymbolHdr &) = delete;
SymbolHdr &operator=(const SymbolHdr &) = delete;
SymbolHdr(SymbolHdr &&) noexcept = default;
SymbolHdr &operator=(SymbolHdr &&) noexcept = default;
void display_stats() const { _dso_symbol_lookup.stats_display(); }
void cycle() { _runtime_symbol_lookup.cycle(); }

const ddog_prof_ProfilesDictionary *profiles_dictionary() const {
return _profiles_dictionary ? *_profiles_dictionary : nullptr;
}

void clear(pid_t pid) {
_base_frame_symbol_lookup.erase(pid);
// mappings are only relevant in the context of a given pid.
_mapinfo_lookup.erase(pid);
_runtime_symbol_lookup.erase(pid);
}

// String interning dictionary (persists across profile exports)
// MUST be declared first so it is destroyed last - Symbol and MapInfo
// objects store pointers into this dictionary.
ProfilesDictionaryPtr _profiles_dictionary;

// Cache symbol associations
BaseFrameSymbolLookup _base_frame_symbol_lookup;
CommonSymbolLookup _common_symbol_lookup;
Expand Down
Loading