Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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.
30 // dynamic_images.h
31 //
32 // Implements most of the function of the dyld API, but allowing an
33 // arbitrary task to be introspected, unlike the dyld API which
34 // only allows operation on the current task. The current implementation
35 // is limited to use by 32-bit tasks.
37 #ifndef CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
38 #define CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
40 #include <mach/mach.h>
41 #include <mach-o/dyld.h>
42 #include <mach-o/loader.h>
43 #include <sys/types.h>
45 #include <string>
46 #include <vector>
48 #include "mach_vm_compat.h"
50 namespace google_breakpad {
52 using std::string;
53 using std::vector;
55 //==============================================================================
56 // The memory layout of this struct matches the dyld_image_info struct
57 // defined in "dyld_gdb.h" in the darwin source.
58 typedef struct dyld_image_info32 {
59 uint32_t load_address_; // struct mach_header*
60 uint32_t file_path_; // char*
61 uint32_t file_mod_date_;
62 } dyld_image_info32;
64 typedef struct dyld_image_info64 {
65 uint64_t load_address_; // struct mach_header*
66 uint64_t file_path_; // char*
67 uint64_t file_mod_date_;
68 } dyld_image_info64;
70 //==============================================================================
71 // This is as defined in "dyld_gdb.h" in the darwin source.
72 // _dyld_all_image_infos (in dyld) is a structure of this type
73 // which will be used to determine which dynamic code has been loaded.
74 typedef struct dyld_all_image_infos32 {
75 uint32_t version; // == 1 in Mac OS X 10.4
76 uint32_t infoArrayCount;
77 uint32_t infoArray; // const struct dyld_image_info*
78 uint32_t notification;
79 bool processDetachedFromSharedRegion;
80 } dyld_all_image_infos32;
82 typedef struct dyld_all_image_infos64 {
83 uint32_t version; // == 1 in Mac OS X 10.4
84 uint32_t infoArrayCount;
85 uint64_t infoArray; // const struct dyld_image_info*
86 uint64_t notification;
87 bool processDetachedFromSharedRegion;
88 } dyld_all_image_infos64;
90 // some typedefs to isolate 64/32 bit differences
91 #ifdef __LP64__
92 typedef mach_header_64 breakpad_mach_header;
93 typedef segment_command_64 breakpad_mach_segment_command;
94 #else
95 typedef mach_header breakpad_mach_header;
96 typedef segment_command breakpad_mach_segment_command;
97 #endif
99 // Helper functions to deal with 32-bit/64-bit Mach-O differences.
100 class DynamicImage;
101 template<typename MachBits>
102 bool FindTextSection(DynamicImage& image);
104 template<typename MachBits>
105 uint32_t GetFileTypeFromHeader(DynamicImage& image);
107 //==============================================================================
108 // Represents a single dynamically loaded mach-o image
109 class DynamicImage {
110 public:
111 DynamicImage(uint8_t *header, // data is copied
112 size_t header_size, // includes load commands
113 uint64_t load_address,
114 string file_path,
115 uintptr_t image_mod_date,
116 mach_port_t task,
117 cpu_type_t cpu_type)
118 : header_(header, header + header_size),
119 header_size_(header_size),
120 load_address_(load_address),
121 vmaddr_(0),
122 vmsize_(0),
123 slide_(0),
124 version_(0),
125 file_path_(file_path),
126 file_mod_date_(image_mod_date),
127 task_(task),
128 cpu_type_(cpu_type) {
129 CalculateMemoryAndVersionInfo();
130 }
132 // Size of mach_header plus load commands
133 size_t GetHeaderSize() const {return header_.size();}
135 // Full path to mach-o binary
136 string GetFilePath() {return file_path_;}
138 uint64_t GetModDate() const {return file_mod_date_;}
140 // Actual address where the image was loaded
141 uint64_t GetLoadAddress() const {return load_address_;}
143 // Address where the image should be loaded
144 mach_vm_address_t GetVMAddr() const {return vmaddr_;}
146 // Difference between GetLoadAddress() and GetVMAddr()
147 ptrdiff_t GetVMAddrSlide() const {return slide_;}
149 // Size of the image
150 mach_vm_size_t GetVMSize() const {return vmsize_;}
152 // Task owning this loaded image
153 mach_port_t GetTask() {return task_;}
155 // CPU type of the task
156 cpu_type_t GetCPUType() {return cpu_type_;}
158 // filetype from the Mach-O header.
159 uint32_t GetFileType();
161 // Return true if the task is a 64-bit architecture.
162 bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
164 uint32_t GetVersion() {return version_;}
165 // For sorting
166 bool operator<(const DynamicImage &inInfo) {
167 return GetLoadAddress() < inInfo.GetLoadAddress();
168 }
170 // Sanity checking
171 bool IsValid() {return GetVMSize() != 0;}
173 private:
174 DynamicImage(const DynamicImage &);
175 DynamicImage &operator=(const DynamicImage &);
177 friend class DynamicImages;
178 template<typename MachBits>
179 friend bool FindTextSection(DynamicImage& image);
180 template<typename MachBits>
181 friend uint32_t GetFileTypeFromHeader(DynamicImage& image);
183 // Initializes vmaddr_, vmsize_, and slide_
184 void CalculateMemoryAndVersionInfo();
186 const vector<uint8_t> header_; // our local copy of the header
187 size_t header_size_; // mach_header plus load commands
188 uint64_t load_address_; // base address image is mapped into
189 mach_vm_address_t vmaddr_;
190 mach_vm_size_t vmsize_;
191 ptrdiff_t slide_;
192 uint32_t version_; // Dylib version
193 string file_path_; // path dyld used to load the image
194 uintptr_t file_mod_date_; // time_t of image file
196 mach_port_t task_;
197 cpu_type_t cpu_type_; // CPU type of task_
198 };
200 //==============================================================================
201 // DynamicImageRef is just a simple wrapper for a pointer to
202 // DynamicImage. The reason we use it instead of a simple typedef is so
203 // that we can use stl::sort() on a vector of DynamicImageRefs
204 // and simple class pointers can't implement operator<().
205 //
206 class DynamicImageRef {
207 public:
208 explicit DynamicImageRef(DynamicImage *inP) : p(inP) {}
209 // The copy constructor is required by STL
210 DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {}
212 bool operator<(const DynamicImageRef &inRef) const {
213 return (*const_cast<DynamicImageRef*>(this)->p)
214 < (*const_cast<DynamicImageRef&>(inRef).p);
215 }
217 bool operator==(const DynamicImageRef &inInfo) const {
218 return (*const_cast<DynamicImageRef*>(this)->p).GetLoadAddress() ==
219 (*const_cast<DynamicImageRef&>(inInfo)).GetLoadAddress();
220 }
222 // Be just like DynamicImage*
223 DynamicImage *operator->() {return p;}
224 operator DynamicImage*() {return p;}
226 private:
227 DynamicImage *p;
228 };
230 // Helper function to deal with 32-bit/64-bit Mach-O differences.
231 class DynamicImages;
232 template<typename MachBits>
233 void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
235 //==============================================================================
236 // An object of type DynamicImages may be created to allow introspection of
237 // an arbitrary task's dynamically loaded mach-o binaries. This makes the
238 // assumption that the current task has send rights to the target task.
239 class DynamicImages {
240 public:
241 explicit DynamicImages(mach_port_t task);
243 ~DynamicImages() {
244 for (int i = 0; i < GetImageCount(); ++i) {
245 delete image_list_[i];
246 }
247 }
249 // Returns the number of dynamically loaded mach-o images.
250 int GetImageCount() const {return static_cast<int>(image_list_.size());}
252 // Returns an individual image.
253 DynamicImage *GetImage(int i) {
254 if (i < (int)image_list_.size()) {
255 return image_list_[i];
256 }
257 return NULL;
258 }
260 // Returns the image corresponding to the main executable.
261 DynamicImage *GetExecutableImage();
262 int GetExecutableImageIndex();
264 // Returns the task which we're looking at.
265 mach_port_t GetTask() const {return task_;}
267 // CPU type of the task
268 cpu_type_t GetCPUType() {return cpu_type_;}
270 // Return true if the task is a 64-bit architecture.
271 bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
273 // Determine the CPU type of the task being dumped.
274 static cpu_type_t DetermineTaskCPUType(task_t task);
276 // Get the native CPU type of this task.
277 static cpu_type_t GetNativeCPUType() {
278 #if defined(__i386__)
279 return CPU_TYPE_I386;
280 #elif defined(__x86_64__)
281 return CPU_TYPE_X86_64;
282 #elif defined(__ppc__)
283 return CPU_TYPE_POWERPC;
284 #elif defined(__ppc64__)
285 return CPU_TYPE_POWERPC64;
286 #elif defined(__arm__)
287 return CPU_TYPE_ARM;
288 #else
289 #error "GetNativeCPUType not implemented for this architecture"
290 #endif
291 }
293 private:
294 template<typename MachBits>
295 friend void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
297 bool IsOurTask() {return task_ == mach_task_self();}
299 // Initialization
300 void ReadImageInfoForTask();
301 uint64_t GetDyldAllImageInfosPointer();
303 mach_port_t task_;
304 cpu_type_t cpu_type_; // CPU type of task_
305 vector<DynamicImageRef> image_list_;
306 };
308 // Fill bytes with the contents of memory at a particular
309 // location in another task.
310 kern_return_t ReadTaskMemory(task_port_t target_task,
311 const uint64_t address,
312 size_t length,
313 vector<uint8_t> &bytes);
315 } // namespace google_breakpad
317 #endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__