已合并
fix: kernel trace at low version kernel #478
wuying39创建于 12 天前
fix: kernel trace at low version kernel #478
已合并
wuying39创建于 12 天前
2 个文件变更+70-10
@@ -275,6 +275,7 @@ struct RawTraceStream {
275 EventFormat entryFormat;275 EventFormat entryFormat;
276 EventFormat returnFormat;276 EventFormat returnFormat;
277 std::unordered_map<uint64_t, uint64_t> canonicalAddressByTraceAddress;277 std::unordered_map<uint64_t, uint64_t> canonicalAddressByTraceAddress;
278+ std::vector<std::pair<uint64_t, uint64_t>> canonicalAddressRanges;
278 std::unordered_map<int, std::string> commByTid;279 std::unordered_map<int, std::string> commByTid;
279 std::vector<CpuPipe> pipes;280 std::vector<CpuPipe> pipes;
280 std::vector<RawFunctionGraphEvent> events;281 std::vector<RawFunctionGraphEvent> events;
@@ -294,6 +295,7 @@ struct RawTraceStream {
294 uint64_t otherEventRecords = 0;295 uint64_t otherEventRecords = 0;
295 uint64_t invalidPayloadRecords = 0;296 uint64_t invalidPayloadRecords = 0;
296 uint64_t adjustedAddressRecords = 0;297 uint64_t adjustedAddressRecords = 0;
298+ uint64_t rangeResolvedAddressRecords = 0;
297 uint64_t addressMissRecords = 0;299 uint64_t addressMissRecords = 0;
298 uint64_t truncatedRecords = 0;300 uint64_t truncatedRecords = 0;
299 uint64_t missedPages = 0;301 uint64_t missedPages = 0;
@@ -377,9 +379,11 @@ struct RawTraceStream {
377 ++invalidPayloadRecords;379 ++invalidPayloadRecords;
378 return;380 return;
379 }381 }
380- uint64_t canonicalAddress = functionAddress;382+ uint64_t canonicalAddress = 0;
381- auto functionIt = canonicalAddressByTraceAddress.find(canonicalAddress);383+ auto functionIt = canonicalAddressByTraceAddress.find(functionAddress);
382- if (functionIt == canonicalAddressByTraceAddress.end()) {384+ if (functionIt != canonicalAddressByTraceAddress.end()) {
385+ canonicalAddress = functionIt->second;
386+ } else {
383 // Convert the architecture-specific fentry call-site IP to the387 // Convert the architecture-specific fentry call-site IP to the
384 // symbol start. Exact matching remains the primary path.388 // symbol start. Exact matching remains the primary path.
385#if defined(__aarch64__)389#if defined(__aarch64__)
@@ -404,11 +408,30 @@ struct RawTraceStream {
404 }408 }
405#endif409#endif
406 }410 }
407- if (functionIt == canonicalAddressByTraceAddress.end()) {411+ 
412+ if (canonicalAddress == 0 && !canonicalAddressRanges.empty()) {
413+ // Function-graph records the architecture's ftrace IP. The
414+ // kernel documentation explicitly permits this patch site to
415+ // differ from the /proc/kallsyms symbol address. If tracefs does
416+ // not provide available_filter_functions_addrs, symbolize the IP
417+ // in the same way as kallsyms: use the nearest preceding text
418+ // symbol. All records reaching this path have already been
419+ // identified as funcgraph entry/exit events.
420+ auto next = std::upper_bound(canonicalAddressRanges.begin(), canonicalAddressRanges.end(),
421+ functionAddress,
422+ [](uint64_t address, const std::pair<uint64_t, uint64_t> &symbol) {
423+ return address < symbol.first;
424+ });
425+ if (next != canonicalAddressRanges.begin()) {
426+ --next;
427+ canonicalAddress = next->second;
428+ ++rangeResolvedAddressRecords;
429+ }
430+ }
431+ if (canonicalAddress == 0) {
408 ++addressMissRecords;432 ++addressMissRecords;
409 return;433 return;
410 }434 }
411- canonicalAddress = functionIt->second;
412 435 
413 int tid = static_cast<int>(pidValue);436 int tid = static_cast<int>(pidValue);
414 if (commByTid.find(tid) == commByTid.end()) {437 if (commByTid.find(tid) == commByTid.end()) {
@@ -613,8 +636,21 @@ bool StartRawTraceStream(KernelTraceManager::Session &session, std::string *erro
613 for (const auto &symbol : session.addresses) {636 for (const auto &symbol : session.addresses) {
614 if (symbol.second != 0) {637 if (symbol.second != 0) {
615 stream->canonicalAddressByTraceAddress.emplace(symbol.second, symbol.second);638 stream->canonicalAddressByTraceAddress.emplace(symbol.second, symbol.second);
639+ stream->canonicalAddressRanges.emplace_back(symbol.second, symbol.second);
616 }640 }
617 }641 }
642+ std::sort(stream->canonicalAddressRanges.begin(), stream->canonicalAddressRanges.end(),
643+ [](const std::pair<uint64_t, uint64_t> &left,
644+ const std::pair<uint64_t, uint64_t> &right) {
645+ return left.first < right.first;
646+ });
647+ stream->canonicalAddressRanges.erase(
648+ std::unique(stream->canonicalAddressRanges.begin(), stream->canonicalAddressRanges.end(),
649+ [](const std::pair<uint64_t, uint64_t> &left,
650+ const std::pair<uint64_t, uint64_t> &right) {
651+ return left.first == right.first;
652+ }),
653+ stream->canonicalAddressRanges.end());
618 for (const auto &patchSite : session.patchAddresses) {654 for (const auto &patchSite : session.patchAddresses) {
619 auto canonical = session.addresses.find(patchSite.first);655 auto canonical = session.addresses.find(patchSite.first);
620 if (canonical != session.addresses.end() && canonical->second != 0 && patchSite.second != 0) {656 if (canonical != session.addresses.end() && canonical->second != 0 && patchSite.second != 0) {
@@ -806,6 +842,10 @@ bool TakeRawTraceEvents(KernelTraceManager::Session &session, std::vector<RawFun
806 TraceLog("[trace-kernel] warning: " + message + "\n");842 TraceLog("[trace-kernel] warning: " + message + "\n");
807 pcerr::SetWarn(LIBPERF_WARN_UTRACE_KERNEL_FAILED, message);843 pcerr::SetWarn(LIBPERF_WARN_UTRACE_KERNEL_FAILED, message);
808 }844 }
845+ if (session.rawStream->rangeResolvedAddressRecords != 0) {
846+ TraceLog("[trace-kernel] symbolized ftrace IPs by kernel symbol range: count=" +
847+ std::to_string(session.rawStream->rangeResolvedAddressRecords) + "\n");
848+ }
809 if (session.rawStream->events.empty() && !session.rawStream->firstPagePrefix.empty()) {849 if (session.rawStream->events.empty() && !session.rawStream->firstPagePrefix.empty()) {
810 static constexpr char K_HEX[] = "0123456789abcdef";850 static constexpr char K_HEX[] = "0123456789abcdef";
811 std::string prefixHex;851 std::string prefixHex;
@@ -771,16 +771,17 @@ bool SelectTraceableFunctions(const std::vector<std::string> &requested, const s
771 771 
772std::unordered_map<std::string, uint64_t> ResolveKernelSymbols(const std::vector<std::string> &functions)772std::unordered_map<std::string, uint64_t> ResolveKernelSymbols(const std::vector<std::string> &functions)
773{773{
774- std::unordered_set<std::string> unresolved(functions.begin(), functions.end());774+ (void)functions;
775 std::unordered_map<std::string, uint64_t> addresses;775 std::unordered_map<std::string, uint64_t> addresses;
776 std::ifstream kallsyms("/proc/kallsyms");776 std::ifstream kallsyms("/proc/kallsyms");
777 std::string line;777 std::string line;
778- while (!unresolved.empty() && std::getline(kallsyms, line)) {778+ while (std::getline(kallsyms, line)) {
779 std::istringstream fields(line);779 std::istringstream fields(line);
780 std::string addressText;780 std::string addressText;
781 std::string type;781 std::string type;
782 std::string name;782 std::string name;
783- if (!(fields >> addressText >> type >> name) || unresolved.find(name) == unresolved.end()) {783+ if (!(fields >> addressText >> type >> name) ||
784+ (type != "t" && type != "T" && type != "w" && type != "W")) {
784 continue;785 continue;
785 }786 }
786 char *end = nullptr;787 char *end = nullptr;
@@ -788,7 +789,6 @@ std::unordered_map<std::string, uint64_t> ResolveKernelSymbols(const std::vector
788 if (end != addressText.c_str() && *end == '\0' && address != 0) {789 if (end != addressText.c_str() && *end == '\0' && address != 0) {
789 addresses.emplace(name, address);790 addresses.emplace(name, address);
790 }791 }
791- unresolved.erase(name);
792 }792 }
793 return addresses;793 return addresses;
794}794}
@@ -912,6 +912,25 @@ static bool WriteFunctionFilter(const KernelTraceManager::Session &session,
912 return true;912 return true;
913}913}
914 914 
915+static bool WriteGraphFunctionFilter(const KernelTraceManager::Session &session,
916+ const std::vector<std::string> &functions, std::string *error)
917+{
918+ std::string path = session.traceFsPath + "/set_graph_function";
919+ // set_graph_function is not available on every supported tracefs version
920+ if (!IsRegularOrVirtualFile(path)) {
921+ return true;
922+ }
923+ if (!ClearTraceFile(path, error)) {
924+ return false;
925+ }
926+ for (const std::string &function : functions) {
927+ if (!AppendTraceFile(path, function + "\n", error)) {
928+ return false;
929+ }
930+ }
931+ return true;
932+}
933+ 
915static bool SetTraceOption(const KernelTraceManager::Session &session, const std::string &name,934static bool SetTraceOption(const KernelTraceManager::Session &session, const std::string &name,
916 bool enabled, bool required, std::string *error)935 bool enabled, bool required, std::string *error)
917{936{
@@ -955,7 +974,8 @@ bool ConfigureGlobalTraceFs(KernelTraceManager::Session &session,
955 !WriteOptionalTraceFile(session.traceFsPath + "/max_graph_depth", "0\n", error) ||974 !WriteOptionalTraceFile(session.traceFsPath + "/max_graph_depth", "0\n", error) ||
956 !WriteOptionalTraceFile(session.traceFsPath + "/tracing_thresh", "0\n", error) ||975 !WriteOptionalTraceFile(session.traceFsPath + "/tracing_thresh", "0\n", error) ||
957 !WriteOptionalTraceFile(session.traceFsPath + "/tracing_cpumask", onlineCpuMask + "\n", error) ||976 !WriteOptionalTraceFile(session.traceFsPath + "/tracing_cpumask", onlineCpuMask + "\n", error) ||
958- !WriteFunctionFilter(session, functions, error)) {977+ !WriteFunctionFilter(session, functions, error) ||
978+ !WriteGraphFunctionFilter(session, functions, error)) {
959 return false;979 return false;
960 }980 }
961 981