mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-10-20 07:28:23 +02:00
Allow to retrieve id of a module from memory instead of going to disk for iOS.
Allow macho_id and macho_walker to read data from memory. Wire up this when reading module on iOS. Review URL: http://breakpad.appspot.com/319001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@873 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
05829315f0
commit
446616ee22
@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
#include "client/minidump_file_writer-inl.h"
|
#include "client/minidump_file_writer-inl.h"
|
||||||
#include "common/mac/file_id.h"
|
#include "common/mac/file_id.h"
|
||||||
|
#include "common/mac/macho_id.h"
|
||||||
#include "common/mac/string_utilities.h"
|
#include "common/mac/string_utilities.h"
|
||||||
|
|
||||||
using MacStringUtils::ConvertToString;
|
using MacStringUtils::ConvertToString;
|
||||||
@ -1160,7 +1161,7 @@ bool MinidumpGenerator::WriteModuleStream(unsigned int index,
|
|||||||
module->version_info.file_version_lo |= (modVersion & 0xff);
|
module->version_info.file_version_lo |= (modVersion & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteCVRecord(module, image->GetCPUType(), name.c_str())) {
|
if (!WriteCVRecord(module, image->GetCPUType(), name.c_str(), false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1206,7 +1207,11 @@ bool MinidumpGenerator::WriteModuleStream(unsigned int index,
|
|||||||
module->size_of_image = static_cast<u_int32_t>(seg->vmsize);
|
module->size_of_image = static_cast<u_int32_t>(seg->vmsize);
|
||||||
module->module_name_rva = string_location.rva;
|
module->module_name_rva = string_location.rva;
|
||||||
|
|
||||||
if (!WriteCVRecord(module, cpu_type, name))
|
bool in_memory = false;
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
in_memory = true;
|
||||||
|
#endif
|
||||||
|
if (!WriteCVRecord(module, cpu_type, name, in_memory))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1244,7 +1249,7 @@ int MinidumpGenerator::FindExecutableModule() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MinidumpGenerator::WriteCVRecord(MDRawModule *module, int cpu_type,
|
bool MinidumpGenerator::WriteCVRecord(MDRawModule *module, int cpu_type,
|
||||||
const char *module_path) {
|
const char *module_path, bool in_memory) {
|
||||||
TypedMDRVA<MDCVInfoPDB70> cv(&writer_);
|
TypedMDRVA<MDCVInfoPDB70> cv(&writer_);
|
||||||
|
|
||||||
// Only return the last path component of the full module path
|
// Only return the last path component of the full module path
|
||||||
@ -1270,10 +1275,23 @@ bool MinidumpGenerator::WriteCVRecord(MDRawModule *module, int cpu_type,
|
|||||||
cv_ptr->age = 0;
|
cv_ptr->age = 0;
|
||||||
|
|
||||||
// Get the module identifier
|
// Get the module identifier
|
||||||
FileID file_id(module_path);
|
|
||||||
unsigned char identifier[16];
|
unsigned char identifier[16];
|
||||||
|
bool result = false;
|
||||||
|
if (in_memory) {
|
||||||
|
MacFileUtilities::MachoID macho(module_path,
|
||||||
|
reinterpret_cast<void *>(module->base_of_image),
|
||||||
|
static_cast<size_t>(module->size_of_image));
|
||||||
|
result = macho.UUIDCommand(cpu_type, identifier);
|
||||||
|
if (!result)
|
||||||
|
result = macho.MD5(cpu_type, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
if (file_id.MachoIdentifier(cpu_type, identifier)) {
|
if (!result) {
|
||||||
|
FileID file_id(module_path);
|
||||||
|
result = file_id.MachoIdentifier(cpu_type, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 |
|
cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 |
|
||||||
(uint32_t)identifier[1] << 16 | (uint32_t)identifier[2] << 8 |
|
(uint32_t)identifier[1] << 16 | (uint32_t)identifier[2] << 8 |
|
||||||
(uint32_t)identifier[3];
|
(uint32_t)identifier[3];
|
||||||
|
@ -128,8 +128,8 @@ class MinidumpGenerator {
|
|||||||
bool WriteContext(breakpad_thread_state_data_t state,
|
bool WriteContext(breakpad_thread_state_data_t state,
|
||||||
MDLocationDescriptor *register_location);
|
MDLocationDescriptor *register_location);
|
||||||
bool WriteThreadStream(mach_port_t thread_id, MDRawThread *thread);
|
bool WriteThreadStream(mach_port_t thread_id, MDRawThread *thread);
|
||||||
bool WriteCVRecord(MDRawModule *module, int cpu_type,
|
bool WriteCVRecord(MDRawModule *module, int cpu_type,
|
||||||
const char *module_path);
|
const char *module_path, bool in_memory);
|
||||||
bool WriteModuleStream(unsigned int index, MDRawModule *module);
|
bool WriteModuleStream(unsigned int index, MDRawModule *module);
|
||||||
size_t CalculateStackSize(mach_vm_address_t start_addr);
|
size_t CalculateStackSize(mach_vm_address_t start_addr);
|
||||||
int FindExecutableModule();
|
int FindExecutableModule();
|
||||||
|
@ -52,17 +52,24 @@ extern "C" { // necessary for Leopard
|
|||||||
namespace MacFileUtilities {
|
namespace MacFileUtilities {
|
||||||
|
|
||||||
MachoID::MachoID(const char *path)
|
MachoID::MachoID(const char *path)
|
||||||
: file_(0),
|
: memory_(0),
|
||||||
|
memory_size_(0),
|
||||||
|
crc_(0),
|
||||||
|
md5_context_(),
|
||||||
|
update_function_(NULL) {
|
||||||
|
strlcpy(path_, path, sizeof(path_));
|
||||||
|
}
|
||||||
|
|
||||||
|
MachoID::MachoID(const char *path, void *memory, size_t size)
|
||||||
|
: memory_(memory),
|
||||||
|
memory_size_(size),
|
||||||
crc_(0),
|
crc_(0),
|
||||||
md5_context_(),
|
md5_context_(),
|
||||||
update_function_(NULL) {
|
update_function_(NULL) {
|
||||||
strlcpy(path_, path, sizeof(path_));
|
strlcpy(path_, path, sizeof(path_));
|
||||||
file_ = open(path, O_RDONLY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MachoID::~MachoID() {
|
MachoID::~MachoID() {
|
||||||
if (file_ != -1)
|
|
||||||
close(file_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The CRC info is from http://en.wikipedia.org/wiki/Adler-32
|
// The CRC info is from http://en.wikipedia.org/wiki/Adler-32
|
||||||
@ -144,10 +151,8 @@ void MachoID::Update(MachoWalker *walker, off_t offset, size_t size) {
|
|||||||
|
|
||||||
bool MachoID::UUIDCommand(int cpu_type, unsigned char bytes[16]) {
|
bool MachoID::UUIDCommand(int cpu_type, unsigned char bytes[16]) {
|
||||||
struct breakpad_uuid_command uuid_cmd;
|
struct breakpad_uuid_command uuid_cmd;
|
||||||
MachoWalker walker(path_, UUIDWalkerCB, &uuid_cmd);
|
|
||||||
|
|
||||||
uuid_cmd.cmd = 0;
|
uuid_cmd.cmd = 0;
|
||||||
if (!walker.WalkHeader(cpu_type))
|
if (!WalkHeader(cpu_type, UUIDWalkerCB, &uuid_cmd))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If we found the command, we'll have initialized the uuid_command
|
// If we found the command, we'll have initialized the uuid_command
|
||||||
@ -162,10 +167,8 @@ bool MachoID::UUIDCommand(int cpu_type, unsigned char bytes[16]) {
|
|||||||
|
|
||||||
bool MachoID::IDCommand(int cpu_type, unsigned char identifier[16]) {
|
bool MachoID::IDCommand(int cpu_type, unsigned char identifier[16]) {
|
||||||
struct dylib_command dylib_cmd;
|
struct dylib_command dylib_cmd;
|
||||||
MachoWalker walker(path_, IDWalkerCB, &dylib_cmd);
|
|
||||||
|
|
||||||
dylib_cmd.cmd = 0;
|
dylib_cmd.cmd = 0;
|
||||||
if (!walker.WalkHeader(cpu_type))
|
if (!WalkHeader(cpu_type, IDWalkerCB, &dylib_cmd))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If we found the command, we'll have initialized the dylib_command
|
// If we found the command, we'll have initialized the dylib_command
|
||||||
@ -204,29 +207,39 @@ bool MachoID::IDCommand(int cpu_type, unsigned char identifier[16]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MachoID::Adler32(int cpu_type) {
|
uint32_t MachoID::Adler32(int cpu_type) {
|
||||||
MachoWalker walker(path_, WalkerCB, this);
|
|
||||||
update_function_ = &MachoID::UpdateCRC;
|
update_function_ = &MachoID::UpdateCRC;
|
||||||
crc_ = 0;
|
crc_ = 0;
|
||||||
|
|
||||||
if (!walker.WalkHeader(cpu_type))
|
if (!WalkHeader(cpu_type, WalkerCB, this))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return crc_;
|
return crc_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MachoID::MD5(int cpu_type, unsigned char identifier[16]) {
|
bool MachoID::MD5(int cpu_type, unsigned char identifier[16]) {
|
||||||
MachoWalker walker(path_, WalkerCB, this);
|
|
||||||
update_function_ = &MachoID::UpdateMD5;
|
update_function_ = &MachoID::UpdateMD5;
|
||||||
|
|
||||||
MD5Init(&md5_context_);
|
MD5Init(&md5_context_);
|
||||||
|
|
||||||
if (!walker.WalkHeader(cpu_type))
|
if (!WalkHeader(cpu_type, WalkerCB, this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MD5Final(identifier, &md5_context_);
|
MD5Final(identifier, &md5_context_);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MachoID::WalkHeader(int cpu_type,
|
||||||
|
MachoWalker::LoadCommandCallback callback,
|
||||||
|
void *context) {
|
||||||
|
if (memory_) {
|
||||||
|
MachoWalker walker(memory_, memory_size_, callback, context);
|
||||||
|
return walker.WalkHeader(cpu_type);
|
||||||
|
} else {
|
||||||
|
MachoWalker walker(path_, callback, context);
|
||||||
|
return walker.WalkHeader(cpu_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
|
bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
|
||||||
bool swap, void *context) {
|
bool swap, void *context) {
|
||||||
|
@ -37,15 +37,15 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <mach-o/loader.h>
|
#include <mach-o/loader.h>
|
||||||
|
|
||||||
|
#include "common/mac/macho_walker.h"
|
||||||
#include "common/md5.h"
|
#include "common/md5.h"
|
||||||
|
|
||||||
namespace MacFileUtilities {
|
namespace MacFileUtilities {
|
||||||
|
|
||||||
class MachoWalker;
|
|
||||||
|
|
||||||
class MachoID {
|
class MachoID {
|
||||||
public:
|
public:
|
||||||
MachoID(const char *path);
|
MachoID(const char *path);
|
||||||
|
MachoID(const char *path, void *memory, size_t size);
|
||||||
~MachoID();
|
~MachoID();
|
||||||
|
|
||||||
// For the given |cpu_type|, return a UUID from the LC_UUID command.
|
// For the given |cpu_type|, return a UUID from the LC_UUID command.
|
||||||
@ -80,6 +80,10 @@ class MachoID {
|
|||||||
// Bottleneck for update routines
|
// Bottleneck for update routines
|
||||||
void Update(MachoWalker *walker, off_t offset, size_t size);
|
void Update(MachoWalker *walker, off_t offset, size_t size);
|
||||||
|
|
||||||
|
// Factory for the MachoWalker
|
||||||
|
bool WalkHeader(int cpu_type, MachoWalker::LoadCommandCallback callback,
|
||||||
|
void *context);
|
||||||
|
|
||||||
// The callback from the MachoWalker for CRC and MD5
|
// The callback from the MachoWalker for CRC and MD5
|
||||||
static bool WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
|
static bool WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
|
||||||
bool swap, void *context);
|
bool swap, void *context);
|
||||||
@ -95,8 +99,11 @@ class MachoID {
|
|||||||
// File path
|
// File path
|
||||||
char path_[PATH_MAX];
|
char path_[PATH_MAX];
|
||||||
|
|
||||||
// File descriptor
|
// Memory region to read from
|
||||||
int file_;
|
void *memory_;
|
||||||
|
|
||||||
|
// Size of the memory region
|
||||||
|
size_t memory_size_;
|
||||||
|
|
||||||
// The current crc value
|
// The current crc value
|
||||||
uint32_t crc_;
|
uint32_t crc_;
|
||||||
|
@ -52,6 +52,8 @@ namespace MacFileUtilities {
|
|||||||
MachoWalker::MachoWalker(const char *path, LoadCommandCallback callback,
|
MachoWalker::MachoWalker(const char *path, LoadCommandCallback callback,
|
||||||
void *context)
|
void *context)
|
||||||
: file_(0),
|
: file_(0),
|
||||||
|
memory_(NULL),
|
||||||
|
memory_size_(0),
|
||||||
callback_(callback),
|
callback_(callback),
|
||||||
callback_context_(context),
|
callback_context_(context),
|
||||||
current_header_(NULL),
|
current_header_(NULL),
|
||||||
@ -60,6 +62,18 @@ MachoWalker::MachoWalker(const char *path, LoadCommandCallback callback,
|
|||||||
file_ = open(path, O_RDONLY);
|
file_ = open(path, O_RDONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MachoWalker::MachoWalker(void *memory, size_t size,
|
||||||
|
LoadCommandCallback callback, void *context)
|
||||||
|
: file_(0),
|
||||||
|
memory_(memory),
|
||||||
|
memory_size_(size),
|
||||||
|
callback_(callback),
|
||||||
|
callback_context_(context),
|
||||||
|
current_header_(NULL),
|
||||||
|
current_header_size_(0),
|
||||||
|
current_header_offset_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
MachoWalker::~MachoWalker() {
|
MachoWalker::~MachoWalker() {
|
||||||
if (file_ != -1)
|
if (file_ != -1)
|
||||||
close(file_);
|
close(file_);
|
||||||
@ -90,7 +104,19 @@ bool MachoWalker::WalkHeader(int cpu_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MachoWalker::ReadBytes(void *buffer, size_t size, off_t offset) {
|
bool MachoWalker::ReadBytes(void *buffer, size_t size, off_t offset) {
|
||||||
return pread(file_, buffer, size, offset) == (ssize_t)size;
|
if (memory_) {
|
||||||
|
bool result = true;
|
||||||
|
if (offset + size > memory_size_) {
|
||||||
|
size = memory_size_ - offset;
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
if (size < 0)
|
||||||
|
return false;
|
||||||
|
memcpy(buffer, static_cast<char *>(memory_) + offset, size);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return pread(file_, buffer, size, offset) == (ssize_t)size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MachoWalker::CurrentHeader(struct mach_header_64 *header, off_t *offset) {
|
bool MachoWalker::CurrentHeader(struct mach_header_64 *header, off_t *offset) {
|
||||||
|
@ -52,7 +52,8 @@ class MachoWalker {
|
|||||||
off_t offset, bool swap, void *context);
|
off_t offset, bool swap, void *context);
|
||||||
|
|
||||||
MachoWalker(const char *path, LoadCommandCallback callback, void *context);
|
MachoWalker(const char *path, LoadCommandCallback callback, void *context);
|
||||||
MachoWalker(int file_descriptor, LoadCommandCallback callback, void *context);
|
MachoWalker(void *memory, size_t size, LoadCommandCallback callback,
|
||||||
|
void *context);
|
||||||
~MachoWalker();
|
~MachoWalker();
|
||||||
|
|
||||||
// Begin walking the header for |cpu_type|. If |cpu_type| is 0, then the
|
// Begin walking the header for |cpu_type|. If |cpu_type| is 0, then the
|
||||||
@ -68,7 +69,7 @@ class MachoWalker {
|
|||||||
|
|
||||||
// Read |size| bytes from the opened file at |offset| into |buffer|
|
// Read |size| bytes from the opened file at |offset| into |buffer|
|
||||||
bool ReadBytes(void *buffer, size_t size, off_t offset);
|
bool ReadBytes(void *buffer, size_t size, off_t offset);
|
||||||
|
|
||||||
// Return the current header and header offset
|
// Return the current header and header offset
|
||||||
bool CurrentHeader(struct mach_header_64 *header, off_t *offset);
|
bool CurrentHeader(struct mach_header_64 *header, off_t *offset);
|
||||||
|
|
||||||
@ -87,19 +88,25 @@ class MachoWalker {
|
|||||||
// File descriptor to the opened file
|
// File descriptor to the opened file
|
||||||
int file_;
|
int file_;
|
||||||
|
|
||||||
|
// Memory location to read from.
|
||||||
|
void *memory_;
|
||||||
|
|
||||||
|
// Size of the memory segment we can read from.
|
||||||
|
size_t memory_size_;
|
||||||
|
|
||||||
// User specified callback & context
|
// User specified callback & context
|
||||||
LoadCommandCallback callback_;
|
LoadCommandCallback callback_;
|
||||||
void *callback_context_;
|
void *callback_context_;
|
||||||
|
|
||||||
// Current header, size, and offset. The mach_header_64 is used for both
|
// Current header, size, and offset. The mach_header_64 is used for both
|
||||||
// 32-bit and 64-bit headers because they only differ in their last field
|
// 32-bit and 64-bit headers because they only differ in their last field
|
||||||
// (reserved). By adding the |current_header_size_| and the
|
// (reserved). By adding the |current_header_size_| and the
|
||||||
// |current_header_offset_|, you can determine the offset in the file just
|
// |current_header_offset_|, you can determine the offset in the file just
|
||||||
// after the header.
|
// after the header.
|
||||||
struct mach_header_64 *current_header_;
|
struct mach_header_64 *current_header_;
|
||||||
unsigned long current_header_size_;
|
unsigned long current_header_size_;
|
||||||
off_t current_header_offset_;
|
off_t current_header_offset_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MachoWalker(const MachoWalker &);
|
MachoWalker(const MachoWalker &);
|
||||||
MachoWalker &operator=(const MachoWalker &);
|
MachoWalker &operator=(const MachoWalker &);
|
||||||
|
Loading…
Reference in New Issue
Block a user