tools/profiler/LulExidxExt.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:faab53e17303
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 /* libunwind - a platform-independent unwind library
5 Copyright 2011 Linaro Limited
6
7 This file is part of libunwind.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
27
28
29 // Copyright (c) 2010, 2011 Google Inc.
30 // All rights reserved.
31 //
32 // Redistribution and use in source and binary forms, with or without
33 // modification, are permitted provided that the following conditions are
34 // met:
35 //
36 // * Redistributions of source code must retain the above copyright
37 // notice, this list of conditions and the following disclaimer.
38 // * Redistributions in binary form must reproduce the above
39 // copyright notice, this list of conditions and the following disclaimer
40 // in the documentation and/or other materials provided with the
41 // distribution.
42 // * Neither the name of Google Inc. nor the names of its
43 // contributors may be used to endorse or promote products derived from
44 // this software without specific prior written permission.
45 //
46 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
49 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
50 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
52 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
53 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
54 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
56 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57
58
59 // Derived from libunwind, with extensive modifications.
60 // This file is derived from the following files in
61 // toolkit/crashreporter/google-breakpad:
62 // src/common/arm_ex_to_module.h
63 // src/common/memory_range.h
64 // src/common/arm_ex_reader.h
65
66 #ifndef LulExidxExt_h
67 #define LulExidxExt_h
68
69 #include "LulMainInt.h"
70
71 using lul::LExpr;
72 using lul::RuleSet;
73 using lul::SecMap;
74
75 namespace lul {
76
77 typedef enum extab_cmd {
78 ARM_EXIDX_CMD_FINISH,
79 ARM_EXIDX_CMD_SUB_FROM_VSP,
80 ARM_EXIDX_CMD_ADD_TO_VSP,
81 ARM_EXIDX_CMD_REG_POP,
82 ARM_EXIDX_CMD_REG_TO_SP,
83 ARM_EXIDX_CMD_VFP_POP,
84 ARM_EXIDX_CMD_WREG_POP,
85 ARM_EXIDX_CMD_WCGR_POP,
86 ARM_EXIDX_CMD_RESERVED,
87 ARM_EXIDX_CMD_REFUSED,
88 } extab_cmd_t;
89
90 struct exidx_entry {
91 uint32_t addr;
92 uint32_t data;
93 };
94
95 struct extab_data {
96 extab_cmd_t cmd;
97 uint32_t data;
98 };
99
100 enum extab_cmd_flags {
101 ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
102 ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX
103 };
104
105 // Receives information from arm_ex_reader::ExceptionTableInfo
106 // and adds it to the SecMap object
107 // This is in effect the EXIDX summariser.
108 class ARMExToModule {
109 public:
110 ARMExToModule(SecMap* smap, void(*log)(const char*)) : smap_(smap)
111 , log_(log) { }
112 ~ARMExToModule() { }
113 void AddStackFrame(uintptr_t addr, size_t size);
114 int ImproveStackFrame(const struct extab_data* edata);
115 void DeleteStackFrame();
116 void SubmitStackFrame();
117 private:
118 SecMap* smap_;
119 LExpr vsp_; // Always appears to be of the form "sp + offset"
120 RuleSet curr_rules_; // Also holds the address range being summarised
121 // debugging message sink
122 void (*log_)(const char*);
123 int TranslateCmd(const struct extab_data* edata, LExpr& vsp);
124 };
125
126
127 // (derived from)
128 // memory_range.h: Define the google_breakpad::MemoryRange class, which
129 // is a lightweight wrapper with a pointer and a length to encapsulate
130 // a contiguous range of memory.
131
132 // A lightweight wrapper with a pointer and a length to encapsulate a
133 // contiguous range of memory. It provides helper methods for checked
134 // access of a subrange of the memory. Its implemementation does not
135 // allocate memory or call into libc functions, and is thus safer to use
136 // in a crashed environment.
137 class MemoryRange {
138 public:
139
140 MemoryRange(const void* data, size_t length) {
141 Set(data, length);
142 }
143
144 // Sets this memory range to point to |data| and its length to |length|.
145 void Set(const void* data, size_t length) {
146 data_ = reinterpret_cast<const uint8_t*>(data);
147 // Always set |length_| to zero if |data_| is NULL.
148 length_ = data ? length : 0;
149 }
150
151 // Returns true if this range covers a subrange of |sub_length| bytes
152 // at |sub_offset| bytes of this memory range, or false otherwise.
153 bool Covers(size_t sub_offset, size_t sub_length) const {
154 // The following checks verify that:
155 // 1. sub_offset is within [ 0 .. length_ - 1 ]
156 // 2. sub_offset + sub_length is within
157 // [ sub_offset .. length_ ]
158 return sub_offset < length_ &&
159 sub_offset + sub_length >= sub_offset &&
160 sub_offset + sub_length <= length_;
161 }
162
163 // Returns a pointer to the beginning of this memory range.
164 const uint8_t* data() const { return data_; }
165
166 // Returns the length, in bytes, of this memory range.
167 size_t length() const { return length_; }
168
169 private:
170 // Pointer to the beginning of this memory range.
171 const uint8_t* data_;
172
173 // Length, in bytes, of this memory range.
174 size_t length_;
175 };
176
177
178 // This class is a reader for ARM unwind information
179 // from .ARM.exidx and .ARM.extab sections.
180 class ExceptionTableInfo {
181 public:
182 ExceptionTableInfo(const char* exidx, size_t exidx_size,
183 const char* extab, size_t extab_size,
184 uint32_t text_last_svma,
185 lul::ARMExToModule* handler,
186 const char* mapping_addr,
187 uint32_t loading_addr,
188 uintptr_t text_bias,
189 void (*log)(const char*))
190 : mr_exidx_(lul::MemoryRange(exidx, exidx_size)),
191 mr_extab_(lul::MemoryRange(extab, extab_size)),
192 text_last_svma_(text_last_svma),
193 handler_(handler), mapping_addr_(mapping_addr),
194 loading_addr_(loading_addr),
195 text_bias_(text_bias),
196 log_(log) { }
197
198 ~ExceptionTableInfo() { }
199
200 // Parses the entries in .ARM.exidx and possibly
201 // in .ARM.extab tables, reports what we find to
202 // arm_ex_to_module::ARMExToModule.
203 void Start();
204
205 private:
206 lul::MemoryRange mr_exidx_;
207 lul::MemoryRange mr_extab_;
208 uint32_t text_last_svma_;
209 lul::ARMExToModule* handler_;
210 const char* mapping_addr_;
211 uint32_t loading_addr_;
212 uintptr_t text_bias_;
213 // debugging message sink
214 void (*log_)(const char*);
215 enum ExExtractResult {
216 ExSuccess, // success
217 ExInBufOverflow, // out-of-range while reading .exidx
218 ExOutBufOverflow, // output buffer is too small
219 ExCantUnwind, // this function is marked CANT_UNWIND
220 ExCantRepresent, // entry valid, but we can't represent it
221 ExInvalid // entry is invalid
222 };
223 ExExtractResult
224 ExtabEntryExtract(const struct lul::exidx_entry* entry,
225 uint8_t* buf, size_t buf_size,
226 /*OUT*/size_t* buf_used);
227
228 int ExtabEntryDecode(const uint8_t* buf, size_t buf_size);
229 };
230
231 } // namespace lul
232
233 #endif // LulExidxExt_h

mercurial