blob: 52673a95e7506f4fe43b8154ac7129045d589388 [file] [log] [blame]
// 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_