backtrace_lib.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #include "backtrace_lib.h"
  2. #include <util/generic/hash.h>
  3. #include <util/system/execpath.h>
  4. #include <algorithm>
  5. #if defined(_linux_) && defined(_x86_64_)
  6. #include <dlfcn.h>
  7. #include <link.h>
  8. #endif
  9. namespace {
  10. const size_t Limit = 400;
  11. void* Stack[Limit];
  12. struct TDllInfo {
  13. const char* Path;
  14. ui64 BaseAddress;
  15. };
  16. const size_t MaxDLLCnt = 100;
  17. TDllInfo DLLs[MaxDLLCnt];
  18. size_t DLLCount = 0;
  19. #if defined(_linux_) && defined(_x86_64_)
  20. int DlIterCallback(struct dl_phdr_info *info, size_t, void *data) {
  21. if (*info->dlpi_name) {
  22. if (DLLCount + 1 < MaxDLLCnt) {
  23. reinterpret_cast<std::remove_reference_t<decltype(DLLs[0])>*>(data)[DLLCount++] = { info->dlpi_name, (ui64)info->dlpi_addr };
  24. }
  25. }
  26. return 0;
  27. }
  28. #endif
  29. bool comp(const TDllInfo& a, const TDllInfo& b) {
  30. return strcmp(a.Path, b.Path) < 0;
  31. }
  32. }
  33. namespace NYql {
  34. namespace NBacktrace {
  35. TCollectedFrame::TCollectedFrame(uintptr_t addr) {
  36. File = GetPersistentExecPath().c_str();
  37. Address = addr;
  38. #if defined(_linux_) && defined(_x86_64_)
  39. Dl_info dlInfo;
  40. memset(&dlInfo, 0, sizeof(dlInfo));
  41. auto ret = dladdr(reinterpret_cast<void*>(addr), &dlInfo);
  42. if (ret) {
  43. auto it = std::lower_bound(DLLs, DLLs + DLLCount, std::remove_reference_t<decltype(DLLs[0])> {dlInfo.dli_fname, {}}, comp);
  44. if (it != DLLs + DLLCount && !strcmp(it->Path, dlInfo.dli_fname)) {
  45. File = it->Path;
  46. Address -= it->BaseAddress;
  47. }
  48. }
  49. #endif
  50. }
  51. size_t CollectFrames(TCollectedFrame* frames, void* data) {
  52. #if defined(_linux_) && defined(_x86_64_)
  53. DLLCount = 0;
  54. dl_iterate_phdr(DlIterCallback, &DLLs);
  55. #endif
  56. std::stable_sort(DLLs, DLLs + DLLCount, comp);
  57. size_t cnt = CollectBacktrace(Stack, Limit, data);
  58. return CollectFrames(frames, Stack, cnt);
  59. }
  60. size_t CollectFrames(TCollectedFrame* frames, void** stack, size_t cnt) {
  61. for (size_t i = 0; i < cnt; ++i) {
  62. new (frames + i)TCollectedFrame(reinterpret_cast<uintptr_t>(stack[i]));
  63. }
  64. return cnt;
  65. }
  66. }
  67. }