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:
Scott Graham 2018-01-19 14:03:34 -08:00 committed by Commit Bot
parent 3a7b80995d
commit dea19c7374
11 changed files with 224 additions and 59 deletions

View File

@ -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) {
# Theres no way to make the link depend on this file. “inputs” doesnt 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) {

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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
View 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
View 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_

View File

@ -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',

View File

@ -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",

View 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

View File

@ -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',