1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/profiler/LulCommonExt.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,573 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 + 1.7 +// Copyright (c) 2006, 2010, 2012, 2013 Google Inc. 1.8 +// All rights reserved. 1.9 +// 1.10 +// Redistribution and use in source and binary forms, with or without 1.11 +// modification, are permitted provided that the following conditions are 1.12 +// met: 1.13 +// 1.14 +// * Redistributions of source code must retain the above copyright 1.15 +// notice, this list of conditions and the following disclaimer. 1.16 +// * Redistributions in binary form must reproduce the above 1.17 +// copyright notice, this list of conditions and the following disclaimer 1.18 +// in the documentation and/or other materials provided with the 1.19 +// distribution. 1.20 +// * Neither the name of Google Inc. nor the names of its 1.21 +// contributors may be used to endorse or promote products derived from 1.22 +// this software without specific prior written permission. 1.23 +// 1.24 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.25 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.26 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.27 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.28 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.29 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.30 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.31 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.32 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.33 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.34 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.35 + 1.36 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.37 + 1.38 +// module.h: Define google_breakpad::Module. A Module holds debugging 1.39 +// information, and can write that information out as a Breakpad 1.40 +// symbol file. 1.41 + 1.42 + 1.43 +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. 1.44 +// Copyright (c) 2001, 2002 Peter Dimov 1.45 +// 1.46 +// Permission to copy, use, modify, sell and distribute this software 1.47 +// is granted provided this copyright notice appears in all copies. 1.48 +// This software is provided "as is" without express or implied 1.49 +// warranty, and with no claim as to its suitability for any purpose. 1.50 +// 1.51 +// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. 1.52 +// 1.53 + 1.54 + 1.55 +// This file is derived from the following files in 1.56 +// toolkit/crashreporter/google-breakpad: 1.57 +// src/common/unique_string.h 1.58 +// src/common/scoped_ptr.h 1.59 +// src/common/module.h 1.60 + 1.61 +// External interface for the "Common" component of LUL. 1.62 + 1.63 +#ifndef LulCommonExt_h 1.64 +#define LulCommonExt_h 1.65 + 1.66 +#include <stdlib.h> 1.67 +#include <stdio.h> 1.68 +#include <stdint.h> 1.69 + 1.70 +#include <string> 1.71 +#include <map> 1.72 +#include <vector> 1.73 +#include <cstddef> // for std::ptrdiff_t 1.74 + 1.75 +#include "mozilla/Assertions.h" 1.76 +#include "mozilla/NullPtr.h" 1.77 + 1.78 +namespace lul { 1.79 + 1.80 +//////////////////////////////////////////////////////////////// 1.81 +// UniqueString 1.82 +// 1.83 + 1.84 +// Abstract type 1.85 +class UniqueString; 1.86 + 1.87 +// Unique-ify a string. |ToUniqueString| can never return nullptr. 1.88 +const UniqueString* ToUniqueString(std::string); 1.89 + 1.90 +// Get the contained C string (debugging only) 1.91 +const char* const FromUniqueString(const UniqueString*); 1.92 + 1.93 +// Some handy pre-uniqified strings. Z is an escape character: 1.94 +// ZS '$' 1.95 +// ZD '.' 1.96 +// Zeq '=' 1.97 +// Zplus '+' 1.98 +// Zstar '*' 1.99 +// Zslash '/' 1.100 +// Zpercent '%' 1.101 +// Zat '@' 1.102 +// Zcaret '^' 1.103 + 1.104 +// Note that ustr__empty and (UniqueString*)nullptr are considered 1.105 +// to be different. 1.106 +// 1.107 +// Unfortunately these have to be written as functions so as to 1.108 +// make them safe to use in static initialisers. 1.109 + 1.110 +// "" 1.111 +inline static const UniqueString* ustr__empty() { 1.112 + static const UniqueString* us = nullptr; 1.113 + if (!us) us = ToUniqueString(""); 1.114 + return us; 1.115 +} 1.116 + 1.117 +// ".cfa" 1.118 +inline static const UniqueString* ustr__ZDcfa() { 1.119 + static const UniqueString* us = nullptr; 1.120 + if (!us) us = ToUniqueString(".cfa"); 1.121 + return us; 1.122 +} 1.123 + 1.124 +// ".ra" 1.125 +inline static const UniqueString* ustr__ZDra() { 1.126 + static const UniqueString* us = nullptr; 1.127 + if (!us) us = ToUniqueString(".ra"); 1.128 + return us; 1.129 +} 1.130 + 1.131 + 1.132 +//////////////////////////////////////////////////////////////// 1.133 +// GUID 1.134 +// 1.135 + 1.136 +typedef struct { 1.137 + uint32_t data1; 1.138 + uint16_t data2; 1.139 + uint16_t data3; 1.140 + uint8_t data4[8]; 1.141 +} MDGUID; // GUID 1.142 + 1.143 +typedef MDGUID GUID; 1.144 + 1.145 + 1.146 +//////////////////////////////////////////////////////////////// 1.147 +// scoped_ptr 1.148 +// 1.149 + 1.150 +// scoped_ptr mimics a built-in pointer except that it guarantees deletion 1.151 +// of the object pointed to, either on destruction of the scoped_ptr or via 1.152 +// an explicit reset(). scoped_ptr is a simple solution for simple needs; 1.153 +// use shared_ptr or std::auto_ptr if your needs are more complex. 1.154 + 1.155 +// *** NOTE *** 1.156 +// If your scoped_ptr is a class member of class FOO pointing to a 1.157 +// forward declared type BAR (as shown below), then you MUST use a non-inlined 1.158 +// version of the destructor. The destructor of a scoped_ptr (called from 1.159 +// FOO's destructor) must have a complete definition of BAR in order to 1.160 +// destroy it. Example: 1.161 +// 1.162 +// -- foo.h -- 1.163 +// class BAR; 1.164 +// 1.165 +// class FOO { 1.166 +// public: 1.167 +// FOO(); 1.168 +// ~FOO(); // Required for sources that instantiate class FOO to compile! 1.169 +// 1.170 +// private: 1.171 +// scoped_ptr<BAR> bar_; 1.172 +// }; 1.173 +// 1.174 +// -- foo.cc -- 1.175 +// #include "foo.h" 1.176 +// FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition. 1.177 + 1.178 +// scoped_ptr_malloc added by Google 1.179 +// When one of these goes out of scope, instead of doing a delete or 1.180 +// delete[], it calls free(). scoped_ptr_malloc<char> is likely to see 1.181 +// much more use than any other specializations. 1.182 + 1.183 +// release() added by Google 1.184 +// Use this to conditionally transfer ownership of a heap-allocated object 1.185 +// to the caller, usually on method success. 1.186 + 1.187 +template <typename T> 1.188 +class scoped_ptr { 1.189 + private: 1.190 + 1.191 + T* ptr; 1.192 + 1.193 + scoped_ptr(scoped_ptr const &); 1.194 + scoped_ptr & operator=(scoped_ptr const &); 1.195 + 1.196 + public: 1.197 + 1.198 + typedef T element_type; 1.199 + 1.200 + explicit scoped_ptr(T* p = 0): ptr(p) {} 1.201 + 1.202 + ~scoped_ptr() { 1.203 + delete ptr; 1.204 + } 1.205 + 1.206 + void reset(T* p = 0) { 1.207 + if (ptr != p) { 1.208 + delete ptr; 1.209 + ptr = p; 1.210 + } 1.211 + } 1.212 + 1.213 + T& operator*() const { 1.214 + MOZ_ASSERT(ptr != 0); 1.215 + return *ptr; 1.216 + } 1.217 + 1.218 + T* operator->() const { 1.219 + MOZ_ASSERT(ptr != 0); 1.220 + return ptr; 1.221 + } 1.222 + 1.223 + bool operator==(T* p) const { 1.224 + return ptr == p; 1.225 + } 1.226 + 1.227 + bool operator!=(T* p) const { 1.228 + return ptr != p; 1.229 + } 1.230 + 1.231 + T* get() const { 1.232 + return ptr; 1.233 + } 1.234 + 1.235 + void swap(scoped_ptr & b) { 1.236 + T* tmp = b.ptr; 1.237 + b.ptr = ptr; 1.238 + ptr = tmp; 1.239 + } 1.240 + 1.241 + T* release() { 1.242 + T* tmp = ptr; 1.243 + ptr = 0; 1.244 + return tmp; 1.245 + } 1.246 + 1.247 + private: 1.248 + 1.249 + // no reason to use these: each scoped_ptr should have its own object 1.250 + template <typename U> bool operator==(scoped_ptr<U> const& p) const; 1.251 + template <typename U> bool operator!=(scoped_ptr<U> const& p) const; 1.252 +}; 1.253 + 1.254 +template<typename T> inline 1.255 +void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) { 1.256 + a.swap(b); 1.257 +} 1.258 + 1.259 +template<typename T> inline 1.260 +bool operator==(T* p, const scoped_ptr<T>& b) { 1.261 + return p == b.get(); 1.262 +} 1.263 + 1.264 +template<typename T> inline 1.265 +bool operator!=(T* p, const scoped_ptr<T>& b) { 1.266 + return p != b.get(); 1.267 +} 1.268 + 1.269 +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to 1.270 +// is guaranteed, either on destruction of the scoped_array or via an explicit 1.271 +// reset(). Use shared_array or std::vector if your needs are more complex. 1.272 + 1.273 +template<typename T> 1.274 +class scoped_array { 1.275 + private: 1.276 + 1.277 + T* ptr; 1.278 + 1.279 + scoped_array(scoped_array const &); 1.280 + scoped_array & operator=(scoped_array const &); 1.281 + 1.282 + public: 1.283 + 1.284 + typedef T element_type; 1.285 + 1.286 + explicit scoped_array(T* p = 0) : ptr(p) {} 1.287 + 1.288 + ~scoped_array() { 1.289 + delete[] ptr; 1.290 + } 1.291 + 1.292 + void reset(T* p = 0) { 1.293 + if (ptr != p) { 1.294 + delete [] ptr; 1.295 + ptr = p; 1.296 + } 1.297 + } 1.298 + 1.299 + T& operator[](std::ptrdiff_t i) const { 1.300 + MOZ_ASSERT(ptr != 0); 1.301 + MOZ_ASSERT(i >= 0); 1.302 + return ptr[i]; 1.303 + } 1.304 + 1.305 + bool operator==(T* p) const { 1.306 + return ptr == p; 1.307 + } 1.308 + 1.309 + bool operator!=(T* p) const { 1.310 + return ptr != p; 1.311 + } 1.312 + 1.313 + T* get() const { 1.314 + return ptr; 1.315 + } 1.316 + 1.317 + void swap(scoped_array & b) { 1.318 + T* tmp = b.ptr; 1.319 + b.ptr = ptr; 1.320 + ptr = tmp; 1.321 + } 1.322 + 1.323 + T* release() { 1.324 + T* tmp = ptr; 1.325 + ptr = 0; 1.326 + return tmp; 1.327 + } 1.328 + 1.329 + private: 1.330 + 1.331 + // no reason to use these: each scoped_array should have its own object 1.332 + template <typename U> bool operator==(scoped_array<U> const& p) const; 1.333 + template <typename U> bool operator!=(scoped_array<U> const& p) const; 1.334 +}; 1.335 + 1.336 +template<class T> inline 1.337 +void swap(scoped_array<T>& a, scoped_array<T>& b) { 1.338 + a.swap(b); 1.339 +} 1.340 + 1.341 +template<typename T> inline 1.342 +bool operator==(T* p, const scoped_array<T>& b) { 1.343 + return p == b.get(); 1.344 +} 1.345 + 1.346 +template<typename T> inline 1.347 +bool operator!=(T* p, const scoped_array<T>& b) { 1.348 + return p != b.get(); 1.349 +} 1.350 + 1.351 + 1.352 +// This class wraps the c library function free() in a class that can be 1.353 +// passed as a template argument to scoped_ptr_malloc below. 1.354 +class ScopedPtrMallocFree { 1.355 + public: 1.356 + inline void operator()(void* x) const { 1.357 + free(x); 1.358 + } 1.359 +}; 1.360 + 1.361 +// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a 1.362 +// second template argument, the functor used to free the object. 1.363 + 1.364 +template<typename T, typename FreeProc = ScopedPtrMallocFree> 1.365 +class scoped_ptr_malloc { 1.366 + private: 1.367 + 1.368 + T* ptr; 1.369 + 1.370 + scoped_ptr_malloc(scoped_ptr_malloc const &); 1.371 + scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); 1.372 + 1.373 + public: 1.374 + 1.375 + typedef T element_type; 1.376 + 1.377 + explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} 1.378 + 1.379 + ~scoped_ptr_malloc() { 1.380 + free_((void*) ptr); 1.381 + } 1.382 + 1.383 + void reset(T* p = 0) { 1.384 + if (ptr != p) { 1.385 + free_((void*) ptr); 1.386 + ptr = p; 1.387 + } 1.388 + } 1.389 + 1.390 + T& operator*() const { 1.391 + MOZ_ASSERT(ptr != 0); 1.392 + return *ptr; 1.393 + } 1.394 + 1.395 + T* operator->() const { 1.396 + MOZ_ASSERT(ptr != 0); 1.397 + return ptr; 1.398 + } 1.399 + 1.400 + bool operator==(T* p) const { 1.401 + return ptr == p; 1.402 + } 1.403 + 1.404 + bool operator!=(T* p) const { 1.405 + return ptr != p; 1.406 + } 1.407 + 1.408 + T* get() const { 1.409 + return ptr; 1.410 + } 1.411 + 1.412 + void swap(scoped_ptr_malloc & b) { 1.413 + T* tmp = b.ptr; 1.414 + b.ptr = ptr; 1.415 + ptr = tmp; 1.416 + } 1.417 + 1.418 + T* release() { 1.419 + T* tmp = ptr; 1.420 + ptr = 0; 1.421 + return tmp; 1.422 + } 1.423 + 1.424 + private: 1.425 + 1.426 + // no reason to use these: each scoped_ptr_malloc should have its own object 1.427 + template <typename U, typename GP> 1.428 + bool operator==(scoped_ptr_malloc<U, GP> const& p) const; 1.429 + template <typename U, typename GP> 1.430 + bool operator!=(scoped_ptr_malloc<U, GP> const& p) const; 1.431 + 1.432 + static FreeProc const free_; 1.433 +}; 1.434 + 1.435 +template<typename T, typename FP> 1.436 +FP const scoped_ptr_malloc<T,FP>::free_ = FP(); 1.437 + 1.438 +template<typename T, typename FP> inline 1.439 +void swap(scoped_ptr_malloc<T,FP>& a, scoped_ptr_malloc<T,FP>& b) { 1.440 + a.swap(b); 1.441 +} 1.442 + 1.443 +template<typename T, typename FP> inline 1.444 +bool operator==(T* p, const scoped_ptr_malloc<T,FP>& b) { 1.445 + return p == b.get(); 1.446 +} 1.447 + 1.448 +template<typename T, typename FP> inline 1.449 +bool operator!=(T* p, const scoped_ptr_malloc<T,FP>& b) { 1.450 + return p != b.get(); 1.451 +} 1.452 + 1.453 + 1.454 +//////////////////////////////////////////////////////////////// 1.455 +// Module 1.456 +// 1.457 + 1.458 +// A Module represents the contents of a module, and supports methods 1.459 +// for adding information produced by parsing STABS or DWARF data 1.460 +// --- possibly both from the same file --- and then writing out the 1.461 +// unified contents as a Breakpad-format symbol file. 1.462 +class Module { 1.463 +public: 1.464 + // The type of addresses and sizes in a symbol table. 1.465 + typedef uint64_t Address; 1.466 + 1.467 + // Representation of an expression. This can either be a postfix 1.468 + // expression, in which case it is stored as a string, or a simple 1.469 + // expression of the form (identifier + imm) or *(identifier + imm). 1.470 + // It can also be invalid (denoting "no value"). 1.471 + enum ExprHow { 1.472 + kExprInvalid = 1, 1.473 + kExprPostfix, 1.474 + kExprSimple, 1.475 + kExprSimpleMem 1.476 + }; 1.477 + 1.478 + struct Expr { 1.479 + // Construct a simple-form expression 1.480 + Expr(const UniqueString* ident, long offset, bool deref) { 1.481 + if (ident == ustr__empty()) { 1.482 + Expr(); 1.483 + } else { 1.484 + postfix_ = ""; 1.485 + ident_ = ident; 1.486 + offset_ = offset; 1.487 + how_ = deref ? kExprSimpleMem : kExprSimple; 1.488 + } 1.489 + } 1.490 + 1.491 + // Construct an invalid expression 1.492 + Expr() { 1.493 + postfix_ = ""; 1.494 + ident_ = nullptr; 1.495 + offset_ = 0; 1.496 + how_ = kExprInvalid; 1.497 + } 1.498 + 1.499 + // Return the postfix expression string, either directly, 1.500 + // if this is a postfix expression, or by synthesising it 1.501 + // for a simple expression. 1.502 + std::string getExprPostfix() const { 1.503 + switch (how_) { 1.504 + case kExprPostfix: 1.505 + return postfix_; 1.506 + case kExprSimple: 1.507 + case kExprSimpleMem: { 1.508 + char buf[40]; 1.509 + sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+', 1.510 + how_ == kExprSimple ? "" : " ^"); 1.511 + return std::string(FromUniqueString(ident_)) + std::string(buf); 1.512 + } 1.513 + case kExprInvalid: 1.514 + default: 1.515 + MOZ_ASSERT(0 && "getExprPostfix: invalid Module::Expr type"); 1.516 + return "Expr::genExprPostfix: kExprInvalid"; 1.517 + } 1.518 + } 1.519 + 1.520 + // The identifier that gives the starting value for simple expressions. 1.521 + const UniqueString* ident_; 1.522 + // The offset to add for simple expressions. 1.523 + long offset_; 1.524 + // The Postfix expression string to evaluate for non-simple expressions. 1.525 + std::string postfix_; 1.526 + // The operation expressed by this expression. 1.527 + ExprHow how_; 1.528 + }; 1.529 + 1.530 + // A map from register names to expressions that recover 1.531 + // their values. This can represent a complete set of rules to 1.532 + // follow at some address, or a set of changes to be applied to an 1.533 + // extant set of rules. 1.534 + // NOTE! there are two completely different types called RuleMap. This 1.535 + // is one of them. 1.536 + typedef std::map<const UniqueString*, Expr> RuleMap; 1.537 + 1.538 + // A map from addresses to RuleMaps, representing changes that take 1.539 + // effect at given addresses. 1.540 + typedef std::map<Address, RuleMap> RuleChangeMap; 1.541 + 1.542 + // A range of 'STACK CFI' stack walking information. An instance of 1.543 + // this structure corresponds to a 'STACK CFI INIT' record and the 1.544 + // subsequent 'STACK CFI' records that fall within its range. 1.545 + struct StackFrameEntry { 1.546 + // The starting address and number of bytes of machine code this 1.547 + // entry covers. 1.548 + Address address, size; 1.549 + 1.550 + // The initial register recovery rules, in force at the starting 1.551 + // address. 1.552 + RuleMap initial_rules; 1.553 + 1.554 + // A map from addresses to rule changes. To find the rules in 1.555 + // force at a given address, start with initial_rules, and then 1.556 + // apply the changes given in this map for all addresses up to and 1.557 + // including the address you're interested in. 1.558 + RuleChangeMap rule_changes; 1.559 + }; 1.560 + 1.561 + // Create a new module with the given name, operating system, 1.562 + // architecture, and ID string. 1.563 + Module(const std::string &name, const std::string &os, 1.564 + const std::string &architecture, const std::string &id); 1.565 + ~Module(); 1.566 + 1.567 +private: 1.568 + 1.569 + // Module header entries. 1.570 + std::string name_, os_, architecture_, id_; 1.571 +}; 1.572 + 1.573 + 1.574 +} // namespace lul 1.575 + 1.576 +#endif // LulCommonExt_h