diff --git a/include/ddprof_cli.hpp b/include/ddprof_cli.hpp index 0b20b4d1..21c22f07 100644 --- a/include/ddprof_cli.hpp +++ b/include/ddprof_cli.hpp @@ -67,6 +67,8 @@ struct DDProfCLI { bool show_samples{false}; bool fault_info{true}; bool help_extended{false}; + bool remote_symbolization{false}; + std::string socket_path; int pipefd_to_library{-1}; bool continue_exec{false}; diff --git a/include/ddprof_context.hpp b/include/ddprof_context.hpp index 4396cbe7..e2a85ddc 100644 --- a/include/ddprof_context.hpp +++ b/include/ddprof_context.hpp @@ -32,6 +32,8 @@ struct DDProfContext { UniqueFd pipefd_to_library; bool show_samples{false}; bool timeline{false}; + bool remote_symbolization{false}; + cpu_set_t cpu_affinity{}; std::string switch_user; std::string internal_stats; diff --git a/include/pprof/ddprof_pprof.hpp b/include/pprof/ddprof_pprof.hpp index 4fa7083c..815720bd 100644 --- a/include/pprof/ddprof_pprof.hpp +++ b/include/pprof/ddprof_pprof.hpp @@ -22,6 +22,7 @@ struct DDProfPProf { ddog_prof_Profile _profile{}; unsigned _nb_values = 0; Tags _tags; + bool use_process_adresses{true}; }; struct DDProfValuePack { diff --git a/include/unwind_helpers.hpp b/include/unwind_helpers.hpp index 7788dd57..94db1969 100644 --- a/include/unwind_helpers.hpp +++ b/include/unwind_helpers.hpp @@ -17,8 +17,8 @@ struct UnwindState; bool is_max_stack_depth_reached(const UnwindState &us); -DDRes add_frame(SymbolIdx_t symbol_idx, MapInfoIdx_t map_idx, ElfAddress_t pc, - UnwindState *us); +DDRes add_frame(SymbolIdx_t symbol_idx, MapInfoIdx_t map_idx, + ProcessAddress_t pc, ElfAddress_t elf_addr, UnwindState *us); void add_common_frame(UnwindState *us, SymbolErrors lookup_case); diff --git a/include/unwind_output.hpp b/include/unwind_output.hpp index 267c7f0c..6e820a68 100644 --- a/include/unwind_output.hpp +++ b/include/unwind_output.hpp @@ -17,7 +17,8 @@ namespace ddprof { struct FunLoc { - uint64_t ip; // Relative to file, not VMA + ProcessAddress_t ip; // process address + ElfAddress_t elf_addr; // elf address (in elf file virtual memory space) SymbolIdx_t _symbol_idx; MapInfoIdx_t _map_info_idx; diff --git a/include/unwind_output_hash.hpp b/include/unwind_output_hash.hpp index c5fc1d4c..f01d9f2b 100644 --- a/include/unwind_output_hash.hpp +++ b/include/unwind_output_hash.hpp @@ -16,6 +16,7 @@ struct UnwindOutputHash { hash_combine(seed, uo.tid); for (const auto &fl : uo.locs) { hash_combine(seed, fl.ip); + // no need to hash fl.elf_addr since it's derived from fl.ip hash_combine(seed, fl._symbol_idx); hash_combine(seed, fl._map_info_idx); } diff --git a/src/ddprof_cli.cc b/src/ddprof_cli.cc index 7d38caee..65aafeb4 100644 --- a/src/ddprof_cli.cc +++ b/src/ddprof_cli.cc @@ -340,6 +340,13 @@ int DDProfCLI::parse(int argc, const char *argv[]) { ->envname("DD_PROFILING_LOADED_LIBS_CHECK_INTERVAL") ->group("")); + extended_options.push_back(app.add_option("--remote_symbolization", + remote_symbolization, + "Enable remote symbolization") + ->default_val(false) + ->envname("DD_PROFILING_REMOTE_SYMBOLIZATION") + ->group("")); + // Parse CLI11_PARSE(app, argc, argv); diff --git a/src/ddprof_context_lib.cc b/src/ddprof_context_lib.cc index 68a06c42..aa65bef7 100644 --- a/src/ddprof_context_lib.cc +++ b/src/ddprof_context_lib.cc @@ -89,6 +89,8 @@ void copy_cli_values(const DDProfCLI &ddprof_cli, DDProfContext &ctx) { ctx.params.show_samples = ddprof_cli.show_samples; ctx.params.timeline = ddprof_cli.timeline; ctx.params.fault_info = ddprof_cli.fault_info; + ctx.params.remote_symbolization = ddprof_cli.remote_symbolization; + ctx.params.initial_loaded_libs_check_delay = ddprof_cli.initial_loaded_libs_check_delay; ctx.params.loaded_libs_check_interval = ddprof_cli.loaded_libs_check_interval; diff --git a/src/pprof/ddprof_pprof.cc b/src/pprof/ddprof_pprof.cc index fe2d5ac6..14fbb445 100644 --- a/src/pprof/ddprof_pprof.cc +++ b/src/pprof/ddprof_pprof.cc @@ -40,10 +40,11 @@ void write_mapping(const MapInfo &mapinfo, ddog_prof_Mapping *ffi_mapping) { } void write_location(const FunLoc *loc, const MapInfo &mapinfo, - const Symbol &symbol, ddog_prof_Location *ffi_location) { + const Symbol &symbol, ddog_prof_Location *ffi_location, + bool use_process_adresses) { write_mapping(mapinfo, &ffi_location->mapping); write_function(symbol, &ffi_location->function); - ffi_location->address = loc->ip; + ffi_location->address = use_process_adresses ? loc->ip : loc->elf_addr; ffi_location->line = symbol._lineno; } @@ -255,6 +256,14 @@ DDRes pprof_create_profile(DDProfPProf *pprof, DDProfContext &ctx) { std::string("container_id")); } + if (ctx.params.remote_symbolization) { + pprof->_tags.emplace_back(std::string("remote_symbols"), + std::string("yes")); + pprof->use_process_adresses = false; + } else { + pprof->use_process_adresses = true; + } + return {}; } @@ -301,7 +310,8 @@ DDRes pprof_aggregate(const UnwindOutput *uw_output, for (const FunLoc &loc : locs) { // possibly several lines to handle inlined function (not handled for now) write_location(&loc, mapinfo_table[loc._map_info_idx], - symbol_table[loc._symbol_idx], &locations_buff[cur_loc]); + symbol_table[loc._symbol_idx], &locations_buff[cur_loc], + pprof->use_process_adresses); ++cur_loc; } @@ -401,7 +411,7 @@ void ddprof_print_sample(const UnwindOutput &uw_output, buf += path.substr(pos == std::string_view::npos ? 0 : pos + 1); buf += ")"; } else { - absl::StrAppendFormat(&buf, "%#x", loc_it->ip); + absl::StrAppendFormat(&buf, "%#x/%#x", loc_it->ip, loc_it->elf_addr); } } else { std::string_view const func{sym._symname}; diff --git a/src/unwind_dwfl.cc b/src/unwind_dwfl.cc index 48269a70..89df989a 100644 --- a/src/unwind_dwfl.cc +++ b/src/unwind_dwfl.cc @@ -224,7 +224,7 @@ DDRes add_dwfl_frame(UnwindState *us, const Dso &dso, ElfAddress_t pc, unwind_symbol_hdr._dso_symbol_lookup, file_info_id, pc, dso); MapInfoIdx_t const map_idx = us->symbol_hdr._mapinfo_lookup.get_or_insert( us->pid, us->symbol_hdr._mapinfo_table, dso, ddprof_mod._build_id); - return add_frame(symbol_idx, map_idx, pc, us); + return add_frame(symbol_idx, map_idx, pc, pc - ddprof_mod._sym_bias, us); } // check for runtime symbols provided in /tmp files @@ -250,7 +250,8 @@ DDRes add_runtime_symbol_frame(UnwindState *us, const Dso &dso, ElfAddress_t pc, MapInfoIdx_t const map_idx = us->symbol_hdr._mapinfo_lookup.get_or_insert( us->pid, us->symbol_hdr._mapinfo_table, dso, {}); - return add_frame(symbol_idx, map_idx, pc, us); + return add_frame(symbol_idx, map_idx, pc, pc - dso.start() + dso.offset(), + us); } } // namespace diff --git a/src/unwind_helpers.cc b/src/unwind_helpers.cc index b475ec3e..41c99fda 100644 --- a/src/unwind_helpers.cc +++ b/src/unwind_helpers.cc @@ -15,7 +15,7 @@ namespace ddprof { namespace { void add_frame_without_mapping(UnwindState *us, SymbolIdx_t symbol_idx) { - add_frame(symbol_idx, -1, 0, us); + add_frame(symbol_idx, -1, 0, 0, us); } } // namespace @@ -25,8 +25,8 @@ bool is_max_stack_depth_reached(const UnwindState &us) { return us.output.locs.size() + 2 >= kMaxStackDepth; } -DDRes add_frame(SymbolIdx_t symbol_idx, MapInfoIdx_t map_idx, ElfAddress_t pc, - UnwindState *us) { +DDRes add_frame(SymbolIdx_t symbol_idx, MapInfoIdx_t map_idx, + ProcessAddress_t pc, ElfAddress_t elf_addr, UnwindState *us) { UnwindOutput *output = &us->output; if (output->locs.size() >= kMaxStackDepth) { DDRES_RETURN_WARN_LOG(DD_WHAT_UW_MAX_DEPTH, @@ -35,6 +35,7 @@ DDRes add_frame(SymbolIdx_t symbol_idx, MapInfoIdx_t map_idx, ElfAddress_t pc, FunLoc current; current._symbol_idx = symbol_idx; current.ip = pc; + current.elf_addr = elf_addr; if (map_idx == -1) { // just add an empty element for mapping info current._map_info_idx = us->symbol_hdr._common_mapinfo_lookup.get_or_insert(