Coverage Report

Created: 2018-09-25 14:53

/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