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:
Joshua Peraza 2020-06-04 17:31:52 -07:00 committed by Commit Bot
parent 294d233ca0
commit 7a70b0f151
4 changed files with 37 additions and 11 deletions

View File

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

View File

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

View File

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

View File

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