mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
fuchsia: Port ElfImageReader and (some of) its tests
(Still need to avoid fork()-dependence for the non-self tests.) Bug: crashpad:196 Change-Id: Ib34fe33c7ec295881c1f555995072d9ff742647f Reviewed-on: https://chromium-review.googlesource.com/876650 Reviewed-by: Joshua Peraza <jperaza@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Scott Graham <scottmg@chromium.org>
This commit is contained in:
parent
3a7b80995d
commit
dea19c7374
@ -102,12 +102,6 @@ static_library("snapshot") {
|
||||
sources += [
|
||||
"crashpad_types/image_annotation_reader.cc",
|
||||
"crashpad_types/image_annotation_reader.h",
|
||||
"elf/elf_dynamic_array_reader.cc",
|
||||
"elf/elf_dynamic_array_reader.h",
|
||||
"elf/elf_image_reader.cc",
|
||||
"elf/elf_image_reader.h",
|
||||
"elf/elf_symbol_table_reader.cc",
|
||||
"elf/elf_symbol_table_reader.h",
|
||||
"linux/cpu_context_linux.cc",
|
||||
"linux/cpu_context_linux.h",
|
||||
"linux/debug_rendezvous.cc",
|
||||
@ -134,6 +128,12 @@ static_library("snapshot") {
|
||||
sources += [
|
||||
"crashpad_types/crashpad_info_reader.cc",
|
||||
"crashpad_types/crashpad_info_reader.h",
|
||||
"elf/elf_dynamic_array_reader.cc",
|
||||
"elf/elf_dynamic_array_reader.h",
|
||||
"elf/elf_image_reader.cc",
|
||||
"elf/elf_image_reader.h",
|
||||
"elf/elf_symbol_table_reader.cc",
|
||||
"elf/elf_symbol_table_reader.h",
|
||||
]
|
||||
}
|
||||
|
||||
@ -263,7 +263,7 @@ static_library("test_support") {
|
||||
|
||||
config("snapshot_test_link") {
|
||||
visibility = [ ":*" ]
|
||||
if (crashpad_is_linux || crashpad_is_android) {
|
||||
if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
|
||||
# There’s no way to make the link depend on this file. “inputs” doesn’t have
|
||||
# the intended effect in a config. https://crbug.com/781858,
|
||||
# https://crbug.com/796187.
|
||||
@ -297,9 +297,6 @@ source_set("snapshot_test") {
|
||||
if (crashpad_is_linux || crashpad_is_android) {
|
||||
sources += [
|
||||
"crashpad_types/image_annotation_reader_test.cc",
|
||||
"elf/elf_image_reader_test.cc",
|
||||
"elf/elf_image_reader_test_note.S",
|
||||
"elf/test_exported_symbols.sym",
|
||||
"linux/debug_rendezvous_test.cc",
|
||||
"linux/exception_snapshot_linux_test.cc",
|
||||
"linux/process_reader_test.cc",
|
||||
@ -310,7 +307,12 @@ source_set("snapshot_test") {
|
||||
}
|
||||
|
||||
if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
|
||||
sources += [ "crashpad_types/crashpad_info_reader_test.cc" ]
|
||||
sources += [
|
||||
"crashpad_types/crashpad_info_reader_test.cc",
|
||||
"elf/elf_image_reader_test.cc",
|
||||
"elf/elf_image_reader_test_note.S",
|
||||
"elf/test_exported_symbols.sym",
|
||||
]
|
||||
}
|
||||
|
||||
if (crashpad_is_win) {
|
||||
|
@ -24,33 +24,19 @@
|
||||
#include "client/simple_string_dictionary.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/multiprocess.h"
|
||||
#include "test/process_type.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/misc/from_pointer_cast.h"
|
||||
#include "util/process/process_memory_native.h"
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include <zircon/process.h>
|
||||
|
||||
#include "util/process/process_memory_fuchsia.h"
|
||||
#elif defined(OS_LINUX) || defined(OS_ANDROID)
|
||||
#include "util/process/process_memory_linux.h"
|
||||
#else
|
||||
#error Port.
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
using ProcessHandle = zx_handle_t;
|
||||
ProcessHandle GetSelf() { return zx_process_self(); }
|
||||
#elif defined(OS_POSIX)
|
||||
using ProcessHandle = pid_t;
|
||||
ProcessHandle GetSelf() { return getpid(); }
|
||||
#else
|
||||
#error Port.
|
||||
#endif
|
||||
|
||||
constexpr TriState kCrashpadHandlerBehavior = TriState::kEnabled;
|
||||
constexpr TriState kSystemCrashReporterForwarding = TriState::kDisabled;
|
||||
constexpr TriState kGatherIndirectlyReferencedMemory = TriState::kUnset;
|
||||
@ -71,14 +57,8 @@ class CrashpadInfoTest {
|
||||
kGatherIndirectlyReferencedMemory, kIndirectlyReferencedMemoryCap);
|
||||
}
|
||||
|
||||
void ExpectCrashpadInfo(ProcessHandle process, bool is_64_bit) {
|
||||
#if defined(OS_FUCHSIA)
|
||||
ProcessMemoryFuchsia memory;
|
||||
#elif defined(OS_LINUX) || defined(OS_ANDROID)
|
||||
ProcessMemoryLinux memory;
|
||||
#else
|
||||
#error Port.
|
||||
#endif
|
||||
void ExpectCrashpadInfo(ProcessType process, bool is_64_bit) {
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
|
||||
ProcessMemoryRange range;
|
||||
@ -120,7 +100,7 @@ TEST(CrashpadInfoReader, ReadFromSelf) {
|
||||
constexpr bool am_64_bit = false;
|
||||
#endif
|
||||
|
||||
test.ExpectCrashpadInfo(GetSelf(), am_64_bit);
|
||||
test.ExpectCrashpadInfo(GetSelfProcess(), am_64_bit);
|
||||
}
|
||||
|
||||
// TODO(scottmg): This needs to be be ported to use MultiprocessExec instead of
|
||||
|
@ -625,9 +625,9 @@ bool ElfImageReader::GetAddressFromDynamicArray(uint64_t tag,
|
||||
if (!dynamic_array_->GetValue(tag, address)) {
|
||||
return false;
|
||||
}
|
||||
#if defined(OS_ANDROID)
|
||||
// The GNU loader updates the dynamic array according to the load bias while
|
||||
// the Android loader only updates the debug address.
|
||||
#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
|
||||
// The GNU loader updates the dynamic array according to the load bias.
|
||||
// The Android and Fuchsia loaders only update the debug address.
|
||||
if (tag != DT_DEBUG) {
|
||||
*address += GetLoadBias();
|
||||
}
|
||||
|
@ -21,12 +21,29 @@
|
||||
#include "build/build_config.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/multiprocess.h"
|
||||
#include "test/process_type.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/linux/auxiliary_vector.h"
|
||||
#include "util/linux/memory_map.h"
|
||||
#include "util/misc/address_types.h"
|
||||
#include "util/misc/from_pointer_cast.h"
|
||||
#include "util/process/process_memory_linux.h"
|
||||
#include "util/process/process_memory_native.h"
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
|
||||
#include <link.h>
|
||||
#include <zircon/syscalls.h>
|
||||
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
|
||||
#elif defined(OS_LINUX) || defined(OS_ANDROID)
|
||||
|
||||
#include "util/linux/auxiliary_vector.h"
|
||||
#include "util/linux/memory_map.h"
|
||||
|
||||
#else
|
||||
|
||||
#error Port.
|
||||
|
||||
#endif // OS_FUCHSIA
|
||||
|
||||
extern "C" {
|
||||
__attribute__((visibility("default"))) void
|
||||
@ -37,15 +54,49 @@ namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
void LocateExecutable(pid_t pid, bool is_64_bit, VMAddress* elf_address) {
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
|
||||
void LocateExecutable(ProcessType process,
|
||||
ProcessMemory* memory,
|
||||
bool is_64_bit,
|
||||
VMAddress* elf_address) {
|
||||
uintptr_t debug_address;
|
||||
zx_status_t status = zx_object_get_property(process,
|
||||
ZX_PROP_PROCESS_DEBUG_ADDR,
|
||||
&debug_address,
|
||||
sizeof(debug_address));
|
||||
ASSERT_EQ(status, ZX_OK)
|
||||
<< "zx_object_get_property: ZX_PROP_PROCESS_DEBUG_ADDR";
|
||||
|
||||
constexpr auto k_r_debug_map_offset = offsetof(r_debug, r_map);
|
||||
uintptr_t map;
|
||||
ASSERT_TRUE(
|
||||
memory->Read(debug_address + k_r_debug_map_offset, sizeof(map), &map))
|
||||
<< "read link_map";
|
||||
|
||||
constexpr auto k_link_map_addr_offset = offsetof(link_map, l_addr);
|
||||
uintptr_t base;
|
||||
ASSERT_TRUE(memory->Read(map + k_link_map_addr_offset, sizeof(base), &base))
|
||||
<< "read base";
|
||||
|
||||
*elf_address = base;
|
||||
}
|
||||
|
||||
#elif defined(OS_LINUX) || defined(OS_ANDROID)
|
||||
|
||||
void LocateExecutable(ProcessType process,
|
||||
ProcessMemory* memory,
|
||||
bool is_64_bit,
|
||||
VMAddress* elf_address) {
|
||||
AuxiliaryVector aux;
|
||||
ASSERT_TRUE(aux.Initialize(pid, is_64_bit));
|
||||
ASSERT_TRUE(aux.Initialize(process, is_64_bit));
|
||||
|
||||
VMAddress phdrs;
|
||||
ASSERT_TRUE(aux.GetValue(AT_PHDR, &phdrs));
|
||||
|
||||
MemoryMap memory_map;
|
||||
ASSERT_TRUE(memory_map.Initialize(pid));
|
||||
ASSERT_TRUE(memory_map.Initialize(process));
|
||||
const MemoryMap::Mapping* phdr_mapping = memory_map.FindMapping(phdrs);
|
||||
ASSERT_TRUE(phdr_mapping);
|
||||
const MemoryMap::Mapping* exe_mapping =
|
||||
@ -54,6 +105,8 @@ void LocateExecutable(pid_t pid, bool is_64_bit, VMAddress* elf_address) {
|
||||
*elf_address = exe_mapping->range.Base();
|
||||
}
|
||||
|
||||
#endif // OS_FUCHSIA
|
||||
|
||||
void ExpectSymbol(ElfImageReader* reader,
|
||||
const std::string& symbol_name,
|
||||
VMAddress expected_symbol_address) {
|
||||
@ -67,21 +120,22 @@ void ExpectSymbol(ElfImageReader* reader,
|
||||
reader->GetDynamicSymbol("notasymbol", &symbol_address, &symbol_size));
|
||||
}
|
||||
|
||||
void ReadThisExecutableInTarget(pid_t pid) {
|
||||
void ReadThisExecutableInTarget(ProcessType process) {
|
||||
#if defined(ARCH_CPU_64_BITS)
|
||||
constexpr bool am_64_bit = true;
|
||||
#else
|
||||
constexpr bool am_64_bit = false;
|
||||
#endif // ARCH_CPU_64_BITS
|
||||
|
||||
VMAddress elf_address;
|
||||
LocateExecutable(pid, am_64_bit, &elf_address);
|
||||
|
||||
ProcessMemoryLinux memory;
|
||||
ASSERT_TRUE(memory.Initialize(pid));
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, am_64_bit));
|
||||
|
||||
VMAddress elf_address;
|
||||
LocateExecutable(process, &memory, am_64_bit, &elf_address);
|
||||
ASSERT_NO_FATAL_FAILURE();
|
||||
|
||||
ElfImageReader reader;
|
||||
ASSERT_TRUE(reader.Initialize(range, elf_address));
|
||||
|
||||
@ -123,7 +177,7 @@ void ReadThisExecutableInTarget(pid_t pid) {
|
||||
|
||||
// Assumes that libc is loaded at the same address in this process as in the
|
||||
// target, which it is for the fork test below.
|
||||
void ReadLibcInTarget(pid_t pid) {
|
||||
void ReadLibcInTarget(ProcessType process) {
|
||||
#if defined(ARCH_CPU_64_BITS)
|
||||
constexpr bool am_64_bit = true;
|
||||
#else
|
||||
@ -135,8 +189,8 @@ void ReadLibcInTarget(pid_t pid) {
|
||||
<< dlerror();
|
||||
VMAddress elf_address = FromPointerCast<VMAddress>(info.dli_fbase);
|
||||
|
||||
ProcessMemoryLinux memory;
|
||||
ASSERT_TRUE(memory.Initialize(pid));
|
||||
ProcessMemoryNative memory;
|
||||
ASSERT_TRUE(memory.Initialize(process));
|
||||
ProcessMemoryRange range;
|
||||
ASSERT_TRUE(range.Initialize(&memory, am_64_bit));
|
||||
|
||||
@ -146,6 +200,11 @@ void ReadLibcInTarget(pid_t pid) {
|
||||
ExpectSymbol(&reader, "getpid", FromPointerCast<VMAddress>(getpid));
|
||||
}
|
||||
|
||||
TEST(ElfImageReader, MainExecutableSelf) {
|
||||
ReadThisExecutableInTarget(GetSelfProcess());
|
||||
}
|
||||
|
||||
#if !defined(OS_FUCHSIA) // TODO(scottmg): Port to MultiprocessExec.
|
||||
class ReadExecutableChildTest : public Multiprocess {
|
||||
public:
|
||||
ReadExecutableChildTest() : Multiprocess() {}
|
||||
@ -156,19 +215,17 @@ class ReadExecutableChildTest : public Multiprocess {
|
||||
void MultiprocessChild() { CheckedReadFileAtEOF(ReadPipeHandle()); }
|
||||
};
|
||||
|
||||
TEST(ElfImageReader, MainExecutableSelf) {
|
||||
ReadThisExecutableInTarget(getpid());
|
||||
}
|
||||
|
||||
TEST(ElfImageReader, MainExecutableChild) {
|
||||
ReadExecutableChildTest test;
|
||||
test.Run();
|
||||
}
|
||||
#endif // !OS_FUCHSIA
|
||||
|
||||
TEST(ElfImageReader, OneModuleSelf) {
|
||||
ReadLibcInTarget(getpid());
|
||||
ReadLibcInTarget(GetSelfProcess());
|
||||
}
|
||||
|
||||
#if !defined(OS_FUCHSIA) // TODO(scottmg): Port to MultiprocessExec.
|
||||
class ReadLibcChildTest : public Multiprocess {
|
||||
public:
|
||||
ReadLibcChildTest() : Multiprocess() {}
|
||||
@ -183,6 +240,7 @@ TEST(ElfImageReader, OneModuleChild) {
|
||||
ReadLibcChildTest test;
|
||||
test.Run();
|
||||
}
|
||||
#endif // !OS_FUCHSIA
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
|
@ -33,6 +33,8 @@ static_library("test") {
|
||||
"main_arguments.h",
|
||||
"multiprocess.h",
|
||||
"multiprocess_exec.h",
|
||||
"process_type.cc",
|
||||
"process_type.h",
|
||||
"scoped_module_handle.cc",
|
||||
"scoped_module_handle.h",
|
||||
"scoped_temp_dir.cc",
|
||||
|
37
test/process_type.cc
Normal file
37
test/process_type.cc
Normal file
@ -0,0 +1,37 @@
|
||||
// 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 "test/process_type.h"
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include <zircon/process.h>
|
||||
#elif defined(OS_POSIX)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
|
||||
ProcessType GetSelfProcess() {
|
||||
#if defined(OS_FUCHSIA)
|
||||
return zx_process_self();
|
||||
#elif defined(OS_POSIX)
|
||||
return getpid();
|
||||
#elif defined(OS_WIN)
|
||||
return GetCurrentProcess();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
48
test/process_type.h
Normal file
48
test/process_type.h
Normal file
@ -0,0 +1,48 @@
|
||||
// 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_TEST_PROCESS_TYPE_H_
|
||||
#define CRASHPAD_TEST_PROCESS_TYPE_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include <zircon/types.h>
|
||||
#elif defined(OS_POSIX)
|
||||
#include <sys/types.h>
|
||||
#elif defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
using ProcessType = zx_handle_t;
|
||||
#elif defined(OS_POSIX) || DOXYGEN
|
||||
//! \brief Alias for platform-specific type to represent a process.
|
||||
using ProcessType = pid_t;
|
||||
#elif defined(OS_WIN)
|
||||
using ProcessType = HANDLE;
|
||||
#else
|
||||
#error Port.
|
||||
#endif
|
||||
|
||||
//! \brief Get a ProcessType representing the current process.
|
||||
ProcessType GetSelfProcess();
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_TEST_PROCESS_TYPE_H_
|
@ -62,6 +62,8 @@
|
||||
'multiprocess_exec_posix.cc',
|
||||
'multiprocess_exec_win.cc',
|
||||
'multiprocess_posix.cc',
|
||||
'process_type.cc',
|
||||
'process_type.h',
|
||||
'scoped_module_handle.cc',
|
||||
'scoped_module_handle.h',
|
||||
'scoped_temp_dir.cc',
|
||||
|
@ -283,6 +283,7 @@ static_library("util") {
|
||||
sources += [
|
||||
"process/process_memory.cc",
|
||||
"process/process_memory.h",
|
||||
"process/process_memory_native.h",
|
||||
|
||||
# TODO: Port to all platforms.
|
||||
"process/process_memory_range.cc",
|
||||
|
34
util/process/process_memory_native.h
Normal file
34
util/process/process_memory_native.h
Normal file
@ -0,0 +1,34 @@
|
||||
// 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 "build/build_config.h"
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include "util/process/process_memory_fuchsia.h"
|
||||
#elif defined(OS_LINUX) || defined(OS_ANDROID)
|
||||
#include "util/process/process_memory_linux.h"
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
#if defined(OS_FUCHSIA) || DOXYGEN
|
||||
//! \brief Alias for platform-specific native implementation of ProcessMemory.
|
||||
using ProcessMemoryNative = ProcessMemoryFuchsia;
|
||||
#elif defined(OS_LINUX) || defined(OS_ANDROID)
|
||||
using ProcessMemoryNative = ProcessMemoryLinux;
|
||||
#else
|
||||
#error Port.
|
||||
#endif
|
||||
|
||||
} // namespace crashpad
|
@ -203,6 +203,7 @@
|
||||
'process/process_memory.h',
|
||||
'process/process_memory_linux.cc',
|
||||
'process/process_memory_linux.h',
|
||||
'process/process_memory_native.h',
|
||||
'process/process_memory_range.cc',
|
||||
'process/process_memory_range.h',
|
||||
'stdlib/aligned_allocator.cc',
|
||||
|
Loading…
x
Reference in New Issue
Block a user