tools/profiler/LulExidxExt.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/profiler/LulExidxExt.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,233 @@
     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 +/* libunwind - a platform-independent unwind library
     1.8 +   Copyright 2011 Linaro Limited
     1.9 +
    1.10 +This file is part of libunwind.
    1.11 +
    1.12 +Permission is hereby granted, free of charge, to any person obtaining
    1.13 +a copy of this software and associated documentation files (the
    1.14 +"Software"), to deal in the Software without restriction, including
    1.15 +without limitation the rights to use, copy, modify, merge, publish,
    1.16 +distribute, sublicense, and/or sell copies of the Software, and to
    1.17 +permit persons to whom the Software is furnished to do so, subject to
    1.18 +the following conditions:
    1.19 +
    1.20 +The above copyright notice and this permission notice shall be
    1.21 +included in all copies or substantial portions of the Software.
    1.22 +
    1.23 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    1.24 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    1.25 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    1.26 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    1.27 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    1.28 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    1.29 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
    1.30 +
    1.31 +
    1.32 +// Copyright (c) 2010, 2011 Google Inc.
    1.33 +// All rights reserved.
    1.34 +//
    1.35 +// Redistribution and use in source and binary forms, with or without
    1.36 +// modification, are permitted provided that the following conditions are
    1.37 +// met:
    1.38 +//
    1.39 +//     * Redistributions of source code must retain the above copyright
    1.40 +// notice, this list of conditions and the following disclaimer.
    1.41 +//     * Redistributions in binary form must reproduce the above
    1.42 +// copyright notice, this list of conditions and the following disclaimer
    1.43 +// in the documentation and/or other materials provided with the
    1.44 +// distribution.
    1.45 +//     * Neither the name of Google Inc. nor the names of its
    1.46 +// contributors may be used to endorse or promote products derived from
    1.47 +// this software without specific prior written permission.
    1.48 +//
    1.49 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.50 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.51 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.52 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.53 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.54 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.55 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.56 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.57 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.58 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.59 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.60 +
    1.61 +
    1.62 +// Derived from libunwind, with extensive modifications.
    1.63 +// This file is derived from the following files in
    1.64 +// toolkit/crashreporter/google-breakpad:
    1.65 +//   src/common/arm_ex_to_module.h
    1.66 +//   src/common/memory_range.h
    1.67 +//   src/common/arm_ex_reader.h
    1.68 +
    1.69 +#ifndef LulExidxExt_h
    1.70 +#define LulExidxExt_h
    1.71 +
    1.72 +#include "LulMainInt.h"
    1.73 +
    1.74 +using lul::LExpr;
    1.75 +using lul::RuleSet;
    1.76 +using lul::SecMap;
    1.77 +
    1.78 +namespace lul {
    1.79 +
    1.80 +typedef enum extab_cmd {
    1.81 +  ARM_EXIDX_CMD_FINISH,
    1.82 +  ARM_EXIDX_CMD_SUB_FROM_VSP,
    1.83 +  ARM_EXIDX_CMD_ADD_TO_VSP,
    1.84 +  ARM_EXIDX_CMD_REG_POP,
    1.85 +  ARM_EXIDX_CMD_REG_TO_SP,
    1.86 +  ARM_EXIDX_CMD_VFP_POP,
    1.87 +  ARM_EXIDX_CMD_WREG_POP,
    1.88 +  ARM_EXIDX_CMD_WCGR_POP,
    1.89 +  ARM_EXIDX_CMD_RESERVED,
    1.90 +  ARM_EXIDX_CMD_REFUSED,
    1.91 +} extab_cmd_t;
    1.92 +
    1.93 +struct exidx_entry {
    1.94 +  uint32_t addr;
    1.95 +  uint32_t data;
    1.96 +};
    1.97 +
    1.98 +struct extab_data {
    1.99 +  extab_cmd_t cmd;
   1.100 +  uint32_t data;
   1.101 +};
   1.102 +
   1.103 +enum extab_cmd_flags {
   1.104 +  ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
   1.105 +  ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX
   1.106 +};
   1.107 +
   1.108 +// Receives information from arm_ex_reader::ExceptionTableInfo
   1.109 +// and adds it to the SecMap object
   1.110 +// This is in effect the EXIDX summariser.
   1.111 +class ARMExToModule {
   1.112 + public:
   1.113 +   ARMExToModule(SecMap* smap, void(*log)(const char*)) : smap_(smap)
   1.114 +                                                        , log_(log) { }
   1.115 +  ~ARMExToModule() { }
   1.116 +  void AddStackFrame(uintptr_t addr, size_t size);
   1.117 +  int  ImproveStackFrame(const struct extab_data* edata);
   1.118 +  void DeleteStackFrame();
   1.119 +  void SubmitStackFrame();
   1.120 + private:
   1.121 +  SecMap* smap_;
   1.122 +  LExpr   vsp_;        // Always appears to be of the form "sp + offset"
   1.123 +  RuleSet curr_rules_; // Also holds the address range being summarised
   1.124 +  // debugging message sink
   1.125 +  void (*log_)(const char*);
   1.126 +  int TranslateCmd(const struct extab_data* edata, LExpr& vsp);
   1.127 +};
   1.128 +
   1.129 +
   1.130 +// (derived from)
   1.131 +// memory_range.h: Define the google_breakpad::MemoryRange class, which
   1.132 +// is a lightweight wrapper with a pointer and a length to encapsulate
   1.133 +// a contiguous range of memory.
   1.134 +
   1.135 +// A lightweight wrapper with a pointer and a length to encapsulate a
   1.136 +// contiguous range of memory. It provides helper methods for checked
   1.137 +// access of a subrange of the memory. Its implemementation does not
   1.138 +// allocate memory or call into libc functions, and is thus safer to use
   1.139 +// in a crashed environment.
   1.140 +class MemoryRange {
   1.141 + public:
   1.142 +
   1.143 +  MemoryRange(const void* data, size_t length) {
   1.144 +    Set(data, length);
   1.145 +  }
   1.146 +
   1.147 +  // Sets this memory range to point to |data| and its length to |length|.
   1.148 +  void Set(const void* data, size_t length) {
   1.149 +    data_ = reinterpret_cast<const uint8_t*>(data);
   1.150 +    // Always set |length_| to zero if |data_| is NULL.
   1.151 +    length_ = data ? length : 0;
   1.152 +  }
   1.153 +
   1.154 +  // Returns true if this range covers a subrange of |sub_length| bytes
   1.155 +  // at |sub_offset| bytes of this memory range, or false otherwise.
   1.156 +  bool Covers(size_t sub_offset, size_t sub_length) const {
   1.157 +    // The following checks verify that:
   1.158 +    // 1. sub_offset is within [ 0 .. length_ - 1 ]
   1.159 +    // 2. sub_offset + sub_length is within
   1.160 +    //    [ sub_offset .. length_ ]
   1.161 +    return sub_offset < length_ &&
   1.162 +           sub_offset + sub_length >= sub_offset &&
   1.163 +           sub_offset + sub_length <= length_;
   1.164 +  }
   1.165 +
   1.166 +  // Returns a pointer to the beginning of this memory range.
   1.167 +  const uint8_t* data() const { return data_; }
   1.168 +
   1.169 +  // Returns the length, in bytes, of this memory range.
   1.170 +  size_t length() const { return length_; }
   1.171 +
   1.172 + private:
   1.173 +  // Pointer to the beginning of this memory range.
   1.174 +  const uint8_t* data_;
   1.175 +
   1.176 +  // Length, in bytes, of this memory range.
   1.177 +  size_t length_;
   1.178 +};
   1.179 +
   1.180 +
   1.181 +// This class is a reader for ARM unwind information
   1.182 +// from .ARM.exidx and .ARM.extab sections.
   1.183 +class ExceptionTableInfo {
   1.184 + public:
   1.185 +  ExceptionTableInfo(const char* exidx, size_t exidx_size,
   1.186 +                     const char* extab, size_t extab_size,
   1.187 +                     uint32_t text_last_svma,
   1.188 +                     lul::ARMExToModule* handler,
   1.189 +                     const char* mapping_addr,
   1.190 +                     uint32_t loading_addr,
   1.191 +                     uintptr_t text_bias,
   1.192 +                     void (*log)(const char*))
   1.193 +      : mr_exidx_(lul::MemoryRange(exidx, exidx_size)),
   1.194 +        mr_extab_(lul::MemoryRange(extab, extab_size)),
   1.195 +        text_last_svma_(text_last_svma),
   1.196 +        handler_(handler), mapping_addr_(mapping_addr),
   1.197 +        loading_addr_(loading_addr),
   1.198 +        text_bias_(text_bias),
   1.199 +        log_(log) { }
   1.200 +
   1.201 +  ~ExceptionTableInfo() { }
   1.202 +
   1.203 +  // Parses the entries in .ARM.exidx and possibly
   1.204 +  // in .ARM.extab tables, reports what we find to
   1.205 +  // arm_ex_to_module::ARMExToModule.
   1.206 +  void Start();
   1.207 +
   1.208 + private:
   1.209 +  lul::MemoryRange mr_exidx_;
   1.210 +  lul::MemoryRange mr_extab_;
   1.211 +  uint32_t text_last_svma_;
   1.212 +  lul::ARMExToModule* handler_;
   1.213 +  const char* mapping_addr_;
   1.214 +  uint32_t loading_addr_;
   1.215 +  uintptr_t text_bias_;
   1.216 +  // debugging message sink
   1.217 +  void (*log_)(const char*);
   1.218 +  enum ExExtractResult {
   1.219 +    ExSuccess,        // success
   1.220 +    ExInBufOverflow,  // out-of-range while reading .exidx
   1.221 +    ExOutBufOverflow, // output buffer is too small
   1.222 +    ExCantUnwind,     // this function is marked CANT_UNWIND
   1.223 +    ExCantRepresent,  // entry valid, but we can't represent it
   1.224 +    ExInvalid         // entry is invalid
   1.225 +  };
   1.226 +  ExExtractResult
   1.227 +    ExtabEntryExtract(const struct lul::exidx_entry* entry,
   1.228 +                      uint8_t* buf, size_t buf_size,
   1.229 +                      /*OUT*/size_t* buf_used);
   1.230 +
   1.231 +  int ExtabEntryDecode(const uint8_t* buf, size_t buf_size);
   1.232 +};
   1.233 +
   1.234 +} // namespace lul
   1.235 +
   1.236 +#endif // LulExidxExt_h

mercurial