diff options
author | Andreas Kling <kling@serenityos.org> | 2021-05-22 17:15:18 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-05-22 18:54:22 +0200 |
commit | d783076a30ac62dc64862eb51bf79b144270aa7a (patch) | |
tree | 502846730a8355d50a6359fa689bffe37ecae284 /Userland/Libraries/LibSymbolication | |
parent | 21cd278b8ab8a8cc3b734e951cea4a26609ade84 (diff) | |
download | serenity-d783076a30ac62dc64862eb51bf79b144270aa7a.zip |
Userland: Rename LibSymbolClient => LibSymbolication
Diffstat (limited to 'Userland/Libraries/LibSymbolication')
-rw-r--r-- | Userland/Libraries/LibSymbolication/CMakeLists.txt | 11 | ||||
-rw-r--r-- | Userland/Libraries/LibSymbolication/Client.cpp | 161 | ||||
-rw-r--r-- | Userland/Libraries/LibSymbolication/Client.h | 41 |
3 files changed, 213 insertions, 0 deletions
diff --git a/Userland/Libraries/LibSymbolication/CMakeLists.txt b/Userland/Libraries/LibSymbolication/CMakeLists.txt new file mode 100644 index 0000000000..09f64acbae --- /dev/null +++ b/Userland/Libraries/LibSymbolication/CMakeLists.txt @@ -0,0 +1,11 @@ +set(SOURCES + Client.cpp +) + +set(GENERATED_SOURCES + ../../Services/SymbolServer/SymbolClientEndpoint.h + ../../Services/SymbolServer/SymbolServerEndpoint.h +) + +serenity_lib(LibSymbolication symbolclient) +target_link_libraries(LibSymbolication LibIPC) diff --git a/Userland/Libraries/LibSymbolication/Client.cpp b/Userland/Libraries/LibSymbolication/Client.cpp new file mode 100644 index 0000000000..5d8bf405db --- /dev/null +++ b/Userland/Libraries/LibSymbolication/Client.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/JsonArray.h> +#include <AK/JsonObject.h> +#include <AK/JsonValue.h> +#include <LibCore/File.h> +#include <LibSymbolication/Client.h> + +namespace SymbolClient { + +Client::Client() + : IPC::ServerConnection<SymbolClientEndpoint, SymbolServerEndpoint>(*this, "/tmp/portal/symbol") +{ + handshake(); +} + +void Client::handshake() +{ + greet(); +} + +void Client::dummy() +{ +} + +Optional<Symbol> Client::symbolicate(const String& path, FlatPtr address) +{ + auto response = IPCProxy::symbolicate(path, address); + if (!response.success()) + return {}; + + return Symbol { + .address = address, + .name = response.name(), + .offset = response.offset(), + .filename = response.filename(), + .line_number = response.line() + }; +} + +Vector<Symbol> symbolicate_thread(pid_t pid, pid_t tid) +{ + struct RegionWithSymbols { + FlatPtr base { 0 }; + size_t size { 0 }; + String path; + bool is_relative { true }; + }; + + Vector<FlatPtr> stack; + Vector<RegionWithSymbols> regions; + + regions.append(RegionWithSymbols { + .base = 0xc0000000, + .size = 0x3fffffff, + .path = "/boot/Kernel", + .is_relative = false }); + + { + + auto stack_path = String::formatted("/proc/{}/stacks/{}", pid, tid); + auto file_or_error = Core::File::open(stack_path, Core::OpenMode::ReadOnly); + if (file_or_error.is_error()) { + warnln("Could not open {}: {}", stack_path, file_or_error.error()); + return {}; + } + + auto json = JsonValue::from_string(file_or_error.value()->read_all()); + if (!json.has_value() || !json.value().is_array()) { + warnln("Invalid contents in {}", stack_path); + return {}; + } + + stack.ensure_capacity(json.value().as_array().size()); + for (auto& value : json.value().as_array().values()) { + stack.append(value.to_u32()); + } + } + + { + auto vm_path = String::formatted("/proc/{}/vm", pid); + auto file_or_error = Core::File::open(vm_path, Core::OpenMode::ReadOnly); + if (file_or_error.is_error()) { + warnln("Could not open {}: {}", vm_path, file_or_error.error()); + return {}; + } + + auto json = JsonValue::from_string(file_or_error.value()->read_all()); + if (!json.has_value() || !json.value().is_array()) { + warnln("Invalid contents in {}", vm_path); + return {}; + } + + for (auto& region_value : json.value().as_array().values()) { + auto& region = region_value.as_object(); + auto name = region.get("name").to_string(); + auto address = region.get("address").to_u32(); + auto size = region.get("size").to_u32(); + + String path; + if (name == "/usr/lib/Loader.so") { + path = name; + } else if (name.ends_with(": .text")) { + auto parts = name.split_view(':'); + path = parts[0]; + if (!path.starts_with('/')) + path = String::formatted("/usr/lib/{}", path); + } else { + continue; + } + + RegionWithSymbols r; + r.base = address; + r.size = size; + r.path = path; + regions.append(move(r)); + } + } + + auto client = SymbolClient::Client::construct(); + + Vector<Symbol> symbols; + + for (auto address : stack) { + const RegionWithSymbols* found_region = nullptr; + for (auto& region : regions) { + if (address >= region.base && address < (region.base + region.size)) { + found_region = ®ion; + break; + } + } + + if (!found_region) { + outln("{:p} ??", address); + continue; + } + + FlatPtr adjusted_address; + if (found_region->is_relative) + adjusted_address = address - found_region->base; + else + adjusted_address = address; + + auto result = client->symbolicate(found_region->path, adjusted_address); + if (!result.has_value()) { + symbols.append(Symbol { + .address = address, + }); + continue; + } + + symbols.append(result.value()); + } + return symbols; +} + +} diff --git a/Userland/Libraries/LibSymbolication/Client.h b/Userland/Libraries/LibSymbolication/Client.h new file mode 100644 index 0000000000..b0e2390a43 --- /dev/null +++ b/Userland/Libraries/LibSymbolication/Client.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibIPC/ServerConnection.h> +#include <SymbolServer/SymbolClientEndpoint.h> +#include <SymbolServer/SymbolServerEndpoint.h> + +namespace SymbolClient { + +struct Symbol { + FlatPtr address { 0 }; + String name {}; + u32 offset { 0 }; + String filename {}; + u32 line_number { 0 }; +}; + +Vector<Symbol> symbolicate_thread(pid_t pid, pid_t tid); + +class Client + : public IPC::ServerConnection<SymbolClientEndpoint, SymbolServerEndpoint> + , public SymbolClientEndpoint { + C_OBJECT(Client); + +public: + virtual void handshake() override; + + Optional<Symbol> symbolicate(const String& path, FlatPtr address); + +private: + Client(); + + virtual void dummy() override; +}; + +} |