toolkit/crashreporter/google-breakpad/src/client/mac/handler/dynamic_images.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 // Copyright (c) 2007, Google Inc.
michael@0 2 // All rights reserved.
michael@0 3 //
michael@0 4 // Redistribution and use in source and binary forms, with or without
michael@0 5 // modification, are permitted provided that the following conditions are
michael@0 6 // met:
michael@0 7 //
michael@0 8 // * Redistributions of source code must retain the above copyright
michael@0 9 // notice, this list of conditions and the following disclaimer.
michael@0 10 // * Redistributions in binary form must reproduce the above
michael@0 11 // copyright notice, this list of conditions and the following disclaimer
michael@0 12 // in the documentation and/or other materials provided with the
michael@0 13 // distribution.
michael@0 14 // * Neither the name of Google Inc. nor the names of its
michael@0 15 // contributors may be used to endorse or promote products derived from
michael@0 16 // this software without specific prior written permission.
michael@0 17 //
michael@0 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
michael@0 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@0 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@0 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
michael@0 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 29
michael@0 30 // dynamic_images.h
michael@0 31 //
michael@0 32 // Implements most of the function of the dyld API, but allowing an
michael@0 33 // arbitrary task to be introspected, unlike the dyld API which
michael@0 34 // only allows operation on the current task. The current implementation
michael@0 35 // is limited to use by 32-bit tasks.
michael@0 36
michael@0 37 #ifndef CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
michael@0 38 #define CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
michael@0 39
michael@0 40 #include <mach/mach.h>
michael@0 41 #include <mach-o/dyld.h>
michael@0 42 #include <mach-o/loader.h>
michael@0 43 #include <sys/types.h>
michael@0 44
michael@0 45 #include <string>
michael@0 46 #include <vector>
michael@0 47
michael@0 48 #include "mach_vm_compat.h"
michael@0 49
michael@0 50 namespace google_breakpad {
michael@0 51
michael@0 52 using std::string;
michael@0 53 using std::vector;
michael@0 54
michael@0 55 //==============================================================================
michael@0 56 // The memory layout of this struct matches the dyld_image_info struct
michael@0 57 // defined in "dyld_gdb.h" in the darwin source.
michael@0 58 typedef struct dyld_image_info32 {
michael@0 59 uint32_t load_address_; // struct mach_header*
michael@0 60 uint32_t file_path_; // char*
michael@0 61 uint32_t file_mod_date_;
michael@0 62 } dyld_image_info32;
michael@0 63
michael@0 64 typedef struct dyld_image_info64 {
michael@0 65 uint64_t load_address_; // struct mach_header*
michael@0 66 uint64_t file_path_; // char*
michael@0 67 uint64_t file_mod_date_;
michael@0 68 } dyld_image_info64;
michael@0 69
michael@0 70 //==============================================================================
michael@0 71 // This is as defined in "dyld_gdb.h" in the darwin source.
michael@0 72 // _dyld_all_image_infos (in dyld) is a structure of this type
michael@0 73 // which will be used to determine which dynamic code has been loaded.
michael@0 74 typedef struct dyld_all_image_infos32 {
michael@0 75 uint32_t version; // == 1 in Mac OS X 10.4
michael@0 76 uint32_t infoArrayCount;
michael@0 77 uint32_t infoArray; // const struct dyld_image_info*
michael@0 78 uint32_t notification;
michael@0 79 bool processDetachedFromSharedRegion;
michael@0 80 } dyld_all_image_infos32;
michael@0 81
michael@0 82 typedef struct dyld_all_image_infos64 {
michael@0 83 uint32_t version; // == 1 in Mac OS X 10.4
michael@0 84 uint32_t infoArrayCount;
michael@0 85 uint64_t infoArray; // const struct dyld_image_info*
michael@0 86 uint64_t notification;
michael@0 87 bool processDetachedFromSharedRegion;
michael@0 88 } dyld_all_image_infos64;
michael@0 89
michael@0 90 // some typedefs to isolate 64/32 bit differences
michael@0 91 #ifdef __LP64__
michael@0 92 typedef mach_header_64 breakpad_mach_header;
michael@0 93 typedef segment_command_64 breakpad_mach_segment_command;
michael@0 94 #else
michael@0 95 typedef mach_header breakpad_mach_header;
michael@0 96 typedef segment_command breakpad_mach_segment_command;
michael@0 97 #endif
michael@0 98
michael@0 99 // Helper functions to deal with 32-bit/64-bit Mach-O differences.
michael@0 100 class DynamicImage;
michael@0 101 template<typename MachBits>
michael@0 102 bool FindTextSection(DynamicImage& image);
michael@0 103
michael@0 104 template<typename MachBits>
michael@0 105 uint32_t GetFileTypeFromHeader(DynamicImage& image);
michael@0 106
michael@0 107 //==============================================================================
michael@0 108 // Represents a single dynamically loaded mach-o image
michael@0 109 class DynamicImage {
michael@0 110 public:
michael@0 111 DynamicImage(uint8_t *header, // data is copied
michael@0 112 size_t header_size, // includes load commands
michael@0 113 uint64_t load_address,
michael@0 114 string file_path,
michael@0 115 uintptr_t image_mod_date,
michael@0 116 mach_port_t task,
michael@0 117 cpu_type_t cpu_type)
michael@0 118 : header_(header, header + header_size),
michael@0 119 header_size_(header_size),
michael@0 120 load_address_(load_address),
michael@0 121 vmaddr_(0),
michael@0 122 vmsize_(0),
michael@0 123 slide_(0),
michael@0 124 version_(0),
michael@0 125 file_path_(file_path),
michael@0 126 file_mod_date_(image_mod_date),
michael@0 127 task_(task),
michael@0 128 cpu_type_(cpu_type) {
michael@0 129 CalculateMemoryAndVersionInfo();
michael@0 130 }
michael@0 131
michael@0 132 // Size of mach_header plus load commands
michael@0 133 size_t GetHeaderSize() const {return header_.size();}
michael@0 134
michael@0 135 // Full path to mach-o binary
michael@0 136 string GetFilePath() {return file_path_;}
michael@0 137
michael@0 138 uint64_t GetModDate() const {return file_mod_date_;}
michael@0 139
michael@0 140 // Actual address where the image was loaded
michael@0 141 uint64_t GetLoadAddress() const {return load_address_;}
michael@0 142
michael@0 143 // Address where the image should be loaded
michael@0 144 mach_vm_address_t GetVMAddr() const {return vmaddr_;}
michael@0 145
michael@0 146 // Difference between GetLoadAddress() and GetVMAddr()
michael@0 147 ptrdiff_t GetVMAddrSlide() const {return slide_;}
michael@0 148
michael@0 149 // Size of the image
michael@0 150 mach_vm_size_t GetVMSize() const {return vmsize_;}
michael@0 151
michael@0 152 // Task owning this loaded image
michael@0 153 mach_port_t GetTask() {return task_;}
michael@0 154
michael@0 155 // CPU type of the task
michael@0 156 cpu_type_t GetCPUType() {return cpu_type_;}
michael@0 157
michael@0 158 // filetype from the Mach-O header.
michael@0 159 uint32_t GetFileType();
michael@0 160
michael@0 161 // Return true if the task is a 64-bit architecture.
michael@0 162 bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
michael@0 163
michael@0 164 uint32_t GetVersion() {return version_;}
michael@0 165 // For sorting
michael@0 166 bool operator<(const DynamicImage &inInfo) {
michael@0 167 return GetLoadAddress() < inInfo.GetLoadAddress();
michael@0 168 }
michael@0 169
michael@0 170 // Sanity checking
michael@0 171 bool IsValid() {return GetVMSize() != 0;}
michael@0 172
michael@0 173 private:
michael@0 174 DynamicImage(const DynamicImage &);
michael@0 175 DynamicImage &operator=(const DynamicImage &);
michael@0 176
michael@0 177 friend class DynamicImages;
michael@0 178 template<typename MachBits>
michael@0 179 friend bool FindTextSection(DynamicImage& image);
michael@0 180 template<typename MachBits>
michael@0 181 friend uint32_t GetFileTypeFromHeader(DynamicImage& image);
michael@0 182
michael@0 183 // Initializes vmaddr_, vmsize_, and slide_
michael@0 184 void CalculateMemoryAndVersionInfo();
michael@0 185
michael@0 186 const vector<uint8_t> header_; // our local copy of the header
michael@0 187 size_t header_size_; // mach_header plus load commands
michael@0 188 uint64_t load_address_; // base address image is mapped into
michael@0 189 mach_vm_address_t vmaddr_;
michael@0 190 mach_vm_size_t vmsize_;
michael@0 191 ptrdiff_t slide_;
michael@0 192 uint32_t version_; // Dylib version
michael@0 193 string file_path_; // path dyld used to load the image
michael@0 194 uintptr_t file_mod_date_; // time_t of image file
michael@0 195
michael@0 196 mach_port_t task_;
michael@0 197 cpu_type_t cpu_type_; // CPU type of task_
michael@0 198 };
michael@0 199
michael@0 200 //==============================================================================
michael@0 201 // DynamicImageRef is just a simple wrapper for a pointer to
michael@0 202 // DynamicImage. The reason we use it instead of a simple typedef is so
michael@0 203 // that we can use stl::sort() on a vector of DynamicImageRefs
michael@0 204 // and simple class pointers can't implement operator<().
michael@0 205 //
michael@0 206 class DynamicImageRef {
michael@0 207 public:
michael@0 208 explicit DynamicImageRef(DynamicImage *inP) : p(inP) {}
michael@0 209 // The copy constructor is required by STL
michael@0 210 DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {}
michael@0 211
michael@0 212 bool operator<(const DynamicImageRef &inRef) const {
michael@0 213 return (*const_cast<DynamicImageRef*>(this)->p)
michael@0 214 < (*const_cast<DynamicImageRef&>(inRef).p);
michael@0 215 }
michael@0 216
michael@0 217 bool operator==(const DynamicImageRef &inInfo) const {
michael@0 218 return (*const_cast<DynamicImageRef*>(this)->p).GetLoadAddress() ==
michael@0 219 (*const_cast<DynamicImageRef&>(inInfo)).GetLoadAddress();
michael@0 220 }
michael@0 221
michael@0 222 // Be just like DynamicImage*
michael@0 223 DynamicImage *operator->() {return p;}
michael@0 224 operator DynamicImage*() {return p;}
michael@0 225
michael@0 226 private:
michael@0 227 DynamicImage *p;
michael@0 228 };
michael@0 229
michael@0 230 // Helper function to deal with 32-bit/64-bit Mach-O differences.
michael@0 231 class DynamicImages;
michael@0 232 template<typename MachBits>
michael@0 233 void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
michael@0 234
michael@0 235 //==============================================================================
michael@0 236 // An object of type DynamicImages may be created to allow introspection of
michael@0 237 // an arbitrary task's dynamically loaded mach-o binaries. This makes the
michael@0 238 // assumption that the current task has send rights to the target task.
michael@0 239 class DynamicImages {
michael@0 240 public:
michael@0 241 explicit DynamicImages(mach_port_t task);
michael@0 242
michael@0 243 ~DynamicImages() {
michael@0 244 for (int i = 0; i < GetImageCount(); ++i) {
michael@0 245 delete image_list_[i];
michael@0 246 }
michael@0 247 }
michael@0 248
michael@0 249 // Returns the number of dynamically loaded mach-o images.
michael@0 250 int GetImageCount() const {return static_cast<int>(image_list_.size());}
michael@0 251
michael@0 252 // Returns an individual image.
michael@0 253 DynamicImage *GetImage(int i) {
michael@0 254 if (i < (int)image_list_.size()) {
michael@0 255 return image_list_[i];
michael@0 256 }
michael@0 257 return NULL;
michael@0 258 }
michael@0 259
michael@0 260 // Returns the image corresponding to the main executable.
michael@0 261 DynamicImage *GetExecutableImage();
michael@0 262 int GetExecutableImageIndex();
michael@0 263
michael@0 264 // Returns the task which we're looking at.
michael@0 265 mach_port_t GetTask() const {return task_;}
michael@0 266
michael@0 267 // CPU type of the task
michael@0 268 cpu_type_t GetCPUType() {return cpu_type_;}
michael@0 269
michael@0 270 // Return true if the task is a 64-bit architecture.
michael@0 271 bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
michael@0 272
michael@0 273 // Determine the CPU type of the task being dumped.
michael@0 274 static cpu_type_t DetermineTaskCPUType(task_t task);
michael@0 275
michael@0 276 // Get the native CPU type of this task.
michael@0 277 static cpu_type_t GetNativeCPUType() {
michael@0 278 #if defined(__i386__)
michael@0 279 return CPU_TYPE_I386;
michael@0 280 #elif defined(__x86_64__)
michael@0 281 return CPU_TYPE_X86_64;
michael@0 282 #elif defined(__ppc__)
michael@0 283 return CPU_TYPE_POWERPC;
michael@0 284 #elif defined(__ppc64__)
michael@0 285 return CPU_TYPE_POWERPC64;
michael@0 286 #elif defined(__arm__)
michael@0 287 return CPU_TYPE_ARM;
michael@0 288 #else
michael@0 289 #error "GetNativeCPUType not implemented for this architecture"
michael@0 290 #endif
michael@0 291 }
michael@0 292
michael@0 293 private:
michael@0 294 template<typename MachBits>
michael@0 295 friend void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
michael@0 296
michael@0 297 bool IsOurTask() {return task_ == mach_task_self();}
michael@0 298
michael@0 299 // Initialization
michael@0 300 void ReadImageInfoForTask();
michael@0 301 uint64_t GetDyldAllImageInfosPointer();
michael@0 302
michael@0 303 mach_port_t task_;
michael@0 304 cpu_type_t cpu_type_; // CPU type of task_
michael@0 305 vector<DynamicImageRef> image_list_;
michael@0 306 };
michael@0 307
michael@0 308 // Fill bytes with the contents of memory at a particular
michael@0 309 // location in another task.
michael@0 310 kern_return_t ReadTaskMemory(task_port_t target_task,
michael@0 311 const uint64_t address,
michael@0 312 size_t length,
michael@0 313 vector<uint8_t> &bytes);
michael@0 314
michael@0 315 } // namespace google_breakpad
michael@0 316
michael@0 317 #endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__

mercurial