Line data Source code
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 : inline void operator()(void* x) const {
335 : free(x);
336 : }
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 : Expr(const UniqueString* ident, long offset, bool deref) {
459 : if (IsEmptyUniqueString(ident)) {
460 : Expr();
461 : } else {
462 : postfix_ = "";
463 : ident_ = ident;
464 : offset_ = offset;
465 : how_ = deref ? kExprSimpleMem : kExprSimple;
466 : }
467 : }
468 :
469 : // Construct an invalid expression
470 : Expr() {
471 : postfix_ = "";
472 : ident_ = nullptr;
473 : offset_ = 0;
474 : how_ = kExprInvalid;
475 : }
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 : std::string getExprPostfix() const {
481 : switch (how_) {
482 : case kExprPostfix:
483 : return postfix_;
484 : case kExprSimple:
485 : case kExprSimpleMem: {
486 : char buf[40];
487 : sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+',
488 : how_ == kExprSimple ? "" : " ^");
489 : return std::string(FromUniqueString(ident_)) + std::string(buf);
490 : }
491 : case kExprInvalid:
492 : default:
493 : MOZ_ASSERT(0 && "getExprPostfix: invalid Module::Expr type");
494 : return "Expr::genExprPostfix: kExprInvalid";
495 : }
496 : }
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
|