Planeshift
|
00001 // Copyright (c) 2007, Google Inc. 00002 // All rights reserved. 00003 // 00004 // Redistribution and use in source and binary forms, with or without 00005 // modification, are permitted provided that the following conditions are 00006 // met: 00007 // 00008 // * Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // * Redistributions in binary form must reproduce the above 00011 // copyright notice, this list of conditions and the following disclaimer 00012 // in the documentation and/or other materials provided with the 00013 // distribution. 00014 // * Neither the name of Google Inc. nor the names of its 00015 // contributors may be used to endorse or promote products derived from 00016 // this software without specific prior written permission. 00017 // 00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00019 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00020 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00021 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00022 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00023 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00024 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00025 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00026 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00028 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 00030 // dynamic_images.h 00031 // 00032 // Implements most of the function of the dyld API, but allowing an 00033 // arbitrary task to be introspected, unlike the dyld API which 00034 // only allows operation on the current task. The current implementation 00035 // is limited to use by 32-bit tasks. 00036 00037 #ifndef CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__ 00038 #define CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__ 00039 00040 #include <mach/mach.h> 00041 #include <mach-o/dyld.h> 00042 #include <mach-o/loader.h> 00043 #include <sys/types.h> 00044 00045 #include <string> 00046 #include <vector> 00047 00048 #include "mach_vm_compat.h" 00049 00050 namespace google_breakpad { 00051 00052 using std::string; 00053 using std::vector; 00054 00055 //============================================================================== 00056 // The memory layout of this struct matches the dyld_image_info struct 00057 // defined in "dyld_gdb.h" in the darwin source. 00058 typedef struct dyld_image_info32 { 00059 uint32_t load_address_; // struct mach_header* 00060 uint32_t file_path_; // char* 00061 uint32_t file_mod_date_; 00062 } dyld_image_info32; 00063 00064 typedef struct dyld_image_info64 { 00065 uint64_t load_address_; // struct mach_header* 00066 uint64_t file_path_; // char* 00067 uint64_t file_mod_date_; 00068 } dyld_image_info64; 00069 00070 //============================================================================== 00071 // This is as defined in "dyld_gdb.h" in the darwin source. 00072 // _dyld_all_image_infos (in dyld) is a structure of this type 00073 // which will be used to determine which dynamic code has been loaded. 00074 typedef struct dyld_all_image_infos32 { 00075 uint32_t version; // == 1 in Mac OS X 10.4 00076 uint32_t infoArrayCount; 00077 uint32_t infoArray; // const struct dyld_image_info* 00078 uint32_t notification; 00079 bool processDetachedFromSharedRegion; 00080 } dyld_all_image_infos32; 00081 00082 typedef struct dyld_all_image_infos64 { 00083 uint32_t version; // == 1 in Mac OS X 10.4 00084 uint32_t infoArrayCount; 00085 uint64_t infoArray; // const struct dyld_image_info* 00086 uint64_t notification; 00087 bool processDetachedFromSharedRegion; 00088 } dyld_all_image_infos64; 00089 00090 // some typedefs to isolate 64/32 bit differences 00091 #ifdef __LP64__ 00092 typedef mach_header_64 breakpad_mach_header; 00093 typedef segment_command_64 breakpad_mach_segment_command; 00094 #else 00095 typedef mach_header breakpad_mach_header; 00096 typedef segment_command breakpad_mach_segment_command; 00097 #endif 00098 00099 // Helper functions to deal with 32-bit/64-bit Mach-O differences. 00100 class DynamicImage; 00101 template<typename MachBits> 00102 bool FindTextSection(DynamicImage& image); 00103 00104 template<typename MachBits> 00105 uint32_t GetFileTypeFromHeader(DynamicImage& image); 00106 00107 //============================================================================== 00108 // Represents a single dynamically loaded mach-o image 00109 class DynamicImage { 00110 public: 00111 DynamicImage(uint8_t *header, // data is copied 00112 size_t header_size, // includes load commands 00113 uint64_t load_address, 00114 string file_path, 00115 uintptr_t image_mod_date, 00116 mach_port_t task, 00117 cpu_type_t cpu_type) 00118 : header_(header, header + header_size), 00119 header_size_(header_size), 00120 load_address_(load_address), 00121 vmaddr_(0), 00122 vmsize_(0), 00123 slide_(0), 00124 version_(0), 00125 file_path_(file_path), 00126 file_mod_date_(image_mod_date), 00127 task_(task), 00128 cpu_type_(cpu_type) { 00129 CalculateMemoryAndVersionInfo(); 00130 } 00131 00132 // Size of mach_header plus load commands 00133 size_t GetHeaderSize() const {return header_.size();} 00134 00135 // Full path to mach-o binary 00136 string GetFilePath() {return file_path_;} 00137 00138 uint64_t GetModDate() const {return file_mod_date_;} 00139 00140 // Actual address where the image was loaded 00141 uint64_t GetLoadAddress() const {return load_address_;} 00142 00143 // Address where the image should be loaded 00144 mach_vm_address_t GetVMAddr() const {return vmaddr_;} 00145 00146 // Difference between GetLoadAddress() and GetVMAddr() 00147 ptrdiff_t GetVMAddrSlide() const {return slide_;} 00148 00149 // Size of the image 00150 mach_vm_size_t GetVMSize() const {return vmsize_;} 00151 00152 // Task owning this loaded image 00153 mach_port_t GetTask() {return task_;} 00154 00155 // CPU type of the task 00156 cpu_type_t GetCPUType() {return cpu_type_;} 00157 00158 // filetype from the Mach-O header. 00159 uint32_t GetFileType(); 00160 00161 // Return true if the task is a 64-bit architecture. 00162 bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; } 00163 00164 uint32_t GetVersion() {return version_;} 00165 // For sorting 00166 bool operator<(const DynamicImage &inInfo) { 00167 return GetLoadAddress() < inInfo.GetLoadAddress(); 00168 } 00169 00170 // Sanity checking 00171 bool IsValid() {return GetVMSize() != 0;} 00172 00173 private: 00174 DynamicImage(const DynamicImage &); 00175 DynamicImage &operator=(const DynamicImage &); 00176 00177 friend class DynamicImages; 00178 template<typename MachBits> 00179 friend bool FindTextSection(DynamicImage& image); 00180 template<typename MachBits> 00181 friend uint32_t GetFileTypeFromHeader(DynamicImage& image); 00182 00183 // Initializes vmaddr_, vmsize_, and slide_ 00184 void CalculateMemoryAndVersionInfo(); 00185 00186 const vector<uint8_t> header_; // our local copy of the header 00187 size_t header_size_; // mach_header plus load commands 00188 uint64_t load_address_; // base address image is mapped into 00189 mach_vm_address_t vmaddr_; 00190 mach_vm_size_t vmsize_; 00191 ptrdiff_t slide_; 00192 uint32_t version_; // Dylib version 00193 string file_path_; // path dyld used to load the image 00194 uintptr_t file_mod_date_; // time_t of image file 00195 00196 mach_port_t task_; 00197 cpu_type_t cpu_type_; // CPU type of task_ 00198 }; 00199 00200 //============================================================================== 00201 // DynamicImageRef is just a simple wrapper for a pointer to 00202 // DynamicImage. The reason we use it instead of a simple typedef is so 00203 // that we can use stl::sort() on a vector of DynamicImageRefs 00204 // and simple class pointers can't implement operator<(). 00205 // 00206 class DynamicImageRef { 00207 public: 00208 explicit DynamicImageRef(DynamicImage *inP) : p(inP) {} 00209 // The copy constructor is required by STL 00210 DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {} 00211 00212 bool operator<(const DynamicImageRef &inRef) const { 00213 return (*const_cast<DynamicImageRef*>(this)->p) 00214 < (*const_cast<DynamicImageRef&>(inRef).p); 00215 } 00216 00217 bool operator==(const DynamicImageRef &inInfo) const { 00218 return (*const_cast<DynamicImageRef*>(this)->p).GetLoadAddress() == 00219 (*const_cast<DynamicImageRef&>(inInfo)).GetLoadAddress(); 00220 } 00221 00222 // Be just like DynamicImage* 00223 DynamicImage *operator->() {return p;} 00224 operator DynamicImage*() {return p;} 00225 00226 private: 00227 DynamicImage *p; 00228 }; 00229 00230 // Helper function to deal with 32-bit/64-bit Mach-O differences. 00231 class DynamicImages; 00232 template<typename MachBits> 00233 void ReadImageInfo(DynamicImages& images, uint64_t image_list_address); 00234 00235 //============================================================================== 00236 // An object of type DynamicImages may be created to allow introspection of 00237 // an arbitrary task's dynamically loaded mach-o binaries. This makes the 00238 // assumption that the current task has send rights to the target task. 00239 class DynamicImages { 00240 public: 00241 explicit DynamicImages(mach_port_t task); 00242 00243 ~DynamicImages() { 00244 for (int i = 0; i < GetImageCount(); ++i) { 00245 delete image_list_[i]; 00246 } 00247 } 00248 00249 // Returns the number of dynamically loaded mach-o images. 00250 int GetImageCount() const {return static_cast<int>(image_list_.size());} 00251 00252 // Returns an individual image. 00253 DynamicImage *GetImage(int i) { 00254 if (i < (int)image_list_.size()) { 00255 return image_list_[i]; 00256 } 00257 return NULL; 00258 } 00259 00260 // Returns the image corresponding to the main executable. 00261 DynamicImage *GetExecutableImage(); 00262 int GetExecutableImageIndex(); 00263 00264 // Returns the task which we're looking at. 00265 mach_port_t GetTask() const {return task_;} 00266 00267 // CPU type of the task 00268 cpu_type_t GetCPUType() {return cpu_type_;} 00269 00270 // Return true if the task is a 64-bit architecture. 00271 bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; } 00272 00273 // Determine the CPU type of the task being dumped. 00274 static cpu_type_t DetermineTaskCPUType(task_t task); 00275 00276 // Get the native CPU type of this task. 00277 static cpu_type_t GetNativeCPUType() { 00278 #if defined(__i386__) 00279 return CPU_TYPE_I386; 00280 #elif defined(__x86_64__) 00281 return CPU_TYPE_X86_64; 00282 #elif defined(__ppc__) 00283 return CPU_TYPE_POWERPC; 00284 #elif defined(__ppc64__) 00285 return CPU_TYPE_POWERPC64; 00286 #elif defined(__arm__) 00287 return CPU_TYPE_ARM; 00288 #else 00289 #error "GetNativeCPUType not implemented for this architecture" 00290 #endif 00291 } 00292 00293 private: 00294 template<typename MachBits> 00295 friend void ReadImageInfo(DynamicImages& images, uint64_t image_list_address); 00296 00297 bool IsOurTask() {return task_ == mach_task_self();} 00298 00299 // Initialization 00300 void ReadImageInfoForTask(); 00301 uint64_t GetDyldAllImageInfosPointer(); 00302 00303 mach_port_t task_; 00304 cpu_type_t cpu_type_; // CPU type of task_ 00305 vector<DynamicImageRef> image_list_; 00306 }; 00307 00308 // Fill bytes with the contents of memory at a particular 00309 // location in another task. 00310 kern_return_t ReadTaskMemory(task_port_t target_task, 00311 const uint64_t address, 00312 size_t length, 00313 vector<uint8_t> &bytes); 00314 00315 } // namespace google_breakpad 00316 00317 #endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__