summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Breakpad/src/client/mac/handler/dynamic_images.h')
-rw-r--r--3rdParty/Breakpad/src/client/mac/handler/dynamic_images.h317
1 files changed, 317 insertions, 0 deletions
diff --git a/3rdParty/Breakpad/src/client/mac/handler/dynamic_images.h b/3rdParty/Breakpad/src/client/mac/handler/dynamic_images.h
new file mode 100644
index 0000000..d039eda
--- /dev/null
+++ b/3rdParty/Breakpad/src/client/mac/handler/dynamic_images.h
@@ -0,0 +1,317 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// dynamic_images.h
+//
+// Implements most of the function of the dyld API, but allowing an
+// arbitrary task to be introspected, unlike the dyld API which
+// only allows operation on the current task. The current implementation
+// is limited to use by 32-bit tasks.
+
+#ifndef CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
+#define CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
+
+#include <mach/mach.h>
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#include <sys/types.h>
+
+#include <string>
+#include <vector>
+
+#include "mach_vm_compat.h"
+
+namespace google_breakpad {
+
+using std::string;
+using std::vector;
+
+//==============================================================================
+// The memory layout of this struct matches the dyld_image_info struct
+// defined in "dyld_gdb.h" in the darwin source.
+typedef struct dyld_image_info32 {
+ uint32_t load_address_; // struct mach_header*
+ uint32_t file_path_; // char*
+ uint32_t file_mod_date_;
+} dyld_image_info32;
+
+typedef struct dyld_image_info64 {
+ uint64_t load_address_; // struct mach_header*
+ uint64_t file_path_; // char*
+ uint64_t file_mod_date_;
+} dyld_image_info64;
+
+//==============================================================================
+// This is as defined in "dyld_gdb.h" in the darwin source.
+// _dyld_all_image_infos (in dyld) is a structure of this type
+// which will be used to determine which dynamic code has been loaded.
+typedef struct dyld_all_image_infos32 {
+ uint32_t version; // == 1 in Mac OS X 10.4
+ uint32_t infoArrayCount;
+ uint32_t infoArray; // const struct dyld_image_info*
+ uint32_t notification;
+ bool processDetachedFromSharedRegion;
+} dyld_all_image_infos32;
+
+typedef struct dyld_all_image_infos64 {
+ uint32_t version; // == 1 in Mac OS X 10.4
+ uint32_t infoArrayCount;
+ uint64_t infoArray; // const struct dyld_image_info*
+ uint64_t notification;
+ bool processDetachedFromSharedRegion;
+} dyld_all_image_infos64;
+
+// some typedefs to isolate 64/32 bit differences
+#ifdef __LP64__
+typedef mach_header_64 breakpad_mach_header;
+typedef segment_command_64 breakpad_mach_segment_command;
+#else
+typedef mach_header breakpad_mach_header;
+typedef segment_command breakpad_mach_segment_command;
+#endif
+
+// Helper functions to deal with 32-bit/64-bit Mach-O differences.
+class DynamicImage;
+template<typename MachBits>
+bool FindTextSection(DynamicImage& image);
+
+template<typename MachBits>
+uint32_t GetFileTypeFromHeader(DynamicImage& image);
+
+//==============================================================================
+// Represents a single dynamically loaded mach-o image
+class DynamicImage {
+ public:
+ DynamicImage(uint8_t *header, // data is copied
+ size_t header_size, // includes load commands
+ uint64_t load_address,
+ string file_path,
+ uintptr_t image_mod_date,
+ mach_port_t task,
+ cpu_type_t cpu_type)
+ : header_(header, header + header_size),
+ header_size_(header_size),
+ load_address_(load_address),
+ vmaddr_(0),
+ vmsize_(0),
+ slide_(0),
+ version_(0),
+ file_path_(file_path),
+ file_mod_date_(image_mod_date),
+ task_(task),
+ cpu_type_(cpu_type) {
+ CalculateMemoryAndVersionInfo();
+ }
+
+ // Size of mach_header plus load commands
+ size_t GetHeaderSize() const {return header_.size();}
+
+ // Full path to mach-o binary
+ string GetFilePath() {return file_path_;}
+
+ uint64_t GetModDate() const {return file_mod_date_;}
+
+ // Actual address where the image was loaded
+ uint64_t GetLoadAddress() const {return load_address_;}
+
+ // Address where the image should be loaded
+ mach_vm_address_t GetVMAddr() const {return vmaddr_;}
+
+ // Difference between GetLoadAddress() and GetVMAddr()
+ ptrdiff_t GetVMAddrSlide() const {return slide_;}
+
+ // Size of the image
+ mach_vm_size_t GetVMSize() const {return vmsize_;}
+
+ // Task owning this loaded image
+ mach_port_t GetTask() {return task_;}
+
+ // CPU type of the task
+ cpu_type_t GetCPUType() {return cpu_type_;}
+
+ // filetype from the Mach-O header.
+ uint32_t GetFileType();
+
+ // Return true if the task is a 64-bit architecture.
+ bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
+
+ uint32_t GetVersion() {return version_;}
+ // For sorting
+ bool operator<(const DynamicImage &inInfo) {
+ return GetLoadAddress() < inInfo.GetLoadAddress();
+ }
+
+ // Sanity checking
+ bool IsValid() {return GetVMSize() != 0;}
+
+ private:
+ DynamicImage(const DynamicImage &);
+ DynamicImage &operator=(const DynamicImage &);
+
+ friend class DynamicImages;
+ template<typename MachBits>
+ friend bool FindTextSection(DynamicImage& image);
+ template<typename MachBits>
+ friend uint32_t GetFileTypeFromHeader(DynamicImage& image);
+
+ // Initializes vmaddr_, vmsize_, and slide_
+ void CalculateMemoryAndVersionInfo();
+
+ const vector<uint8_t> header_; // our local copy of the header
+ size_t header_size_; // mach_header plus load commands
+ uint64_t load_address_; // base address image is mapped into
+ mach_vm_address_t vmaddr_;
+ mach_vm_size_t vmsize_;
+ ptrdiff_t slide_;
+ uint32_t version_; // Dylib version
+ string file_path_; // path dyld used to load the image
+ uintptr_t file_mod_date_; // time_t of image file
+
+ mach_port_t task_;
+ cpu_type_t cpu_type_; // CPU type of task_
+};
+
+//==============================================================================
+// DynamicImageRef is just a simple wrapper for a pointer to
+// DynamicImage. The reason we use it instead of a simple typedef is so
+// that we can use stl::sort() on a vector of DynamicImageRefs
+// and simple class pointers can't implement operator<().
+//
+class DynamicImageRef {
+ public:
+ explicit DynamicImageRef(DynamicImage *inP) : p(inP) {}
+ // The copy constructor is required by STL
+ DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {}
+
+ bool operator<(const DynamicImageRef &inRef) const {
+ return (*const_cast<DynamicImageRef*>(this)->p)
+ < (*const_cast<DynamicImageRef&>(inRef).p);
+ }
+
+ bool operator==(const DynamicImageRef &inInfo) const {
+ return (*const_cast<DynamicImageRef*>(this)->p).GetLoadAddress() ==
+ (*const_cast<DynamicImageRef&>(inInfo)).GetLoadAddress();
+ }
+
+ // Be just like DynamicImage*
+ DynamicImage *operator->() {return p;}
+ operator DynamicImage*() {return p;}
+
+ private:
+ DynamicImage *p;
+};
+
+// Helper function to deal with 32-bit/64-bit Mach-O differences.
+class DynamicImages;
+template<typename MachBits>
+void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
+
+//==============================================================================
+// An object of type DynamicImages may be created to allow introspection of
+// an arbitrary task's dynamically loaded mach-o binaries. This makes the
+// assumption that the current task has send rights to the target task.
+class DynamicImages {
+ public:
+ explicit DynamicImages(mach_port_t task);
+
+ ~DynamicImages() {
+ for (int i = 0; i < GetImageCount(); ++i) {
+ delete image_list_[i];
+ }
+ }
+
+ // Returns the number of dynamically loaded mach-o images.
+ int GetImageCount() const {return static_cast<int>(image_list_.size());}
+
+ // Returns an individual image.
+ DynamicImage *GetImage(int i) {
+ if (i < (int)image_list_.size()) {
+ return image_list_[i];
+ }
+ return NULL;
+ }
+
+ // Returns the image corresponding to the main executable.
+ DynamicImage *GetExecutableImage();
+ int GetExecutableImageIndex();
+
+ // Returns the task which we're looking at.
+ mach_port_t GetTask() const {return task_;}
+
+ // CPU type of the task
+ cpu_type_t GetCPUType() {return cpu_type_;}
+
+ // Return true if the task is a 64-bit architecture.
+ bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
+
+ // Determine the CPU type of the task being dumped.
+ static cpu_type_t DetermineTaskCPUType(task_t task);
+
+ // Get the native CPU type of this task.
+ static cpu_type_t GetNativeCPUType() {
+#if defined(__i386__)
+ return CPU_TYPE_I386;
+#elif defined(__x86_64__)
+ return CPU_TYPE_X86_64;
+#elif defined(__ppc__)
+ return CPU_TYPE_POWERPC;
+#elif defined(__ppc64__)
+ return CPU_TYPE_POWERPC64;
+#elif defined(__arm__)
+ return CPU_TYPE_ARM;
+#else
+#error "GetNativeCPUType not implemented for this architecture"
+#endif
+ }
+
+ private:
+ template<typename MachBits>
+ friend void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
+
+ bool IsOurTask() {return task_ == mach_task_self();}
+
+ // Initialization
+ void ReadImageInfoForTask();
+ uint64_t GetDyldAllImageInfosPointer();
+
+ mach_port_t task_;
+ cpu_type_t cpu_type_; // CPU type of task_
+ vector<DynamicImageRef> image_list_;
+};
+
+// Fill bytes with the contents of memory at a particular
+// location in another task.
+kern_return_t ReadTaskMemory(task_port_t target_task,
+ const uint64_t address,
+ size_t length,
+ vector<uint8_t> &bytes);
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__