1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_MEMORY_PARTITION_ALLOCATOR_INSPECT_UTILS_H_
#define TOOLS_MEMORY_PARTITION_ALLOCATOR_INSPECT_UTILS_H_
// This file includes utilities used in PartitionAlloc tools, also
// found in this directory.
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <optional>
#include "base/files/file.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_MAC)
#include <mach/mach.h>
#endif
namespace partition_alloc::tools {
// SIGSTOPs a process.
class ScopedSigStopper {
public:
explicit ScopedSigStopper(pid_t pid) : pid_(pid) { kill(pid_, SIGSTOP); }
~ScopedSigStopper() { kill(pid_, SIGCONT); }
private:
const pid_t pid_;
};
base::ScopedFD OpenProcMem(pid_t pid);
base::ScopedFD OpenPagemap(pid_t pid);
char* CreateMappingAtAddress(uintptr_t address, size_t size);
// Reads the memory of a remote process.
class RemoteProcessMemoryReader {
public:
explicit RemoteProcessMemoryReader(pid_t pid);
~RemoteProcessMemoryReader();
// Whether access to the remote process memory has been granted.
bool IsValid() const;
// Returns true for success.
bool ReadMemory(uintptr_t remote_address, size_t size, char* buffer);
// Reads remote process memory at the *same* address in the current
// process. Local memory is mapped with mmap(). Returns nullptr in case of
// failure.
char* ReadAtSameAddressInLocalMemory(uintptr_t address, size_t size);
pid_t pid() const { return pid_; }
private:
const pid_t pid_;
bool is_valid_;
#if BUILDFLAG(IS_LINUX)
base::ScopedFD mem_fd_;
#elif BUILDFLAG(IS_MAC)
task_t task_;
#endif
};
uintptr_t IndexThreadCacheNeedleArray(RemoteProcessMemoryReader& reader,
size_t index);
// Allows to access an object copied from remote memory "as if" it were
// local. Of course, dereferencing any pointer from within it will at best
// fault.
template <typename T>
class RawBuffer {
public:
RawBuffer() = default;
const T* get() const { return reinterpret_cast<const T*>(buffer_); }
char* get_buffer() { return buffer_; }
static std::optional<RawBuffer<T>> ReadFromProcessMemory(
RemoteProcessMemoryReader& reader,
uintptr_t address) {
RawBuffer<T> buf;
bool ok = reader.ReadMemory(reinterpret_cast<unsigned long>(address),
sizeof(T), buf.get_buffer());
if (!ok)
return std::nullopt;
return {buf};
}
static RawBuffer<T> FromData(const void* data) {
RawBuffer<T> ret;
memcpy(ret.buffer_, data, sizeof(T));
return ret;
}
private:
alignas(T) char buffer_[sizeof(T)];
};
} // namespace partition_alloc::tools
#endif // TOOLS_MEMORY_PARTITION_ALLOCATOR_INSPECT_UTILS_H_
|