|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
|
3 |
|
4 // Copyright (c) 2006, 2010, 2012, 2013 Google Inc. |
|
5 // All rights reserved. |
|
6 // |
|
7 // Redistribution and use in source and binary forms, with or without |
|
8 // modification, are permitted provided that the following conditions are |
|
9 // met: |
|
10 // |
|
11 // * Redistributions of source code must retain the above copyright |
|
12 // notice, this list of conditions and the following disclaimer. |
|
13 // * Redistributions in binary form must reproduce the above |
|
14 // copyright notice, this list of conditions and the following disclaimer |
|
15 // in the documentation and/or other materials provided with the |
|
16 // distribution. |
|
17 // * Neither the name of Google Inc. nor the names of its |
|
18 // contributors may be used to endorse or promote products derived from |
|
19 // this software without specific prior written permission. |
|
20 // |
|
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
32 |
|
33 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> |
|
34 |
|
35 // module.h: Define google_breakpad::Module. A Module holds debugging |
|
36 // information, and can write that information out as a Breakpad |
|
37 // symbol file. |
|
38 |
|
39 |
|
40 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. |
|
41 // Copyright (c) 2001, 2002 Peter Dimov |
|
42 // |
|
43 // Permission to copy, use, modify, sell and distribute this software |
|
44 // is granted provided this copyright notice appears in all copies. |
|
45 // This software is provided "as is" without express or implied |
|
46 // warranty, and with no claim as to its suitability for any purpose. |
|
47 // |
|
48 // See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. |
|
49 // |
|
50 |
|
51 |
|
52 // This file is derived from the following files in |
|
53 // toolkit/crashreporter/google-breakpad: |
|
54 // src/common/unique_string.h |
|
55 // src/common/scoped_ptr.h |
|
56 // src/common/module.h |
|
57 |
|
58 // External interface for the "Common" component of LUL. |
|
59 |
|
60 #ifndef LulCommonExt_h |
|
61 #define LulCommonExt_h |
|
62 |
|
63 #include <stdlib.h> |
|
64 #include <stdio.h> |
|
65 #include <stdint.h> |
|
66 |
|
67 #include <string> |
|
68 #include <map> |
|
69 #include <vector> |
|
70 #include <cstddef> // for std::ptrdiff_t |
|
71 |
|
72 #include "mozilla/Assertions.h" |
|
73 #include "mozilla/NullPtr.h" |
|
74 |
|
75 namespace lul { |
|
76 |
|
77 //////////////////////////////////////////////////////////////// |
|
78 // UniqueString |
|
79 // |
|
80 |
|
81 // Abstract type |
|
82 class UniqueString; |
|
83 |
|
84 // Unique-ify a string. |ToUniqueString| can never return nullptr. |
|
85 const UniqueString* ToUniqueString(std::string); |
|
86 |
|
87 // Get the contained C string (debugging only) |
|
88 const char* const FromUniqueString(const UniqueString*); |
|
89 |
|
90 // Some handy pre-uniqified strings. Z is an escape character: |
|
91 // ZS '$' |
|
92 // ZD '.' |
|
93 // Zeq '=' |
|
94 // Zplus '+' |
|
95 // Zstar '*' |
|
96 // Zslash '/' |
|
97 // Zpercent '%' |
|
98 // Zat '@' |
|
99 // Zcaret '^' |
|
100 |
|
101 // Note that ustr__empty and (UniqueString*)nullptr are considered |
|
102 // to be different. |
|
103 // |
|
104 // Unfortunately these have to be written as functions so as to |
|
105 // make them safe to use in static initialisers. |
|
106 |
|
107 // "" |
|
108 inline static const UniqueString* ustr__empty() { |
|
109 static const UniqueString* us = nullptr; |
|
110 if (!us) us = ToUniqueString(""); |
|
111 return us; |
|
112 } |
|
113 |
|
114 // ".cfa" |
|
115 inline static const UniqueString* ustr__ZDcfa() { |
|
116 static const UniqueString* us = nullptr; |
|
117 if (!us) us = ToUniqueString(".cfa"); |
|
118 return us; |
|
119 } |
|
120 |
|
121 // ".ra" |
|
122 inline static const UniqueString* ustr__ZDra() { |
|
123 static const UniqueString* us = nullptr; |
|
124 if (!us) us = ToUniqueString(".ra"); |
|
125 return us; |
|
126 } |
|
127 |
|
128 |
|
129 //////////////////////////////////////////////////////////////// |
|
130 // GUID |
|
131 // |
|
132 |
|
133 typedef struct { |
|
134 uint32_t data1; |
|
135 uint16_t data2; |
|
136 uint16_t data3; |
|
137 uint8_t data4[8]; |
|
138 } MDGUID; // GUID |
|
139 |
|
140 typedef MDGUID GUID; |
|
141 |
|
142 |
|
143 //////////////////////////////////////////////////////////////// |
|
144 // scoped_ptr |
|
145 // |
|
146 |
|
147 // scoped_ptr mimics a built-in pointer except that it guarantees deletion |
|
148 // of the object pointed to, either on destruction of the scoped_ptr or via |
|
149 // an explicit reset(). scoped_ptr is a simple solution for simple needs; |
|
150 // use shared_ptr or std::auto_ptr if your needs are more complex. |
|
151 |
|
152 // *** NOTE *** |
|
153 // If your scoped_ptr is a class member of class FOO pointing to a |
|
154 // forward declared type BAR (as shown below), then you MUST use a non-inlined |
|
155 // version of the destructor. The destructor of a scoped_ptr (called from |
|
156 // FOO's destructor) must have a complete definition of BAR in order to |
|
157 // destroy it. Example: |
|
158 // |
|
159 // -- foo.h -- |
|
160 // class BAR; |
|
161 // |
|
162 // class FOO { |
|
163 // public: |
|
164 // FOO(); |
|
165 // ~FOO(); // Required for sources that instantiate class FOO to compile! |
|
166 // |
|
167 // private: |
|
168 // scoped_ptr<BAR> bar_; |
|
169 // }; |
|
170 // |
|
171 // -- foo.cc -- |
|
172 // #include "foo.h" |
|
173 // FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition. |
|
174 |
|
175 // scoped_ptr_malloc added by Google |
|
176 // When one of these goes out of scope, instead of doing a delete or |
|
177 // delete[], it calls free(). scoped_ptr_malloc<char> is likely to see |
|
178 // much more use than any other specializations. |
|
179 |
|
180 // release() added by Google |
|
181 // Use this to conditionally transfer ownership of a heap-allocated object |
|
182 // to the caller, usually on method success. |
|
183 |
|
184 template <typename T> |
|
185 class scoped_ptr { |
|
186 private: |
|
187 |
|
188 T* ptr; |
|
189 |
|
190 scoped_ptr(scoped_ptr const &); |
|
191 scoped_ptr & operator=(scoped_ptr const &); |
|
192 |
|
193 public: |
|
194 |
|
195 typedef T element_type; |
|
196 |
|
197 explicit scoped_ptr(T* p = 0): ptr(p) {} |
|
198 |
|
199 ~scoped_ptr() { |
|
200 delete ptr; |
|
201 } |
|
202 |
|
203 void reset(T* p = 0) { |
|
204 if (ptr != p) { |
|
205 delete ptr; |
|
206 ptr = p; |
|
207 } |
|
208 } |
|
209 |
|
210 T& operator*() const { |
|
211 MOZ_ASSERT(ptr != 0); |
|
212 return *ptr; |
|
213 } |
|
214 |
|
215 T* operator->() const { |
|
216 MOZ_ASSERT(ptr != 0); |
|
217 return ptr; |
|
218 } |
|
219 |
|
220 bool operator==(T* p) const { |
|
221 return ptr == p; |
|
222 } |
|
223 |
|
224 bool operator!=(T* p) const { |
|
225 return ptr != p; |
|
226 } |
|
227 |
|
228 T* get() const { |
|
229 return ptr; |
|
230 } |
|
231 |
|
232 void swap(scoped_ptr & b) { |
|
233 T* tmp = b.ptr; |
|
234 b.ptr = ptr; |
|
235 ptr = tmp; |
|
236 } |
|
237 |
|
238 T* release() { |
|
239 T* tmp = ptr; |
|
240 ptr = 0; |
|
241 return tmp; |
|
242 } |
|
243 |
|
244 private: |
|
245 |
|
246 // no reason to use these: each scoped_ptr should have its own object |
|
247 template <typename U> bool operator==(scoped_ptr<U> const& p) const; |
|
248 template <typename U> bool operator!=(scoped_ptr<U> const& p) const; |
|
249 }; |
|
250 |
|
251 template<typename T> inline |
|
252 void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) { |
|
253 a.swap(b); |
|
254 } |
|
255 |
|
256 template<typename T> inline |
|
257 bool operator==(T* p, const scoped_ptr<T>& b) { |
|
258 return p == b.get(); |
|
259 } |
|
260 |
|
261 template<typename T> inline |
|
262 bool operator!=(T* p, const scoped_ptr<T>& b) { |
|
263 return p != b.get(); |
|
264 } |
|
265 |
|
266 // scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to |
|
267 // is guaranteed, either on destruction of the scoped_array or via an explicit |
|
268 // reset(). Use shared_array or std::vector if your needs are more complex. |
|
269 |
|
270 template<typename T> |
|
271 class scoped_array { |
|
272 private: |
|
273 |
|
274 T* ptr; |
|
275 |
|
276 scoped_array(scoped_array const &); |
|
277 scoped_array & operator=(scoped_array const &); |
|
278 |
|
279 public: |
|
280 |
|
281 typedef T element_type; |
|
282 |
|
283 explicit scoped_array(T* p = 0) : ptr(p) {} |
|
284 |
|
285 ~scoped_array() { |
|
286 delete[] ptr; |
|
287 } |
|
288 |
|
289 void reset(T* p = 0) { |
|
290 if (ptr != p) { |
|
291 delete [] ptr; |
|
292 ptr = p; |
|
293 } |
|
294 } |
|
295 |
|
296 T& operator[](std::ptrdiff_t i) const { |
|
297 MOZ_ASSERT(ptr != 0); |
|
298 MOZ_ASSERT(i >= 0); |
|
299 return ptr[i]; |
|
300 } |
|
301 |
|
302 bool operator==(T* p) const { |
|
303 return ptr == p; |
|
304 } |
|
305 |
|
306 bool operator!=(T* p) const { |
|
307 return ptr != p; |
|
308 } |
|
309 |
|
310 T* get() const { |
|
311 return ptr; |
|
312 } |
|
313 |
|
314 void swap(scoped_array & b) { |
|
315 T* tmp = b.ptr; |
|
316 b.ptr = ptr; |
|
317 ptr = tmp; |
|
318 } |
|
319 |
|
320 T* release() { |
|
321 T* tmp = ptr; |
|
322 ptr = 0; |
|
323 return tmp; |
|
324 } |
|
325 |
|
326 private: |
|
327 |
|
328 // no reason to use these: each scoped_array should have its own object |
|
329 template <typename U> bool operator==(scoped_array<U> const& p) const; |
|
330 template <typename U> bool operator!=(scoped_array<U> const& p) const; |
|
331 }; |
|
332 |
|
333 template<class T> inline |
|
334 void swap(scoped_array<T>& a, scoped_array<T>& b) { |
|
335 a.swap(b); |
|
336 } |
|
337 |
|
338 template<typename T> inline |
|
339 bool operator==(T* p, const scoped_array<T>& b) { |
|
340 return p == b.get(); |
|
341 } |
|
342 |
|
343 template<typename T> inline |
|
344 bool operator!=(T* p, const scoped_array<T>& b) { |
|
345 return p != b.get(); |
|
346 } |
|
347 |
|
348 |
|
349 // This class wraps the c library function free() in a class that can be |
|
350 // passed as a template argument to scoped_ptr_malloc below. |
|
351 class ScopedPtrMallocFree { |
|
352 public: |
|
353 inline void operator()(void* x) const { |
|
354 free(x); |
|
355 } |
|
356 }; |
|
357 |
|
358 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a |
|
359 // second template argument, the functor used to free the object. |
|
360 |
|
361 template<typename T, typename FreeProc = ScopedPtrMallocFree> |
|
362 class scoped_ptr_malloc { |
|
363 private: |
|
364 |
|
365 T* ptr; |
|
366 |
|
367 scoped_ptr_malloc(scoped_ptr_malloc const &); |
|
368 scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); |
|
369 |
|
370 public: |
|
371 |
|
372 typedef T element_type; |
|
373 |
|
374 explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} |
|
375 |
|
376 ~scoped_ptr_malloc() { |
|
377 free_((void*) ptr); |
|
378 } |
|
379 |
|
380 void reset(T* p = 0) { |
|
381 if (ptr != p) { |
|
382 free_((void*) ptr); |
|
383 ptr = p; |
|
384 } |
|
385 } |
|
386 |
|
387 T& operator*() const { |
|
388 MOZ_ASSERT(ptr != 0); |
|
389 return *ptr; |
|
390 } |
|
391 |
|
392 T* operator->() const { |
|
393 MOZ_ASSERT(ptr != 0); |
|
394 return ptr; |
|
395 } |
|
396 |
|
397 bool operator==(T* p) const { |
|
398 return ptr == p; |
|
399 } |
|
400 |
|
401 bool operator!=(T* p) const { |
|
402 return ptr != p; |
|
403 } |
|
404 |
|
405 T* get() const { |
|
406 return ptr; |
|
407 } |
|
408 |
|
409 void swap(scoped_ptr_malloc & b) { |
|
410 T* tmp = b.ptr; |
|
411 b.ptr = ptr; |
|
412 ptr = tmp; |
|
413 } |
|
414 |
|
415 T* release() { |
|
416 T* tmp = ptr; |
|
417 ptr = 0; |
|
418 return tmp; |
|
419 } |
|
420 |
|
421 private: |
|
422 |
|
423 // no reason to use these: each scoped_ptr_malloc should have its own object |
|
424 template <typename U, typename GP> |
|
425 bool operator==(scoped_ptr_malloc<U, GP> const& p) const; |
|
426 template <typename U, typename GP> |
|
427 bool operator!=(scoped_ptr_malloc<U, GP> const& p) const; |
|
428 |
|
429 static FreeProc const free_; |
|
430 }; |
|
431 |
|
432 template<typename T, typename FP> |
|
433 FP const scoped_ptr_malloc<T,FP>::free_ = FP(); |
|
434 |
|
435 template<typename T, typename FP> inline |
|
436 void swap(scoped_ptr_malloc<T,FP>& a, scoped_ptr_malloc<T,FP>& b) { |
|
437 a.swap(b); |
|
438 } |
|
439 |
|
440 template<typename T, typename FP> inline |
|
441 bool operator==(T* p, const scoped_ptr_malloc<T,FP>& b) { |
|
442 return p == b.get(); |
|
443 } |
|
444 |
|
445 template<typename T, typename FP> inline |
|
446 bool operator!=(T* p, const scoped_ptr_malloc<T,FP>& b) { |
|
447 return p != b.get(); |
|
448 } |
|
449 |
|
450 |
|
451 //////////////////////////////////////////////////////////////// |
|
452 // Module |
|
453 // |
|
454 |
|
455 // A Module represents the contents of a module, and supports methods |
|
456 // for adding information produced by parsing STABS or DWARF data |
|
457 // --- possibly both from the same file --- and then writing out the |
|
458 // unified contents as a Breakpad-format symbol file. |
|
459 class Module { |
|
460 public: |
|
461 // The type of addresses and sizes in a symbol table. |
|
462 typedef uint64_t Address; |
|
463 |
|
464 // Representation of an expression. This can either be a postfix |
|
465 // expression, in which case it is stored as a string, or a simple |
|
466 // expression of the form (identifier + imm) or *(identifier + imm). |
|
467 // It can also be invalid (denoting "no value"). |
|
468 enum ExprHow { |
|
469 kExprInvalid = 1, |
|
470 kExprPostfix, |
|
471 kExprSimple, |
|
472 kExprSimpleMem |
|
473 }; |
|
474 |
|
475 struct Expr { |
|
476 // Construct a simple-form expression |
|
477 Expr(const UniqueString* ident, long offset, bool deref) { |
|
478 if (ident == ustr__empty()) { |
|
479 Expr(); |
|
480 } else { |
|
481 postfix_ = ""; |
|
482 ident_ = ident; |
|
483 offset_ = offset; |
|
484 how_ = deref ? kExprSimpleMem : kExprSimple; |
|
485 } |
|
486 } |
|
487 |
|
488 // Construct an invalid expression |
|
489 Expr() { |
|
490 postfix_ = ""; |
|
491 ident_ = nullptr; |
|
492 offset_ = 0; |
|
493 how_ = kExprInvalid; |
|
494 } |
|
495 |
|
496 // Return the postfix expression string, either directly, |
|
497 // if this is a postfix expression, or by synthesising it |
|
498 // for a simple expression. |
|
499 std::string getExprPostfix() const { |
|
500 switch (how_) { |
|
501 case kExprPostfix: |
|
502 return postfix_; |
|
503 case kExprSimple: |
|
504 case kExprSimpleMem: { |
|
505 char buf[40]; |
|
506 sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+', |
|
507 how_ == kExprSimple ? "" : " ^"); |
|
508 return std::string(FromUniqueString(ident_)) + std::string(buf); |
|
509 } |
|
510 case kExprInvalid: |
|
511 default: |
|
512 MOZ_ASSERT(0 && "getExprPostfix: invalid Module::Expr type"); |
|
513 return "Expr::genExprPostfix: kExprInvalid"; |
|
514 } |
|
515 } |
|
516 |
|
517 // The identifier that gives the starting value for simple expressions. |
|
518 const UniqueString* ident_; |
|
519 // The offset to add for simple expressions. |
|
520 long offset_; |
|
521 // The Postfix expression string to evaluate for non-simple expressions. |
|
522 std::string postfix_; |
|
523 // The operation expressed by this expression. |
|
524 ExprHow how_; |
|
525 }; |
|
526 |
|
527 // A map from register names to expressions that recover |
|
528 // their values. This can represent a complete set of rules to |
|
529 // follow at some address, or a set of changes to be applied to an |
|
530 // extant set of rules. |
|
531 // NOTE! there are two completely different types called RuleMap. This |
|
532 // is one of them. |
|
533 typedef std::map<const UniqueString*, Expr> RuleMap; |
|
534 |
|
535 // A map from addresses to RuleMaps, representing changes that take |
|
536 // effect at given addresses. |
|
537 typedef std::map<Address, RuleMap> RuleChangeMap; |
|
538 |
|
539 // A range of 'STACK CFI' stack walking information. An instance of |
|
540 // this structure corresponds to a 'STACK CFI INIT' record and the |
|
541 // subsequent 'STACK CFI' records that fall within its range. |
|
542 struct StackFrameEntry { |
|
543 // The starting address and number of bytes of machine code this |
|
544 // entry covers. |
|
545 Address address, size; |
|
546 |
|
547 // The initial register recovery rules, in force at the starting |
|
548 // address. |
|
549 RuleMap initial_rules; |
|
550 |
|
551 // A map from addresses to rule changes. To find the rules in |
|
552 // force at a given address, start with initial_rules, and then |
|
553 // apply the changes given in this map for all addresses up to and |
|
554 // including the address you're interested in. |
|
555 RuleChangeMap rule_changes; |
|
556 }; |
|
557 |
|
558 // Create a new module with the given name, operating system, |
|
559 // architecture, and ID string. |
|
560 Module(const std::string &name, const std::string &os, |
|
561 const std::string &architecture, const std::string &id); |
|
562 ~Module(); |
|
563 |
|
564 private: |
|
565 |
|
566 // Module header entries. |
|
567 std::string name_, os_, architecture_, id_; |
|
568 }; |
|
569 |
|
570 |
|
571 } // namespace lul |
|
572 |
|
573 #endif // LulCommonExt_h |