| // Copyright 2023 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef SRC_DEVELOPER_DEBUG_DEBUG_AGENT_LINUX_UTILS_H_ | |
| #define SRC_DEVELOPER_DEBUG_DEBUG_AGENT_LINUX_UTILS_H_ | |
| #include <elf.h> | |
| #include <sys/ptrace.h> | |
| #include <sys/user.h> | |
| #include <zircon/types.h> | |
| #include <filesystem> | |
| #include <map> | |
| #include <optional> | |
| #include <vector> | |
| #include <fbl/unique_fd.h> | |
| #include "src/developer/debug/debug_agent/thread_handle.h" | |
| #include "src/developer/debug/shared/address_range.h" | |
| namespace debug_agent { | |
| namespace linux { | |
| // Wrapper around pidfd_open. | |
| fbl::unique_fd OpenPidfd(int pid); | |
| std::optional<user_regs_struct> ReadGeneralRegisters(int pid); | |
| zx_status_t WriteGeneralRegisters(int pid, const user_regs_struct& regs); | |
| // Represents one line in the Linux /proc/.../maps file. | |
| struct MapEntry { | |
| debug::AddressRange range; | |
| bool read = false; | |
| bool write = false; | |
| bool execute = false; | |
| bool shared = false; | |
| uint64_t offset = 0; | |
| std::string device; | |
| int inode = 0; | |
| std::string path; | |
| }; | |
| // Parse/read the given Linux maps file. | |
| std::vector<MapEntry> ParseMaps(const std::string& contents); | |
| std::vector<MapEntry> GetMaps(int pid); | |
| // Entries from /proc/.../stat we care about. This is not all of them and more can be added here if | |
| // needed. | |
| struct ProcStat { | |
| int pid = 0; | |
| std::string name; | |
| char state = 0; | |
| }; | |
| // Parse/read the given Linux status file (this is "status" with key/value pairs and not the "stat" | |
| // file that's just numbers). Returns an empty may on failure (the process doesn't exist or | |
| // something). | |
| std::map<std::string, std::string> ParseStatus(const std::string& contents); | |
| std::map<std::string, std::string> GetStatus(int pid); | |
| // Returns the executable file name as defined in /proc/<pid>/exe. Empty on failure. | |
| std::string GetExe(int pid); | |
| // Returns the command line for the given process. Will be empty on failure. | |
| std::vector<std::string> GetCommandLine(int pid); | |
| // Returns the load address of the ld.so for the given process ID. Returns 0 on failure. | |
| uint64_t GetLdSoLoadAddress(int pid); | |
| // Returns the load address and path for the ld.so associated with the given process ID. Returns | |
| // nullopt on failure. | |
| struct LdSoInfo { | |
| uint64_t load_address = 0; | |
| std::string path; | |
| }; | |
| std::optional<LdSoInfo> GetLdSoInfo(int pid); | |
| // Returns the ld.so debug address in memory for the given process. Returns 0 if not found. | |
| uint64_t GetLdSoDebugAddress(int pid); | |
| // Returns the address at which to set a breakpoint to observe load events for the given process. | |
| // Returns 0 if not found. | |
| uint64_t GetLdSoBreakpointAddress(int pid); | |
| // Reads the contents of /proc/<pid>/auxv and returns the key/value store. The keys are AT_* | |
| // constants from <linux/auxvec.h>. Returns the empty map on failure. | |
| std::map<uint64_t, uint64_t> ReadAuxv(int pid); | |
| // Decodes the value of a /proc/status "State" line. Returns nullopt if parsing failed. | |
| std::optional<ThreadHandle::State> ThreadStateFromLinuxState(const std::string& linux_state); | |
| // Returns a vector of all numeric subdirectories in the given path. The path is specifyable to | |
| // support enumerating the "task" subdirectory of a process as well as the toplevel processes. | |
| std::vector<int> GetDirectoryPids(const std::filesystem::path& path = "/proc"); | |
| // Returns the string for the given signal name. If include_number is set, this also includes the | |
| // numeric signal number. | |
| std::string SignalToString(int signal, bool include_number); | |
| // Given a local path to the dynamic loader on disk, returns the address (relative to the beginning | |
| // of the module in memory) of the debug address or load breakpoint address. | |
| // | |
| // The Fuchsia loader does not expose these symbols which is why they're in a Linux-specific file. | |
| uint64_t GetLdSoDebugRelativeAddress(const std::string& ld_so_path); | |
| uint64_t GetLdSoBreakpointRelativeAddress(const std::string& ld_so_path); | |
| } // namespace linux | |
| } // namespace debug_agent | |
| #endif // SRC_DEVELOPER_DEBUG_DEBUG_AGENT_LINUX_UTILS_H_ |