mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-26 23:01:05 +08:00
android: correct executable placement in debug rendezvous
On Android P, Bionic mistakenly places the vdso first in the list where the executable should be. Also correctly set the section size in the section headers for test module string tables. Bug: chromium:1050178 Change-Id: I83581d05c5ed3e25a237d1ce4a27c45755a3ab3c Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2231525 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
294d233ca0
commit
7a70b0f151
@ -19,6 +19,11 @@
|
||||
#include <set>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
#include <android/api-level.h>
|
||||
#endif
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
@ -137,6 +142,17 @@ bool DebugRendezvous::InitializeSpecific(const ProcessMemoryRange& memory,
|
||||
modules_.push_back(entry);
|
||||
}
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
// Android P (API 28) mistakenly places the vdso in the first entry in the
|
||||
// link map.
|
||||
const int android_runtime_api = android_get_device_api_level();
|
||||
if (android_runtime_api == 28 && executable_.name == "[vdso]") {
|
||||
LinkEntry executable = modules_[0];
|
||||
modules_[0] = executable_;
|
||||
executable_ = executable;
|
||||
}
|
||||
#endif // OS_ANDROID
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,8 @@ void TestAgainstTarget(PtraceConnection* connection) {
|
||||
std::string::npos);
|
||||
|
||||
// Android's loader doesn't set the dynamic array for the executable in the
|
||||
// link map until Android 9.0 (API 28).
|
||||
if (android_runtime_api >= 28) {
|
||||
// link map until Android 10.0 (API 29).
|
||||
if (android_runtime_api >= 29) {
|
||||
EXPECT_EQ(debug.Executable()->dynamic_array, exe_dynamic_address);
|
||||
} else {
|
||||
EXPECT_EQ(debug.Executable()->dynamic_array, 0u);
|
||||
@ -147,7 +147,8 @@ void TestAgainstTarget(PtraceConnection* connection) {
|
||||
while ((mapping = possible_mappings->Next())) {
|
||||
auto parsed_module = std::make_unique<ElfImageReader>();
|
||||
VMAddress dynamic_address;
|
||||
if (parsed_module->Initialize(range, mapping->range.Base()) &&
|
||||
if (parsed_module->Initialize(
|
||||
range, mapping->range.Base(), possible_mappings->Count() == 0) &&
|
||||
parsed_module->GetDynamicArrayAddress(&dynamic_address) &&
|
||||
dynamic_address == module.dynamic_array) {
|
||||
module_reader = std::move(parsed_module);
|
||||
|
@ -439,7 +439,7 @@ void ProcessReaderLinux::InitializeModules() {
|
||||
if (parsed_exe->Initialize(
|
||||
range,
|
||||
mapping->range.Base(),
|
||||
/* verbose= */ possible_mappings->Count() == 1) &&
|
||||
/* verbose= */ possible_mappings->Count() == 0) &&
|
||||
parsed_exe->GetProgramHeaderTableAddress() == phdrs) {
|
||||
exe_mapping = mapping;
|
||||
exe_reader = std::move(parsed_exe);
|
||||
@ -508,7 +508,7 @@ void ProcessReaderLinux::InitializeModules() {
|
||||
if (parsed_module->Initialize(
|
||||
range,
|
||||
mapping->range.Base(),
|
||||
/* verbose= */ possible_mappings->Count() == 1) &&
|
||||
/* verbose= */ possible_mappings->Count() == 0) &&
|
||||
parsed_module->GetDynamicArrayAddress(&dynamic_address) &&
|
||||
dynamic_address == entry.dynamic_array) {
|
||||
module_mapping = mapping;
|
||||
|
@ -491,23 +491,29 @@ int ExpectFindModule(dl_phdr_info* info, size_t size, void* data) {
|
||||
auto modules =
|
||||
reinterpret_cast<const std::vector<ProcessReaderLinux::Module>*>(data);
|
||||
|
||||
auto phdr_addr = FromPointerCast<LinuxVMAddress>(info->dlpi_phdr);
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
// Bionic includes a null entry.
|
||||
if (!phdr_addr) {
|
||||
EXPECT_EQ(info->dlpi_name, nullptr);
|
||||
// Prior to API 27, Bionic includes a null entry for /system/bin/linker.
|
||||
if (!info->dlpi_name) {
|
||||
EXPECT_EQ(info->dlpi_addr, 0u);
|
||||
EXPECT_EQ(info->dlpi_phnum, 0u);
|
||||
EXPECT_EQ(info->dlpi_phdr, nullptr);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Bionic doesn't always set both of these addresses for the vdso and
|
||||
// /system/bin/linker, but it does always set one of them.
|
||||
VMAddress module_addr = info->dlpi_phdr
|
||||
? FromPointerCast<LinuxVMAddress>(info->dlpi_phdr)
|
||||
: info->dlpi_addr;
|
||||
|
||||
// TODO(jperaza): This can use a range map when one is available.
|
||||
bool found = false;
|
||||
for (const auto& module : *modules) {
|
||||
if (module.elf_reader && phdr_addr >= module.elf_reader->Address() &&
|
||||
phdr_addr < module.elf_reader->Address() + module.elf_reader->Size()) {
|
||||
if (module.elf_reader && module_addr >= module.elf_reader->Address() &&
|
||||
module_addr <
|
||||
module.elf_reader->Address() + module.elf_reader->Size()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@ -702,11 +708,14 @@ bool WriteTestModule(const base::FilePath& module_path,
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user