Process.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Process.h"
  7. namespace Profiler {
  8. Thread* Process::find_thread(pid_t tid, EventSerialNumber serial)
  9. {
  10. auto it = threads.find(tid);
  11. if (it == threads.end())
  12. return nullptr;
  13. for (auto& thread : it->value) {
  14. if (thread.start_valid < serial && (thread.end_valid == EventSerialNumber {} || thread.end_valid > serial))
  15. return &thread;
  16. }
  17. return nullptr;
  18. }
  19. void Process::handle_thread_create(pid_t tid, EventSerialNumber serial)
  20. {
  21. auto it = threads.find(tid);
  22. if (it == threads.end()) {
  23. threads.set(tid, {});
  24. it = threads.find(tid);
  25. }
  26. auto thread = Thread { tid, serial, {} };
  27. it->value.append(move(thread));
  28. }
  29. void Process::handle_thread_exit(pid_t tid, EventSerialNumber serial)
  30. {
  31. auto* thread = find_thread(tid, serial);
  32. if (!thread)
  33. return;
  34. thread->end_valid = serial;
  35. }
  36. HashMap<String, OwnPtr<MappedObject>> g_mapped_object_cache;
  37. static MappedObject* get_or_create_mapped_object(const String& path)
  38. {
  39. if (auto it = g_mapped_object_cache.find(path); it != g_mapped_object_cache.end())
  40. return it->value.ptr();
  41. auto file_or_error = MappedFile::map(path);
  42. if (file_or_error.is_error()) {
  43. g_mapped_object_cache.set(path, {});
  44. return nullptr;
  45. }
  46. auto elf = ELF::Image(file_or_error.value()->bytes());
  47. if (!elf.is_valid()) {
  48. g_mapped_object_cache.set(path, {});
  49. return nullptr;
  50. }
  51. auto new_mapped_object = adopt_own(*new MappedObject {
  52. .file = file_or_error.release_value(),
  53. .elf = elf,
  54. });
  55. auto* ptr = new_mapped_object.ptr();
  56. g_mapped_object_cache.set(path, move(new_mapped_object));
  57. return ptr;
  58. }
  59. void LibraryMetadata::handle_mmap(FlatPtr base, size_t size, const String& name)
  60. {
  61. String path;
  62. if (name.contains("Loader.so"))
  63. path = "Loader.so";
  64. else if (!name.contains(":"))
  65. return;
  66. else
  67. path = name.substring(0, name.view().find_first_of(":").value());
  68. String full_path;
  69. if (name.contains(".so"))
  70. full_path = String::formatted("/usr/lib/{}", path);
  71. else
  72. full_path = path;
  73. auto* mapped_object = get_or_create_mapped_object(full_path);
  74. if (!mapped_object) {
  75. full_path = String::formatted("/usr/local/lib/{}", path);
  76. mapped_object = get_or_create_mapped_object(full_path);
  77. if (!mapped_object)
  78. return;
  79. }
  80. FlatPtr text_base {};
  81. mapped_object->elf.for_each_program_header([&](const ELF::Image::ProgramHeader& ph) {
  82. if (ph.is_executable())
  83. text_base = ph.vaddr().get();
  84. return IterationDecision::Continue;
  85. });
  86. m_libraries.set(name, adopt_own(*new Library { base, size, name, text_base, mapped_object }));
  87. }
  88. String LibraryMetadata::Library::symbolicate(FlatPtr ptr, u32* offset) const
  89. {
  90. if (!object)
  91. return String::formatted("?? <{:p}>", ptr);
  92. return object->elf.symbolicate(ptr - base + text_base, offset);
  93. }
  94. const LibraryMetadata::Library* LibraryMetadata::library_containing(FlatPtr ptr) const
  95. {
  96. for (auto& it : m_libraries) {
  97. auto& library = *it.value;
  98. if (ptr >= library.base && ptr < (library.base + library.size))
  99. return &library;
  100. }
  101. return nullptr;
  102. }
  103. }