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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/dynamic_images.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,317 @@
     1.4 +// Copyright (c) 2007, Google Inc.
     1.5 +// All rights reserved.
     1.6 +//
     1.7 +// Redistribution and use in source and binary forms, with or without
     1.8 +// modification, are permitted provided that the following conditions are
     1.9 +// met:
    1.10 +//
    1.11 +//     * Redistributions of source code must retain the above copyright
    1.12 +// notice, this list of conditions and the following disclaimer.
    1.13 +//     * Redistributions in binary form must reproduce the above
    1.14 +// copyright notice, this list of conditions and the following disclaimer
    1.15 +// in the documentation and/or other materials provided with the
    1.16 +// distribution.
    1.17 +//     * Neither the name of Google Inc. nor the names of its
    1.18 +// contributors may be used to endorse or promote products derived from
    1.19 +// this software without specific prior written permission.
    1.20 +//
    1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.32 +
    1.33 +//  dynamic_images.h
    1.34 +//
    1.35 +//    Implements most of the function of the dyld API, but allowing an
    1.36 +//    arbitrary task to be introspected, unlike the dyld API which
    1.37 +//    only allows operation on the current task.  The current implementation
    1.38 +//    is limited to use by 32-bit tasks.
    1.39 +
    1.40 +#ifndef CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
    1.41 +#define CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
    1.42 +
    1.43 +#include <mach/mach.h>
    1.44 +#include <mach-o/dyld.h>
    1.45 +#include <mach-o/loader.h>
    1.46 +#include <sys/types.h>
    1.47 +
    1.48 +#include <string>
    1.49 +#include <vector>
    1.50 +
    1.51 +#include "mach_vm_compat.h"
    1.52 +
    1.53 +namespace google_breakpad {
    1.54 +
    1.55 +using std::string;
    1.56 +using std::vector;
    1.57 +
    1.58 +//==============================================================================
    1.59 +// The memory layout of this struct matches the dyld_image_info struct
    1.60 +// defined in "dyld_gdb.h" in the darwin source.
    1.61 +typedef struct dyld_image_info32 {
    1.62 +  uint32_t                   load_address_;  // struct mach_header*
    1.63 +  uint32_t                   file_path_;     // char*
    1.64 +  uint32_t                   file_mod_date_;
    1.65 +} dyld_image_info32;
    1.66 +
    1.67 +typedef struct dyld_image_info64 {
    1.68 +  uint64_t                   load_address_;  // struct mach_header*
    1.69 +  uint64_t                   file_path_;     // char*
    1.70 +  uint64_t                   file_mod_date_;
    1.71 +} dyld_image_info64;
    1.72 +
    1.73 +//==============================================================================
    1.74 +// This is as defined in "dyld_gdb.h" in the darwin source.
    1.75 +// _dyld_all_image_infos (in dyld) is a structure of this type
    1.76 +// which will be used to determine which dynamic code has been loaded.
    1.77 +typedef struct dyld_all_image_infos32 {
    1.78 +  uint32_t                      version;  // == 1 in Mac OS X 10.4
    1.79 +  uint32_t                      infoArrayCount;
    1.80 +  uint32_t                      infoArray;  // const struct dyld_image_info*
    1.81 +  uint32_t                      notification;
    1.82 +  bool                          processDetachedFromSharedRegion;
    1.83 +} dyld_all_image_infos32;
    1.84 +
    1.85 +typedef struct dyld_all_image_infos64 {
    1.86 +  uint32_t                      version;  // == 1 in Mac OS X 10.4
    1.87 +  uint32_t                      infoArrayCount;
    1.88 +  uint64_t                      infoArray;  // const struct dyld_image_info*
    1.89 +  uint64_t                      notification;
    1.90 +  bool                          processDetachedFromSharedRegion;
    1.91 +} dyld_all_image_infos64;
    1.92 +
    1.93 +// some typedefs to isolate 64/32 bit differences
    1.94 +#ifdef __LP64__
    1.95 +typedef mach_header_64 breakpad_mach_header;
    1.96 +typedef segment_command_64 breakpad_mach_segment_command;
    1.97 +#else
    1.98 +typedef mach_header breakpad_mach_header;
    1.99 +typedef segment_command breakpad_mach_segment_command;
   1.100 +#endif
   1.101 +
   1.102 +// Helper functions to deal with 32-bit/64-bit Mach-O differences.
   1.103 +class DynamicImage;
   1.104 +template<typename MachBits>
   1.105 +bool FindTextSection(DynamicImage& image);
   1.106 +
   1.107 +template<typename MachBits>
   1.108 +uint32_t GetFileTypeFromHeader(DynamicImage& image);
   1.109 +
   1.110 +//==============================================================================
   1.111 +// Represents a single dynamically loaded mach-o image
   1.112 +class DynamicImage {
   1.113 + public:
   1.114 +  DynamicImage(uint8_t *header,     // data is copied
   1.115 +               size_t header_size,  // includes load commands
   1.116 +               uint64_t load_address,
   1.117 +               string file_path,
   1.118 +               uintptr_t image_mod_date,
   1.119 +               mach_port_t task,
   1.120 +               cpu_type_t cpu_type)
   1.121 +    : header_(header, header + header_size),
   1.122 +      header_size_(header_size),
   1.123 +      load_address_(load_address),
   1.124 +      vmaddr_(0),
   1.125 +      vmsize_(0),
   1.126 +      slide_(0),
   1.127 +      version_(0),
   1.128 +      file_path_(file_path),
   1.129 +      file_mod_date_(image_mod_date),
   1.130 +      task_(task),
   1.131 +      cpu_type_(cpu_type) {
   1.132 +    CalculateMemoryAndVersionInfo();
   1.133 +  }
   1.134 +
   1.135 +  // Size of mach_header plus load commands
   1.136 +  size_t GetHeaderSize() const {return header_.size();}
   1.137 +
   1.138 +  // Full path to mach-o binary
   1.139 +  string GetFilePath() {return file_path_;}
   1.140 +
   1.141 +  uint64_t GetModDate() const {return file_mod_date_;}
   1.142 +
   1.143 +  // Actual address where the image was loaded
   1.144 +  uint64_t GetLoadAddress() const {return load_address_;}
   1.145 +
   1.146 +  // Address where the image should be loaded
   1.147 +  mach_vm_address_t GetVMAddr() const {return vmaddr_;}
   1.148 +
   1.149 +  // Difference between GetLoadAddress() and GetVMAddr()
   1.150 +  ptrdiff_t GetVMAddrSlide() const {return slide_;}
   1.151 +
   1.152 +  // Size of the image
   1.153 +  mach_vm_size_t GetVMSize() const {return vmsize_;}
   1.154 +
   1.155 +  // Task owning this loaded image
   1.156 +  mach_port_t GetTask() {return task_;}
   1.157 +
   1.158 +  // CPU type of the task
   1.159 +  cpu_type_t GetCPUType() {return cpu_type_;}
   1.160 +
   1.161 +  // filetype from the Mach-O header.
   1.162 +  uint32_t GetFileType();
   1.163 +
   1.164 +  // Return true if the task is a 64-bit architecture.
   1.165 +  bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
   1.166 +
   1.167 +  uint32_t GetVersion() {return version_;}
   1.168 +  // For sorting
   1.169 +  bool operator<(const DynamicImage &inInfo) {
   1.170 +    return GetLoadAddress() < inInfo.GetLoadAddress();
   1.171 +  }
   1.172 +
   1.173 +  // Sanity checking
   1.174 +  bool IsValid() {return GetVMSize() != 0;}
   1.175 +
   1.176 + private:
   1.177 +  DynamicImage(const DynamicImage &);
   1.178 +  DynamicImage &operator=(const DynamicImage &);
   1.179 +
   1.180 +  friend class DynamicImages;
   1.181 +  template<typename MachBits>
   1.182 +  friend bool FindTextSection(DynamicImage& image);
   1.183 +  template<typename MachBits>
   1.184 +  friend uint32_t GetFileTypeFromHeader(DynamicImage& image);
   1.185 +
   1.186 +  // Initializes vmaddr_, vmsize_, and slide_
   1.187 +  void CalculateMemoryAndVersionInfo();
   1.188 +
   1.189 +  const vector<uint8_t>   header_;        // our local copy of the header
   1.190 +  size_t                  header_size_;    // mach_header plus load commands
   1.191 +  uint64_t                load_address_;   // base address image is mapped into
   1.192 +  mach_vm_address_t       vmaddr_;
   1.193 +  mach_vm_size_t          vmsize_;
   1.194 +  ptrdiff_t               slide_;
   1.195 +  uint32_t                version_;        // Dylib version
   1.196 +  string                  file_path_;     // path dyld used to load the image
   1.197 +  uintptr_t               file_mod_date_;  // time_t of image file
   1.198 +
   1.199 +  mach_port_t             task_;
   1.200 +  cpu_type_t              cpu_type_;        // CPU type of task_
   1.201 +};
   1.202 +
   1.203 +//==============================================================================
   1.204 +// DynamicImageRef is just a simple wrapper for a pointer to
   1.205 +// DynamicImage.  The reason we use it instead of a simple typedef is so
   1.206 +// that we can use stl::sort() on a vector of DynamicImageRefs
   1.207 +// and simple class pointers can't implement operator<().
   1.208 +//
   1.209 +class DynamicImageRef {
   1.210 + public:
   1.211 +  explicit DynamicImageRef(DynamicImage *inP) : p(inP) {}
   1.212 +  // The copy constructor is required by STL
   1.213 +  DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {}
   1.214 +
   1.215 +  bool operator<(const DynamicImageRef &inRef) const {
   1.216 +    return (*const_cast<DynamicImageRef*>(this)->p)
   1.217 +      < (*const_cast<DynamicImageRef&>(inRef).p);
   1.218 +  }
   1.219 +
   1.220 +  bool operator==(const DynamicImageRef &inInfo) const {
   1.221 +    return (*const_cast<DynamicImageRef*>(this)->p).GetLoadAddress() ==
   1.222 +        (*const_cast<DynamicImageRef&>(inInfo)).GetLoadAddress();
   1.223 +  }
   1.224 +
   1.225 +  // Be just like DynamicImage*
   1.226 +  DynamicImage  *operator->() {return p;}
   1.227 +  operator DynamicImage*() {return p;}
   1.228 +
   1.229 + private:
   1.230 +  DynamicImage  *p;
   1.231 +};
   1.232 +
   1.233 +// Helper function to deal with 32-bit/64-bit Mach-O differences.
   1.234 +class DynamicImages;
   1.235 +template<typename MachBits>
   1.236 +void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
   1.237 +
   1.238 +//==============================================================================
   1.239 +// An object of type DynamicImages may be created to allow introspection of
   1.240 +// an arbitrary task's dynamically loaded mach-o binaries.  This makes the
   1.241 +// assumption that the current task has send rights to the target task.
   1.242 +class DynamicImages {
   1.243 + public:
   1.244 +  explicit DynamicImages(mach_port_t task);
   1.245 +
   1.246 +  ~DynamicImages() {
   1.247 +    for (int i = 0; i < GetImageCount(); ++i) {
   1.248 +      delete image_list_[i];
   1.249 +    }
   1.250 +  }
   1.251 +
   1.252 +  // Returns the number of dynamically loaded mach-o images.
   1.253 +  int GetImageCount() const {return static_cast<int>(image_list_.size());}
   1.254 +
   1.255 +  // Returns an individual image.
   1.256 +  DynamicImage *GetImage(int i) {
   1.257 +    if (i < (int)image_list_.size()) {
   1.258 +      return image_list_[i];
   1.259 +    }
   1.260 +    return NULL;
   1.261 +  }
   1.262 +
   1.263 +  // Returns the image corresponding to the main executable.
   1.264 +  DynamicImage *GetExecutableImage();
   1.265 +  int GetExecutableImageIndex();
   1.266 +
   1.267 +  // Returns the task which we're looking at.
   1.268 +  mach_port_t GetTask() const {return task_;}
   1.269 +
   1.270 +  // CPU type of the task
   1.271 +  cpu_type_t GetCPUType() {return cpu_type_;}
   1.272 +
   1.273 +  // Return true if the task is a 64-bit architecture.
   1.274 +  bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
   1.275 +
   1.276 +  // Determine the CPU type of the task being dumped.
   1.277 +  static cpu_type_t DetermineTaskCPUType(task_t task);
   1.278 +
   1.279 +  // Get the native CPU type of this task.
   1.280 +  static cpu_type_t GetNativeCPUType() {
   1.281 +#if defined(__i386__)
   1.282 +    return CPU_TYPE_I386;
   1.283 +#elif defined(__x86_64__)
   1.284 +    return CPU_TYPE_X86_64;
   1.285 +#elif defined(__ppc__)
   1.286 +    return CPU_TYPE_POWERPC;
   1.287 +#elif defined(__ppc64__)
   1.288 +    return CPU_TYPE_POWERPC64;
   1.289 +#elif defined(__arm__)
   1.290 +    return CPU_TYPE_ARM;
   1.291 +#else
   1.292 +#error "GetNativeCPUType not implemented for this architecture"
   1.293 +#endif
   1.294 +  }
   1.295 +
   1.296 + private:
   1.297 +  template<typename MachBits>
   1.298 +  friend void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
   1.299 +
   1.300 +  bool IsOurTask() {return task_ == mach_task_self();}
   1.301 +
   1.302 +  // Initialization
   1.303 +  void ReadImageInfoForTask();
   1.304 +  uint64_t GetDyldAllImageInfosPointer();
   1.305 +
   1.306 +  mach_port_t              task_;
   1.307 +  cpu_type_t               cpu_type_;  // CPU type of task_
   1.308 +  vector<DynamicImageRef>  image_list_;
   1.309 +};
   1.310 +
   1.311 +// Fill bytes with the contents of memory at a particular
   1.312 +// location in another task.
   1.313 +kern_return_t ReadTaskMemory(task_port_t target_task,
   1.314 +                             const uint64_t address,
   1.315 +                             size_t length,
   1.316 +                             vector<uint8_t> &bytes);
   1.317 +
   1.318 +}   // namespace google_breakpad
   1.319 +
   1.320 +#endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__

mercurial