1fd98b2af3773437487af0df22c428f3db630949awaylonis// Copyright (c) 2006, Google Inc. 2fd98b2af3773437487af0df22c428f3db630949awaylonis// All rights reserved. 3fd98b2af3773437487af0df22c428f3db630949awaylonis// 4fd98b2af3773437487af0df22c428f3db630949awaylonis// Redistribution and use in source and binary forms, with or without 5fd98b2af3773437487af0df22c428f3db630949awaylonis// modification, are permitted provided that the following conditions are 6fd98b2af3773437487af0df22c428f3db630949awaylonis// met: 7fd98b2af3773437487af0df22c428f3db630949awaylonis// 8fd98b2af3773437487af0df22c428f3db630949awaylonis// * Redistributions of source code must retain the above copyright 9fd98b2af3773437487af0df22c428f3db630949awaylonis// notice, this list of conditions and the following disclaimer. 10fd98b2af3773437487af0df22c428f3db630949awaylonis// * Redistributions in binary form must reproduce the above 11fd98b2af3773437487af0df22c428f3db630949awaylonis// copyright notice, this list of conditions and the following disclaimer 12fd98b2af3773437487af0df22c428f3db630949awaylonis// in the documentation and/or other materials provided with the 13fd98b2af3773437487af0df22c428f3db630949awaylonis// distribution. 14fd98b2af3773437487af0df22c428f3db630949awaylonis// * Neither the name of Google Inc. nor the names of its 15fd98b2af3773437487af0df22c428f3db630949awaylonis// contributors may be used to endorse or promote products derived from 16fd98b2af3773437487af0df22c428f3db630949awaylonis// this software without specific prior written permission. 17fd98b2af3773437487af0df22c428f3db630949awaylonis// 18fd98b2af3773437487af0df22c428f3db630949awaylonis// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19fd98b2af3773437487af0df22c428f3db630949awaylonis// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20fd98b2af3773437487af0df22c428f3db630949awaylonis// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21fd98b2af3773437487af0df22c428f3db630949awaylonis// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22fd98b2af3773437487af0df22c428f3db630949awaylonis// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23fd98b2af3773437487af0df22c428f3db630949awaylonis// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24fd98b2af3773437487af0df22c428f3db630949awaylonis// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25fd98b2af3773437487af0df22c428f3db630949awaylonis// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26fd98b2af3773437487af0df22c428f3db630949awaylonis// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27fd98b2af3773437487af0df22c428f3db630949awaylonis// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28fd98b2af3773437487af0df22c428f3db630949awaylonis// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29e5dc60822e5938fea2ae892ccddb906641ba174emmentovai 30fd98b2af3773437487af0df22c428f3db630949awaylonis// macho_id.cc: Functions to gather identifying information from a macho file 31fd98b2af3773437487af0df22c428f3db630949awaylonis// 32fd98b2af3773437487af0df22c428f3db630949awaylonis// See macho_id.h for documentation 33fd98b2af3773437487af0df22c428f3db630949awaylonis// 34fd98b2af3773437487af0df22c428f3db630949awaylonis// Author: Dan Waylonis 35fd98b2af3773437487af0df22c428f3db630949awaylonis 368aef89f021c687e96c66cb99b5dac312324e785cladderbreakerextern "C" { // necessary for Leopard 378aef89f021c687e96c66cb99b5dac312324e785cladderbreaker #include <fcntl.h> 388aef89f021c687e96c66cb99b5dac312324e785cladderbreaker #include <mach-o/loader.h> 398aef89f021c687e96c66cb99b5dac312324e785cladderbreaker #include <mach-o/swap.h> 408aef89f021c687e96c66cb99b5dac312324e785cladderbreaker #include <stdio.h> 418aef89f021c687e96c66cb99b5dac312324e785cladderbreaker #include <stdlib.h> 428aef89f021c687e96c66cb99b5dac312324e785cladderbreaker #include <string.h> 438aef89f021c687e96c66cb99b5dac312324e785cladderbreaker #include <sys/time.h> 448aef89f021c687e96c66cb99b5dac312324e785cladderbreaker #include <sys/types.h> 458aef89f021c687e96c66cb99b5dac312324e785cladderbreaker #include <unistd.h> 468aef89f021c687e96c66cb99b5dac312324e785cladderbreaker} 47fd98b2af3773437487af0df22c428f3db630949awaylonis 48fd98b2af3773437487af0df22c428f3db630949awaylonis#include "common/mac/macho_id.h" 49fd98b2af3773437487af0df22c428f3db630949awaylonis#include "common/mac/macho_walker.h" 50255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek#include "common/mac/macho_utilities.h" 51fd98b2af3773437487af0df22c428f3db630949awaylonis 52fd98b2af3773437487af0df22c428f3db630949awaylonisnamespace MacFileUtilities { 53fd98b2af3773437487af0df22c428f3db630949awaylonis 5497bed584e322953bad9eee43c49955aa4684b19eted.mielczarekusing google_breakpad::MD5Init; 5597bed584e322953bad9eee43c49955aa4684b19eted.mielczarekusing google_breakpad::MD5Update; 5697bed584e322953bad9eee43c49955aa4684b19eted.mielczarekusing google_breakpad::MD5Final; 5797bed584e322953bad9eee43c49955aa4684b19eted.mielczarek 584ac61acb3a7dad6ce722fe07564be8ec92713228dmaclachMachoID::MachoID(const char *path) 598fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org : memory_(0), 608fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org memory_size_(0), 618fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org crc_(0), 628fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org md5_context_(), 638fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org update_function_(NULL) { 648fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org strlcpy(path_, path, sizeof(path_)); 658fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org} 668fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org 678fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.orgMachoID::MachoID(const char *path, void *memory, size_t size) 688fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org : memory_(memory), 698fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org memory_size_(size), 704ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach crc_(0), 714ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach md5_context_(), 724ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach update_function_(NULL) { 73fd98b2af3773437487af0df22c428f3db630949awaylonis strlcpy(path_, path, sizeof(path_)); 74fd98b2af3773437487af0df22c428f3db630949awaylonis} 75fd98b2af3773437487af0df22c428f3db630949awaylonis 76fd98b2af3773437487af0df22c428f3db630949awaylonisMachoID::~MachoID() { 77fd98b2af3773437487af0df22c428f3db630949awaylonis} 78fd98b2af3773437487af0df22c428f3db630949awaylonis 79fd98b2af3773437487af0df22c428f3db630949awaylonis// The CRC info is from http://en.wikipedia.org/wiki/Adler-32 80fd98b2af3773437487af0df22c428f3db630949awaylonis// With optimizations from http://www.zlib.net/ 81fd98b2af3773437487af0df22c428f3db630949awaylonis 82fd98b2af3773437487af0df22c428f3db630949awaylonis// The largest prime smaller than 65536 83fd98b2af3773437487af0df22c428f3db630949awaylonis#define MOD_ADLER 65521 84fd98b2af3773437487af0df22c428f3db630949awaylonis// MAX_BLOCK is the largest n such that 255n(n+1)/2 + (n+1)(MAX_BLOCK-1) <= 2^32-1 85fd98b2af3773437487af0df22c428f3db630949awaylonis#define MAX_BLOCK 5552 86fd98b2af3773437487af0df22c428f3db630949awaylonis 87fd98b2af3773437487af0df22c428f3db630949awaylonisvoid MachoID::UpdateCRC(unsigned char *bytes, size_t size) { 88fd98b2af3773437487af0df22c428f3db630949awaylonis// Unrolled loops for summing 89fd98b2af3773437487af0df22c428f3db630949awaylonis#define DO1(buf,i) {sum1 += (buf)[i]; sum2 += sum1;} 90fd98b2af3773437487af0df22c428f3db630949awaylonis#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); 91fd98b2af3773437487af0df22c428f3db630949awaylonis#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); 92fd98b2af3773437487af0df22c428f3db630949awaylonis#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); 93fd98b2af3773437487af0df22c428f3db630949awaylonis#define DO16(buf) DO8(buf,0); DO8(buf,8); 94fd98b2af3773437487af0df22c428f3db630949awaylonis // Split up the crc 95fd98b2af3773437487af0df22c428f3db630949awaylonis uint32_t sum1 = crc_ & 0xFFFF; 96fd98b2af3773437487af0df22c428f3db630949awaylonis uint32_t sum2 = (crc_ >> 16) & 0xFFFF; 97fd98b2af3773437487af0df22c428f3db630949awaylonis 98fd98b2af3773437487af0df22c428f3db630949awaylonis // Do large blocks 99fd98b2af3773437487af0df22c428f3db630949awaylonis while (size >= MAX_BLOCK) { 100fd98b2af3773437487af0df22c428f3db630949awaylonis size -= MAX_BLOCK; 101fd98b2af3773437487af0df22c428f3db630949awaylonis int block_count = MAX_BLOCK / 16; 102fd98b2af3773437487af0df22c428f3db630949awaylonis do { 103fd98b2af3773437487af0df22c428f3db630949awaylonis DO16(bytes); 104fd98b2af3773437487af0df22c428f3db630949awaylonis bytes += 16; 105fd98b2af3773437487af0df22c428f3db630949awaylonis } while (--block_count); 106fd98b2af3773437487af0df22c428f3db630949awaylonis sum1 %= MOD_ADLER; 107fd98b2af3773437487af0df22c428f3db630949awaylonis sum2 %= MOD_ADLER; 108fd98b2af3773437487af0df22c428f3db630949awaylonis } 109fd98b2af3773437487af0df22c428f3db630949awaylonis 110fd98b2af3773437487af0df22c428f3db630949awaylonis // Do remaining bytes 111fd98b2af3773437487af0df22c428f3db630949awaylonis if (size) { 112fd98b2af3773437487af0df22c428f3db630949awaylonis while (size >= 16) { 113fd98b2af3773437487af0df22c428f3db630949awaylonis size -= 16; 114fd98b2af3773437487af0df22c428f3db630949awaylonis DO16(bytes); 115fd98b2af3773437487af0df22c428f3db630949awaylonis bytes += 16; 116fd98b2af3773437487af0df22c428f3db630949awaylonis } 117fd98b2af3773437487af0df22c428f3db630949awaylonis while (size--) { 118fd98b2af3773437487af0df22c428f3db630949awaylonis sum1 += *bytes++; 119fd98b2af3773437487af0df22c428f3db630949awaylonis sum2 += sum1; 120fd98b2af3773437487af0df22c428f3db630949awaylonis } 121fd98b2af3773437487af0df22c428f3db630949awaylonis sum1 %= MOD_ADLER; 122fd98b2af3773437487af0df22c428f3db630949awaylonis sum2 %= MOD_ADLER; 123fd98b2af3773437487af0df22c428f3db630949awaylonis crc_ = (sum2 << 16) | sum1; 124fd98b2af3773437487af0df22c428f3db630949awaylonis } 125fd98b2af3773437487af0df22c428f3db630949awaylonis} 126fd98b2af3773437487af0df22c428f3db630949awaylonis 127fd98b2af3773437487af0df22c428f3db630949awaylonisvoid MachoID::UpdateMD5(unsigned char *bytes, size_t size) { 128360347fe279b42eb00cef7863f3d44e7eb0d236civan.penkov@gmail.com MD5Update(&md5_context_, bytes, static_cast<unsigned>(size)); 129fd98b2af3773437487af0df22c428f3db630949awaylonis} 130fd98b2af3773437487af0df22c428f3db630949awaylonis 1314ac61acb3a7dad6ce722fe07564be8ec92713228dmaclachvoid MachoID::Update(MachoWalker *walker, off_t offset, size_t size) { 13287d965538b4f9306a4c6e59fcb741b5a11a95963waylonis if (!update_function_ || !size) 13387d965538b4f9306a4c6e59fcb741b5a11a95963waylonis return; 13487d965538b4f9306a4c6e59fcb741b5a11a95963waylonis 13587d965538b4f9306a4c6e59fcb741b5a11a95963waylonis // Read up to 4k bytes at a time 13687d965538b4f9306a4c6e59fcb741b5a11a95963waylonis unsigned char buffer[4096]; 13787d965538b4f9306a4c6e59fcb741b5a11a95963waylonis size_t buffer_size; 13887d965538b4f9306a4c6e59fcb741b5a11a95963waylonis off_t file_offset = offset; 13987d965538b4f9306a4c6e59fcb741b5a11a95963waylonis while (size > 0) { 14087d965538b4f9306a4c6e59fcb741b5a11a95963waylonis if (size > sizeof(buffer)) { 14187d965538b4f9306a4c6e59fcb741b5a11a95963waylonis buffer_size = sizeof(buffer); 14287d965538b4f9306a4c6e59fcb741b5a11a95963waylonis size -= buffer_size; 14387d965538b4f9306a4c6e59fcb741b5a11a95963waylonis } else { 14487d965538b4f9306a4c6e59fcb741b5a11a95963waylonis buffer_size = size; 14587d965538b4f9306a4c6e59fcb741b5a11a95963waylonis size = 0; 14687d965538b4f9306a4c6e59fcb741b5a11a95963waylonis } 14787d965538b4f9306a4c6e59fcb741b5a11a95963waylonis 14887d965538b4f9306a4c6e59fcb741b5a11a95963waylonis if (!walker->ReadBytes(buffer, buffer_size, file_offset)) 14987d965538b4f9306a4c6e59fcb741b5a11a95963waylonis return; 15087d965538b4f9306a4c6e59fcb741b5a11a95963waylonis 15187d965538b4f9306a4c6e59fcb741b5a11a95963waylonis (this->*update_function_)(buffer, buffer_size); 15287d965538b4f9306a4c6e59fcb741b5a11a95963waylonis file_offset += buffer_size; 15387d965538b4f9306a4c6e59fcb741b5a11a95963waylonis } 154fd98b2af3773437487af0df22c428f3db630949awaylonis} 155fd98b2af3773437487af0df22c428f3db630949awaylonis 156b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.orgbool MachoID::UUIDCommand(cpu_type_t cpu_type, 157b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org cpu_subtype_t cpu_subtype, 158b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org unsigned char bytes[16]) { 159255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek struct breakpad_uuid_command uuid_cmd; 160fd98b2af3773437487af0df22c428f3db630949awaylonis uuid_cmd.cmd = 0; 161b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org if (!WalkHeader(cpu_type, cpu_subtype, UUIDWalkerCB, &uuid_cmd)) 162fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 163fd98b2af3773437487af0df22c428f3db630949awaylonis 164fd98b2af3773437487af0df22c428f3db630949awaylonis // If we found the command, we'll have initialized the uuid_command 165fd98b2af3773437487af0df22c428f3db630949awaylonis // structure 166fd98b2af3773437487af0df22c428f3db630949awaylonis if (uuid_cmd.cmd == LC_UUID) { 167fd98b2af3773437487af0df22c428f3db630949awaylonis memcpy(bytes, uuid_cmd.uuid, sizeof(uuid_cmd.uuid)); 168fd98b2af3773437487af0df22c428f3db630949awaylonis return true; 169fd98b2af3773437487af0df22c428f3db630949awaylonis } 170fd98b2af3773437487af0df22c428f3db630949awaylonis 171fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 172fd98b2af3773437487af0df22c428f3db630949awaylonis} 173fd98b2af3773437487af0df22c428f3db630949awaylonis 174b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.orgbool MachoID::IDCommand(cpu_type_t cpu_type, 175b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org cpu_subtype_t cpu_subtype, 176b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org unsigned char identifier[16]) { 177fd98b2af3773437487af0df22c428f3db630949awaylonis struct dylib_command dylib_cmd; 178fd98b2af3773437487af0df22c428f3db630949awaylonis dylib_cmd.cmd = 0; 179b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org if (!WalkHeader(cpu_type, cpu_subtype, IDWalkerCB, &dylib_cmd)) 180fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 181fd98b2af3773437487af0df22c428f3db630949awaylonis 182fd98b2af3773437487af0df22c428f3db630949awaylonis // If we found the command, we'll have initialized the dylib_command 183fd98b2af3773437487af0df22c428f3db630949awaylonis // structure 184fd98b2af3773437487af0df22c428f3db630949awaylonis if (dylib_cmd.cmd == LC_ID_DYLIB) { 1851a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker // Take the hashed filename, version, and compatability version bytes 1861a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker // to form the first 12 bytes, pad the rest with zeros 1871a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker 1881a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker // create a crude hash of the filename to generate the first 4 bytes 1891a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker identifier[0] = 0; 1901a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker identifier[1] = 0; 1911a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker identifier[2] = 0; 1921a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker identifier[3] = 0; 1931a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker 1944ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach for (int j = 0, i = (int)strlen(path_)-1; i>=0 && path_[i]!='/'; ++j, --i) { 1951a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker identifier[j%4] += path_[i]; 1961a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker } 1971a4310017ec3af237399ccbc4ff096de4c08cf6dladderbreaker 198fd98b2af3773437487af0df22c428f3db630949awaylonis identifier[4] = (dylib_cmd.dylib.current_version >> 24) & 0xFF; 199fd98b2af3773437487af0df22c428f3db630949awaylonis identifier[5] = (dylib_cmd.dylib.current_version >> 16) & 0xFF; 200fd98b2af3773437487af0df22c428f3db630949awaylonis identifier[6] = (dylib_cmd.dylib.current_version >> 8) & 0xFF; 201fd98b2af3773437487af0df22c428f3db630949awaylonis identifier[7] = dylib_cmd.dylib.current_version & 0xFF; 202fd98b2af3773437487af0df22c428f3db630949awaylonis identifier[8] = (dylib_cmd.dylib.compatibility_version >> 24) & 0xFF; 203fd98b2af3773437487af0df22c428f3db630949awaylonis identifier[9] = (dylib_cmd.dylib.compatibility_version >> 16) & 0xFF; 204fd98b2af3773437487af0df22c428f3db630949awaylonis identifier[10] = (dylib_cmd.dylib.compatibility_version >> 8) & 0xFF; 205fd98b2af3773437487af0df22c428f3db630949awaylonis identifier[11] = dylib_cmd.dylib.compatibility_version & 0xFF; 206baaeb5af7149f9a4ced95331a6c577f6c0c96e34ladderbreaker identifier[12] = (cpu_type >> 24) & 0xFF; 207baaeb5af7149f9a4ced95331a6c577f6c0c96e34ladderbreaker identifier[13] = (cpu_type >> 16) & 0xFF; 208baaeb5af7149f9a4ced95331a6c577f6c0c96e34ladderbreaker identifier[14] = (cpu_type >> 8) & 0xFF; 209baaeb5af7149f9a4ced95331a6c577f6c0c96e34ladderbreaker identifier[15] = cpu_type & 0xFF; 210fd98b2af3773437487af0df22c428f3db630949awaylonis 211fd98b2af3773437487af0df22c428f3db630949awaylonis return true; 212fd98b2af3773437487af0df22c428f3db630949awaylonis } 213fd98b2af3773437487af0df22c428f3db630949awaylonis 214fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 215fd98b2af3773437487af0df22c428f3db630949awaylonis} 216fd98b2af3773437487af0df22c428f3db630949awaylonis 217b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.orguint32_t MachoID::Adler32(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) { 218fd98b2af3773437487af0df22c428f3db630949awaylonis update_function_ = &MachoID::UpdateCRC; 219fd98b2af3773437487af0df22c428f3db630949awaylonis crc_ = 0; 220fd98b2af3773437487af0df22c428f3db630949awaylonis 221b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org if (!WalkHeader(cpu_type, cpu_subtype, WalkerCB, this)) 222fd98b2af3773437487af0df22c428f3db630949awaylonis return 0; 223fd98b2af3773437487af0df22c428f3db630949awaylonis 224fd98b2af3773437487af0df22c428f3db630949awaylonis return crc_; 225fd98b2af3773437487af0df22c428f3db630949awaylonis} 226fd98b2af3773437487af0df22c428f3db630949awaylonis 227b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.orgbool MachoID::MD5(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype, unsigned char identifier[16]) { 228fd98b2af3773437487af0df22c428f3db630949awaylonis update_function_ = &MachoID::UpdateMD5; 229fd98b2af3773437487af0df22c428f3db630949awaylonis 230e919fdd63b4550a3261422ffde3c8d631007f75bmark@chromium.org MD5Init(&md5_context_); 231fd98b2af3773437487af0df22c428f3db630949awaylonis 232b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org if (!WalkHeader(cpu_type, cpu_subtype, WalkerCB, this)) 233e919fdd63b4550a3261422ffde3c8d631007f75bmark@chromium.org return false; 234fd98b2af3773437487af0df22c428f3db630949awaylonis 235e919fdd63b4550a3261422ffde3c8d631007f75bmark@chromium.org MD5Final(identifier, &md5_context_); 236e919fdd63b4550a3261422ffde3c8d631007f75bmark@chromium.org return true; 237fd98b2af3773437487af0df22c428f3db630949awaylonis} 238fd98b2af3773437487af0df22c428f3db630949awaylonis 239b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.orgbool MachoID::WalkHeader(cpu_type_t cpu_type, 240b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org cpu_subtype_t cpu_subtype, 2418fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org MachoWalker::LoadCommandCallback callback, 2428fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org void *context) { 2438fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org if (memory_) { 2448fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org MachoWalker walker(memory_, memory_size_, callback, context); 245b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org return walker.WalkHeader(cpu_type, cpu_subtype); 2468fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org } else { 2478fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org MachoWalker walker(path_, callback, context); 248b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org return walker.WalkHeader(cpu_type, cpu_subtype); 2498fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org } 2508fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org} 2518fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org 252fd98b2af3773437487af0df22c428f3db630949awaylonis// static 253fd98b2af3773437487af0df22c428f3db630949awaylonisbool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, 254fd98b2af3773437487af0df22c428f3db630949awaylonis bool swap, void *context) { 255fd98b2af3773437487af0df22c428f3db630949awaylonis MachoID *macho_id = (MachoID *)context; 256fd98b2af3773437487af0df22c428f3db630949awaylonis 257fd98b2af3773437487af0df22c428f3db630949awaylonis if (cmd->cmd == LC_SEGMENT) { 258fd98b2af3773437487af0df22c428f3db630949awaylonis struct segment_command seg; 259fd98b2af3773437487af0df22c428f3db630949awaylonis 260fd98b2af3773437487af0df22c428f3db630949awaylonis if (!walker->ReadBytes(&seg, sizeof(seg), offset)) 261fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 262fd98b2af3773437487af0df22c428f3db630949awaylonis 263fd98b2af3773437487af0df22c428f3db630949awaylonis if (swap) 264fd98b2af3773437487af0df22c428f3db630949awaylonis swap_segment_command(&seg, NXHostByteOrder()); 265fd98b2af3773437487af0df22c428f3db630949awaylonis 266983264848d5372d8e64d62eb67f672c71e4b6470waylonis struct mach_header_64 header; 267983264848d5372d8e64d62eb67f672c71e4b6470waylonis off_t header_offset; 268983264848d5372d8e64d62eb67f672c71e4b6470waylonis 269983264848d5372d8e64d62eb67f672c71e4b6470waylonis if (!walker->CurrentHeader(&header, &header_offset)) 270983264848d5372d8e64d62eb67f672c71e4b6470waylonis return false; 271983264848d5372d8e64d62eb67f672c71e4b6470waylonis 27287d965538b4f9306a4c6e59fcb741b5a11a95963waylonis // Process segments that have sections: 27387d965538b4f9306a4c6e59fcb741b5a11a95963waylonis // (e.g., __TEXT, __DATA, __IMPORT, __OBJC) 27487d965538b4f9306a4c6e59fcb741b5a11a95963waylonis offset += sizeof(struct segment_command); 27587d965538b4f9306a4c6e59fcb741b5a11a95963waylonis struct section sec; 27687d965538b4f9306a4c6e59fcb741b5a11a95963waylonis for (unsigned long i = 0; i < seg.nsects; ++i) { 27787d965538b4f9306a4c6e59fcb741b5a11a95963waylonis if (!walker->ReadBytes(&sec, sizeof(sec), offset)) 27887d965538b4f9306a4c6e59fcb741b5a11a95963waylonis return false; 27987d965538b4f9306a4c6e59fcb741b5a11a95963waylonis 28087d965538b4f9306a4c6e59fcb741b5a11a95963waylonis if (swap) 28187d965538b4f9306a4c6e59fcb741b5a11a95963waylonis swap_section(&sec, 1, NXHostByteOrder()); 28287d965538b4f9306a4c6e59fcb741b5a11a95963waylonis 2832e86dfe70513091a0fb8f5725a4c81c476f993e8ladderbreaker // sections of type S_ZEROFILL are "virtual" and contain no data 2842e86dfe70513091a0fb8f5725a4c81c476f993e8ladderbreaker // in the file itself 2852e86dfe70513091a0fb8f5725a4c81c476f993e8ladderbreaker if ((sec.flags & SECTION_TYPE) != S_ZEROFILL && sec.offset != 0) 2862e86dfe70513091a0fb8f5725a4c81c476f993e8ladderbreaker macho_id->Update(walker, header_offset + sec.offset, sec.size); 2872e86dfe70513091a0fb8f5725a4c81c476f993e8ladderbreaker 28887d965538b4f9306a4c6e59fcb741b5a11a95963waylonis offset += sizeof(struct section); 28987d965538b4f9306a4c6e59fcb741b5a11a95963waylonis } 290fd98b2af3773437487af0df22c428f3db630949awaylonis } else if (cmd->cmd == LC_SEGMENT_64) { 291fd98b2af3773437487af0df22c428f3db630949awaylonis struct segment_command_64 seg64; 292fd98b2af3773437487af0df22c428f3db630949awaylonis 293fd98b2af3773437487af0df22c428f3db630949awaylonis if (!walker->ReadBytes(&seg64, sizeof(seg64), offset)) 294fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 295fd98b2af3773437487af0df22c428f3db630949awaylonis 296fd98b2af3773437487af0df22c428f3db630949awaylonis if (swap) 297255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek breakpad_swap_segment_command_64(&seg64, NXHostByteOrder()); 298fd98b2af3773437487af0df22c428f3db630949awaylonis 299983264848d5372d8e64d62eb67f672c71e4b6470waylonis struct mach_header_64 header; 300983264848d5372d8e64d62eb67f672c71e4b6470waylonis off_t header_offset; 301983264848d5372d8e64d62eb67f672c71e4b6470waylonis 302983264848d5372d8e64d62eb67f672c71e4b6470waylonis if (!walker->CurrentHeader(&header, &header_offset)) 303983264848d5372d8e64d62eb67f672c71e4b6470waylonis return false; 304983264848d5372d8e64d62eb67f672c71e4b6470waylonis 30587d965538b4f9306a4c6e59fcb741b5a11a95963waylonis // Process segments that have sections: 30687d965538b4f9306a4c6e59fcb741b5a11a95963waylonis // (e.g., __TEXT, __DATA, __IMPORT, __OBJC) 30787d965538b4f9306a4c6e59fcb741b5a11a95963waylonis offset += sizeof(struct segment_command_64); 30887d965538b4f9306a4c6e59fcb741b5a11a95963waylonis struct section_64 sec64; 30987d965538b4f9306a4c6e59fcb741b5a11a95963waylonis for (unsigned long i = 0; i < seg64.nsects; ++i) { 31087d965538b4f9306a4c6e59fcb741b5a11a95963waylonis if (!walker->ReadBytes(&sec64, sizeof(sec64), offset)) 311fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 312fd98b2af3773437487af0df22c428f3db630949awaylonis 31387d965538b4f9306a4c6e59fcb741b5a11a95963waylonis if (swap) 314255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek breakpad_swap_section_64(&sec64, 1, NXHostByteOrder()); 31587d965538b4f9306a4c6e59fcb741b5a11a95963waylonis 3162e86dfe70513091a0fb8f5725a4c81c476f993e8ladderbreaker // sections of type S_ZEROFILL are "virtual" and contain no data 3172e86dfe70513091a0fb8f5725a4c81c476f993e8ladderbreaker // in the file itself 3182e86dfe70513091a0fb8f5725a4c81c476f993e8ladderbreaker if ((sec64.flags & SECTION_TYPE) != S_ZEROFILL && sec64.offset != 0) 3194ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach macho_id->Update(walker, 3204ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach header_offset + sec64.offset, 3214ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach (size_t)sec64.size); 3222e86dfe70513091a0fb8f5725a4c81c476f993e8ladderbreaker 32387d965538b4f9306a4c6e59fcb741b5a11a95963waylonis offset += sizeof(struct section_64); 324fd98b2af3773437487af0df22c428f3db630949awaylonis } 325fd98b2af3773437487af0df22c428f3db630949awaylonis } 326fd98b2af3773437487af0df22c428f3db630949awaylonis 327fd98b2af3773437487af0df22c428f3db630949awaylonis // Continue processing 328fd98b2af3773437487af0df22c428f3db630949awaylonis return true; 329fd98b2af3773437487af0df22c428f3db630949awaylonis} 330fd98b2af3773437487af0df22c428f3db630949awaylonis 331fd98b2af3773437487af0df22c428f3db630949awaylonis// static 332fd98b2af3773437487af0df22c428f3db630949awaylonisbool MachoID::UUIDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, 333fd98b2af3773437487af0df22c428f3db630949awaylonis bool swap, void *context) { 334fd98b2af3773437487af0df22c428f3db630949awaylonis if (cmd->cmd == LC_UUID) { 335255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek struct breakpad_uuid_command *uuid_cmd = 336255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek (struct breakpad_uuid_command *)context; 337fd98b2af3773437487af0df22c428f3db630949awaylonis 338255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek if (!walker->ReadBytes(uuid_cmd, sizeof(struct breakpad_uuid_command), 339255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek offset)) 340fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 341fd98b2af3773437487af0df22c428f3db630949awaylonis 342fd98b2af3773437487af0df22c428f3db630949awaylonis if (swap) 343255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek breakpad_swap_uuid_command(uuid_cmd, NXHostByteOrder()); 344fd98b2af3773437487af0df22c428f3db630949awaylonis 345fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 346fd98b2af3773437487af0df22c428f3db630949awaylonis } 347fd98b2af3773437487af0df22c428f3db630949awaylonis 348fd98b2af3773437487af0df22c428f3db630949awaylonis // Continue processing 349fd98b2af3773437487af0df22c428f3db630949awaylonis return true; 350fd98b2af3773437487af0df22c428f3db630949awaylonis} 351fd98b2af3773437487af0df22c428f3db630949awaylonis 352fd98b2af3773437487af0df22c428f3db630949awaylonis// static 353fd98b2af3773437487af0df22c428f3db630949awaylonisbool MachoID::IDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset, 354fd98b2af3773437487af0df22c428f3db630949awaylonis bool swap, void *context) { 355fd98b2af3773437487af0df22c428f3db630949awaylonis if (cmd->cmd == LC_ID_DYLIB) { 356fd98b2af3773437487af0df22c428f3db630949awaylonis struct dylib_command *dylib_cmd = (struct dylib_command *)context; 357fd98b2af3773437487af0df22c428f3db630949awaylonis 358fd98b2af3773437487af0df22c428f3db630949awaylonis if (!walker->ReadBytes(dylib_cmd, sizeof(struct dylib_command), offset)) 359fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 360fd98b2af3773437487af0df22c428f3db630949awaylonis 361fd98b2af3773437487af0df22c428f3db630949awaylonis if (swap) 362fd98b2af3773437487af0df22c428f3db630949awaylonis swap_dylib_command(dylib_cmd, NXHostByteOrder()); 363fd98b2af3773437487af0df22c428f3db630949awaylonis 364fd98b2af3773437487af0df22c428f3db630949awaylonis return false; 365fd98b2af3773437487af0df22c428f3db630949awaylonis } 366fd98b2af3773437487af0df22c428f3db630949awaylonis 367fd98b2af3773437487af0df22c428f3db630949awaylonis // Continue processing 368fd98b2af3773437487af0df22c428f3db630949awaylonis return true; 369fd98b2af3773437487af0df22c428f3db630949awaylonis} 370fd98b2af3773437487af0df22c428f3db630949awaylonis 371fd98b2af3773437487af0df22c428f3db630949awaylonis} // namespace MacFileUtilities 372