aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorwaylonis <waylonis@4c0a9323-5329-0410-9bdc-e9ce6186880e>2007-02-07 18:57:09 +0000
committerwaylonis <waylonis@4c0a9323-5329-0410-9bdc-e9ce6186880e>2007-02-07 18:57:09 +0000
commit983264848d5372d8e64d62eb67f672c71e4b6470 (patch)
treef5d496832a6a4e0c85b701c36778885d333828b5 /src/common
parentStore 128-bit values as a struct with high and low fields, so that consumers (diff)
downloadbreakpad-983264848d5372d8e64d62eb67f672c71e4b6470.tar.xz
Fix bug with mach-o walker not properly walking universal binary (Issue #125)
Fix exception handler so that it will properly forward exceptions (Issue #126) r=mmentovai git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@119 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common')
-rw-r--r--src/common/mac/macho_id.cc17
-rw-r--r--src/common/mac/macho_walker.cc39
-rw-r--r--src/common/mac/macho_walker.h12
3 files changed, 63 insertions, 5 deletions
diff --git a/src/common/mac/macho_id.cc b/src/common/mac/macho_id.cc
index ca155ed4..59cd1e21 100644
--- a/src/common/mac/macho_id.cc
+++ b/src/common/mac/macho_id.cc
@@ -39,6 +39,7 @@
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -246,6 +247,12 @@ bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
if (swap)
swap_segment_command(&seg, NXHostByteOrder());
+ struct mach_header_64 header;
+ off_t header_offset;
+
+ if (!walker->CurrentHeader(&header, &header_offset))
+ return false;
+
// Process segments that have sections:
// (e.g., __TEXT, __DATA, __IMPORT, __OBJC)
offset += sizeof(struct segment_command);
@@ -257,7 +264,7 @@ bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
if (swap)
swap_section(&sec, 1, NXHostByteOrder());
- macho_id->Update(walker, sec.offset, sec.size);
+ macho_id->Update(walker, header_offset + sec.offset, sec.size);
offset += sizeof(struct section);
}
} else if (cmd->cmd == LC_SEGMENT_64) {
@@ -269,6 +276,12 @@ bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
if (swap)
swap_segment_command_64(&seg64, NXHostByteOrder());
+ struct mach_header_64 header;
+ off_t header_offset;
+
+ if (!walker->CurrentHeader(&header, &header_offset))
+ return false;
+
// Process segments that have sections:
// (e.g., __TEXT, __DATA, __IMPORT, __OBJC)
offset += sizeof(struct segment_command_64);
@@ -280,7 +293,7 @@ bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
if (swap)
swap_section_64(&sec64, 1, NXHostByteOrder());
- macho_id->Update(walker, sec64.offset, sec64.size);
+ macho_id->Update(walker, header_offset + sec64.offset, sec64.size);
offset += sizeof(struct section_64);
}
}
diff --git a/src/common/mac/macho_walker.cc b/src/common/mac/macho_walker.cc
index 5e9de5f4..81ba3bb5 100644
--- a/src/common/mac/macho_walker.cc
+++ b/src/common/mac/macho_walker.cc
@@ -38,6 +38,7 @@
#include <mach-o/arch.h>
#include <mach-o/loader.h>
#include <mach-o/swap.h>
+#include <string.h>
#include <unistd.h>
#include "common/mac/macho_walker.h"
@@ -93,6 +94,16 @@ bool MachoWalker::ReadBytes(void *buffer, size_t size, off_t offset) {
return pread(file_, buffer, size, offset) == (ssize_t)size;
}
+bool MachoWalker::CurrentHeader(struct mach_header_64 *header, off_t *offset) {
+ if (current_header_) {
+ memcpy(header, current_header_, sizeof(mach_header_64));
+ *offset = current_header_offset_;
+ return true;
+ }
+
+ return false;
+}
+
bool MachoWalker::FindHeader(int cpu_type, off_t &offset) {
int valid_cpu_type = ValidateCPUType(cpu_type);
// Read the magic bytes that's common amongst all mach-o files
@@ -165,8 +176,22 @@ bool MachoWalker::WalkHeaderAtOffset(off_t offset) {
bool swap = (header.magic == MH_CIGAM);
if (swap)
swap_mach_header(&header, NXHostByteOrder());
-
- return WalkHeaderCore(offset + sizeof(header), header.ncmds, swap);
+
+ // Copy the data into the mach_header_64 structure. Since the 32-bit and
+ // 64-bit only differ in the last field (reserved), this is safe to do.
+ struct mach_header_64 header64;
+ memcpy((void *)&header64, (const void *)&header, sizeof(header));
+ header64.reserved = 0;
+
+ current_header_ = &header64;
+ current_header_size_ = sizeof(header); // 32-bit, not 64-bit
+ current_header_offset_ = offset;
+ offset += current_header_size_;
+ bool result = WalkHeaderCore(offset, header.ncmds, swap);
+ current_header_ = NULL;
+ current_header_size_ = 0;
+ current_header_offset_ = 0;
+ return result;
}
bool MachoWalker::WalkHeader64AtOffset(off_t offset) {
@@ -178,7 +203,15 @@ bool MachoWalker::WalkHeader64AtOffset(off_t offset) {
if (swap)
swap_mach_header_64(&header, NXHostByteOrder());
- return WalkHeaderCore(offset + sizeof(header), header.ncmds, swap);
+ current_header_ = &header;
+ current_header_size_ = sizeof(header);
+ current_header_offset_ = offset;
+ offset += current_header_size_;
+ bool result = WalkHeaderCore(offset, header.ncmds, swap);
+ current_header_ = NULL;
+ current_header_size_ = 0;
+ current_header_offset_ = 0;
+ return result;
}
bool MachoWalker::WalkHeaderCore(off_t offset, uint32_t number_of_commands,
diff --git a/src/common/mac/macho_walker.h b/src/common/mac/macho_walker.h
index 0d55dd79..eb9575b0 100644
--- a/src/common/mac/macho_walker.h
+++ b/src/common/mac/macho_walker.h
@@ -68,6 +68,9 @@ class MachoWalker {
// Read |size| bytes from the opened file at |offset| into |buffer|
bool ReadBytes(void *buffer, size_t size, off_t offset);
+
+ // Return the current header and header offset
+ bool CurrentHeader(struct mach_header_64 *header, off_t *offset);
private:
// Validate the |cpu_type|
@@ -87,6 +90,15 @@ class MachoWalker {
// User specified callback & context
LoadCommandCallback callback_;
void *callback_context_;
+
+ // 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
+ // (reserved). By adding the |current_header_size_| and the
+ // |current_header_offset_|, you can determine the offset in the file just
+ // after the header.
+ struct mach_header_64 *current_header_;
+ unsigned long current_header_size_;
+ off_t current_header_offset_;
};
} // namespace MacFileUtilities