Commit ec9c7d1c authored by Balazs Engedy's avatar Balazs Engedy Committed by Chromium LUCI CQ

Revert "Update Crashpad to 83f194ee8544aec1c00683e1cf4e86458f33e035"

This reverts commit 7ecd3d78.

Reason for revert: `crashpad_tests` failures on `Linux MSan Tests`:
  DebugRendezvous.Self
  ProcessReaderLinux.ChildModules
  ProcessReaderLinux.SelfModules

Original change's description:
> Update Crashpad to 83f194ee8544aec1c00683e1cf4e86458f33e035
>
> bccb9504d1fb Roll crashpad/third_party/edo/edo/ 97121c640..6ffbf8331 (19
>              commits)
> 70f1ec86f95d ios: Fix setup_ios_gn.py after gn roll
> 0917d31d19ef Update lss README.crashpad to point to corrected name for
>              license
> ed132d5ec247 [syslog] Expect logsink client includes
> 121d92ca3f1a Roll crashpad/third_party/mini_chromium/mini_chromium/
>              cb82d7129..c748b289b (2 commits)
> 6c270cf239df linux: Refactor test modules
> 20cbfa49719c linux: Use mmap for attachments in PtraceBroker
> 00491d58ee29 linux: Correct handling of load bias
> 83f194ee8544 linux: Add linux-gate.so to valid vdso prefixes
>
> Bug: chromium:1147922, chromium:1128441
> Change-Id: If032f0e3c81b5fc1452867ecab4211fa713c276c
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2573518
> Commit-Queue: Joshua Peraza <jperaza@chromium.org>
> Reviewed-by: Mark Mentovai <mark@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#834592}

TBR=jperaza@chromium.org,mark@chromium.org,chromium-scoped@luci-project-accounts.iam.gserviceaccount.com

Change-Id: Idc66bf0f9c5d65738dec1a55fb58eb503a500dc8
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:1147922
Bug: chromium:1128441
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2578976Reviewed-by: default avatarBalazs Engedy <engedy@chromium.org>
Commit-Queue: Balazs Engedy <engedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834676}
parent eb493883
...@@ -2,7 +2,7 @@ Name: Crashpad ...@@ -2,7 +2,7 @@ Name: Crashpad
Short Name: crashpad Short Name: crashpad
URL: https://crashpad.chromium.org/ URL: https://crashpad.chromium.org/
Version: unknown Version: unknown
Revision: 83f194ee8544aec1c00683e1cf4e86458f33e035 Revision: b6f2d06996335c951bfb72f98b5b9e22dc9bc03e
License: Apache 2.0 License: Apache 2.0
License File: crashpad/LICENSE License File: crashpad/LICENSE
Security Critical: yes Security Critical: yes
......
...@@ -28,7 +28,7 @@ deps = { ...@@ -28,7 +28,7 @@ deps = {
'9e121212d42be62a7cce38072f925f8398d11e49', '9e121212d42be62a7cce38072f925f8398d11e49',
'crashpad/third_party/edo/edo': { 'crashpad/third_party/edo/edo': {
'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git@' + 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git@' +
'6ffbf833173f53fcd06ecf08670a95cc01c01f72', '97121c64019fa0e8bfbc8254e3ccb5572c500746',
'condition': 'checkout_ios', 'condition': 'checkout_ios',
}, },
'crashpad/third_party/googletest/googletest': 'crashpad/third_party/googletest/googletest':
...@@ -42,7 +42,7 @@ deps = { ...@@ -42,7 +42,7 @@ deps = {
'7bde79cc274d06451bf65ae82c012a5d3e476b5a', '7bde79cc274d06451bf65ae82c012a5d3e476b5a',
'crashpad/third_party/mini_chromium/mini_chromium': 'crashpad/third_party/mini_chromium/mini_chromium':
Var('chromium_git') + '/chromium/mini_chromium@' + Var('chromium_git') + '/chromium/mini_chromium@' +
'c748b289b825056985f3dd3b36dc86c766d787ad', 'cb82d71291f19590d3ee138ba64fcf1e9e0edd84',
'crashpad/third_party/libfuzzer/src': 'crashpad/third_party/libfuzzer/src':
Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' + Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' +
'fda403cf93ecb8792cb1d061564d89a6553ca020', 'fda403cf93ecb8792cb1d061564d89a6553ca020',
......
...@@ -199,6 +199,7 @@ class GnGenerator(object): ...@@ -199,6 +199,7 @@ class GnGenerator(object):
gn_command = [gn_path, '--root=%s' % os.path.realpath(src_path), '-q'] gn_command = [gn_path, '--root=%s' % os.path.realpath(src_path), '-q']
if generate_xcode_project: if generate_xcode_project:
gn_command.append('--ide=xcode') gn_command.append('--ide=xcode')
gn_command.append('--root-target=gn_all')
gn_command.append('--ninja-executable=autoninja') gn_command.append('--ninja-executable=autoninja')
if self._settings.has_section('filters'): if self._settings.has_section('filters'):
target_filters = self._settings.values('filters') target_filters = self._settings.values('filters')
......
...@@ -368,8 +368,6 @@ source_set("snapshot_test") { ...@@ -368,8 +368,6 @@ source_set("snapshot_test") {
"linux/exception_snapshot_linux_test.cc", "linux/exception_snapshot_linux_test.cc",
"linux/process_reader_linux_test.cc", "linux/process_reader_linux_test.cc",
"linux/system_snapshot_linux_test.cc", "linux/system_snapshot_linux_test.cc",
"linux/test_modules.cc",
"linux/test_modules.h",
"sanitized/process_snapshot_sanitized_test.cc", "sanitized/process_snapshot_sanitized_test.cc",
"sanitized/sanitization_information_test.cc", "sanitized/sanitization_information_test.cc",
] ]
......
...@@ -41,7 +41,7 @@ class DebugRendezvous { ...@@ -41,7 +41,7 @@ class DebugRendezvous {
//! \brief The difference between the preferred load address in the ELF file //! \brief The difference between the preferred load address in the ELF file
//! and the actual loaded address in memory. //! and the actual loaded address in memory.
VMAddress load_bias; LinuxVMOffset load_bias;
//! \brief The address of the dynamic array for this object. //! \brief The address of the dynamic array for this object.
LinuxVMAddress dynamic_array; LinuxVMAddress dynamic_array;
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "snapshot/elf/elf_image_reader.h" #include "snapshot/elf/elf_image_reader.h"
#include "snapshot/linux/test_modules.h"
#include "test/linux/fake_ptrace_connection.h" #include "test/linux/fake_ptrace_connection.h"
#include "test/main_arguments.h" #include "test/main_arguments.h"
#include "test/multiprocess.h" #include "test/multiprocess.h"
...@@ -35,7 +34,6 @@ ...@@ -35,7 +34,6 @@
#include "util/linux/auxiliary_vector.h" #include "util/linux/auxiliary_vector.h"
#include "util/linux/direct_ptrace_connection.h" #include "util/linux/direct_ptrace_connection.h"
#include "util/linux/memory_map.h" #include "util/linux/memory_map.h"
#include "util/numeric/safe_assignment.h"
#include "util/process/process_memory_linux.h" #include "util/process/process_memory_linux.h"
#include "util/process/process_memory_range.h" #include "util/process/process_memory_range.h"
...@@ -47,20 +45,6 @@ namespace crashpad { ...@@ -47,20 +45,6 @@ namespace crashpad {
namespace test { namespace test {
namespace { namespace {
void ExpectLoadBias(bool is_64_bit,
VMAddress unsigned_bias,
VMOffset signed_bias) {
if (is_64_bit) {
EXPECT_EQ(unsigned_bias, static_cast<VMAddress>(signed_bias));
} else {
uint32_t unsigned_bias32;
ASSERT_TRUE(AssignIfInRange(&unsigned_bias32, unsigned_bias));
uint32_t casted_bias32 = static_cast<uint32_t>(signed_bias);
EXPECT_EQ(unsigned_bias32, casted_bias32);
}
}
void TestAgainstTarget(PtraceConnection* connection) { void TestAgainstTarget(PtraceConnection* connection) {
// Use ElfImageReader on the main executable which can tell us the debug // Use ElfImageReader on the main executable which can tell us the debug
// address. glibc declares the symbol _r_debug in link.h which we can use to // address. glibc declares the symbol _r_debug in link.h which we can use to
...@@ -128,11 +112,9 @@ void TestAgainstTarget(PtraceConnection* connection) { ...@@ -128,11 +112,9 @@ void TestAgainstTarget(PtraceConnection* connection) {
// Android's loader doesn't set the load bias until Android 4.3 (API 18). // Android's loader doesn't set the load bias until Android 4.3 (API 18).
if (android_runtime_api >= 18) { if (android_runtime_api >= 18) {
ExpectLoadBias(connection->Is64Bit(), EXPECT_EQ(debug.Executable()->load_bias, exe_reader.GetLoadBias());
debug.Executable()->load_bias,
exe_reader.GetLoadBias());
} else { } else {
EXPECT_EQ(debug.Executable()->load_bias, 0u); EXPECT_EQ(debug.Executable()->load_bias, 0);
} }
for (const DebugRendezvous::LinkEntry& module : debug.Modules()) { for (const DebugRendezvous::LinkEntry& module : debug.Modules()) {
...@@ -148,7 +130,7 @@ void TestAgainstTarget(PtraceConnection* connection) { ...@@ -148,7 +130,7 @@ void TestAgainstTarget(PtraceConnection* connection) {
// (API 17). // (API 17).
if (is_android_loader && android_runtime_api < 17) { if (is_android_loader && android_runtime_api < 17) {
EXPECT_EQ(module.dynamic_array, 0u); EXPECT_EQ(module.dynamic_array, 0u);
EXPECT_EQ(module.load_bias, 0u); EXPECT_EQ(module.load_bias, 0);
continue; continue;
} }
...@@ -188,11 +170,7 @@ void TestAgainstTarget(PtraceConnection* connection) { ...@@ -188,11 +170,7 @@ void TestAgainstTarget(PtraceConnection* connection) {
const std::string& module_name) { const std::string& module_name) {
const bool is_vdso_mapping = const bool is_vdso_mapping =
device == 0 && inode == 0 && mapping_name == "[vdso]"; device == 0 && inode == 0 && mapping_name == "[vdso]";
#if defined(ARCH_CPU_X86)
static constexpr char kPrefix[] = "linux-gate.so.";
#else
static constexpr char kPrefix[] = "linux-vdso.so."; static constexpr char kPrefix[] = "linux-vdso.so.";
#endif
return is_vdso_mapping == return is_vdso_mapping ==
(module_name.empty() || (module_name.empty() ||
module_name.compare(0, strlen(kPrefix), kPrefix) == 0); module_name.compare(0, strlen(kPrefix), kPrefix) == 0);
...@@ -207,11 +185,9 @@ void TestAgainstTarget(PtraceConnection* connection) { ...@@ -207,11 +185,9 @@ void TestAgainstTarget(PtraceConnection* connection) {
// (API 20) until Android 6.0 (API 23). // (API 20) until Android 6.0 (API 23).
if (is_android_loader && android_runtime_api > 20 && if (is_android_loader && android_runtime_api > 20 &&
android_runtime_api < 23) { android_runtime_api < 23) {
EXPECT_EQ(module.load_bias, 0u); EXPECT_EQ(module.load_bias, 0);
} else { } else {
ExpectLoadBias(connection->Is64Bit(), EXPECT_EQ(module.load_bias, module_reader->GetLoadBias());
module.load_bias,
static_cast<VMAddress>(module_reader->GetLoadBias()));
} }
CheckedLinuxAddressRange module_range( CheckedLinuxAddressRange module_range(
...@@ -220,13 +196,7 @@ void TestAgainstTarget(PtraceConnection* connection) { ...@@ -220,13 +196,7 @@ void TestAgainstTarget(PtraceConnection* connection) {
} }
} }
TEST(DebugRendezvous, Self) { TEST(DebugRendezvous, DISABLED_Self) {
const std::string module_name = "test_module.so";
const std::string module_soname = "test_module_soname";
ScopedModuleHandle empty_test_module(
LoadTestModule(module_name, module_soname));
ASSERT_TRUE(empty_test_module.valid());
FakePtraceConnection connection; FakePtraceConnection connection;
ASSERT_TRUE(connection.Initialize(getpid())); ASSERT_TRUE(connection.Initialize(getpid()));
...@@ -251,7 +221,7 @@ class ChildTest : public Multiprocess { ...@@ -251,7 +221,7 @@ class ChildTest : public Multiprocess {
DISALLOW_COPY_AND_ASSIGN(ChildTest); DISALLOW_COPY_AND_ASSIGN(ChildTest);
}; };
TEST(DebugRendezvous, Child) { TEST(DebugRendezvous, DISABLED_Child) {
ChildTest test; ChildTest test;
test.Run(); test.Run();
} }
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "snapshot/linux/test_modules.h"
#include "test/errors.h" #include "test/errors.h"
#include "test/linux/fake_ptrace_connection.h" #include "test/linux/fake_ptrace_connection.h"
#include "test/linux/get_tls.h" #include "test/linux/get_tls.h"
...@@ -542,6 +541,218 @@ void ExpectModulesFromSelf( ...@@ -542,6 +541,218 @@ void ExpectModulesFromSelf(
#endif // !OS_ANDROID || !ARCH_CPU_ARMEL || __ANDROID_API__ >= 21 #endif // !OS_ANDROID || !ARCH_CPU_ARMEL || __ANDROID_API__ >= 21
} }
bool WriteTestModule(const base::FilePath& module_path,
const std::string& soname) {
#if defined(ARCH_CPU_64_BITS)
using Ehdr = Elf64_Ehdr;
using Phdr = Elf64_Phdr;
using Shdr = Elf64_Shdr;
using Dyn = Elf64_Dyn;
using Sym = Elf64_Sym;
unsigned char elf_class = ELFCLASS64;
#else
using Ehdr = Elf32_Ehdr;
using Phdr = Elf32_Phdr;
using Shdr = Elf32_Shdr;
using Dyn = Elf32_Dyn;
using Sym = Elf32_Sym;
unsigned char elf_class = ELFCLASS32;
#endif
struct {
Ehdr ehdr;
struct {
Phdr load1;
Phdr load2;
Phdr dynamic;
} phdr_table;
struct {
Dyn hash;
Dyn strtab;
Dyn symtab;
Dyn strsz;
Dyn syment;
Dyn soname;
Dyn null;
} dynamic_array;
struct {
Elf32_Word nbucket;
Elf32_Word nchain;
Elf32_Word bucket;
Elf32_Word chain;
} hash_table;
char string_table[32];
struct {
} section_header_string_table;
struct {
Sym und_symbol;
} symbol_table;
struct {
Shdr null;
Shdr dynamic;
Shdr string_table;
Shdr section_header_string_table;
} shdr_table;
} module = {};
module.ehdr.e_ident[EI_MAG0] = ELFMAG0;
module.ehdr.e_ident[EI_MAG1] = ELFMAG1;
module.ehdr.e_ident[EI_MAG2] = ELFMAG2;
module.ehdr.e_ident[EI_MAG3] = ELFMAG3;
module.ehdr.e_ident[EI_CLASS] = elf_class;
#if defined(ARCH_CPU_LITTLE_ENDIAN)
module.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
#else
module.ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
#endif // ARCH_CPU_LITTLE_ENDIAN
module.ehdr.e_ident[EI_VERSION] = EV_CURRENT;
module.ehdr.e_type = ET_DYN;
#if defined(ARCH_CPU_X86)
module.ehdr.e_machine = EM_386;
#elif defined(ARCH_CPU_X86_64)
module.ehdr.e_machine = EM_X86_64;
#elif defined(ARCH_CPU_ARMEL)
module.ehdr.e_machine = EM_ARM;
#elif defined(ARCH_CPU_ARM64)
module.ehdr.e_machine = EM_AARCH64;
#elif defined(ARCH_CPU_MIPSEL) || defined(ARCH_CPU_MIPS64EL)
module.ehdr.e_machine = EM_MIPS;
#endif
module.ehdr.e_version = EV_CURRENT;
module.ehdr.e_ehsize = sizeof(module.ehdr);
module.ehdr.e_phoff = offsetof(decltype(module), phdr_table);
module.ehdr.e_phnum = sizeof(module.phdr_table) / sizeof(Phdr);
module.ehdr.e_phentsize = sizeof(Phdr);
module.ehdr.e_shoff = offsetof(decltype(module), shdr_table);
module.ehdr.e_shentsize = sizeof(Shdr);
module.ehdr.e_shnum = sizeof(module.shdr_table) / sizeof(Shdr);
module.ehdr.e_shstrndx =
offsetof(decltype(module.shdr_table), section_header_string_table) /
sizeof(Shdr);
constexpr size_t load2_vaddr = 0x200000;
module.phdr_table.load1.p_type = PT_LOAD;
module.phdr_table.load1.p_offset = 0;
module.phdr_table.load1.p_vaddr = 0;
module.phdr_table.load1.p_filesz = offsetof(decltype(module), shdr_table);
module.phdr_table.load1.p_memsz = offsetof(decltype(module), shdr_table);
module.phdr_table.load1.p_flags = PF_R;
module.phdr_table.load1.p_align = load2_vaddr;
module.phdr_table.load2.p_type = PT_LOAD;
module.phdr_table.load2.p_offset = 0;
module.phdr_table.load2.p_vaddr = load2_vaddr;
module.phdr_table.load2.p_filesz = offsetof(decltype(module), shdr_table);
module.phdr_table.load2.p_memsz = offsetof(decltype(module), shdr_table);
module.phdr_table.load2.p_flags = PF_R | PF_W;
module.phdr_table.load2.p_align = load2_vaddr;
module.phdr_table.dynamic.p_type = PT_DYNAMIC;
module.phdr_table.dynamic.p_offset =
offsetof(decltype(module), dynamic_array);
module.phdr_table.dynamic.p_vaddr =
load2_vaddr + module.phdr_table.dynamic.p_offset;
module.phdr_table.dynamic.p_filesz = sizeof(module.dynamic_array);
module.phdr_table.dynamic.p_memsz = sizeof(module.dynamic_array);
module.phdr_table.dynamic.p_flags = PF_R | PF_W;
module.phdr_table.dynamic.p_align = 8;
module.dynamic_array.hash.d_tag = DT_HASH;
module.dynamic_array.hash.d_un.d_ptr = offsetof(decltype(module), hash_table);
module.dynamic_array.strtab.d_tag = DT_STRTAB;
module.dynamic_array.strtab.d_un.d_ptr =
offsetof(decltype(module), string_table);
module.dynamic_array.symtab.d_tag = DT_SYMTAB;
module.dynamic_array.symtab.d_un.d_ptr =
offsetof(decltype(module), symbol_table);
module.dynamic_array.strsz.d_tag = DT_STRSZ;
module.dynamic_array.strsz.d_un.d_val = sizeof(module.string_table);
module.dynamic_array.syment.d_tag = DT_SYMENT;
module.dynamic_array.syment.d_un.d_val = sizeof(Sym);
constexpr size_t kSonameOffset = 1;
module.dynamic_array.soname.d_tag = DT_SONAME;
module.dynamic_array.soname.d_un.d_val = kSonameOffset;
module.dynamic_array.null.d_tag = DT_NULL;
module.hash_table.nbucket = 1;
module.hash_table.nchain = 1;
module.hash_table.bucket = 0;
module.hash_table.chain = 0;
CHECK_GE(sizeof(module.string_table), soname.size() + 2);
module.string_table[0] = '\0';
memcpy(&module.string_table[kSonameOffset], soname.c_str(), soname.size());
module.shdr_table.null.sh_type = SHT_NULL;
module.shdr_table.dynamic.sh_name = 0;
module.shdr_table.dynamic.sh_type = SHT_DYNAMIC;
module.shdr_table.dynamic.sh_flags = SHF_WRITE | SHF_ALLOC;
module.shdr_table.dynamic.sh_addr = module.phdr_table.dynamic.p_vaddr;
module.shdr_table.dynamic.sh_offset = module.phdr_table.dynamic.p_offset;
module.shdr_table.dynamic.sh_size = module.phdr_table.dynamic.p_filesz;
module.shdr_table.dynamic.sh_link =
offsetof(decltype(module.shdr_table), string_table) / sizeof(Shdr);
module.shdr_table.string_table.sh_name = 0;
module.shdr_table.string_table.sh_type = SHT_STRTAB;
module.shdr_table.string_table.sh_offset =
offsetof(decltype(module), string_table);
module.shdr_table.string_table.sh_size = sizeof(module.string_table);
module.shdr_table.section_header_string_table.sh_name = 0;
module.shdr_table.section_header_string_table.sh_type = SHT_STRTAB;
module.shdr_table.section_header_string_table.sh_offset =
offsetof(decltype(module), section_header_string_table);
module.shdr_table.section_header_string_table.sh_size =
sizeof(module.section_header_string_table);
FileWriter writer;
if (!writer.Open(module_path,
FileWriteMode::kCreateOrFail,
FilePermissions::kWorldReadable)) {
ADD_FAILURE();
return false;
}
if (!writer.Write(&module, sizeof(module))) {
ADD_FAILURE();
return false;
}
return true;
}
ScopedModuleHandle LoadTestModule(const std::string& module_name,
const std::string& module_soname) {
base::FilePath module_path(
TestPaths::Executable().DirName().Append(module_name));
if (!WriteTestModule(module_path, module_soname)) {
return ScopedModuleHandle(nullptr);
}
EXPECT_TRUE(IsRegularFile(module_path));
ScopedModuleHandle handle(
dlopen(module_path.value().c_str(), RTLD_LAZY | RTLD_LOCAL));
EXPECT_TRUE(handle.valid())
<< "dlopen: " << module_path.value() << " " << dlerror();
EXPECT_TRUE(LoggingRemoveFile(module_path));
return handle;
}
void ExpectTestModule(ProcessReaderLinux* reader, void ExpectTestModule(ProcessReaderLinux* reader,
const std::string& module_name) { const std::string& module_name) {
for (const auto& module : reader->Modules()) { for (const auto& module : reader->Modules()) {
......
// Copyright 2020 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 "snapshot/linux/test_modules.h"
#include <elf.h>
#include <limits>
#include "base/check_op.h"
#include "base/files/file_path.h"
#include "build/build_config.h"
#include "gtest/gtest.h"
#include "test/test_paths.h"
#include "util/file/filesystem.h"
#include "util/file/file_writer.h"
namespace crashpad {
namespace test {
bool WriteTestModule(const base::FilePath& module_path,
const std::string& soname) {
#if defined(ARCH_CPU_64_BITS)
using Ehdr = Elf64_Ehdr;
using Phdr = Elf64_Phdr;
using Shdr = Elf64_Shdr;
using Dyn = Elf64_Dyn;
using Sym = Elf64_Sym;
unsigned char elf_class = ELFCLASS64;
#else
using Ehdr = Elf32_Ehdr;
using Phdr = Elf32_Phdr;
using Shdr = Elf32_Shdr;
using Dyn = Elf32_Dyn;
using Sym = Elf32_Sym;
unsigned char elf_class = ELFCLASS32;
#endif
struct {
Ehdr ehdr;
struct {
Phdr load1;
Phdr load2;
Phdr dynamic;
} phdr_table;
struct {
Dyn hash;
Dyn strtab;
Dyn symtab;
Dyn strsz;
Dyn syment;
Dyn soname;
Dyn null;
} dynamic_array;
struct {
Elf32_Word nbucket;
Elf32_Word nchain;
Elf32_Word bucket;
Elf32_Word chain;
} hash_table;
char string_table[32];
struct {
} section_header_string_table;
struct {
Sym und_symbol;
} symbol_table;
struct {
Shdr null;
Shdr dynamic;
Shdr string_table;
Shdr section_header_string_table;
} shdr_table;
} module = {};
module.ehdr.e_ident[EI_MAG0] = ELFMAG0;
module.ehdr.e_ident[EI_MAG1] = ELFMAG1;
module.ehdr.e_ident[EI_MAG2] = ELFMAG2;
module.ehdr.e_ident[EI_MAG3] = ELFMAG3;
module.ehdr.e_ident[EI_CLASS] = elf_class;
#if defined(ARCH_CPU_LITTLE_ENDIAN)
module.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
#else
module.ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
#endif // ARCH_CPU_LITTLE_ENDIAN
module.ehdr.e_ident[EI_VERSION] = EV_CURRENT;
module.ehdr.e_type = ET_DYN;
#if defined(ARCH_CPU_X86)
module.ehdr.e_machine = EM_386;
#elif defined(ARCH_CPU_X86_64)
module.ehdr.e_machine = EM_X86_64;
#elif defined(ARCH_CPU_ARMEL)
module.ehdr.e_machine = EM_ARM;
#elif defined(ARCH_CPU_ARM64)
module.ehdr.e_machine = EM_AARCH64;
#elif defined(ARCH_CPU_MIPSEL) || defined(ARCH_CPU_MIPS64EL)
module.ehdr.e_machine = EM_MIPS;
#endif
module.ehdr.e_version = EV_CURRENT;
module.ehdr.e_ehsize = sizeof(module.ehdr);
module.ehdr.e_phoff = offsetof(decltype(module), phdr_table);
module.ehdr.e_phnum = sizeof(module.phdr_table) / sizeof(Phdr);
module.ehdr.e_phentsize = sizeof(Phdr);
module.ehdr.e_shoff = offsetof(decltype(module), shdr_table);
module.ehdr.e_shentsize = sizeof(Shdr);
module.ehdr.e_shnum = sizeof(module.shdr_table) / sizeof(Shdr);
module.ehdr.e_shstrndx =
offsetof(decltype(module.shdr_table), section_header_string_table) /
sizeof(Shdr);
const size_t page_size = getpagesize();
auto align = [page_size](uintptr_t addr) {
return (addr + page_size - 1) & ~(page_size - 1);
};
constexpr size_t segment_size = offsetof(decltype(module), shdr_table);
// This test module covers cases where:
// 1. Multiple segments are mapped from file offset 0.
// 2. Load bias is negative.
const uintptr_t load2_vaddr = align(std::numeric_limits<uintptr_t>::max() -
align(segment_size) - page_size);
const uintptr_t load1_vaddr = load2_vaddr - align(segment_size);
module.phdr_table.load1.p_type = PT_LOAD;
module.phdr_table.load1.p_offset = 0;
module.phdr_table.load1.p_vaddr = load1_vaddr;
module.phdr_table.load1.p_filesz = segment_size;
module.phdr_table.load1.p_memsz = segment_size;
module.phdr_table.load1.p_flags = PF_R;
module.phdr_table.load1.p_align = page_size;
module.phdr_table.load2.p_type = PT_LOAD;
module.phdr_table.load2.p_offset = 0;
module.phdr_table.load2.p_vaddr = load2_vaddr;
module.phdr_table.load2.p_filesz = segment_size;
module.phdr_table.load2.p_memsz = segment_size;
module.phdr_table.load2.p_flags = PF_R | PF_W;
module.phdr_table.load2.p_align = page_size;
module.phdr_table.dynamic.p_type = PT_DYNAMIC;
module.phdr_table.dynamic.p_offset =
offsetof(decltype(module), dynamic_array);
module.phdr_table.dynamic.p_vaddr =
load2_vaddr + module.phdr_table.dynamic.p_offset;
module.phdr_table.dynamic.p_filesz = sizeof(module.dynamic_array);
module.phdr_table.dynamic.p_memsz = sizeof(module.dynamic_array);
module.phdr_table.dynamic.p_flags = PF_R | PF_W;
module.phdr_table.dynamic.p_align = 8;
module.dynamic_array.hash.d_tag = DT_HASH;
module.dynamic_array.hash.d_un.d_ptr =
load1_vaddr + offsetof(decltype(module), hash_table);
module.dynamic_array.strtab.d_tag = DT_STRTAB;
module.dynamic_array.strtab.d_un.d_ptr =
load1_vaddr + offsetof(decltype(module), string_table);
module.dynamic_array.symtab.d_tag = DT_SYMTAB;
module.dynamic_array.symtab.d_un.d_ptr =
load1_vaddr + offsetof(decltype(module), symbol_table);
module.dynamic_array.strsz.d_tag = DT_STRSZ;
module.dynamic_array.strsz.d_un.d_val = sizeof(module.string_table);
module.dynamic_array.syment.d_tag = DT_SYMENT;
module.dynamic_array.syment.d_un.d_val = sizeof(Sym);
constexpr size_t kSonameOffset = 1;
module.dynamic_array.soname.d_tag = DT_SONAME;
module.dynamic_array.soname.d_un.d_val = kSonameOffset;
module.dynamic_array.null.d_tag = DT_NULL;
module.hash_table.nbucket = 1;
module.hash_table.nchain = 1;
module.hash_table.bucket = 0;
module.hash_table.chain = 0;
if (sizeof(module.string_table) < soname.size() + 2) {
ADD_FAILURE() << "string table too small";
return false;
}
module.string_table[0] = '\0';
memcpy(&module.string_table[kSonameOffset], soname.c_str(), soname.size());
module.shdr_table.null.sh_type = SHT_NULL;
module.shdr_table.dynamic.sh_name = 0;
module.shdr_table.dynamic.sh_type = SHT_DYNAMIC;
module.shdr_table.dynamic.sh_flags = SHF_WRITE | SHF_ALLOC;
module.shdr_table.dynamic.sh_addr = module.phdr_table.dynamic.p_vaddr;
module.shdr_table.dynamic.sh_offset = module.phdr_table.dynamic.p_offset;
module.shdr_table.dynamic.sh_size = module.phdr_table.dynamic.p_filesz;
module.shdr_table.dynamic.sh_link =
offsetof(decltype(module.shdr_table), string_table) / sizeof(Shdr);
module.shdr_table.string_table.sh_name = 0;
module.shdr_table.string_table.sh_type = SHT_STRTAB;
module.shdr_table.string_table.sh_offset =
offsetof(decltype(module), string_table);
module.shdr_table.string_table.sh_size = sizeof(module.string_table);
module.shdr_table.section_header_string_table.sh_name = 0;
module.shdr_table.section_header_string_table.sh_type = SHT_STRTAB;
module.shdr_table.section_header_string_table.sh_offset =
offsetof(decltype(module), section_header_string_table);
module.shdr_table.section_header_string_table.sh_size =
sizeof(module.section_header_string_table);
FileWriter writer;
if (!writer.Open(module_path,
FileWriteMode::kCreateOrFail,
FilePermissions::kWorldReadable)) {
ADD_FAILURE();
return false;
}
if (!writer.Write(&module, sizeof(module))) {
ADD_FAILURE();
LoggingRemoveFile(module_path);
return false;
}
return true;
}
ScopedModuleHandle LoadTestModule(const std::string& module_name,
const std::string& module_soname) {
base::FilePath module_path(
TestPaths::Executable().DirName().Append(module_name));
if (!WriteTestModule(module_path, module_soname)) {
return ScopedModuleHandle(nullptr);
}
EXPECT_TRUE(IsRegularFile(module_path));
ScopedModuleHandle handle(
dlopen(module_path.value().c_str(), RTLD_LAZY | RTLD_LOCAL));
EXPECT_TRUE(handle.valid())
<< "dlopen: " << module_path.value() << " " << dlerror();
EXPECT_TRUE(LoggingRemoveFile(module_path));
return handle;
}
} // namespace test
} // namespace crashpad
// Copyright 2020 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_SNAPSHOT_LINUX_TEST_MODULES_H_
#define CRASHPAD_SNAPSHOT_LINUX_TEST_MODULES_H_
#include <string>
#include "test/scoped_module_handle.h"
namespace crashpad {
namespace test {
//! \brief Constructs and loads a test module.
//!
//! \param module_name The filename of the mdoule.
//! \param module_soname The SONAME for the module.
//! \return a handle to the loaded module on success. On failure, the handle
//! will be invalid and a message will be logged.
ScopedModuleHandle LoadTestModule(const std::string& module_name,
const std::string& module_soname);
} // namespace test
} // namespace crashpad
#endif // CRASHPAD_SNAPSHOT_LINUX_DEBUG_RENDEZVOUS_H_
...@@ -80,8 +80,6 @@ ...@@ -80,8 +80,6 @@
'linux/exception_snapshot_linux_test.cc', 'linux/exception_snapshot_linux_test.cc',
'linux/process_reader_linux_test.cc', 'linux/process_reader_linux_test.cc',
'linux/system_snapshot_linux_test.cc', 'linux/system_snapshot_linux_test.cc',
'linux/test_modules.cc',
'linux/test_modules.h',
'mac/cpu_context_mac_test.cc', 'mac/cpu_context_mac_test.cc',
'mac/mach_o_image_annotations_reader_test.cc', 'mac/mach_o_image_annotations_reader_test.cc',
'mac/mach_o_image_reader_test.cc', 'mac/mach_o_image_reader_test.cc',
......
...@@ -7,9 +7,6 @@ ...@@ -7,9 +7,6 @@
} }
} }
}, },
"include": [
"sdk/lib/diagnostics/syslog/client.shard.cmx"
],
"program": { "program": {
"binary": "test/crashpad_tests" "binary": "test/crashpad_tests"
}, },
......
...@@ -124,8 +124,8 @@ if (crashpad_is_in_chromium) { ...@@ -124,8 +124,8 @@ if (crashpad_is_in_chromium) {
"edo/Service/Sources/NSKeyedArchiver+EDOAdditions.m", "edo/Service/Sources/NSKeyedArchiver+EDOAdditions.m",
"edo/Service/Sources/NSKeyedUnarchiver+EDOAdditions.h", "edo/Service/Sources/NSKeyedUnarchiver+EDOAdditions.h",
"edo/Service/Sources/NSKeyedUnarchiver+EDOAdditions.m", "edo/Service/Sources/NSKeyedUnarchiver+EDOAdditions.m",
"edo/Service/Sources/NSObject+EDOBlockedType.h", "edo/Service/Sources/NSObject+EDOBlacklistedType.h",
"edo/Service/Sources/NSObject+EDOBlockedType.m", "edo/Service/Sources/NSObject+EDOBlacklistedType.m",
"edo/Service/Sources/NSObject+EDOParameter.h", "edo/Service/Sources/NSObject+EDOParameter.h",
"edo/Service/Sources/NSObject+EDOParameter.m", "edo/Service/Sources/NSObject+EDOParameter.m",
"edo/Service/Sources/NSObject+EDOValue.h", "edo/Service/Sources/NSObject+EDOValue.h",
......
...@@ -3,7 +3,7 @@ Short Name: lss ...@@ -3,7 +3,7 @@ Short Name: lss
URL: https://chromium.googlesource.com/linux-syscall-support/ URL: https://chromium.googlesource.com/linux-syscall-support/
Revision: See DEPS Revision: See DEPS
License: BSD 3-clause License: BSD 3-clause
License File: lss/linux_syscall_support.h License File: lss/linux-syscall-support.h
Security Critical: yes Security Critical: yes
Description: Description:
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <sys/mman.h>
#include <syscall.h> #include <syscall.h>
#include <unistd.h> #include <unistd.h>
...@@ -25,11 +24,7 @@ ...@@ -25,11 +24,7 @@
#include "base/check_op.h" #include "base/check_op.h"
#include "base/posix/eintr_wrapper.h" #include "base/posix/eintr_wrapper.h"
#include "base/process/process_metrics.h"
#include "third_party/lss/lss.h"
#include "util/linux/scoped_ptrace_attach.h"
#include "util/misc/memory_sanitizer.h" #include "util/misc/memory_sanitizer.h"
#include "util/posix/scoped_mmap.h"
namespace crashpad { namespace crashpad {
...@@ -57,58 +52,18 @@ size_t FormatPID(char* buffer, pid_t pid) { ...@@ -57,58 +52,18 @@ size_t FormatPID(char* buffer, pid_t pid) {
} // namespace } // namespace
class PtraceBroker::AttachmentsArray {
public:
AttachmentsArray() : allocation_(false), attach_count_(0) {}
~AttachmentsArray() {
for (size_t index = 0; index < attach_count_; ++index) {
PtraceDetach(Attachments()[index], false);
}
}
bool Initialize() {
return allocation_.ResetMmap(nullptr,
base::GetPageSize(),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1,
0);
}
bool Attach(pid_t pid) {
pid_t* attach = AllocateAttachment();
if (!attach || !PtraceAttach(pid, false)) {
return false;
}
*attach = pid;
return true;
}
private:
pid_t* AllocateAttachment() {
if (attach_count_ >= (allocation_.len() / sizeof(pid_t))) {
return nullptr;
}
return &Attachments()[attach_count_++];
}
pid_t* Attachments() { return allocation_.addr_as<pid_t*>(); }
ScopedMmap allocation_;
size_t attach_count_;
DISALLOW_COPY_AND_ASSIGN(AttachmentsArray);
};
PtraceBroker::PtraceBroker(int sock, pid_t pid, bool is_64_bit) PtraceBroker::PtraceBroker(int sock, pid_t pid, bool is_64_bit)
: ptracer_(is_64_bit, /* can_log= */ false), : ptracer_(is_64_bit, /* can_log= */ false),
file_root_(file_root_buffer_), file_root_(file_root_buffer_),
attachments_(nullptr),
attach_count_(0),
attach_capacity_(0),
memory_file_(), memory_file_(),
sock_(sock), sock_(sock),
memory_pid_(pid), memory_pid_(pid),
tried_opening_mem_file_(false) { tried_opening_mem_file_(false) {
AllocateAttachments();
static constexpr char kProc[] = "/proc/"; static constexpr char kProc[] = "/proc/";
size_t root_length = strlen(kProc); size_t root_length = strlen(kProc);
memcpy(file_root_buffer_, kProc, root_length); memcpy(file_root_buffer_, kProc, root_length);
...@@ -133,12 +88,35 @@ void PtraceBroker::SetFileRoot(const char* new_root) { ...@@ -133,12 +88,35 @@ void PtraceBroker::SetFileRoot(const char* new_root) {
} }
int PtraceBroker::Run() { int PtraceBroker::Run() {
AttachmentsArray attachments; int result = RunImpl();
attachments.Initialize(); ReleaseAttachments();
return RunImpl(&attachments); return result;
}
bool PtraceBroker::AllocateAttachments() {
constexpr size_t page_size = 4096;
constexpr size_t alloc_size =
(sizeof(ScopedPtraceAttach) + page_size - 1) & ~(page_size - 1);
void* alloc = sbrk(alloc_size);
if (reinterpret_cast<intptr_t>(alloc) == -1) {
return false;
}
if (attachments_ == nullptr) {
attachments_ = reinterpret_cast<ScopedPtraceAttach*>(alloc);
}
attach_capacity_ += alloc_size / sizeof(ScopedPtraceAttach);
return true;
} }
int PtraceBroker::RunImpl(AttachmentsArray* attachments) { void PtraceBroker::ReleaseAttachments() {
for (size_t index = 0; index < attach_count_; ++index) {
attachments_[index].Reset();
}
}
int PtraceBroker::RunImpl() {
while (true) { while (true) {
Request request = {}; Request request = {};
if (!ReadFileExactly(sock_, &request, sizeof(request))) { if (!ReadFileExactly(sock_, &request, sizeof(request))) {
...@@ -151,10 +129,25 @@ int PtraceBroker::RunImpl(AttachmentsArray* attachments) { ...@@ -151,10 +129,25 @@ int PtraceBroker::RunImpl(AttachmentsArray* attachments) {
switch (request.type) { switch (request.type) {
case Request::kTypeAttach: { case Request::kTypeAttach: {
ScopedPtraceAttach* attach;
ScopedPtraceAttach stack_attach;
bool attach_on_stack = false;
if (attach_capacity_ > attach_count_ || AllocateAttachments()) {
attach = new (&attachments_[attach_count_]) ScopedPtraceAttach;
} else {
attach = &stack_attach;
attach_on_stack = true;
}
ExceptionHandlerProtocol::Bool status = ExceptionHandlerProtocol::Bool status =
attachments->Attach(request.tid) ExceptionHandlerProtocol::kBoolFalse;
? ExceptionHandlerProtocol::kBoolTrue if (attach->ResetAttach(request.tid)) {
: ExceptionHandlerProtocol::kBoolFalse; status = ExceptionHandlerProtocol::kBoolTrue;
if (!attach_on_stack) {
++attach_count_;
}
}
if (!WriteFile(sock_, &status, sizeof(status))) { if (!WriteFile(sock_, &status, sizeof(status))) {
return errno; return errno;
...@@ -167,6 +160,9 @@ int PtraceBroker::RunImpl(AttachmentsArray* attachments) { ...@@ -167,6 +160,9 @@ int PtraceBroker::RunImpl(AttachmentsArray* attachments) {
} }
} }
if (attach_on_stack && status == ExceptionHandlerProtocol::kBoolTrue) {
return RunImpl();
}
continue; continue;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "util/linux/exception_handler_protocol.h" #include "util/linux/exception_handler_protocol.h"
#include "util/linux/ptrace_connection.h" #include "util/linux/ptrace_connection.h"
#include "util/linux/ptracer.h" #include "util/linux/ptracer.h"
#include "util/linux/scoped_ptrace_attach.h"
#include "util/linux/thread_info.h" #include "util/linux/thread_info.h"
#include "util/misc/address_types.h" #include "util/misc/address_types.h"
...@@ -185,13 +186,16 @@ class PtraceBroker { ...@@ -185,13 +186,16 @@ class PtraceBroker {
//! This method returns when a PtraceBrokerRequest with type kTypeExit is //! This method returns when a PtraceBrokerRequest with type kTypeExit is
//! received or an error is encountered on the socket. //! received or an error is encountered on the socket.
//! //!
//! This method calls `sbrk`, which may break other memory management tools,
//! such as `malloc`.
//!
//! \return 0 if Run() exited due to an exit request. Otherwise an error code. //! \return 0 if Run() exited due to an exit request. Otherwise an error code.
int Run(); int Run();
private: private:
class AttachmentsArray; bool AllocateAttachments();
void ReleaseAttachments();
int RunImpl(AttachmentsArray*); int RunImpl();
int SendError(ExceptionHandlerProtocol::Errno err); int SendError(ExceptionHandlerProtocol::Errno err);
int SendReadError(ReadError err); int SendReadError(ReadError err);
int SendOpenResult(OpenResult result); int SendOpenResult(OpenResult result);
...@@ -206,6 +210,9 @@ class PtraceBroker { ...@@ -206,6 +210,9 @@ class PtraceBroker {
char file_root_buffer_[32]; char file_root_buffer_[32];
Ptracer ptracer_; Ptracer ptracer_;
const char* file_root_; const char* file_root_;
ScopedPtraceAttach* attachments_;
size_t attach_count_;
size_t attach_capacity_;
ScopedFileHandle memory_file_; ScopedFileHandle memory_file_;
int sock_; int sock_;
pid_t memory_pid_; pid_t memory_pid_;
......
...@@ -22,32 +22,6 @@ ...@@ -22,32 +22,6 @@
namespace crashpad { namespace crashpad {
bool PtraceAttach(pid_t pid, bool can_log) {
if (ptrace(PTRACE_ATTACH, pid, nullptr, nullptr) != 0) {
PLOG_IF(ERROR, can_log) << "ptrace";
return false;
}
int status;
if (HANDLE_EINTR(waitpid(pid, &status, __WALL)) < 0) {
PLOG_IF(ERROR, can_log) << "waitpid";
return false;
}
if (!WIFSTOPPED(status)) {
LOG_IF(ERROR, can_log) << "process not stopped";
return false;
}
return true;
}
bool PtraceDetach(pid_t pid, bool can_log) {
if (pid >= 0 && ptrace(PTRACE_DETACH, pid, nullptr, nullptr) != 0) {
PLOG_IF(ERROR, can_log) << "ptrace";
return false;
}
return true;
}
ScopedPtraceAttach::ScopedPtraceAttach() ScopedPtraceAttach::ScopedPtraceAttach()
: pid_(-1) {} : pid_(-1) {}
...@@ -56,7 +30,8 @@ ScopedPtraceAttach::~ScopedPtraceAttach() { ...@@ -56,7 +30,8 @@ ScopedPtraceAttach::~ScopedPtraceAttach() {
} }
bool ScopedPtraceAttach::Reset() { bool ScopedPtraceAttach::Reset() {
if (!PtraceDetach(pid_, true)) { if (pid_ >= 0 && ptrace(PTRACE_DETACH, pid_, nullptr, nullptr) != 0) {
PLOG(ERROR) << "ptrace";
return false; return false;
} }
pid_ = -1; pid_ = -1;
...@@ -66,11 +41,21 @@ bool ScopedPtraceAttach::Reset() { ...@@ -66,11 +41,21 @@ bool ScopedPtraceAttach::Reset() {
bool ScopedPtraceAttach::ResetAttach(pid_t pid) { bool ScopedPtraceAttach::ResetAttach(pid_t pid) {
Reset(); Reset();
if (!PtraceAttach(pid, true)) { if (ptrace(PTRACE_ATTACH, pid, nullptr, nullptr) != 0) {
PLOG(ERROR) << "ptrace";
return false; return false;
} }
pid_ = pid; pid_ = pid;
int status;
if (HANDLE_EINTR(waitpid(pid_, &status, __WALL)) < 0) {
PLOG(ERROR) << "waitpid";
return false;
}
if (!WIFSTOPPED(status)) {
LOG(ERROR) << "process not stopped";
return false;
}
return true; return true;
} }
......
...@@ -21,24 +21,6 @@ ...@@ -21,24 +21,6 @@
namespace crashpad { namespace crashpad {
//! \brief Attaches to the process with process ID \a pid and blocks until the
//! target process has stopped by calling `waitpid()`.
//!
//! \param pid The process ID of the process to attach to.
//! \param can_log Whether this function may log messages on failure.
//! \return `true` on success. `false` on failure with a message logged if \a
//! can_log is `true`.
bool PtraceAttach(pid_t pid, bool can_log = true);
//! \brief Detaches the process with process ID \a pid. The process must
//! already be ptrace attached.
//!
//! \param pid The process ID of the process to detach.
//! \param can_log Whether this function may log messages on failure.
//! \return `true` on success. `false` on failure with a message logged if \a
//! ca_log is `true `true`
bool PtraceDetach(pid_t pid, bool can_log = true);
//! \brief Maintains a `ptrace()` attachment to a process. //! \brief Maintains a `ptrace()` attachment to a process.
//! //!
//! On destruction, the process will be detached. //! On destruction, the process will be detached.
......
...@@ -22,54 +22,12 @@ ...@@ -22,54 +22,12 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "base/numerics/safe_math.h" #include "base/numerics/safe_math.h"
#include "base/process/process_metrics.h"
#include "build/build_config.h"
#if defined(OS_LINUX)
#include "third_party/lss/lss.h"
#endif
namespace { namespace {
#if defined(OS_LINUX) bool Munmap(uintptr_t addr, size_t len) {
void* CallMmap(void* addr, if (munmap(reinterpret_cast<void*>(addr), len) != 0) {
size_t len, PLOG(ERROR) << "munmap";
int prot,
int flags,
int fd,
off_t offset) {
return sys_mmap(addr, len, prot, flags, fd, offset);
}
int CallMunmap(void* addr, size_t len) {
return sys_munmap(addr, len);
}
int CallMprotect(void* addr, size_t len, int prot) {
return sys_mprotect(addr, len, prot);
}
#else
void* CallMmap(void* addr,
size_t len,
int prot,
int flags,
int fd,
off_t offset) {
return mmap(addr, len, prot, flags, fd, offset);
}
int CallMunmap(void* addr, size_t len) {
return munmap(addr, len);
}
int CallMprotect(void* addr, size_t len, int prot) {
return mprotect(addr, len, prot);
}
#endif
bool LoggingMunmap(uintptr_t addr, size_t len, bool can_log) {
if (CallMunmap(reinterpret_cast<void*>(addr), len) != 0) {
PLOG_IF(ERROR, can_log) << "munmap";
return false; return false;
} }
...@@ -77,7 +35,7 @@ bool LoggingMunmap(uintptr_t addr, size_t len, bool can_log) { ...@@ -77,7 +35,7 @@ bool LoggingMunmap(uintptr_t addr, size_t len, bool can_log) {
} }
size_t RoundPage(size_t size) { size_t RoundPage(size_t size) {
const size_t kPageMask = base::checked_cast<size_t>(base::GetPageSize()) - 1; const size_t kPageMask = base::checked_cast<size_t>(getpagesize()) - 1;
return (size + kPageMask) & ~kPageMask; return (size + kPageMask) & ~kPageMask;
} }
...@@ -85,12 +43,11 @@ size_t RoundPage(size_t size) { ...@@ -85,12 +43,11 @@ size_t RoundPage(size_t size) {
namespace crashpad { namespace crashpad {
ScopedMmap::ScopedMmap(bool can_log) : can_log_(can_log) {} ScopedMmap::ScopedMmap() {}
ScopedMmap::~ScopedMmap() { ScopedMmap::~ScopedMmap() {
if (is_valid()) { if (is_valid()) {
LoggingMunmap( Munmap(reinterpret_cast<uintptr_t>(addr_), RoundPage(len_));
reinterpret_cast<uintptr_t>(addr_), RoundPage(len_), can_log_);
} }
} }
...@@ -106,7 +63,7 @@ bool ScopedMmap::ResetAddrLen(void* addr, size_t len) { ...@@ -106,7 +63,7 @@ bool ScopedMmap::ResetAddrLen(void* addr, size_t len) {
DCHECK_EQ(len, 0u); DCHECK_EQ(len, 0u);
} else { } else {
DCHECK_NE(len, 0u); DCHECK_NE(len, 0u);
DCHECK_EQ(new_addr % base::GetPageSize(), 0u); DCHECK_EQ(new_addr % getpagesize(), 0u);
DCHECK((base::CheckedNumeric<uintptr_t>(new_addr) + (new_len_round - 1)) DCHECK((base::CheckedNumeric<uintptr_t>(new_addr) + (new_len_round - 1))
.IsValid()); .IsValid());
} }
...@@ -117,13 +74,11 @@ bool ScopedMmap::ResetAddrLen(void* addr, size_t len) { ...@@ -117,13 +74,11 @@ bool ScopedMmap::ResetAddrLen(void* addr, size_t len) {
const uintptr_t old_addr = reinterpret_cast<uintptr_t>(addr_); const uintptr_t old_addr = reinterpret_cast<uintptr_t>(addr_);
const size_t old_len_round = RoundPage(len_); const size_t old_len_round = RoundPage(len_);
if (old_addr < new_addr) { if (old_addr < new_addr) {
result &= LoggingMunmap( result &= Munmap(old_addr, std::min(old_len_round, new_addr - old_addr));
old_addr, std::min(old_len_round, new_addr - old_addr), can_log_);
} }
if (old_addr + old_len_round > new_addr + new_len_round) { if (old_addr + old_len_round > new_addr + new_len_round) {
uintptr_t unmap_start = std::max(old_addr, new_addr + new_len_round); uintptr_t unmap_start = std::max(old_addr, new_addr + new_len_round);
result &= LoggingMunmap( result &= Munmap(unmap_start, old_addr + old_len_round - unmap_start);
unmap_start, old_addr + old_len_round - unmap_start, can_log_);
} }
} }
...@@ -145,9 +100,9 @@ bool ScopedMmap::ResetMmap(void* addr, ...@@ -145,9 +100,9 @@ bool ScopedMmap::ResetMmap(void* addr,
// consider the return value from Reset(). // consider the return value from Reset().
Reset(); Reset();
void* new_addr = CallMmap(addr, len, prot, flags, fd, offset); void* new_addr = mmap(addr, len, prot, flags, fd, offset);
if (new_addr == MAP_FAILED) { if (new_addr == MAP_FAILED) {
PLOG_IF(ERROR, can_log_) << "mmap"; PLOG(ERROR) << "mmap";
return false; return false;
} }
...@@ -158,8 +113,8 @@ bool ScopedMmap::ResetMmap(void* addr, ...@@ -158,8 +113,8 @@ bool ScopedMmap::ResetMmap(void* addr,
} }
bool ScopedMmap::Mprotect(int prot) { bool ScopedMmap::Mprotect(int prot) {
if (CallMprotect(addr_, RoundPage(len_), prot) < 0) { if (mprotect(addr_, RoundPage(len_), prot) < 0) {
PLOG_IF(ERROR, can_log_) << "mprotect"; PLOG(ERROR) << "mprotect";
return false; return false;
} }
......
...@@ -30,10 +30,7 @@ namespace crashpad { ...@@ -30,10 +30,7 @@ namespace crashpad {
//! will be released by calling `munmap()`. //! will be released by calling `munmap()`.
class ScopedMmap { class ScopedMmap {
public: public:
//! \brief Constructs this object. ScopedMmap();
//!
//! \param can_log `true` if methods of this class may log messages.
explicit ScopedMmap(bool can_log = true);
~ScopedMmap(); ~ScopedMmap();
//! \brief Releases the memory-mapped region by calling `munmap()`. //! \brief Releases the memory-mapped region by calling `munmap()`.
...@@ -108,7 +105,6 @@ class ScopedMmap { ...@@ -108,7 +105,6 @@ class ScopedMmap {
private: private:
void* addr_ = MAP_FAILED; void* addr_ = MAP_FAILED;
size_t len_ = 0; size_t len_ = 0;
bool can_log_;
DISALLOW_COPY_AND_ASSIGN(ScopedMmap); DISALLOW_COPY_AND_ASSIGN(ScopedMmap);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment