/thirdparty/breakpad/client/mac/handler/dynamic_images.h

http://github.com/tomahawk-player/tomahawk · C Header · 317 lines · 179 code · 56 blank · 82 comment · 6 complexity · af8252893f769a920b3b3ee3353284b6 MD5 · raw file

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