Only use the segments that contain sections in the identifer calculation.

Fixes Issue #121.



git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@115 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
waylonis 2007-01-31 19:31:52 +00:00
parent d986a54f67
commit 87d965538b
2 changed files with 49 additions and 31 deletions

View File

@ -115,9 +115,29 @@ void MachoID::UpdateSHA1(unsigned char *bytes, size_t size) {
SHA_Update(&sha1_context_, bytes, size); SHA_Update(&sha1_context_, bytes, size);
} }
void MachoID::Update(unsigned char *bytes, size_t size) { void MachoID::Update(MachoWalker *walker, unsigned long offset, size_t size) {
if (update_function_) if (!update_function_ || !size)
(this->*update_function_)(bytes, size); return;
// Read up to 4k bytes at a time
unsigned char buffer[4096];
size_t buffer_size;
off_t file_offset = offset;
while (size > 0) {
if (size > sizeof(buffer)) {
buffer_size = sizeof(buffer);
size -= buffer_size;
} else {
buffer_size = size;
size = 0;
}
if (!walker->ReadBytes(buffer, buffer_size, file_offset))
return;
(this->*update_function_)(buffer, buffer_size);
file_offset += buffer_size;
}
} }
bool MachoID::UUIDCommand(int cpu_type, unsigned char bytes[16]) { bool MachoID::UUIDCommand(int cpu_type, unsigned char bytes[16]) {
@ -216,8 +236,6 @@ bool MachoID::SHA1(int cpu_type, unsigned char identifier[16]) {
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) {
MachoID *macho_id = (MachoID *)context; MachoID *macho_id = (MachoID *)context;
off_t seg_offset = 0;
size_t seg_size = 0;
if (cmd->cmd == LC_SEGMENT) { if (cmd->cmd == LC_SEGMENT) {
struct segment_command seg; struct segment_command seg;
@ -228,8 +246,20 @@ bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
if (swap) if (swap)
swap_segment_command(&seg, NXHostByteOrder()); swap_segment_command(&seg, NXHostByteOrder());
seg_offset = seg.fileoff; // Process segments that have sections:
seg_size = seg.filesize; // (e.g., __TEXT, __DATA, __IMPORT, __OBJC)
offset += sizeof(struct segment_command);
struct section sec;
for (unsigned long i = 0; i < seg.nsects; ++i) {
if (!walker->ReadBytes(&sec, sizeof(sec), offset))
return false;
if (swap)
swap_section(&sec, 1, NXHostByteOrder());
macho_id->Update(walker, sec.offset, sec.size);
offset += sizeof(struct section);
}
} else if (cmd->cmd == LC_SEGMENT_64) { } else if (cmd->cmd == LC_SEGMENT_64) {
struct segment_command_64 seg64; struct segment_command_64 seg64;
@ -239,31 +269,19 @@ bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
if (swap) if (swap)
swap_segment_command_64(&seg64, NXHostByteOrder()); swap_segment_command_64(&seg64, NXHostByteOrder());
seg_offset = seg64.fileoff; // Process segments that have sections:
seg_size = seg64.filesize; // (e.g., __TEXT, __DATA, __IMPORT, __OBJC)
} offset += sizeof(struct segment_command_64);
struct section_64 sec64;
// If this was a non-zero segment, read the bytes, update the hash for (unsigned long i = 0; i < seg64.nsects; ++i) {
if (seg_size) { if (!walker->ReadBytes(&sec64, sizeof(sec64), offset))
// Read 4k x 2 bytes at a time. This is faster than just 4k bytes, but
// doesn't seem to be an unreasonable size for the stack.
unsigned char buffer[4096 * 2];
size_t buffer_size;
off_t file_offset = seg_offset;
while (seg_size > 0) {
if (seg_size > sizeof(buffer)) {
buffer_size = sizeof(buffer);
seg_size -= buffer_size;
} else {
buffer_size = seg_size;
seg_size = 0;
}
if (!walker->ReadBytes(buffer, buffer_size, file_offset))
return false; return false;
macho_id->Update(buffer, buffer_size); if (swap)
file_offset += buffer_size; swap_section_64(&sec64, 1, NXHostByteOrder());
macho_id->Update(walker, sec64.offset, sec64.size);
offset += sizeof(struct section_64);
} }
} }

View File

@ -86,7 +86,7 @@ class MachoID {
void UpdateSHA1(unsigned char *bytes, size_t size); void UpdateSHA1(unsigned char *bytes, size_t size);
// Bottleneck for update routines // Bottleneck for update routines
void Update(unsigned char *bytes, size_t size); void Update(MachoWalker *walker, unsigned long offset, size_t size);
// The callback from the MachoWalker for CRC, MD5, and SHA1 // The callback from the MachoWalker for CRC, MD5, and SHA1
static bool WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, static bool WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,