mirror of
https://github.com/chromium/crashpad.git
synced 2025-01-14 09:17:57 +08:00
fuchsia: Add implemention of ProcessMemory
Bug: crashpad:196 Change-Id: I04a29afcbb16b5ef14d6f83d7af1d954f5164ee9 Reviewed-on: https://chromium-review.googlesource.com/868736 Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org> Commit-Queue: Scott Graham <scottmg@chromium.org>
This commit is contained in:
parent
970ac5a636
commit
4d2414e38e
@ -276,6 +276,13 @@ static_library("util") {
|
||||
"posix/process_info_linux.cc",
|
||||
"process/process_memory_linux.cc",
|
||||
"process/process_memory_linux.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
|
||||
sources += [
|
||||
"process/process_memory.cc",
|
||||
"process/process_memory.h",
|
||||
|
||||
# TODO: Port to all platforms.
|
||||
"process/process_memory_range.cc",
|
||||
@ -364,6 +371,8 @@ static_library("util") {
|
||||
sources += [
|
||||
"misc/paths_fuchsia.cc",
|
||||
"net/http_transport_fuchsia.cc",
|
||||
"process/process_memory_fuchsia.cc",
|
||||
"process/process_memory_fuchsia.h",
|
||||
]
|
||||
}
|
||||
|
||||
@ -509,7 +518,11 @@ source_set("util_test") {
|
||||
"linux/ptrace_broker_test.cc",
|
||||
"linux/ptracer_test.cc",
|
||||
"linux/scoped_ptrace_attach_test.cc",
|
||||
]
|
||||
}
|
||||
|
||||
if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
|
||||
sources += [
|
||||
# TODO: Port to all platforms.
|
||||
"process/process_memory_range_test.cc",
|
||||
"process/process_memory_test.cc",
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "util/win/address_types.h"
|
||||
#elif defined(OS_LINUX) || defined(OS_ANDROID)
|
||||
#include "util/linux/address_types.h"
|
||||
#elif defined(OS_FUCHSIA)
|
||||
#include <zircon/types.h>
|
||||
#else
|
||||
#error "Unhandled OS type"
|
||||
#endif
|
||||
@ -58,6 +60,11 @@ using VMSize = WinVMSize;
|
||||
using VMAddress = LinuxVMAddress;
|
||||
using VMSize = LinuxVMSize;
|
||||
|
||||
#elif defined(OS_FUCHSIA)
|
||||
|
||||
using VMAddress = zx_vaddr_t;
|
||||
using VMSize = size_t;
|
||||
|
||||
#endif
|
||||
|
||||
//! \brief Type used to represent an offset from a VMAddress, potentially
|
||||
|
55
util/process/process_memory.cc
Normal file
55
util/process/process_memory.cc
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2018 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "util/process/process_memory.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
bool ProcessMemory::ReadCStringInternal(VMAddress address,
|
||||
bool has_size,
|
||||
size_t size,
|
||||
std::string* string) const {
|
||||
string->clear();
|
||||
|
||||
char buffer[4096];
|
||||
do {
|
||||
size_t read_size;
|
||||
if (has_size) {
|
||||
read_size = std::min(sizeof(buffer), size);
|
||||
} else {
|
||||
read_size = sizeof(buffer);
|
||||
}
|
||||
|
||||
if (!Read(address, read_size, buffer)) {
|
||||
break;
|
||||
}
|
||||
|
||||
char* nul = static_cast<char*>(memchr(buffer, '\0', read_size));
|
||||
if (nul != nullptr) {
|
||||
string->append(buffer, nul - buffer);
|
||||
return true;
|
||||
}
|
||||
string->append(buffer, read_size);
|
||||
|
||||
address += read_size;
|
||||
size -= read_size;
|
||||
} while (!has_size || size > 0);
|
||||
|
||||
LOG(ERROR) << "unterminated string";
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
@ -102,7 +102,7 @@ class ProcessMemory {
|
||||
virtual bool ReadCStringInternal(VMAddress address,
|
||||
bool has_size,
|
||||
size_t size,
|
||||
std::string* string) const = 0;
|
||||
std::string* string) const;
|
||||
};
|
||||
|
||||
} // namespace crashpad
|
||||
|
57
util/process/process_memory_fuchsia.cc
Normal file
57
util/process/process_memory_fuchsia.cc
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2018 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "util/process/process_memory_fuchsia.h"
|
||||
|
||||
#include <zircon/syscalls.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
ProcessMemoryFuchsia::ProcessMemoryFuchsia()
|
||||
: ProcessMemory(), process_(), initialized_() {}
|
||||
|
||||
ProcessMemoryFuchsia::~ProcessMemoryFuchsia() {}
|
||||
|
||||
bool ProcessMemoryFuchsia::Initialize(zx_handle_t process) {
|
||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||
process_ = process;
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcessMemoryFuchsia::Read(VMAddress address,
|
||||
size_t size,
|
||||
void* buffer) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
size_t actual;
|
||||
zx_status_t status =
|
||||
zx_process_read_memory(process_, address, buffer, size, &actual);
|
||||
|
||||
if (status != ZX_OK) {
|
||||
ZX_LOG(ERROR, status) << "zx_process_read_memory";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actual != size) {
|
||||
LOG(ERROR) << "zx_process_read_memory: short read";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
56
util/process/process_memory_fuchsia.h
Normal file
56
util/process/process_memory_fuchsia.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2018 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CRASHPAD_UTIL_PROCESS_PROCESS_MEMORY_FUCHSIA_H_
|
||||
#define CRASHPAD_UTIL_PROCESS_PROCESS_MEMORY_FUCHSIA_H_
|
||||
|
||||
#include <zircon/types.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "util/misc/address_types.h"
|
||||
#include "util/misc/initialization_state_dcheck.h"
|
||||
#include "util/process/process_memory.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
//! \brief Accesses the memory of another Fuchsia process.
|
||||
class ProcessMemoryFuchsia final : public ProcessMemory {
|
||||
public:
|
||||
ProcessMemoryFuchsia();
|
||||
~ProcessMemoryFuchsia();
|
||||
|
||||
//! \brief Initializes this object to read the memory of a process by handle.
|
||||
//!
|
||||
//! This method must be called successfully prior to calling any other method
|
||||
//! in this class.
|
||||
//!
|
||||
//! \param[in] pid The handle to the target process.
|
||||
//!
|
||||
//! \return `true` on success, `false` on failure with a message logged.
|
||||
bool Initialize(zx_handle_t process);
|
||||
|
||||
bool Read(VMAddress address, size_t size, void* buffer) const override;
|
||||
|
||||
private:
|
||||
zx_handle_t process_;
|
||||
InitializationStateDcheck initialized_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryFuchsia);
|
||||
};
|
||||
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_UTIL_PROCESS_PROCESS_MEMORY_FUCHSIA_H_
|
@ -27,11 +27,12 @@
|
||||
namespace crashpad {
|
||||
|
||||
ProcessMemoryLinux::ProcessMemoryLinux()
|
||||
: ProcessMemory(), mem_fd_(), pid_(-1) {}
|
||||
: ProcessMemory(), mem_fd_(), pid_(-1), initialized_() {}
|
||||
|
||||
ProcessMemoryLinux::~ProcessMemoryLinux() {}
|
||||
|
||||
bool ProcessMemoryLinux::Initialize(pid_t pid) {
|
||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||
pid_ = pid;
|
||||
char path[32];
|
||||
snprintf(path, sizeof(path), "/proc/%d/mem", pid_);
|
||||
@ -40,12 +41,14 @@ bool ProcessMemoryLinux::Initialize(pid_t pid) {
|
||||
PLOG(ERROR) << "open";
|
||||
return false;
|
||||
}
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcessMemoryLinux::Read(VMAddress address,
|
||||
size_t size,
|
||||
void* buffer) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
DCHECK(mem_fd_.is_valid());
|
||||
|
||||
char* buffer_c = static_cast<char*>(buffer);
|
||||
@ -68,47 +71,4 @@ bool ProcessMemoryLinux::Read(VMAddress address,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcessMemoryLinux::ReadCStringInternal(VMAddress address,
|
||||
bool has_size,
|
||||
size_t size,
|
||||
std::string* string) const {
|
||||
DCHECK(mem_fd_.is_valid());
|
||||
|
||||
string->clear();
|
||||
|
||||
char buffer[4096];
|
||||
do {
|
||||
size_t read_size;
|
||||
if (has_size) {
|
||||
read_size = std::min(sizeof(buffer), size);
|
||||
} else {
|
||||
read_size = sizeof(buffer);
|
||||
}
|
||||
ssize_t bytes_read;
|
||||
bytes_read =
|
||||
HANDLE_EINTR(pread64(mem_fd_.get(), buffer, read_size, address));
|
||||
if (bytes_read < 0) {
|
||||
PLOG(ERROR) << "pread64";
|
||||
return false;
|
||||
}
|
||||
if (bytes_read == 0) {
|
||||
break;
|
||||
}
|
||||
DCHECK_LE(static_cast<size_t>(bytes_read), read_size);
|
||||
|
||||
char* nul = static_cast<char*>(memchr(buffer, '\0', bytes_read));
|
||||
if (nul != nullptr) {
|
||||
string->append(buffer, nul - buffer);
|
||||
return true;
|
||||
}
|
||||
string->append(buffer, bytes_read);
|
||||
|
||||
address += bytes_read;
|
||||
size -= bytes_read;
|
||||
} while (!has_size || size > 0);
|
||||
|
||||
LOG(ERROR) << "unterminated string";
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "base/files/scoped_file.h"
|
||||
#include "base/macros.h"
|
||||
#include "util/misc/address_types.h"
|
||||
#include "util/misc/initialization_state_dcheck.h"
|
||||
#include "util/process/process_memory.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -46,13 +47,9 @@ class ProcessMemoryLinux final : public ProcessMemory {
|
||||
bool Read(VMAddress address, size_t size, void* buffer) const override;
|
||||
|
||||
private:
|
||||
bool ReadCStringInternal(VMAddress address,
|
||||
bool has_size,
|
||||
size_t size,
|
||||
std::string* string) const override;
|
||||
|
||||
base::ScopedFD mem_fd_;
|
||||
pid_t pid_;
|
||||
InitializationStateDcheck initialized_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryLinux);
|
||||
};
|
||||
|
@ -22,7 +22,14 @@
|
||||
#include "build/build_config.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "util/misc/from_pointer_cast.h"
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include <zircon/process.h>
|
||||
|
||||
#include "util/process/process_memory_fuchsia.h"
|
||||
#else
|
||||
#include "util/process/process_memory_linux.h"
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
@ -34,6 +41,11 @@ struct TestObject {
|
||||
} kTestObject = {"string1", "string2"};
|
||||
|
||||
TEST(ProcessMemoryRange, Basic) {
|
||||
#if defined(OS_FUCHSIA)
|
||||
ProcessMemoryFuchsia memory;
|
||||
ASSERT_TRUE(memory.Initialize(zx_process_self()));
|
||||
constexpr bool is_64_bit = true;
|
||||
#else
|
||||
pid_t pid = getpid();
|
||||
#if defined(ARCH_CPU_64_BITS)
|
||||
constexpr bool is_64_bit = true;
|
||||
@ -43,6 +55,7 @@ TEST(ProcessMemoryRange, Basic) {
|
||||
|
||||
ProcessMemoryLinux memory;
|
||||
ASSERT_TRUE(memory.Initialize(pid));
|
||||
#endif // OS_FUCHSIA
|
||||
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, is_64_bit));
|
||||
|
@ -32,6 +32,10 @@ namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
// TODO(scottmg): https://crashpad.chromium.org/bug/196. Multiprocess isn't
|
||||
// ported yet.
|
||||
#if !defined(OS_FUCHSIA)
|
||||
|
||||
class TargetProcessTest : public Multiprocess {
|
||||
public:
|
||||
TargetProcessTest() : Multiprocess() {}
|
||||
@ -400,6 +404,8 @@ TEST(ProcessMemory, ReadCStringSizeLimitedUnmappedForked) {
|
||||
test.RunAgainstForked();
|
||||
}
|
||||
|
||||
#endif // !defined(OS_FUCHSIA)
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
|
Loading…
x
Reference in New Issue
Block a user