mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
ios: Use fewer vm_reads when iterating modules.
Rather than vm_reading each individual module load_command, load all of the commands at once. This saves nearly 200ms on an iPhone 12 Pro. Change-Id: I06f56c3ecbdf74f78759648ea62bcccd027f304c Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3764242 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Justin Cohen <justincohen@chromium.org>
This commit is contained in:
parent
df86075acc
commit
ae7d8a9ba4
@ -1053,68 +1053,63 @@ void InProcessIntermediateDumpHandler::WriteModuleInfoAtAddress(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const load_command* command_ptr = reinterpret_cast<const load_command*>(
|
const load_command* unsafe_command_ptr =
|
||||||
|
reinterpret_cast<const load_command*>(
|
||||||
reinterpret_cast<const mach_header_64*>(address) + 1);
|
reinterpret_cast<const mach_header_64*>(address) + 1);
|
||||||
|
|
||||||
ScopedVMRead<load_command> command;
|
// Rather than using an individual ScopedVMRead for each load_command, load
|
||||||
if (!command.Read(command_ptr)) {
|
// the entire block of commands at once.
|
||||||
CRASHPAD_RAW_LOG("Invalid module command");
|
ScopedVMRead<char> all_commands;
|
||||||
|
if (!all_commands.Read(unsafe_command_ptr, header->sizeofcmds)) {
|
||||||
|
CRASHPAD_RAW_LOG("Unable to read module load_commands.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All the *_vm_read_ptr variables in the load_command loop below have been
|
||||||
|
// vm_read in `all_commands` above, and may be dereferenced without additional
|
||||||
|
// ScopedVMReads.
|
||||||
|
const load_command* command_vm_read_ptr =
|
||||||
|
reinterpret_cast<const load_command*>(all_commands.get());
|
||||||
|
|
||||||
// Make sure that the basic load command structure doesn’t overflow the
|
// Make sure that the basic load command structure doesn’t overflow the
|
||||||
// space allotted for load commands, as well as iterating through ncmds.
|
// space allotted for load commands, as well as iterating through ncmds.
|
||||||
vm_size_t slide = 0;
|
vm_size_t slide = 0;
|
||||||
for (uint32_t cmd_index = 0, cumulative_cmd_size = 0;
|
for (uint32_t cmd_index = 0, cumulative_cmd_size = 0;
|
||||||
cmd_index <= header->ncmds && cumulative_cmd_size < header->sizeofcmds;
|
cmd_index < header->ncmds && cumulative_cmd_size < header->sizeofcmds;
|
||||||
++cmd_index, cumulative_cmd_size += command->cmdsize) {
|
++cmd_index) {
|
||||||
if (command->cmd == LC_SEGMENT_64) {
|
if (command_vm_read_ptr->cmd == LC_SEGMENT_64) {
|
||||||
ScopedVMRead<segment_command_64> segment;
|
const segment_command_64* segment_vm_read_ptr =
|
||||||
if (!segment.Read(command_ptr)) {
|
reinterpret_cast<const segment_command_64*>(command_vm_read_ptr);
|
||||||
CRASHPAD_RAW_LOG("Invalid LC_SEGMENT_64 segment");
|
if (strcmp(segment_vm_read_ptr->segname, SEG_TEXT) == 0) {
|
||||||
return;
|
WriteProperty(
|
||||||
}
|
writer, IntermediateDumpKey::kSize, &segment_vm_read_ptr->vmsize);
|
||||||
const segment_command_64* segment_ptr =
|
slide = address - segment_vm_read_ptr->vmaddr;
|
||||||
reinterpret_cast<const segment_command_64*>(command_ptr);
|
} else if (strcmp(segment_vm_read_ptr->segname, SEG_DATA) == 0) {
|
||||||
if (strcmp(segment->segname, SEG_TEXT) == 0) {
|
WriteDataSegmentAnnotations(writer, segment_vm_read_ptr, slide);
|
||||||
WriteProperty(writer, IntermediateDumpKey::kSize, &segment->vmsize);
|
|
||||||
slide = address - segment->vmaddr;
|
|
||||||
} else if (strcmp(segment->segname, SEG_DATA) == 0) {
|
|
||||||
WriteDataSegmentAnnotations(writer, segment_ptr, slide);
|
|
||||||
}
|
|
||||||
} else if (command->cmd == LC_ID_DYLIB) {
|
|
||||||
ScopedVMRead<dylib_command> dylib;
|
|
||||||
if (!dylib.Read(command_ptr)) {
|
|
||||||
CRASHPAD_RAW_LOG("Invalid LC_ID_DYLIB segment");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} else if (command_vm_read_ptr->cmd == LC_ID_DYLIB) {
|
||||||
|
const dylib_command* dylib_vm_read_ptr =
|
||||||
|
reinterpret_cast<const dylib_command*>(command_vm_read_ptr);
|
||||||
WriteProperty(writer,
|
WriteProperty(writer,
|
||||||
IntermediateDumpKey::kDylibCurrentVersion,
|
IntermediateDumpKey::kDylibCurrentVersion,
|
||||||
&dylib->dylib.current_version);
|
&dylib_vm_read_ptr->dylib.current_version);
|
||||||
} else if (command->cmd == LC_SOURCE_VERSION) {
|
} else if (command_vm_read_ptr->cmd == LC_SOURCE_VERSION) {
|
||||||
ScopedVMRead<source_version_command> source_version;
|
const source_version_command* source_version_vm_read_ptr =
|
||||||
if (!source_version.Read(command_ptr)) {
|
reinterpret_cast<const source_version_command*>(command_vm_read_ptr);
|
||||||
CRASHPAD_RAW_LOG("Invalid LC_SOURCE_VERSION segment");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
WriteProperty(writer,
|
WriteProperty(writer,
|
||||||
IntermediateDumpKey::kSourceVersion,
|
IntermediateDumpKey::kSourceVersion,
|
||||||
&source_version->version);
|
&source_version_vm_read_ptr->version);
|
||||||
} else if (command->cmd == LC_UUID) {
|
} else if (command_vm_read_ptr->cmd == LC_UUID) {
|
||||||
ScopedVMRead<uuid_command> uuid;
|
const uuid_command* uuid_vm_read_ptr =
|
||||||
if (!uuid.Read(command_ptr)) {
|
reinterpret_cast<const uuid_command*>(command_vm_read_ptr);
|
||||||
CRASHPAD_RAW_LOG("Invalid LC_UUID segment");
|
WriteProperty(
|
||||||
return;
|
writer, IntermediateDumpKey::kUUID, &uuid_vm_read_ptr->uuid);
|
||||||
}
|
|
||||||
WriteProperty(writer, IntermediateDumpKey::kUUID, &uuid->uuid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
command_ptr = reinterpret_cast<const load_command*>(
|
cumulative_cmd_size += command_vm_read_ptr->cmdsize;
|
||||||
reinterpret_cast<const uint8_t*>(command_ptr) + command->cmdsize);
|
command_vm_read_ptr = reinterpret_cast<const load_command*>(
|
||||||
if (!command.Read(command_ptr)) {
|
reinterpret_cast<const uint8_t*>(command_vm_read_ptr) +
|
||||||
CRASHPAD_RAW_LOG("Invalid module command");
|
command_vm_read_ptr->cmdsize);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteProperty(writer, IntermediateDumpKey::kFileType, &header->filetype);
|
WriteProperty(writer, IntermediateDumpKey::kFileType, &header->filetype);
|
||||||
@ -1122,40 +1117,32 @@ void InProcessIntermediateDumpHandler::WriteModuleInfoAtAddress(
|
|||||||
|
|
||||||
void InProcessIntermediateDumpHandler::WriteDataSegmentAnnotations(
|
void InProcessIntermediateDumpHandler::WriteDataSegmentAnnotations(
|
||||||
IOSIntermediateDumpWriter* writer,
|
IOSIntermediateDumpWriter* writer,
|
||||||
const segment_command_64* segment_ptr,
|
const segment_command_64* segment_vm_read_ptr,
|
||||||
vm_size_t slide) {
|
vm_size_t slide) {
|
||||||
ScopedVMRead<segment_command_64> segment;
|
const section_64* section_vm_read_ptr = reinterpret_cast<const section_64*>(
|
||||||
if (!segment.Read(segment_ptr)) {
|
reinterpret_cast<uint64_t>(segment_vm_read_ptr) +
|
||||||
CRASHPAD_RAW_LOG("Unable to read SEG_DATA.");
|
sizeof(segment_command_64));
|
||||||
return;
|
for (uint32_t sect_index = 0; sect_index <= segment_vm_read_ptr->nsects;
|
||||||
}
|
++sect_index) {
|
||||||
const section_64* section_ptr = reinterpret_cast<const section_64*>(
|
if (strcmp(section_vm_read_ptr->sectname, "crashpad_info") == 0) {
|
||||||
reinterpret_cast<uint64_t>(segment_ptr) + sizeof(segment_command_64));
|
|
||||||
for (uint32_t sect_index = 0; sect_index <= segment->nsects; ++sect_index) {
|
|
||||||
ScopedVMRead<section_64> section;
|
|
||||||
if (!section.Read(section_ptr)) {
|
|
||||||
CRASHPAD_RAW_LOG("Unable to read SEG_DATA section.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (strcmp(section->sectname, "crashpad_info") == 0) {
|
|
||||||
ScopedVMRead<CrashpadInfo> crashpad_info;
|
ScopedVMRead<CrashpadInfo> crashpad_info;
|
||||||
if (crashpad_info.Read(section->addr + slide) &&
|
if (crashpad_info.Read(section_vm_read_ptr->addr + slide) &&
|
||||||
crashpad_info->size() == sizeof(CrashpadInfo) &&
|
crashpad_info->size() == sizeof(CrashpadInfo) &&
|
||||||
crashpad_info->signature() == CrashpadInfo::kSignature &&
|
crashpad_info->signature() == CrashpadInfo::kSignature &&
|
||||||
crashpad_info->version() == 1) {
|
crashpad_info->version() == 1) {
|
||||||
WriteCrashpadAnnotationsList(writer, crashpad_info.get());
|
WriteCrashpadAnnotationsList(writer, crashpad_info.get());
|
||||||
WriteCrashpadSimpleAnnotationsDictionary(writer, crashpad_info.get());
|
WriteCrashpadSimpleAnnotationsDictionary(writer, crashpad_info.get());
|
||||||
}
|
}
|
||||||
} else if (strcmp(section->sectname, "__crash_info") == 0) {
|
} else if (strcmp(section_vm_read_ptr->sectname, "__crash_info") == 0) {
|
||||||
ScopedVMRead<crashreporter_annotations_t> crash_info;
|
ScopedVMRead<crashreporter_annotations_t> crash_info;
|
||||||
if (!crash_info.Read(section->addr + slide) ||
|
if (!crash_info.Read(section_vm_read_ptr->addr + slide) ||
|
||||||
(crash_info->version != 4 && crash_info->version != 5)) {
|
(crash_info->version != 4 && crash_info->version != 5)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
WriteAppleCrashReporterAnnotations(writer, crash_info.get());
|
WriteAppleCrashReporterAnnotations(writer, crash_info.get());
|
||||||
}
|
}
|
||||||
section_ptr = reinterpret_cast<const section_64*>(
|
section_vm_read_ptr = reinterpret_cast<const section_64*>(
|
||||||
reinterpret_cast<uint64_t>(section_ptr) + sizeof(section_64));
|
reinterpret_cast<uint64_t>(section_vm_read_ptr) + sizeof(section_64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,9 +139,11 @@ class InProcessIntermediateDumpHandler final {
|
|||||||
bool is_dyld);
|
bool is_dyld);
|
||||||
|
|
||||||
//! \brief Extract and write Apple crashreporter_annotations_t data and
|
//! \brief Extract and write Apple crashreporter_annotations_t data and
|
||||||
//! Crashpad annotations.
|
//! Crashpad annotations. Note that \a segment_vm_read_ptr has already
|
||||||
static void WriteDataSegmentAnnotations(IOSIntermediateDumpWriter* writer,
|
//! been read via vm_read and may be dereferenced without a ScopedVMRead.
|
||||||
const segment_command_64* segment_ptr,
|
static void WriteDataSegmentAnnotations(
|
||||||
|
IOSIntermediateDumpWriter* writer,
|
||||||
|
const segment_command_64* segment_vm_read_ptr,
|
||||||
vm_size_t slide);
|
vm_size_t slide);
|
||||||
|
|
||||||
//! \brief Write Crashpad annotations list.
|
//! \brief Write Crashpad annotations list.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user