/src/mozilla-central/tools/profiler/lul/LulCommonExt.h
Line | Count | Source (jump to first uncovered line) |
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 | | |
74 | | namespace lul { |
75 | | |
76 | | using std::string; |
77 | | using std::map; |
78 | | |
79 | | |
80 | | //////////////////////////////////////////////////////////////// |
81 | | // UniqueString |
82 | | // |
83 | | |
84 | | // Abstract type |
85 | | class UniqueString; |
86 | | |
87 | | // Get the contained C string (debugging only) |
88 | | const char* FromUniqueString(const UniqueString*); |
89 | | |
90 | | // Is the given string empty (that is, "") ? |
91 | | bool IsEmptyUniqueString(const UniqueString*); |
92 | | |
93 | | |
94 | | //////////////////////////////////////////////////////////////// |
95 | | // UniqueStringUniverse |
96 | | // |
97 | | |
98 | | // All UniqueStrings live in some specific UniqueStringUniverse. |
99 | | class UniqueStringUniverse { |
100 | | public: |
101 | 0 | UniqueStringUniverse() {} |
102 | | ~UniqueStringUniverse(); |
103 | | // Convert a |string| to a UniqueString, that lives in this universe. |
104 | | const UniqueString* ToUniqueString(string str); |
105 | | private: |
106 | | map<string, UniqueString*> map_; |
107 | | }; |
108 | | |
109 | | |
110 | | //////////////////////////////////////////////////////////////// |
111 | | // GUID |
112 | | // |
113 | | |
114 | | typedef struct { |
115 | | uint32_t data1; |
116 | | uint16_t data2; |
117 | | uint16_t data3; |
118 | | uint8_t data4[8]; |
119 | | } MDGUID; // GUID |
120 | | |
121 | | typedef MDGUID GUID; |
122 | | |
123 | | |
124 | | //////////////////////////////////////////////////////////////// |
125 | | // scoped_ptr |
126 | | // |
127 | | |
128 | | // scoped_ptr mimics a built-in pointer except that it guarantees deletion |
129 | | // of the object pointed to, either on destruction of the scoped_ptr or via |
130 | | // an explicit reset(). scoped_ptr is a simple solution for simple needs; |
131 | | // use shared_ptr or std::auto_ptr if your needs are more complex. |
132 | | |
133 | | // *** NOTE *** |
134 | | // If your scoped_ptr is a class member of class FOO pointing to a |
135 | | // forward declared type BAR (as shown below), then you MUST use a non-inlined |
136 | | // version of the destructor. The destructor of a scoped_ptr (called from |
137 | | // FOO's destructor) must have a complete definition of BAR in order to |
138 | | // destroy it. Example: |
139 | | // |
140 | | // -- foo.h -- |
141 | | // class BAR; |
142 | | // |
143 | | // class FOO { |
144 | | // public: |
145 | | // FOO(); |
146 | | // ~FOO(); // Required for sources that instantiate class FOO to compile! |
147 | | // |
148 | | // private: |
149 | | // scoped_ptr<BAR> bar_; |
150 | | // }; |
151 | | // |
152 | | // -- foo.cc -- |
153 | | // #include "foo.h" |
154 | | // FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition. |
155 | | |
156 | | // scoped_ptr_malloc added by Google |
157 | | // When one of these goes out of scope, instead of doing a delete or |
158 | | // delete[], it calls free(). scoped_ptr_malloc<char> is likely to see |
159 | | // much more use than any other specializations. |
160 | | |
161 | | // release() added by Google |
162 | | // Use this to conditionally transfer ownership of a heap-allocated object |
163 | | // to the caller, usually on method success. |
164 | | |
165 | | template <typename T> |
166 | | class scoped_ptr { |
167 | | private: |
168 | | |
169 | | T* ptr; |
170 | | |
171 | | scoped_ptr(scoped_ptr const &); |
172 | | scoped_ptr & operator=(scoped_ptr const &); |
173 | | |
174 | | public: |
175 | | |
176 | | typedef T element_type; |
177 | | |
178 | | explicit scoped_ptr(T* p = 0): ptr(p) {} |
179 | | |
180 | | ~scoped_ptr() { |
181 | | delete ptr; |
182 | | } |
183 | | |
184 | | void reset(T* p = 0) { |
185 | | if (ptr != p) { |
186 | | delete ptr; |
187 | | ptr = p; |
188 | | } |
189 | | } |
190 | | |
191 | | T& operator*() const { |
192 | | MOZ_ASSERT(ptr != 0); |
193 | | return *ptr; |
194 | | } |
195 | | |
196 | | T* operator->() const { |
197 | | MOZ_ASSERT(ptr != 0); |
198 | | return ptr; |
199 | | } |
200 | | |
201 | | bool operator==(T* p) const { |
202 | | return ptr == p; |
203 | | } |
204 | | |
205 | | bool operator!=(T* p) const { |
206 | | return ptr != p; |
207 | | } |
208 | | |
209 | | T* get() const { |
210 | | return ptr; |
211 | | } |
212 | | |
213 | | void swap(scoped_ptr & b) { |
214 | | T* tmp = b.ptr; |
215 | | b.ptr = ptr; |
216 | | ptr = tmp; |
217 | | } |
218 | | |
219 | | T* release() { |
220 | | T* tmp = ptr; |
221 | | ptr = 0; |
222 | | return tmp; |
223 | | } |
224 | | |
225 | | private: |
226 | | |
227 | | // no reason to use these: each scoped_ptr should have its own object |
228 | | template <typename U> bool operator==(scoped_ptr<U> const& p) const; |
229 | | template <typename U> bool operator!=(scoped_ptr<U> const& p) const; |
230 | | }; |
231 | | |
232 | | template<typename T> inline |
233 | | void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) { |
234 | | a.swap(b); |
235 | | } |
236 | | |
237 | | template<typename T> inline |
238 | | bool operator==(T* p, const scoped_ptr<T>& b) { |
239 | | return p == b.get(); |
240 | | } |
241 | | |
242 | | template<typename T> inline |
243 | | bool operator!=(T* p, const scoped_ptr<T>& b) { |
244 | | return p != b.get(); |
245 | | } |
246 | | |
247 | | // scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to |
248 | | // is guaranteed, either on destruction of the scoped_array or via an explicit |
249 | | // reset(). Use shared_array or std::vector if your needs are more complex. |
250 | | |
251 | | template<typename T> |
252 | | class scoped_array { |
253 | | private: |
254 | | |
255 | | T* ptr; |
256 | | |
257 | | scoped_array(scoped_array const &); |
258 | | scoped_array & operator=(scoped_array const &); |
259 | | |
260 | | public: |
261 | | |
262 | | typedef T element_type; |
263 | | |
264 | | explicit scoped_array(T* p = 0) : ptr(p) {} |
265 | | |
266 | | ~scoped_array() { |
267 | | delete[] ptr; |
268 | | } |
269 | | |
270 | | void reset(T* p = 0) { |
271 | | if (ptr != p) { |
272 | | delete [] ptr; |
273 | | ptr = p; |
274 | | } |
275 | | } |
276 | | |
277 | | T& operator[](std::ptrdiff_t i) const { |
278 | | MOZ_ASSERT(ptr != 0); |
279 | | MOZ_ASSERT(i >= 0); |
280 | | return ptr[i]; |
281 | | } |
282 | | |
283 | | bool operator==(T* p) const { |
284 | | return ptr == p; |
285 | | } |
286 | | |
287 | | bool operator!=(T* p) const { |
288 | | return ptr != p; |
289 | | } |
290 | | |
291 | | T* get() const { |
292 | | return ptr; |
293 | | } |
294 | | |
295 | | void swap(scoped_array & b) { |
296 | | T* tmp = b.ptr; |
297 | | b.ptr = ptr; |
298 | | ptr = tmp; |
299 | | } |
300 | | |
301 | | T* release() { |
302 | | T* tmp = ptr; |
303 | | ptr = 0; |
304 | | return tmp; |
305 | | } |
306 | | |
307 | | private: |
308 | | |
309 | | // no reason to use these: each scoped_array should have its own object |
310 | | template <typename U> bool operator==(scoped_array<U> const& p) const; |
311 | | template <typename U> bool operator!=(scoped_array<U> const& p) const; |
312 | | }; |
313 | | |
314 | | template<class T> inline |
315 | | void swap(scoped_array<T>& a, scoped_array<T>& b) { |
316 | | a.swap(b); |
317 | | } |
318 | | |
319 | | template<typename T> inline |
320 | | bool operator==(T* p, const scoped_array<T>& b) { |
321 | | return p == b.get(); |
322 | | } |
323 | | |
324 | | template<typename T> inline |
325 | | bool operator!=(T* p, const scoped_array<T>& b) { |
326 | | return p != b.get(); |
327 | | } |
328 | | |
329 | | |
330 | | // This class wraps the c library function free() in a class that can be |
331 | | // passed as a template argument to scoped_ptr_malloc below. |
332 | | class ScopedPtrMallocFree { |
333 | | public: |
334 | 0 | inline void operator()(void* x) const { |
335 | 0 | free(x); |
336 | 0 | } |
337 | | }; |
338 | | |
339 | | // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a |
340 | | // second template argument, the functor used to free the object. |
341 | | |
342 | | template<typename T, typename FreeProc = ScopedPtrMallocFree> |
343 | | class scoped_ptr_malloc { |
344 | | private: |
345 | | |
346 | | T* ptr; |
347 | | |
348 | | scoped_ptr_malloc(scoped_ptr_malloc const &); |
349 | | scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); |
350 | | |
351 | | public: |
352 | | |
353 | | typedef T element_type; |
354 | | |
355 | | explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} |
356 | | |
357 | | ~scoped_ptr_malloc() { |
358 | | free_((void*) ptr); |
359 | | } |
360 | | |
361 | | void reset(T* p = 0) { |
362 | | if (ptr != p) { |
363 | | free_((void*) ptr); |
364 | | ptr = p; |
365 | | } |
366 | | } |
367 | | |
368 | | T& operator*() const { |
369 | | MOZ_ASSERT(ptr != 0); |
370 | | return *ptr; |
371 | | } |
372 | | |
373 | | T* operator->() const { |
374 | | MOZ_ASSERT(ptr != 0); |
375 | | return ptr; |
376 | | } |
377 | | |
378 | | bool operator==(T* p) const { |
379 | | return ptr == p; |
380 | | } |
381 | | |
382 | | bool operator!=(T* p) const { |
383 | | return ptr != p; |
384 | | } |
385 | | |
386 | | T* get() const { |
387 | | return ptr; |
388 | | } |
389 | | |
390 | | void swap(scoped_ptr_malloc & b) { |
391 | | T* tmp = b.ptr; |
392 | | b.ptr = ptr; |
393 | | ptr = tmp; |
394 | | } |
395 | | |
396 | | T* release() { |
397 | | T* tmp = ptr; |
398 | | ptr = 0; |
399 | | return tmp; |
400 | | } |
401 | | |
402 | | private: |
403 | | |
404 | | // no reason to use these: each scoped_ptr_malloc should have its own object |
405 | | template <typename U, typename GP> |
406 | | bool operator==(scoped_ptr_malloc<U, GP> const& p) const; |
407 | | template <typename U, typename GP> |
408 | | bool operator!=(scoped_ptr_malloc<U, GP> const& p) const; |
409 | | |
410 | | static FreeProc const free_; |
411 | | }; |
412 | | |
413 | | template<typename T, typename FP> |
414 | | FP const scoped_ptr_malloc<T,FP>::free_ = FP(); |
415 | | |
416 | | template<typename T, typename FP> inline |
417 | | void swap(scoped_ptr_malloc<T,FP>& a, scoped_ptr_malloc<T,FP>& b) { |
418 | | a.swap(b); |
419 | | } |
420 | | |
421 | | template<typename T, typename FP> inline |
422 | | bool operator==(T* p, const scoped_ptr_malloc<T,FP>& b) { |
423 | | return p == b.get(); |
424 | | } |
425 | | |
426 | | template<typename T, typename FP> inline |
427 | | bool operator!=(T* p, const scoped_ptr_malloc<T,FP>& b) { |
428 | | return p != b.get(); |
429 | | } |
430 | | |
431 | | |
432 | | //////////////////////////////////////////////////////////////// |
433 | | // Module |
434 | | // |
435 | | |
436 | | // A Module represents the contents of a module, and supports methods |
437 | | // for adding information produced by parsing STABS or DWARF data |
438 | | // --- possibly both from the same file --- and then writing out the |
439 | | // unified contents as a Breakpad-format symbol file. |
440 | | class Module { |
441 | | public: |
442 | | // The type of addresses and sizes in a symbol table. |
443 | | typedef uint64_t Address; |
444 | | |
445 | | // Representation of an expression. This can either be a postfix |
446 | | // expression, in which case it is stored as a string, or a simple |
447 | | // expression of the form (identifier + imm) or *(identifier + imm). |
448 | | // It can also be invalid (denoting "no value"). |
449 | | enum ExprHow { |
450 | | kExprInvalid = 1, |
451 | | kExprPostfix, |
452 | | kExprSimple, |
453 | | kExprSimpleMem |
454 | | }; |
455 | | |
456 | | struct Expr { |
457 | | // Construct a simple-form expression |
458 | 0 | Expr(const UniqueString* ident, long offset, bool deref) { |
459 | 0 | if (IsEmptyUniqueString(ident)) { |
460 | 0 | Expr(); |
461 | 0 | } else { |
462 | 0 | postfix_ = ""; |
463 | 0 | ident_ = ident; |
464 | 0 | offset_ = offset; |
465 | 0 | how_ = deref ? kExprSimpleMem : kExprSimple; |
466 | 0 | } |
467 | 0 | } |
468 | | |
469 | | // Construct an invalid expression |
470 | 0 | Expr() { |
471 | 0 | postfix_ = ""; |
472 | 0 | ident_ = nullptr; |
473 | 0 | offset_ = 0; |
474 | 0 | how_ = kExprInvalid; |
475 | 0 | } |
476 | | |
477 | | // Return the postfix expression string, either directly, |
478 | | // if this is a postfix expression, or by synthesising it |
479 | | // for a simple expression. |
480 | 0 | std::string getExprPostfix() const { |
481 | 0 | switch (how_) { |
482 | 0 | case kExprPostfix: |
483 | 0 | return postfix_; |
484 | 0 | case kExprSimple: |
485 | 0 | case kExprSimpleMem: { |
486 | 0 | char buf[40]; |
487 | 0 | sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+', |
488 | 0 | how_ == kExprSimple ? "" : " ^"); |
489 | 0 | return std::string(FromUniqueString(ident_)) + std::string(buf); |
490 | 0 | } |
491 | 0 | case kExprInvalid: |
492 | 0 | default: |
493 | 0 | MOZ_ASSERT(0 && "getExprPostfix: invalid Module::Expr type"); |
494 | 0 | return "Expr::genExprPostfix: kExprInvalid"; |
495 | 0 | } |
496 | 0 | } |
497 | | |
498 | | // The identifier that gives the starting value for simple expressions. |
499 | | const UniqueString* ident_; |
500 | | // The offset to add for simple expressions. |
501 | | long offset_; |
502 | | // The Postfix expression string to evaluate for non-simple expressions. |
503 | | std::string postfix_; |
504 | | // The operation expressed by this expression. |
505 | | ExprHow how_; |
506 | | }; |
507 | | |
508 | | // A map from register names to expressions that recover |
509 | | // their values. This can represent a complete set of rules to |
510 | | // follow at some address, or a set of changes to be applied to an |
511 | | // extant set of rules. |
512 | | // NOTE! there are two completely different types called RuleMap. This |
513 | | // is one of them. |
514 | | typedef std::map<const UniqueString*, Expr> RuleMap; |
515 | | |
516 | | // A map from addresses to RuleMaps, representing changes that take |
517 | | // effect at given addresses. |
518 | | typedef std::map<Address, RuleMap> RuleChangeMap; |
519 | | |
520 | | // A range of 'STACK CFI' stack walking information. An instance of |
521 | | // this structure corresponds to a 'STACK CFI INIT' record and the |
522 | | // subsequent 'STACK CFI' records that fall within its range. |
523 | | struct StackFrameEntry { |
524 | | // The starting address and number of bytes of machine code this |
525 | | // entry covers. |
526 | | Address address, size; |
527 | | |
528 | | // The initial register recovery rules, in force at the starting |
529 | | // address. |
530 | | RuleMap initial_rules; |
531 | | |
532 | | // A map from addresses to rule changes. To find the rules in |
533 | | // force at a given address, start with initial_rules, and then |
534 | | // apply the changes given in this map for all addresses up to and |
535 | | // including the address you're interested in. |
536 | | RuleChangeMap rule_changes; |
537 | | }; |
538 | | |
539 | | // Create a new module with the given name, operating system, |
540 | | // architecture, and ID string. |
541 | | Module(const std::string &name, const std::string &os, |
542 | | const std::string &architecture, const std::string &id); |
543 | | ~Module(); |
544 | | |
545 | | private: |
546 | | |
547 | | // Module header entries. |
548 | | std::string name_, os_, architecture_, id_; |
549 | | }; |
550 | | |
551 | | |
552 | | } // namespace lul |
553 | | |
554 | | #endif // LulCommonExt_h |