Serenity Operating System
at master 137 lines 4.6 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "Process.h" 8#include <LibCore/DeprecatedFile.h> 9 10namespace Profiler { 11 12Thread* Process::find_thread(pid_t tid, EventSerialNumber serial) 13{ 14 auto it = threads.find(tid); 15 if (it == threads.end()) 16 return nullptr; 17 for (auto& thread : it->value) { 18 if (thread.start_valid < serial && (thread.end_valid == EventSerialNumber {} || thread.end_valid > serial)) 19 return &thread; 20 } 21 return nullptr; 22} 23 24void Process::handle_thread_create(pid_t tid, EventSerialNumber serial) 25{ 26 auto it = threads.find(tid); 27 if (it == threads.end()) { 28 threads.set(tid, {}); 29 it = threads.find(tid); 30 } 31 32 auto thread = Thread { tid, serial, {} }; 33 it->value.append(move(thread)); 34} 35 36void Process::handle_thread_exit(pid_t tid, EventSerialNumber serial) 37{ 38 auto* thread = find_thread(tid, serial); 39 if (!thread) 40 return; 41 thread->end_valid = serial; 42} 43 44HashMap<DeprecatedString, OwnPtr<MappedObject>> g_mapped_object_cache; 45 46static MappedObject* get_or_create_mapped_object(DeprecatedString const& path) 47{ 48 if (auto it = g_mapped_object_cache.find(path); it != g_mapped_object_cache.end()) 49 return it->value.ptr(); 50 51 auto file_or_error = Core::MappedFile::map(path); 52 if (file_or_error.is_error()) { 53 g_mapped_object_cache.set(path, {}); 54 return nullptr; 55 } 56 auto elf = ELF::Image(file_or_error.value()->bytes()); 57 if (!elf.is_valid()) { 58 g_mapped_object_cache.set(path, {}); 59 return nullptr; 60 } 61 auto new_mapped_object = adopt_own(*new MappedObject { 62 .file = file_or_error.release_value(), 63 .elf = elf, 64 }); 65 auto* ptr = new_mapped_object.ptr(); 66 g_mapped_object_cache.set(path, move(new_mapped_object)); 67 return ptr; 68} 69 70void LibraryMetadata::handle_mmap(FlatPtr base, size_t size, DeprecatedString const& name) 71{ 72 StringView path; 73 if (name.contains("Loader.so"sv)) 74 path = "Loader.so"sv; 75 else if (!name.contains(':')) 76 return; 77 else 78 path = name.substring_view(0, name.view().find(':').value()); 79 80 // Each loaded object has at least 4 segments associated with it: .rodata, .text, .relro, .data. 81 // We only want to create a single LibraryMetadata object for each library, so we need to update the 82 // associated base address and size as new regions are discovered. 83 84 // We don't allocate a temporary String object if an entry already exists. 85 // This assumes that DeprecatedString::hash and StringView::hash return the same result. 86 auto string_view_compare = [&path](auto& entry) { return path == entry.key.view(); }; 87 if (auto existing_it = m_libraries.find(path.hash(), string_view_compare); existing_it != m_libraries.end()) { 88 auto& entry = *existing_it->value; 89 entry.base = min(entry.base, base); 90 entry.size = max(entry.size + size, base - entry.base + size); 91 } else { 92 DeprecatedString path_string = path.to_deprecated_string(); 93 DeprecatedString full_path; 94 if (path_string.starts_with('/')) 95 full_path = path_string; 96 else if (Core::DeprecatedFile::looks_like_shared_library(path_string)) 97 full_path = DeprecatedString::formatted("/usr/lib/{}", path); 98 else 99 full_path = path_string; 100 101 auto* mapped_object = get_or_create_mapped_object(full_path); 102 if (!mapped_object) { 103 full_path = DeprecatedString::formatted("/usr/local/lib/{}", path); 104 mapped_object = get_or_create_mapped_object(full_path); 105 if (!mapped_object) 106 return; 107 } 108 m_libraries.set(path_string, adopt_own(*new Library { base, size, path_string, mapped_object, {} })); 109 } 110} 111 112Debug::DebugInfo const& LibraryMetadata::Library::load_debug_info(FlatPtr base_address) const 113{ 114 if (debug_info == nullptr) 115 debug_info = make<Debug::DebugInfo>(object->elf, DeprecatedString::empty(), base_address); 116 return *debug_info.ptr(); 117} 118 119DeprecatedString LibraryMetadata::Library::symbolicate(FlatPtr ptr, u32* offset) const 120{ 121 if (!object) 122 return DeprecatedString::formatted("?? <{:p}>", ptr); 123 124 return object->elf.symbolicate(ptr - base, offset); 125} 126 127LibraryMetadata::Library const* LibraryMetadata::library_containing(FlatPtr ptr) const 128{ 129 for (auto& it : m_libraries) { 130 auto& library = *it.value; 131 if (ptr >= library.base && ptr < (library.base + library.size)) 132 return &library; 133 } 134 return nullptr; 135} 136 137}