|
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) 2010 Google Inc. All Rights Reserved. |
|
5 // |
|
6 // Redistribution and use in source and binary forms, with or without |
|
7 // modification, are permitted provided that the following conditions are |
|
8 // met: |
|
9 // |
|
10 // * Redistributions of source code must retain the above copyright |
|
11 // notice, this list of conditions and the following disclaimer. |
|
12 // * Redistributions in binary form must reproduce the above |
|
13 // copyright notice, this list of conditions and the following disclaimer |
|
14 // in the documentation and/or other materials provided with the |
|
15 // distribution. |
|
16 // * Neither the name of Google Inc. nor the names of its |
|
17 // contributors may be used to endorse or promote products derived from |
|
18 // this software without specific prior written permission. |
|
19 // |
|
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
31 |
|
32 // CFI reader author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> |
|
33 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> |
|
34 |
|
35 // Implementation of dwarf2reader::LineInfo, dwarf2reader::CompilationUnit, |
|
36 // and dwarf2reader::CallFrameInfo. See dwarf2reader.h for details. |
|
37 |
|
38 // This file is derived from the following files in |
|
39 // toolkit/crashreporter/google-breakpad: |
|
40 // src/common/dwarf/bytereader.cc |
|
41 // src/common/dwarf/dwarf2reader.cc |
|
42 // src/common/dwarf_cfi_to_module.cc |
|
43 |
|
44 #include <stdint.h> |
|
45 #include <stdio.h> |
|
46 #include <string.h> |
|
47 #include <stdlib.h> |
|
48 |
|
49 #include <map> |
|
50 #include <stack> |
|
51 #include <string> |
|
52 |
|
53 #include "mozilla/Assertions.h" |
|
54 |
|
55 #include "LulCommonExt.h" |
|
56 #include "LulDwarfInt.h" |
|
57 |
|
58 // Set this to 1 for verbose logging |
|
59 #define DEBUG_DWARF 0 |
|
60 |
|
61 |
|
62 namespace lul { |
|
63 |
|
64 using std::string; |
|
65 |
|
66 ByteReader::ByteReader(enum Endianness endian) |
|
67 :offset_reader_(NULL), address_reader_(NULL), endian_(endian), |
|
68 address_size_(0), offset_size_(0), |
|
69 have_section_base_(), have_text_base_(), have_data_base_(), |
|
70 have_function_base_() { } |
|
71 |
|
72 ByteReader::~ByteReader() { } |
|
73 |
|
74 void ByteReader::SetOffsetSize(uint8 size) { |
|
75 offset_size_ = size; |
|
76 MOZ_ASSERT(size == 4 || size == 8); |
|
77 if (size == 4) { |
|
78 this->offset_reader_ = &ByteReader::ReadFourBytes; |
|
79 } else { |
|
80 this->offset_reader_ = &ByteReader::ReadEightBytes; |
|
81 } |
|
82 } |
|
83 |
|
84 void ByteReader::SetAddressSize(uint8 size) { |
|
85 address_size_ = size; |
|
86 MOZ_ASSERT(size == 4 || size == 8); |
|
87 if (size == 4) { |
|
88 this->address_reader_ = &ByteReader::ReadFourBytes; |
|
89 } else { |
|
90 this->address_reader_ = &ByteReader::ReadEightBytes; |
|
91 } |
|
92 } |
|
93 |
|
94 uint64 ByteReader::ReadInitialLength(const char* start, size_t* len) { |
|
95 const uint64 initial_length = ReadFourBytes(start); |
|
96 start += 4; |
|
97 |
|
98 // In DWARF2/3, if the initial length is all 1 bits, then the offset |
|
99 // size is 8 and we need to read the next 8 bytes for the real length. |
|
100 if (initial_length == 0xffffffff) { |
|
101 SetOffsetSize(8); |
|
102 *len = 12; |
|
103 return ReadOffset(start); |
|
104 } else { |
|
105 SetOffsetSize(4); |
|
106 *len = 4; |
|
107 } |
|
108 return initial_length; |
|
109 } |
|
110 |
|
111 bool ByteReader::ValidEncoding(DwarfPointerEncoding encoding) const { |
|
112 if (encoding == DW_EH_PE_omit) return true; |
|
113 if (encoding == DW_EH_PE_aligned) return true; |
|
114 if ((encoding & 0x7) > DW_EH_PE_udata8) |
|
115 return false; |
|
116 if ((encoding & 0x70) > DW_EH_PE_funcrel) |
|
117 return false; |
|
118 return true; |
|
119 } |
|
120 |
|
121 bool ByteReader::UsableEncoding(DwarfPointerEncoding encoding) const { |
|
122 switch (encoding & 0x70) { |
|
123 case DW_EH_PE_absptr: return true; |
|
124 case DW_EH_PE_pcrel: return have_section_base_; |
|
125 case DW_EH_PE_textrel: return have_text_base_; |
|
126 case DW_EH_PE_datarel: return have_data_base_; |
|
127 case DW_EH_PE_funcrel: return have_function_base_; |
|
128 default: return false; |
|
129 } |
|
130 } |
|
131 |
|
132 uint64 ByteReader::ReadEncodedPointer(const char *buffer, |
|
133 DwarfPointerEncoding encoding, |
|
134 size_t *len) const { |
|
135 // UsableEncoding doesn't approve of DW_EH_PE_omit, so we shouldn't |
|
136 // see it here. |
|
137 MOZ_ASSERT(encoding != DW_EH_PE_omit); |
|
138 |
|
139 // The Linux Standards Base 4.0 does not make this clear, but the |
|
140 // GNU tools (gcc/unwind-pe.h; readelf/dwarf.c; gdb/dwarf2-frame.c) |
|
141 // agree that aligned pointers are always absolute, machine-sized, |
|
142 // machine-signed pointers. |
|
143 if (encoding == DW_EH_PE_aligned) { |
|
144 MOZ_ASSERT(have_section_base_); |
|
145 |
|
146 // We don't need to align BUFFER in *our* address space. Rather, we |
|
147 // need to find the next position in our buffer that would be aligned |
|
148 // when the .eh_frame section the buffer contains is loaded into the |
|
149 // program's memory. So align assuming that buffer_base_ gets loaded at |
|
150 // address section_base_, where section_base_ itself may or may not be |
|
151 // aligned. |
|
152 |
|
153 // First, find the offset to START from the closest prior aligned |
|
154 // address. |
|
155 uint64 skew = section_base_ & (AddressSize() - 1); |
|
156 // Now find the offset from that aligned address to buffer. |
|
157 uint64 offset = skew + (buffer - buffer_base_); |
|
158 // Round up to the next boundary. |
|
159 uint64 aligned = (offset + AddressSize() - 1) & -AddressSize(); |
|
160 // Convert back to a pointer. |
|
161 const char *aligned_buffer = buffer_base_ + (aligned - skew); |
|
162 // Finally, store the length and actually fetch the pointer. |
|
163 *len = aligned_buffer - buffer + AddressSize(); |
|
164 return ReadAddress(aligned_buffer); |
|
165 } |
|
166 |
|
167 // Extract the value first, ignoring whether it's a pointer or an |
|
168 // offset relative to some base. |
|
169 uint64 offset; |
|
170 switch (encoding & 0x0f) { |
|
171 case DW_EH_PE_absptr: |
|
172 // DW_EH_PE_absptr is weird, as it is used as a meaningful value for |
|
173 // both the high and low nybble of encoding bytes. When it appears in |
|
174 // the high nybble, it means that the pointer is absolute, not an |
|
175 // offset from some base address. When it appears in the low nybble, |
|
176 // as here, it means that the pointer is stored as a normal |
|
177 // machine-sized and machine-signed address. A low nybble of |
|
178 // DW_EH_PE_absptr does not imply that the pointer is absolute; it is |
|
179 // correct for us to treat the value as an offset from a base address |
|
180 // if the upper nybble is not DW_EH_PE_absptr. |
|
181 offset = ReadAddress(buffer); |
|
182 *len = AddressSize(); |
|
183 break; |
|
184 |
|
185 case DW_EH_PE_uleb128: |
|
186 offset = ReadUnsignedLEB128(buffer, len); |
|
187 break; |
|
188 |
|
189 case DW_EH_PE_udata2: |
|
190 offset = ReadTwoBytes(buffer); |
|
191 *len = 2; |
|
192 break; |
|
193 |
|
194 case DW_EH_PE_udata4: |
|
195 offset = ReadFourBytes(buffer); |
|
196 *len = 4; |
|
197 break; |
|
198 |
|
199 case DW_EH_PE_udata8: |
|
200 offset = ReadEightBytes(buffer); |
|
201 *len = 8; |
|
202 break; |
|
203 |
|
204 case DW_EH_PE_sleb128: |
|
205 offset = ReadSignedLEB128(buffer, len); |
|
206 break; |
|
207 |
|
208 case DW_EH_PE_sdata2: |
|
209 offset = ReadTwoBytes(buffer); |
|
210 // Sign-extend from 16 bits. |
|
211 offset = (offset ^ 0x8000) - 0x8000; |
|
212 *len = 2; |
|
213 break; |
|
214 |
|
215 case DW_EH_PE_sdata4: |
|
216 offset = ReadFourBytes(buffer); |
|
217 // Sign-extend from 32 bits. |
|
218 offset = (offset ^ 0x80000000ULL) - 0x80000000ULL; |
|
219 *len = 4; |
|
220 break; |
|
221 |
|
222 case DW_EH_PE_sdata8: |
|
223 // No need to sign-extend; this is the full width of our type. |
|
224 offset = ReadEightBytes(buffer); |
|
225 *len = 8; |
|
226 break; |
|
227 |
|
228 default: |
|
229 abort(); |
|
230 } |
|
231 |
|
232 // Find the appropriate base address. |
|
233 uint64 base; |
|
234 switch (encoding & 0x70) { |
|
235 case DW_EH_PE_absptr: |
|
236 base = 0; |
|
237 break; |
|
238 |
|
239 case DW_EH_PE_pcrel: |
|
240 MOZ_ASSERT(have_section_base_); |
|
241 base = section_base_ + (buffer - buffer_base_); |
|
242 break; |
|
243 |
|
244 case DW_EH_PE_textrel: |
|
245 MOZ_ASSERT(have_text_base_); |
|
246 base = text_base_; |
|
247 break; |
|
248 |
|
249 case DW_EH_PE_datarel: |
|
250 MOZ_ASSERT(have_data_base_); |
|
251 base = data_base_; |
|
252 break; |
|
253 |
|
254 case DW_EH_PE_funcrel: |
|
255 MOZ_ASSERT(have_function_base_); |
|
256 base = function_base_; |
|
257 break; |
|
258 |
|
259 default: |
|
260 abort(); |
|
261 } |
|
262 |
|
263 uint64 pointer = base + offset; |
|
264 |
|
265 // Remove inappropriate upper bits. |
|
266 if (AddressSize() == 4) |
|
267 pointer = pointer & 0xffffffff; |
|
268 else |
|
269 MOZ_ASSERT(AddressSize() == sizeof(uint64)); |
|
270 |
|
271 return pointer; |
|
272 } |
|
273 |
|
274 |
|
275 // A DWARF rule for recovering the address or value of a register, or |
|
276 // computing the canonical frame address. There is one subclass of this for |
|
277 // each '*Rule' member function in CallFrameInfo::Handler. |
|
278 // |
|
279 // It's annoying that we have to handle Rules using pointers (because |
|
280 // the concrete instances can have an arbitrary size). They're small, |
|
281 // so it would be much nicer if we could just handle them by value |
|
282 // instead of fretting about ownership and destruction. |
|
283 // |
|
284 // It seems like all these could simply be instances of std::tr1::bind, |
|
285 // except that we need instances to be EqualityComparable, too. |
|
286 // |
|
287 // This could logically be nested within State, but then the qualified names |
|
288 // get horrendous. |
|
289 class CallFrameInfo::Rule { |
|
290 public: |
|
291 virtual ~Rule() { } |
|
292 |
|
293 // Tell HANDLER that, at ADDRESS in the program, REGISTER can be |
|
294 // recovered using this rule. If REGISTER is kCFARegister, then this rule |
|
295 // describes how to compute the canonical frame address. Return what the |
|
296 // HANDLER member function returned. |
|
297 virtual bool Handle(Handler *handler, |
|
298 uint64 address, int register) const = 0; |
|
299 |
|
300 // Equality on rules. We use these to decide which rules we need |
|
301 // to report after a DW_CFA_restore_state instruction. |
|
302 virtual bool operator==(const Rule &rhs) const = 0; |
|
303 |
|
304 bool operator!=(const Rule &rhs) const { return ! (*this == rhs); } |
|
305 |
|
306 // Return a pointer to a copy of this rule. |
|
307 virtual Rule *Copy() const = 0; |
|
308 |
|
309 // If this is a base+offset rule, change its base register to REG. |
|
310 // Otherwise, do nothing. (Ugly, but required for DW_CFA_def_cfa_register.) |
|
311 virtual void SetBaseRegister(unsigned reg) { } |
|
312 |
|
313 // If this is a base+offset rule, change its offset to OFFSET. Otherwise, |
|
314 // do nothing. (Ugly, but required for DW_CFA_def_cfa_offset.) |
|
315 virtual void SetOffset(long long offset) { } |
|
316 |
|
317 // A RTTI workaround, to make it possible to implement equality |
|
318 // comparisons on classes derived from this one. |
|
319 enum CFIRTag { |
|
320 CFIR_UNDEFINED_RULE, |
|
321 CFIR_SAME_VALUE_RULE, |
|
322 CFIR_OFFSET_RULE, |
|
323 CFIR_VAL_OFFSET_RULE, |
|
324 CFIR_REGISTER_RULE, |
|
325 CFIR_EXPRESSION_RULE, |
|
326 CFIR_VAL_EXPRESSION_RULE |
|
327 }; |
|
328 |
|
329 // Produce the tag that identifies the child class of this object. |
|
330 virtual CFIRTag getTag() const = 0; |
|
331 }; |
|
332 |
|
333 // Rule: the value the register had in the caller cannot be recovered. |
|
334 class CallFrameInfo::UndefinedRule: public CallFrameInfo::Rule { |
|
335 public: |
|
336 UndefinedRule() { } |
|
337 ~UndefinedRule() { } |
|
338 CFIRTag getTag() const { return CFIR_UNDEFINED_RULE; } |
|
339 bool Handle(Handler *handler, uint64 address, int reg) const { |
|
340 return handler->UndefinedRule(address, reg); |
|
341 } |
|
342 bool operator==(const Rule &rhs) const { |
|
343 if (rhs.getTag() != CFIR_UNDEFINED_RULE) return false; |
|
344 return true; |
|
345 } |
|
346 Rule *Copy() const { return new UndefinedRule(*this); } |
|
347 }; |
|
348 |
|
349 // Rule: the register's value is the same as that it had in the caller. |
|
350 class CallFrameInfo::SameValueRule: public CallFrameInfo::Rule { |
|
351 public: |
|
352 SameValueRule() { } |
|
353 ~SameValueRule() { } |
|
354 CFIRTag getTag() const { return CFIR_SAME_VALUE_RULE; } |
|
355 bool Handle(Handler *handler, uint64 address, int reg) const { |
|
356 return handler->SameValueRule(address, reg); |
|
357 } |
|
358 bool operator==(const Rule &rhs) const { |
|
359 if (rhs.getTag() != CFIR_SAME_VALUE_RULE) return false; |
|
360 return true; |
|
361 } |
|
362 Rule *Copy() const { return new SameValueRule(*this); } |
|
363 }; |
|
364 |
|
365 // Rule: the register is saved at OFFSET from BASE_REGISTER. BASE_REGISTER |
|
366 // may be CallFrameInfo::Handler::kCFARegister. |
|
367 class CallFrameInfo::OffsetRule: public CallFrameInfo::Rule { |
|
368 public: |
|
369 OffsetRule(int base_register, long offset) |
|
370 : base_register_(base_register), offset_(offset) { } |
|
371 ~OffsetRule() { } |
|
372 CFIRTag getTag() const { return CFIR_OFFSET_RULE; } |
|
373 bool Handle(Handler *handler, uint64 address, int reg) const { |
|
374 return handler->OffsetRule(address, reg, base_register_, offset_); |
|
375 } |
|
376 bool operator==(const Rule &rhs) const { |
|
377 if (rhs.getTag() != CFIR_OFFSET_RULE) return false; |
|
378 const OffsetRule *our_rhs = static_cast<const OffsetRule *>(&rhs); |
|
379 return (base_register_ == our_rhs->base_register_ && |
|
380 offset_ == our_rhs->offset_); |
|
381 } |
|
382 Rule *Copy() const { return new OffsetRule(*this); } |
|
383 // We don't actually need SetBaseRegister or SetOffset here, since they |
|
384 // are only ever applied to CFA rules, for DW_CFA_def_cfa_offset, and it |
|
385 // doesn't make sense to use OffsetRule for computing the CFA: it |
|
386 // computes the address at which a register is saved, not a value. |
|
387 private: |
|
388 int base_register_; |
|
389 long offset_; |
|
390 }; |
|
391 |
|
392 // Rule: the value the register had in the caller is the value of |
|
393 // BASE_REGISTER plus offset. BASE_REGISTER may be |
|
394 // CallFrameInfo::Handler::kCFARegister. |
|
395 class CallFrameInfo::ValOffsetRule: public CallFrameInfo::Rule { |
|
396 public: |
|
397 ValOffsetRule(int base_register, long offset) |
|
398 : base_register_(base_register), offset_(offset) { } |
|
399 ~ValOffsetRule() { } |
|
400 CFIRTag getTag() const { return CFIR_VAL_OFFSET_RULE; } |
|
401 bool Handle(Handler *handler, uint64 address, int reg) const { |
|
402 return handler->ValOffsetRule(address, reg, base_register_, offset_); |
|
403 } |
|
404 bool operator==(const Rule &rhs) const { |
|
405 if (rhs.getTag() != CFIR_VAL_OFFSET_RULE) return false; |
|
406 const ValOffsetRule *our_rhs = static_cast<const ValOffsetRule *>(&rhs); |
|
407 return (base_register_ == our_rhs->base_register_ && |
|
408 offset_ == our_rhs->offset_); |
|
409 } |
|
410 Rule *Copy() const { return new ValOffsetRule(*this); } |
|
411 void SetBaseRegister(unsigned reg) { base_register_ = reg; } |
|
412 void SetOffset(long long offset) { offset_ = offset; } |
|
413 private: |
|
414 int base_register_; |
|
415 long offset_; |
|
416 }; |
|
417 |
|
418 // Rule: the register has been saved in another register REGISTER_NUMBER_. |
|
419 class CallFrameInfo::RegisterRule: public CallFrameInfo::Rule { |
|
420 public: |
|
421 explicit RegisterRule(int register_number) |
|
422 : register_number_(register_number) { } |
|
423 ~RegisterRule() { } |
|
424 CFIRTag getTag() const { return CFIR_REGISTER_RULE; } |
|
425 bool Handle(Handler *handler, uint64 address, int reg) const { |
|
426 return handler->RegisterRule(address, reg, register_number_); |
|
427 } |
|
428 bool operator==(const Rule &rhs) const { |
|
429 if (rhs.getTag() != CFIR_REGISTER_RULE) return false; |
|
430 const RegisterRule *our_rhs = static_cast<const RegisterRule *>(&rhs); |
|
431 return (register_number_ == our_rhs->register_number_); |
|
432 } |
|
433 Rule *Copy() const { return new RegisterRule(*this); } |
|
434 private: |
|
435 int register_number_; |
|
436 }; |
|
437 |
|
438 // Rule: EXPRESSION evaluates to the address at which the register is saved. |
|
439 class CallFrameInfo::ExpressionRule: public CallFrameInfo::Rule { |
|
440 public: |
|
441 explicit ExpressionRule(const string &expression) |
|
442 : expression_(expression) { } |
|
443 ~ExpressionRule() { } |
|
444 CFIRTag getTag() const { return CFIR_EXPRESSION_RULE; } |
|
445 bool Handle(Handler *handler, uint64 address, int reg) const { |
|
446 return handler->ExpressionRule(address, reg, expression_); |
|
447 } |
|
448 bool operator==(const Rule &rhs) const { |
|
449 if (rhs.getTag() != CFIR_EXPRESSION_RULE) return false; |
|
450 const ExpressionRule *our_rhs = static_cast<const ExpressionRule *>(&rhs); |
|
451 return (expression_ == our_rhs->expression_); |
|
452 } |
|
453 Rule *Copy() const { return new ExpressionRule(*this); } |
|
454 private: |
|
455 string expression_; |
|
456 }; |
|
457 |
|
458 // Rule: EXPRESSION evaluates to the previous value of the register. |
|
459 class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule { |
|
460 public: |
|
461 explicit ValExpressionRule(const string &expression) |
|
462 : expression_(expression) { } |
|
463 ~ValExpressionRule() { } |
|
464 CFIRTag getTag() const { return CFIR_VAL_EXPRESSION_RULE; } |
|
465 bool Handle(Handler *handler, uint64 address, int reg) const { |
|
466 return handler->ValExpressionRule(address, reg, expression_); |
|
467 } |
|
468 bool operator==(const Rule &rhs) const { |
|
469 if (rhs.getTag() != CFIR_VAL_EXPRESSION_RULE) return false; |
|
470 const ValExpressionRule *our_rhs = |
|
471 static_cast<const ValExpressionRule *>(&rhs); |
|
472 return (expression_ == our_rhs->expression_); |
|
473 } |
|
474 Rule *Copy() const { return new ValExpressionRule(*this); } |
|
475 private: |
|
476 string expression_; |
|
477 }; |
|
478 |
|
479 // A map from register numbers to rules. |
|
480 class CallFrameInfo::RuleMap { |
|
481 public: |
|
482 RuleMap() : cfa_rule_(NULL) { } |
|
483 RuleMap(const RuleMap &rhs) : cfa_rule_(NULL) { *this = rhs; } |
|
484 ~RuleMap() { Clear(); } |
|
485 |
|
486 RuleMap &operator=(const RuleMap &rhs); |
|
487 |
|
488 // Set the rule for computing the CFA to RULE. Take ownership of RULE. |
|
489 void SetCFARule(Rule *rule) { delete cfa_rule_; cfa_rule_ = rule; } |
|
490 |
|
491 // Return the current CFA rule. Unlike RegisterRule, this RuleMap retains |
|
492 // ownership of the rule. We use this for DW_CFA_def_cfa_offset and |
|
493 // DW_CFA_def_cfa_register, and for detecting references to the CFA before |
|
494 // a rule for it has been established. |
|
495 Rule *CFARule() const { return cfa_rule_; } |
|
496 |
|
497 // Return the rule for REG, or NULL if there is none. The caller takes |
|
498 // ownership of the result. |
|
499 Rule *RegisterRule(int reg) const; |
|
500 |
|
501 // Set the rule for computing REG to RULE. Take ownership of RULE. |
|
502 void SetRegisterRule(int reg, Rule *rule); |
|
503 |
|
504 // Make all the appropriate calls to HANDLER as if we were changing from |
|
505 // this RuleMap to NEW_RULES at ADDRESS. We use this to implement |
|
506 // DW_CFA_restore_state, where lots of rules can change simultaneously. |
|
507 // Return true if all handlers returned true; otherwise, return false. |
|
508 bool HandleTransitionTo(Handler *handler, uint64 address, |
|
509 const RuleMap &new_rules) const; |
|
510 |
|
511 private: |
|
512 // A map from register numbers to Rules. |
|
513 typedef std::map<int, Rule *> RuleByNumber; |
|
514 |
|
515 // Remove all register rules and clear cfa_rule_. |
|
516 void Clear(); |
|
517 |
|
518 // The rule for computing the canonical frame address. This RuleMap owns |
|
519 // this rule. |
|
520 Rule *cfa_rule_; |
|
521 |
|
522 // A map from register numbers to postfix expressions to recover |
|
523 // their values. This RuleMap owns the Rules the map refers to. |
|
524 RuleByNumber registers_; |
|
525 }; |
|
526 |
|
527 CallFrameInfo::RuleMap &CallFrameInfo::RuleMap::operator=(const RuleMap &rhs) { |
|
528 Clear(); |
|
529 // Since each map owns the rules it refers to, assignment must copy them. |
|
530 if (rhs.cfa_rule_) cfa_rule_ = rhs.cfa_rule_->Copy(); |
|
531 for (RuleByNumber::const_iterator it = rhs.registers_.begin(); |
|
532 it != rhs.registers_.end(); it++) |
|
533 registers_[it->first] = it->second->Copy(); |
|
534 return *this; |
|
535 } |
|
536 |
|
537 CallFrameInfo::Rule *CallFrameInfo::RuleMap::RegisterRule(int reg) const { |
|
538 MOZ_ASSERT(reg != Handler::kCFARegister); |
|
539 RuleByNumber::const_iterator it = registers_.find(reg); |
|
540 if (it != registers_.end()) |
|
541 return it->second->Copy(); |
|
542 else |
|
543 return NULL; |
|
544 } |
|
545 |
|
546 void CallFrameInfo::RuleMap::SetRegisterRule(int reg, Rule *rule) { |
|
547 MOZ_ASSERT(reg != Handler::kCFARegister); |
|
548 MOZ_ASSERT(rule); |
|
549 Rule **slot = ®isters_[reg]; |
|
550 delete *slot; |
|
551 *slot = rule; |
|
552 } |
|
553 |
|
554 bool CallFrameInfo::RuleMap::HandleTransitionTo( |
|
555 Handler *handler, |
|
556 uint64 address, |
|
557 const RuleMap &new_rules) const { |
|
558 // Transition from cfa_rule_ to new_rules.cfa_rule_. |
|
559 if (cfa_rule_ && new_rules.cfa_rule_) { |
|
560 if (*cfa_rule_ != *new_rules.cfa_rule_ && |
|
561 !new_rules.cfa_rule_->Handle(handler, address, Handler::kCFARegister)) |
|
562 return false; |
|
563 } else if (cfa_rule_) { |
|
564 // this RuleMap has a CFA rule but new_rules doesn't. |
|
565 // CallFrameInfo::Handler has no way to handle this --- and shouldn't; |
|
566 // it's garbage input. The instruction interpreter should have |
|
567 // detected this and warned, so take no action here. |
|
568 } else if (new_rules.cfa_rule_) { |
|
569 // This shouldn't be possible: NEW_RULES is some prior state, and |
|
570 // there's no way to remove entries. |
|
571 MOZ_ASSERT(0); |
|
572 } else { |
|
573 // Both CFA rules are empty. No action needed. |
|
574 } |
|
575 |
|
576 // Traverse the two maps in order by register number, and report |
|
577 // whatever differences we find. |
|
578 RuleByNumber::const_iterator old_it = registers_.begin(); |
|
579 RuleByNumber::const_iterator new_it = new_rules.registers_.begin(); |
|
580 while (old_it != registers_.end() && new_it != new_rules.registers_.end()) { |
|
581 if (old_it->first < new_it->first) { |
|
582 // This RuleMap has an entry for old_it->first, but NEW_RULES |
|
583 // doesn't. |
|
584 // |
|
585 // This isn't really the right thing to do, but since CFI generally |
|
586 // only mentions callee-saves registers, and GCC's convention for |
|
587 // callee-saves registers is that they are unchanged, it's a good |
|
588 // approximation. |
|
589 if (!handler->SameValueRule(address, old_it->first)) |
|
590 return false; |
|
591 old_it++; |
|
592 } else if (old_it->first > new_it->first) { |
|
593 // NEW_RULES has entry for new_it->first, but this RuleMap |
|
594 // doesn't. This shouldn't be possible: NEW_RULES is some prior |
|
595 // state, and there's no way to remove entries. |
|
596 MOZ_ASSERT(0); |
|
597 } else { |
|
598 // Both maps have an entry for this register. Report the new |
|
599 // rule if it is different. |
|
600 if (*old_it->second != *new_it->second && |
|
601 !new_it->second->Handle(handler, address, new_it->first)) |
|
602 return false; |
|
603 new_it++, old_it++; |
|
604 } |
|
605 } |
|
606 // Finish off entries from this RuleMap with no counterparts in new_rules. |
|
607 while (old_it != registers_.end()) { |
|
608 if (!handler->SameValueRule(address, old_it->first)) |
|
609 return false; |
|
610 old_it++; |
|
611 } |
|
612 // Since we only make transitions from a rule set to some previously |
|
613 // saved rule set, and we can only add rules to the map, NEW_RULES |
|
614 // must have fewer rules than *this. |
|
615 MOZ_ASSERT(new_it == new_rules.registers_.end()); |
|
616 |
|
617 return true; |
|
618 } |
|
619 |
|
620 // Remove all register rules and clear cfa_rule_. |
|
621 void CallFrameInfo::RuleMap::Clear() { |
|
622 delete cfa_rule_; |
|
623 cfa_rule_ = NULL; |
|
624 for (RuleByNumber::iterator it = registers_.begin(); |
|
625 it != registers_.end(); it++) |
|
626 delete it->second; |
|
627 registers_.clear(); |
|
628 } |
|
629 |
|
630 // The state of the call frame information interpreter as it processes |
|
631 // instructions from a CIE and FDE. |
|
632 class CallFrameInfo::State { |
|
633 public: |
|
634 // Create a call frame information interpreter state with the given |
|
635 // reporter, reader, handler, and initial call frame info address. |
|
636 State(ByteReader *reader, Handler *handler, Reporter *reporter, |
|
637 uint64 address) |
|
638 : reader_(reader), handler_(handler), reporter_(reporter), |
|
639 address_(address), entry_(NULL), cursor_(NULL), |
|
640 saved_rules_(NULL) { } |
|
641 |
|
642 ~State() { |
|
643 if (saved_rules_) |
|
644 delete saved_rules_; |
|
645 } |
|
646 |
|
647 // Interpret instructions from CIE, save the resulting rule set for |
|
648 // DW_CFA_restore instructions, and return true. On error, report |
|
649 // the problem to reporter_ and return false. |
|
650 bool InterpretCIE(const CIE &cie); |
|
651 |
|
652 // Interpret instructions from FDE, and return true. On error, |
|
653 // report the problem to reporter_ and return false. |
|
654 bool InterpretFDE(const FDE &fde); |
|
655 |
|
656 private: |
|
657 // The operands of a CFI instruction, for ParseOperands. |
|
658 struct Operands { |
|
659 unsigned register_number; // A register number. |
|
660 uint64 offset; // An offset or address. |
|
661 long signed_offset; // A signed offset. |
|
662 string expression; // A DWARF expression. |
|
663 }; |
|
664 |
|
665 // Parse CFI instruction operands from STATE's instruction stream as |
|
666 // described by FORMAT. On success, populate OPERANDS with the |
|
667 // results, and return true. On failure, report the problem and |
|
668 // return false. |
|
669 // |
|
670 // Each character of FORMAT should be one of the following: |
|
671 // |
|
672 // 'r' unsigned LEB128 register number (OPERANDS->register_number) |
|
673 // 'o' unsigned LEB128 offset (OPERANDS->offset) |
|
674 // 's' signed LEB128 offset (OPERANDS->signed_offset) |
|
675 // 'a' machine-size address (OPERANDS->offset) |
|
676 // (If the CIE has a 'z' augmentation string, 'a' uses the |
|
677 // encoding specified by the 'R' argument.) |
|
678 // '1' a one-byte offset (OPERANDS->offset) |
|
679 // '2' a two-byte offset (OPERANDS->offset) |
|
680 // '4' a four-byte offset (OPERANDS->offset) |
|
681 // '8' an eight-byte offset (OPERANDS->offset) |
|
682 // 'e' a DW_FORM_block holding a (OPERANDS->expression) |
|
683 // DWARF expression |
|
684 bool ParseOperands(const char *format, Operands *operands); |
|
685 |
|
686 // Interpret one CFI instruction from STATE's instruction stream, update |
|
687 // STATE, report any rule changes to handler_, and return true. On |
|
688 // failure, report the problem and return false. |
|
689 bool DoInstruction(); |
|
690 |
|
691 // The following Do* member functions are subroutines of DoInstruction, |
|
692 // factoring out the actual work of operations that have several |
|
693 // different encodings. |
|
694 |
|
695 // Set the CFA rule to be the value of BASE_REGISTER plus OFFSET, and |
|
696 // return true. On failure, report and return false. (Used for |
|
697 // DW_CFA_def_cfa and DW_CFA_def_cfa_sf.) |
|
698 bool DoDefCFA(unsigned base_register, long offset); |
|
699 |
|
700 // Change the offset of the CFA rule to OFFSET, and return true. On |
|
701 // failure, report and return false. (Subroutine for |
|
702 // DW_CFA_def_cfa_offset and DW_CFA_def_cfa_offset_sf.) |
|
703 bool DoDefCFAOffset(long offset); |
|
704 |
|
705 // Specify that REG can be recovered using RULE, and return true. On |
|
706 // failure, report and return false. |
|
707 bool DoRule(unsigned reg, Rule *rule); |
|
708 |
|
709 // Specify that REG can be found at OFFSET from the CFA, and return true. |
|
710 // On failure, report and return false. (Subroutine for DW_CFA_offset, |
|
711 // DW_CFA_offset_extended, and DW_CFA_offset_extended_sf.) |
|
712 bool DoOffset(unsigned reg, long offset); |
|
713 |
|
714 // Specify that the caller's value for REG is the CFA plus OFFSET, |
|
715 // and return true. On failure, report and return false. (Subroutine |
|
716 // for DW_CFA_val_offset and DW_CFA_val_offset_sf.) |
|
717 bool DoValOffset(unsigned reg, long offset); |
|
718 |
|
719 // Restore REG to the rule established in the CIE, and return true. On |
|
720 // failure, report and return false. (Subroutine for DW_CFA_restore and |
|
721 // DW_CFA_restore_extended.) |
|
722 bool DoRestore(unsigned reg); |
|
723 |
|
724 // Return the section offset of the instruction at cursor. For use |
|
725 // in error messages. |
|
726 uint64 CursorOffset() { return entry_->offset + (cursor_ - entry_->start); } |
|
727 |
|
728 // Report that entry_ is incomplete, and return false. For brevity. |
|
729 bool ReportIncomplete() { |
|
730 reporter_->Incomplete(entry_->offset, entry_->kind); |
|
731 return false; |
|
732 } |
|
733 |
|
734 // For reading multi-byte values with the appropriate endianness. |
|
735 ByteReader *reader_; |
|
736 |
|
737 // The handler to which we should report the data we find. |
|
738 Handler *handler_; |
|
739 |
|
740 // For reporting problems in the info we're parsing. |
|
741 Reporter *reporter_; |
|
742 |
|
743 // The code address to which the next instruction in the stream applies. |
|
744 uint64 address_; |
|
745 |
|
746 // The entry whose instructions we are currently processing. This is |
|
747 // first a CIE, and then an FDE. |
|
748 const Entry *entry_; |
|
749 |
|
750 // The next instruction to process. |
|
751 const char *cursor_; |
|
752 |
|
753 // The current set of rules. |
|
754 RuleMap rules_; |
|
755 |
|
756 // The set of rules established by the CIE, used by DW_CFA_restore |
|
757 // and DW_CFA_restore_extended. We set this after interpreting the |
|
758 // CIE's instructions. |
|
759 RuleMap cie_rules_; |
|
760 |
|
761 // A stack of saved states, for DW_CFA_remember_state and |
|
762 // DW_CFA_restore_state. |
|
763 std::stack<RuleMap>* saved_rules_; |
|
764 }; |
|
765 |
|
766 bool CallFrameInfo::State::InterpretCIE(const CIE &cie) { |
|
767 entry_ = &cie; |
|
768 cursor_ = entry_->instructions; |
|
769 while (cursor_ < entry_->end) |
|
770 if (!DoInstruction()) |
|
771 return false; |
|
772 // Note the rules established by the CIE, for use by DW_CFA_restore |
|
773 // and DW_CFA_restore_extended. |
|
774 cie_rules_ = rules_; |
|
775 return true; |
|
776 } |
|
777 |
|
778 bool CallFrameInfo::State::InterpretFDE(const FDE &fde) { |
|
779 entry_ = &fde; |
|
780 cursor_ = entry_->instructions; |
|
781 while (cursor_ < entry_->end) |
|
782 if (!DoInstruction()) |
|
783 return false; |
|
784 return true; |
|
785 } |
|
786 |
|
787 bool CallFrameInfo::State::ParseOperands(const char *format, |
|
788 Operands *operands) { |
|
789 size_t len; |
|
790 const char *operand; |
|
791 |
|
792 for (operand = format; *operand; operand++) { |
|
793 size_t bytes_left = entry_->end - cursor_; |
|
794 switch (*operand) { |
|
795 case 'r': |
|
796 operands->register_number = reader_->ReadUnsignedLEB128(cursor_, &len); |
|
797 if (len > bytes_left) return ReportIncomplete(); |
|
798 cursor_ += len; |
|
799 break; |
|
800 |
|
801 case 'o': |
|
802 operands->offset = reader_->ReadUnsignedLEB128(cursor_, &len); |
|
803 if (len > bytes_left) return ReportIncomplete(); |
|
804 cursor_ += len; |
|
805 break; |
|
806 |
|
807 case 's': |
|
808 operands->signed_offset = reader_->ReadSignedLEB128(cursor_, &len); |
|
809 if (len > bytes_left) return ReportIncomplete(); |
|
810 cursor_ += len; |
|
811 break; |
|
812 |
|
813 case 'a': |
|
814 operands->offset = |
|
815 reader_->ReadEncodedPointer(cursor_, entry_->cie->pointer_encoding, |
|
816 &len); |
|
817 if (len > bytes_left) return ReportIncomplete(); |
|
818 cursor_ += len; |
|
819 break; |
|
820 |
|
821 case '1': |
|
822 if (1 > bytes_left) return ReportIncomplete(); |
|
823 operands->offset = static_cast<unsigned char>(*cursor_++); |
|
824 break; |
|
825 |
|
826 case '2': |
|
827 if (2 > bytes_left) return ReportIncomplete(); |
|
828 operands->offset = reader_->ReadTwoBytes(cursor_); |
|
829 cursor_ += 2; |
|
830 break; |
|
831 |
|
832 case '4': |
|
833 if (4 > bytes_left) return ReportIncomplete(); |
|
834 operands->offset = reader_->ReadFourBytes(cursor_); |
|
835 cursor_ += 4; |
|
836 break; |
|
837 |
|
838 case '8': |
|
839 if (8 > bytes_left) return ReportIncomplete(); |
|
840 operands->offset = reader_->ReadEightBytes(cursor_); |
|
841 cursor_ += 8; |
|
842 break; |
|
843 |
|
844 case 'e': { |
|
845 size_t expression_length = reader_->ReadUnsignedLEB128(cursor_, &len); |
|
846 if (len > bytes_left || expression_length > bytes_left - len) |
|
847 return ReportIncomplete(); |
|
848 cursor_ += len; |
|
849 operands->expression = string(cursor_, expression_length); |
|
850 cursor_ += expression_length; |
|
851 break; |
|
852 } |
|
853 |
|
854 default: |
|
855 MOZ_ASSERT(0); |
|
856 } |
|
857 } |
|
858 |
|
859 return true; |
|
860 } |
|
861 |
|
862 bool CallFrameInfo::State::DoInstruction() { |
|
863 CIE *cie = entry_->cie; |
|
864 Operands ops; |
|
865 |
|
866 // Our entry's kind should have been set by now. |
|
867 MOZ_ASSERT(entry_->kind != kUnknown); |
|
868 |
|
869 // We shouldn't have been invoked unless there were more |
|
870 // instructions to parse. |
|
871 MOZ_ASSERT(cursor_ < entry_->end); |
|
872 |
|
873 unsigned opcode = *cursor_++; |
|
874 if ((opcode & 0xc0) != 0) { |
|
875 switch (opcode & 0xc0) { |
|
876 // Advance the address. |
|
877 case DW_CFA_advance_loc: { |
|
878 size_t code_offset = opcode & 0x3f; |
|
879 address_ += code_offset * cie->code_alignment_factor; |
|
880 break; |
|
881 } |
|
882 |
|
883 // Find a register at an offset from the CFA. |
|
884 case DW_CFA_offset: |
|
885 if (!ParseOperands("o", &ops) || |
|
886 !DoOffset(opcode & 0x3f, ops.offset * cie->data_alignment_factor)) |
|
887 return false; |
|
888 break; |
|
889 |
|
890 // Restore the rule established for a register by the CIE. |
|
891 case DW_CFA_restore: |
|
892 if (!DoRestore(opcode & 0x3f)) return false; |
|
893 break; |
|
894 |
|
895 // The 'if' above should have excluded this possibility. |
|
896 default: |
|
897 MOZ_ASSERT(0); |
|
898 } |
|
899 |
|
900 // Return here, so the big switch below won't be indented. |
|
901 return true; |
|
902 } |
|
903 |
|
904 switch (opcode) { |
|
905 // Set the address. |
|
906 case DW_CFA_set_loc: |
|
907 if (!ParseOperands("a", &ops)) return false; |
|
908 address_ = ops.offset; |
|
909 break; |
|
910 |
|
911 // Advance the address. |
|
912 case DW_CFA_advance_loc1: |
|
913 if (!ParseOperands("1", &ops)) return false; |
|
914 address_ += ops.offset * cie->code_alignment_factor; |
|
915 break; |
|
916 |
|
917 // Advance the address. |
|
918 case DW_CFA_advance_loc2: |
|
919 if (!ParseOperands("2", &ops)) return false; |
|
920 address_ += ops.offset * cie->code_alignment_factor; |
|
921 break; |
|
922 |
|
923 // Advance the address. |
|
924 case DW_CFA_advance_loc4: |
|
925 if (!ParseOperands("4", &ops)) return false; |
|
926 address_ += ops.offset * cie->code_alignment_factor; |
|
927 break; |
|
928 |
|
929 // Advance the address. |
|
930 case DW_CFA_MIPS_advance_loc8: |
|
931 if (!ParseOperands("8", &ops)) return false; |
|
932 address_ += ops.offset * cie->code_alignment_factor; |
|
933 break; |
|
934 |
|
935 // Compute the CFA by adding an offset to a register. |
|
936 case DW_CFA_def_cfa: |
|
937 if (!ParseOperands("ro", &ops) || |
|
938 !DoDefCFA(ops.register_number, ops.offset)) |
|
939 return false; |
|
940 break; |
|
941 |
|
942 // Compute the CFA by adding an offset to a register. |
|
943 case DW_CFA_def_cfa_sf: |
|
944 if (!ParseOperands("rs", &ops) || |
|
945 !DoDefCFA(ops.register_number, |
|
946 ops.signed_offset * cie->data_alignment_factor)) |
|
947 return false; |
|
948 break; |
|
949 |
|
950 // Change the base register used to compute the CFA. |
|
951 case DW_CFA_def_cfa_register: { |
|
952 Rule *cfa_rule = rules_.CFARule(); |
|
953 if (!cfa_rule) { |
|
954 reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset()); |
|
955 return false; |
|
956 } |
|
957 if (!ParseOperands("r", &ops)) return false; |
|
958 cfa_rule->SetBaseRegister(ops.register_number); |
|
959 if (!cfa_rule->Handle(handler_, address_, Handler::kCFARegister)) |
|
960 return false; |
|
961 break; |
|
962 } |
|
963 |
|
964 // Change the offset used to compute the CFA. |
|
965 case DW_CFA_def_cfa_offset: |
|
966 if (!ParseOperands("o", &ops) || |
|
967 !DoDefCFAOffset(ops.offset)) |
|
968 return false; |
|
969 break; |
|
970 |
|
971 // Change the offset used to compute the CFA. |
|
972 case DW_CFA_def_cfa_offset_sf: |
|
973 if (!ParseOperands("s", &ops) || |
|
974 !DoDefCFAOffset(ops.signed_offset * cie->data_alignment_factor)) |
|
975 return false; |
|
976 break; |
|
977 |
|
978 // Specify an expression whose value is the CFA. |
|
979 case DW_CFA_def_cfa_expression: { |
|
980 if (!ParseOperands("e", &ops)) |
|
981 return false; |
|
982 Rule *rule = new ValExpressionRule(ops.expression); |
|
983 rules_.SetCFARule(rule); |
|
984 if (!rule->Handle(handler_, address_, Handler::kCFARegister)) |
|
985 return false; |
|
986 break; |
|
987 } |
|
988 |
|
989 // The register's value cannot be recovered. |
|
990 case DW_CFA_undefined: { |
|
991 if (!ParseOperands("r", &ops) || |
|
992 !DoRule(ops.register_number, new UndefinedRule())) |
|
993 return false; |
|
994 break; |
|
995 } |
|
996 |
|
997 // The register's value is unchanged from its value in the caller. |
|
998 case DW_CFA_same_value: { |
|
999 if (!ParseOperands("r", &ops) || |
|
1000 !DoRule(ops.register_number, new SameValueRule())) |
|
1001 return false; |
|
1002 break; |
|
1003 } |
|
1004 |
|
1005 // Find a register at an offset from the CFA. |
|
1006 case DW_CFA_offset_extended: |
|
1007 if (!ParseOperands("ro", &ops) || |
|
1008 !DoOffset(ops.register_number, |
|
1009 ops.offset * cie->data_alignment_factor)) |
|
1010 return false; |
|
1011 break; |
|
1012 |
|
1013 // The register is saved at an offset from the CFA. |
|
1014 case DW_CFA_offset_extended_sf: |
|
1015 if (!ParseOperands("rs", &ops) || |
|
1016 !DoOffset(ops.register_number, |
|
1017 ops.signed_offset * cie->data_alignment_factor)) |
|
1018 return false; |
|
1019 break; |
|
1020 |
|
1021 // The register is saved at an offset from the CFA. |
|
1022 case DW_CFA_GNU_negative_offset_extended: |
|
1023 if (!ParseOperands("ro", &ops) || |
|
1024 !DoOffset(ops.register_number, |
|
1025 -ops.offset * cie->data_alignment_factor)) |
|
1026 return false; |
|
1027 break; |
|
1028 |
|
1029 // The register's value is the sum of the CFA plus an offset. |
|
1030 case DW_CFA_val_offset: |
|
1031 if (!ParseOperands("ro", &ops) || |
|
1032 !DoValOffset(ops.register_number, |
|
1033 ops.offset * cie->data_alignment_factor)) |
|
1034 return false; |
|
1035 break; |
|
1036 |
|
1037 // The register's value is the sum of the CFA plus an offset. |
|
1038 case DW_CFA_val_offset_sf: |
|
1039 if (!ParseOperands("rs", &ops) || |
|
1040 !DoValOffset(ops.register_number, |
|
1041 ops.signed_offset * cie->data_alignment_factor)) |
|
1042 return false; |
|
1043 break; |
|
1044 |
|
1045 // The register has been saved in another register. |
|
1046 case DW_CFA_register: { |
|
1047 if (!ParseOperands("ro", &ops) || |
|
1048 !DoRule(ops.register_number, new RegisterRule(ops.offset))) |
|
1049 return false; |
|
1050 break; |
|
1051 } |
|
1052 |
|
1053 // An expression yields the address at which the register is saved. |
|
1054 case DW_CFA_expression: { |
|
1055 if (!ParseOperands("re", &ops) || |
|
1056 !DoRule(ops.register_number, new ExpressionRule(ops.expression))) |
|
1057 return false; |
|
1058 break; |
|
1059 } |
|
1060 |
|
1061 // An expression yields the caller's value for the register. |
|
1062 case DW_CFA_val_expression: { |
|
1063 if (!ParseOperands("re", &ops) || |
|
1064 !DoRule(ops.register_number, new ValExpressionRule(ops.expression))) |
|
1065 return false; |
|
1066 break; |
|
1067 } |
|
1068 |
|
1069 // Restore the rule established for a register by the CIE. |
|
1070 case DW_CFA_restore_extended: |
|
1071 if (!ParseOperands("r", &ops) || |
|
1072 !DoRestore( ops.register_number)) |
|
1073 return false; |
|
1074 break; |
|
1075 |
|
1076 // Save the current set of rules on a stack. |
|
1077 case DW_CFA_remember_state: |
|
1078 if (!saved_rules_) { |
|
1079 saved_rules_ = new std::stack<RuleMap>(); |
|
1080 } |
|
1081 saved_rules_->push(rules_); |
|
1082 break; |
|
1083 |
|
1084 // Pop the current set of rules off the stack. |
|
1085 case DW_CFA_restore_state: { |
|
1086 if (!saved_rules_ || saved_rules_->empty()) { |
|
1087 reporter_->EmptyStateStack(entry_->offset, entry_->kind, |
|
1088 CursorOffset()); |
|
1089 return false; |
|
1090 } |
|
1091 const RuleMap &new_rules = saved_rules_->top(); |
|
1092 if (rules_.CFARule() && !new_rules.CFARule()) { |
|
1093 reporter_->ClearingCFARule(entry_->offset, entry_->kind, |
|
1094 CursorOffset()); |
|
1095 return false; |
|
1096 } |
|
1097 rules_.HandleTransitionTo(handler_, address_, new_rules); |
|
1098 rules_ = new_rules; |
|
1099 saved_rules_->pop(); |
|
1100 break; |
|
1101 } |
|
1102 |
|
1103 // No operation. (Padding instruction.) |
|
1104 case DW_CFA_nop: |
|
1105 break; |
|
1106 |
|
1107 // A SPARC register window save: Registers 8 through 15 (%o0-%o7) |
|
1108 // are saved in registers 24 through 31 (%i0-%i7), and registers |
|
1109 // 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets |
|
1110 // (0-15 * the register size). The register numbers must be |
|
1111 // hard-coded. A GNU extension, and not a pretty one. |
|
1112 case DW_CFA_GNU_window_save: { |
|
1113 // Save %o0-%o7 in %i0-%i7. |
|
1114 for (int i = 8; i < 16; i++) |
|
1115 if (!DoRule(i, new RegisterRule(i + 16))) |
|
1116 return false; |
|
1117 // Save %l0-%l7 and %i0-%i7 at the CFA. |
|
1118 for (int i = 16; i < 32; i++) |
|
1119 // Assume that the byte reader's address size is the same as |
|
1120 // the architecture's register size. !@#%*^ hilarious. |
|
1121 if (!DoRule(i, new OffsetRule(Handler::kCFARegister, |
|
1122 (i - 16) * reader_->AddressSize()))) |
|
1123 return false; |
|
1124 break; |
|
1125 } |
|
1126 |
|
1127 // I'm not sure what this is. GDB doesn't use it for unwinding. |
|
1128 case DW_CFA_GNU_args_size: |
|
1129 if (!ParseOperands("o", &ops)) return false; |
|
1130 break; |
|
1131 |
|
1132 // An opcode we don't recognize. |
|
1133 default: { |
|
1134 reporter_->BadInstruction(entry_->offset, entry_->kind, CursorOffset()); |
|
1135 return false; |
|
1136 } |
|
1137 } |
|
1138 |
|
1139 return true; |
|
1140 } |
|
1141 |
|
1142 bool CallFrameInfo::State::DoDefCFA(unsigned base_register, long offset) { |
|
1143 Rule *rule = new ValOffsetRule(base_register, offset); |
|
1144 rules_.SetCFARule(rule); |
|
1145 return rule->Handle(handler_, address_, Handler::kCFARegister); |
|
1146 } |
|
1147 |
|
1148 bool CallFrameInfo::State::DoDefCFAOffset(long offset) { |
|
1149 Rule *cfa_rule = rules_.CFARule(); |
|
1150 if (!cfa_rule) { |
|
1151 reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset()); |
|
1152 return false; |
|
1153 } |
|
1154 cfa_rule->SetOffset(offset); |
|
1155 return cfa_rule->Handle(handler_, address_, Handler::kCFARegister); |
|
1156 } |
|
1157 |
|
1158 bool CallFrameInfo::State::DoRule(unsigned reg, Rule *rule) { |
|
1159 rules_.SetRegisterRule(reg, rule); |
|
1160 return rule->Handle(handler_, address_, reg); |
|
1161 } |
|
1162 |
|
1163 bool CallFrameInfo::State::DoOffset(unsigned reg, long offset) { |
|
1164 if (!rules_.CFARule()) { |
|
1165 reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset()); |
|
1166 return false; |
|
1167 } |
|
1168 return DoRule(reg, |
|
1169 new OffsetRule(Handler::kCFARegister, offset)); |
|
1170 } |
|
1171 |
|
1172 bool CallFrameInfo::State::DoValOffset(unsigned reg, long offset) { |
|
1173 if (!rules_.CFARule()) { |
|
1174 reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset()); |
|
1175 return false; |
|
1176 } |
|
1177 return DoRule(reg, |
|
1178 new ValOffsetRule(Handler::kCFARegister, offset)); |
|
1179 } |
|
1180 |
|
1181 bool CallFrameInfo::State::DoRestore(unsigned reg) { |
|
1182 // DW_CFA_restore and DW_CFA_restore_extended don't make sense in a CIE. |
|
1183 if (entry_->kind == kCIE) { |
|
1184 reporter_->RestoreInCIE(entry_->offset, CursorOffset()); |
|
1185 return false; |
|
1186 } |
|
1187 Rule *rule = cie_rules_.RegisterRule(reg); |
|
1188 if (!rule) { |
|
1189 // This isn't really the right thing to do, but since CFI generally |
|
1190 // only mentions callee-saves registers, and GCC's convention for |
|
1191 // callee-saves registers is that they are unchanged, it's a good |
|
1192 // approximation. |
|
1193 rule = new SameValueRule(); |
|
1194 } |
|
1195 return DoRule(reg, rule); |
|
1196 } |
|
1197 |
|
1198 bool CallFrameInfo::ReadEntryPrologue(const char *cursor, Entry *entry) { |
|
1199 const char *buffer_end = buffer_ + buffer_length_; |
|
1200 |
|
1201 // Initialize enough of ENTRY for use in error reporting. |
|
1202 entry->offset = cursor - buffer_; |
|
1203 entry->start = cursor; |
|
1204 entry->kind = kUnknown; |
|
1205 entry->end = NULL; |
|
1206 |
|
1207 // Read the initial length. This sets reader_'s offset size. |
|
1208 size_t length_size; |
|
1209 uint64 length = reader_->ReadInitialLength(cursor, &length_size); |
|
1210 if (length_size > size_t(buffer_end - cursor)) |
|
1211 return ReportIncomplete(entry); |
|
1212 cursor += length_size; |
|
1213 |
|
1214 // In a .eh_frame section, a length of zero marks the end of the series |
|
1215 // of entries. |
|
1216 if (length == 0 && eh_frame_) { |
|
1217 entry->kind = kTerminator; |
|
1218 entry->end = cursor; |
|
1219 return true; |
|
1220 } |
|
1221 |
|
1222 // Validate the length. |
|
1223 if (length > size_t(buffer_end - cursor)) |
|
1224 return ReportIncomplete(entry); |
|
1225 |
|
1226 // The length is the number of bytes after the initial length field; |
|
1227 // we have that position handy at this point, so compute the end |
|
1228 // now. (If we're parsing 64-bit-offset DWARF on a 32-bit machine, |
|
1229 // and the length didn't fit in a size_t, we would have rejected it |
|
1230 // above.) |
|
1231 entry->end = cursor + length; |
|
1232 |
|
1233 // Parse the next field: either the offset of a CIE or a CIE id. |
|
1234 size_t offset_size = reader_->OffsetSize(); |
|
1235 if (offset_size > size_t(entry->end - cursor)) return ReportIncomplete(entry); |
|
1236 entry->id = reader_->ReadOffset(cursor); |
|
1237 |
|
1238 // Don't advance cursor past id field yet; in .eh_frame data we need |
|
1239 // the id's position to compute the section offset of an FDE's CIE. |
|
1240 |
|
1241 // Now we can decide what kind of entry this is. |
|
1242 if (eh_frame_) { |
|
1243 // In .eh_frame data, an ID of zero marks the entry as a CIE, and |
|
1244 // anything else is an offset from the id field of the FDE to the start |
|
1245 // of the CIE. |
|
1246 if (entry->id == 0) { |
|
1247 entry->kind = kCIE; |
|
1248 } else { |
|
1249 entry->kind = kFDE; |
|
1250 // Turn the offset from the id into an offset from the buffer's start. |
|
1251 entry->id = (cursor - buffer_) - entry->id; |
|
1252 } |
|
1253 } else { |
|
1254 // In DWARF CFI data, an ID of ~0 (of the appropriate width, given the |
|
1255 // offset size for the entry) marks the entry as a CIE, and anything |
|
1256 // else is the offset of the CIE from the beginning of the section. |
|
1257 if (offset_size == 4) |
|
1258 entry->kind = (entry->id == 0xffffffff) ? kCIE : kFDE; |
|
1259 else { |
|
1260 MOZ_ASSERT(offset_size == 8); |
|
1261 entry->kind = (entry->id == 0xffffffffffffffffULL) ? kCIE : kFDE; |
|
1262 } |
|
1263 } |
|
1264 |
|
1265 // Now advance cursor past the id. |
|
1266 cursor += offset_size; |
|
1267 |
|
1268 // The fields specific to this kind of entry start here. |
|
1269 entry->fields = cursor; |
|
1270 |
|
1271 entry->cie = NULL; |
|
1272 |
|
1273 return true; |
|
1274 } |
|
1275 |
|
1276 bool CallFrameInfo::ReadCIEFields(CIE *cie) { |
|
1277 const char *cursor = cie->fields; |
|
1278 size_t len; |
|
1279 |
|
1280 MOZ_ASSERT(cie->kind == kCIE); |
|
1281 |
|
1282 // Prepare for early exit. |
|
1283 cie->version = 0; |
|
1284 cie->augmentation.clear(); |
|
1285 cie->code_alignment_factor = 0; |
|
1286 cie->data_alignment_factor = 0; |
|
1287 cie->return_address_register = 0; |
|
1288 cie->has_z_augmentation = false; |
|
1289 cie->pointer_encoding = DW_EH_PE_absptr; |
|
1290 cie->instructions = 0; |
|
1291 |
|
1292 // Parse the version number. |
|
1293 if (cie->end - cursor < 1) |
|
1294 return ReportIncomplete(cie); |
|
1295 cie->version = reader_->ReadOneByte(cursor); |
|
1296 cursor++; |
|
1297 |
|
1298 // If we don't recognize the version, we can't parse any more fields of the |
|
1299 // CIE. For DWARF CFI, we handle versions 1 through 3 (there was never a |
|
1300 // version 2 of CFI data). For .eh_frame, we handle versions 1 and 3 as well; |
|
1301 // the difference between those versions seems to be the same as for |
|
1302 // .debug_frame. |
|
1303 if (cie->version < 1 || cie->version > 3) { |
|
1304 reporter_->UnrecognizedVersion(cie->offset, cie->version); |
|
1305 return false; |
|
1306 } |
|
1307 |
|
1308 const char *augmentation_start = cursor; |
|
1309 const void *augmentation_end = |
|
1310 memchr(augmentation_start, '\0', cie->end - augmentation_start); |
|
1311 if (! augmentation_end) return ReportIncomplete(cie); |
|
1312 cursor = static_cast<const char *>(augmentation_end); |
|
1313 cie->augmentation = string(augmentation_start, |
|
1314 cursor - augmentation_start); |
|
1315 // Skip the terminating '\0'. |
|
1316 cursor++; |
|
1317 |
|
1318 // Is this CFI augmented? |
|
1319 if (!cie->augmentation.empty()) { |
|
1320 // Is it an augmentation we recognize? |
|
1321 if (cie->augmentation[0] == DW_Z_augmentation_start) { |
|
1322 // Linux C++ ABI 'z' augmentation, used for exception handling data. |
|
1323 cie->has_z_augmentation = true; |
|
1324 } else { |
|
1325 // Not an augmentation we recognize. Augmentations can have arbitrary |
|
1326 // effects on the form of rest of the content, so we have to give up. |
|
1327 reporter_->UnrecognizedAugmentation(cie->offset, cie->augmentation); |
|
1328 return false; |
|
1329 } |
|
1330 } |
|
1331 |
|
1332 // Parse the code alignment factor. |
|
1333 cie->code_alignment_factor = reader_->ReadUnsignedLEB128(cursor, &len); |
|
1334 if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie); |
|
1335 cursor += len; |
|
1336 |
|
1337 // Parse the data alignment factor. |
|
1338 cie->data_alignment_factor = reader_->ReadSignedLEB128(cursor, &len); |
|
1339 if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie); |
|
1340 cursor += len; |
|
1341 |
|
1342 // Parse the return address register. This is a ubyte in version 1, and |
|
1343 // a ULEB128 in version 3. |
|
1344 if (cie->version == 1) { |
|
1345 if (cursor >= cie->end) return ReportIncomplete(cie); |
|
1346 cie->return_address_register = uint8(*cursor++); |
|
1347 } else { |
|
1348 cie->return_address_register = reader_->ReadUnsignedLEB128(cursor, &len); |
|
1349 if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie); |
|
1350 cursor += len; |
|
1351 } |
|
1352 |
|
1353 // If we have a 'z' augmentation string, find the augmentation data and |
|
1354 // use the augmentation string to parse it. |
|
1355 if (cie->has_z_augmentation) { |
|
1356 uint64_t data_size = reader_->ReadUnsignedLEB128(cursor, &len); |
|
1357 if (size_t(cie->end - cursor) < len + data_size) |
|
1358 return ReportIncomplete(cie); |
|
1359 cursor += len; |
|
1360 const char *data = cursor; |
|
1361 cursor += data_size; |
|
1362 const char *data_end = cursor; |
|
1363 |
|
1364 cie->has_z_lsda = false; |
|
1365 cie->has_z_personality = false; |
|
1366 cie->has_z_signal_frame = false; |
|
1367 |
|
1368 // Walk the augmentation string, and extract values from the |
|
1369 // augmentation data as the string directs. |
|
1370 for (size_t i = 1; i < cie->augmentation.size(); i++) { |
|
1371 switch (cie->augmentation[i]) { |
|
1372 case DW_Z_has_LSDA: |
|
1373 // The CIE's augmentation data holds the language-specific data |
|
1374 // area pointer's encoding, and the FDE's augmentation data holds |
|
1375 // the pointer itself. |
|
1376 cie->has_z_lsda = true; |
|
1377 // Fetch the LSDA encoding from the augmentation data. |
|
1378 if (data >= data_end) return ReportIncomplete(cie); |
|
1379 cie->lsda_encoding = DwarfPointerEncoding(*data++); |
|
1380 if (!reader_->ValidEncoding(cie->lsda_encoding)) { |
|
1381 reporter_->InvalidPointerEncoding(cie->offset, cie->lsda_encoding); |
|
1382 return false; |
|
1383 } |
|
1384 // Don't check if the encoding is usable here --- we haven't |
|
1385 // read the FDE's fields yet, so we're not prepared for |
|
1386 // DW_EH_PE_funcrel, although that's a fine encoding for the |
|
1387 // LSDA to use, since it appears in the FDE. |
|
1388 break; |
|
1389 |
|
1390 case DW_Z_has_personality_routine: |
|
1391 // The CIE's augmentation data holds the personality routine |
|
1392 // pointer's encoding, followed by the pointer itself. |
|
1393 cie->has_z_personality = true; |
|
1394 // Fetch the personality routine pointer's encoding from the |
|
1395 // augmentation data. |
|
1396 if (data >= data_end) return ReportIncomplete(cie); |
|
1397 cie->personality_encoding = DwarfPointerEncoding(*data++); |
|
1398 if (!reader_->ValidEncoding(cie->personality_encoding)) { |
|
1399 reporter_->InvalidPointerEncoding(cie->offset, |
|
1400 cie->personality_encoding); |
|
1401 return false; |
|
1402 } |
|
1403 if (!reader_->UsableEncoding(cie->personality_encoding)) { |
|
1404 reporter_->UnusablePointerEncoding(cie->offset, |
|
1405 cie->personality_encoding); |
|
1406 return false; |
|
1407 } |
|
1408 // Fetch the personality routine's pointer itself from the data. |
|
1409 cie->personality_address = |
|
1410 reader_->ReadEncodedPointer(data, cie->personality_encoding, |
|
1411 &len); |
|
1412 if (len > size_t(data_end - data)) |
|
1413 return ReportIncomplete(cie); |
|
1414 data += len; |
|
1415 break; |
|
1416 |
|
1417 case DW_Z_has_FDE_address_encoding: |
|
1418 // The CIE's augmentation data holds the pointer encoding to use |
|
1419 // for addresses in the FDE. |
|
1420 if (data >= data_end) return ReportIncomplete(cie); |
|
1421 cie->pointer_encoding = DwarfPointerEncoding(*data++); |
|
1422 if (!reader_->ValidEncoding(cie->pointer_encoding)) { |
|
1423 reporter_->InvalidPointerEncoding(cie->offset, |
|
1424 cie->pointer_encoding); |
|
1425 return false; |
|
1426 } |
|
1427 if (!reader_->UsableEncoding(cie->pointer_encoding)) { |
|
1428 reporter_->UnusablePointerEncoding(cie->offset, |
|
1429 cie->pointer_encoding); |
|
1430 return false; |
|
1431 } |
|
1432 break; |
|
1433 |
|
1434 case DW_Z_is_signal_trampoline: |
|
1435 // Frames using this CIE are signal delivery frames. |
|
1436 cie->has_z_signal_frame = true; |
|
1437 break; |
|
1438 |
|
1439 default: |
|
1440 // An augmentation we don't recognize. |
|
1441 reporter_->UnrecognizedAugmentation(cie->offset, cie->augmentation); |
|
1442 return false; |
|
1443 } |
|
1444 } |
|
1445 } |
|
1446 |
|
1447 // The CIE's instructions start here. |
|
1448 cie->instructions = cursor; |
|
1449 |
|
1450 return true; |
|
1451 } |
|
1452 |
|
1453 bool CallFrameInfo::ReadFDEFields(FDE *fde) { |
|
1454 const char *cursor = fde->fields; |
|
1455 size_t size; |
|
1456 |
|
1457 fde->address = reader_->ReadEncodedPointer(cursor, fde->cie->pointer_encoding, |
|
1458 &size); |
|
1459 if (size > size_t(fde->end - cursor)) |
|
1460 return ReportIncomplete(fde); |
|
1461 cursor += size; |
|
1462 reader_->SetFunctionBase(fde->address); |
|
1463 |
|
1464 // For the length, we strip off the upper nybble of the encoding used for |
|
1465 // the starting address. |
|
1466 DwarfPointerEncoding length_encoding = |
|
1467 DwarfPointerEncoding(fde->cie->pointer_encoding & 0x0f); |
|
1468 fde->size = reader_->ReadEncodedPointer(cursor, length_encoding, &size); |
|
1469 if (size > size_t(fde->end - cursor)) |
|
1470 return ReportIncomplete(fde); |
|
1471 cursor += size; |
|
1472 |
|
1473 // If the CIE has a 'z' augmentation string, then augmentation data |
|
1474 // appears here. |
|
1475 if (fde->cie->has_z_augmentation) { |
|
1476 uint64_t data_size = reader_->ReadUnsignedLEB128(cursor, &size); |
|
1477 if (size_t(fde->end - cursor) < size + data_size) |
|
1478 return ReportIncomplete(fde); |
|
1479 cursor += size; |
|
1480 |
|
1481 // In the abstract, we should walk the augmentation string, and extract |
|
1482 // items from the FDE's augmentation data as we encounter augmentation |
|
1483 // string characters that specify their presence: the ordering of items |
|
1484 // in the augmentation string determines the arrangement of values in |
|
1485 // the augmentation data. |
|
1486 // |
|
1487 // In practice, there's only ever one value in FDE augmentation data |
|
1488 // that we support --- the LSDA pointer --- and we have to bail if we |
|
1489 // see any unrecognized augmentation string characters. So if there is |
|
1490 // anything here at all, we know what it is, and where it starts. |
|
1491 if (fde->cie->has_z_lsda) { |
|
1492 // Check whether the LSDA's pointer encoding is usable now: only once |
|
1493 // we've parsed the FDE's starting address do we call reader_-> |
|
1494 // SetFunctionBase, so that the DW_EH_PE_funcrel encoding becomes |
|
1495 // usable. |
|
1496 if (!reader_->UsableEncoding(fde->cie->lsda_encoding)) { |
|
1497 reporter_->UnusablePointerEncoding(fde->cie->offset, |
|
1498 fde->cie->lsda_encoding); |
|
1499 return false; |
|
1500 } |
|
1501 |
|
1502 fde->lsda_address = |
|
1503 reader_->ReadEncodedPointer(cursor, fde->cie->lsda_encoding, &size); |
|
1504 if (size > data_size) |
|
1505 return ReportIncomplete(fde); |
|
1506 // Ideally, we would also complain here if there were unconsumed |
|
1507 // augmentation data. |
|
1508 } |
|
1509 |
|
1510 cursor += data_size; |
|
1511 } |
|
1512 |
|
1513 // The FDE's instructions start after those. |
|
1514 fde->instructions = cursor; |
|
1515 |
|
1516 return true; |
|
1517 } |
|
1518 |
|
1519 bool CallFrameInfo::Start() { |
|
1520 const char *buffer_end = buffer_ + buffer_length_; |
|
1521 const char *cursor; |
|
1522 bool all_ok = true; |
|
1523 const char *entry_end; |
|
1524 bool ok; |
|
1525 |
|
1526 // Traverse all the entries in buffer_, skipping CIEs and offering |
|
1527 // FDEs to the handler. |
|
1528 for (cursor = buffer_; cursor < buffer_end; |
|
1529 cursor = entry_end, all_ok = all_ok && ok) { |
|
1530 FDE fde; |
|
1531 |
|
1532 // Make it easy to skip this entry with 'continue': assume that |
|
1533 // things are not okay until we've checked all the data, and |
|
1534 // prepare the address of the next entry. |
|
1535 ok = false; |
|
1536 |
|
1537 // Read the entry's prologue. |
|
1538 if (!ReadEntryPrologue(cursor, &fde)) { |
|
1539 if (!fde.end) { |
|
1540 // If we couldn't even figure out this entry's extent, then we |
|
1541 // must stop processing entries altogether. |
|
1542 all_ok = false; |
|
1543 break; |
|
1544 } |
|
1545 entry_end = fde.end; |
|
1546 continue; |
|
1547 } |
|
1548 |
|
1549 // The next iteration picks up after this entry. |
|
1550 entry_end = fde.end; |
|
1551 |
|
1552 // Did we see an .eh_frame terminating mark? |
|
1553 if (fde.kind == kTerminator) { |
|
1554 // If there appears to be more data left in the section after the |
|
1555 // terminating mark, warn the user. But this is just a warning; |
|
1556 // we leave all_ok true. |
|
1557 if (fde.end < buffer_end) reporter_->EarlyEHTerminator(fde.offset); |
|
1558 break; |
|
1559 } |
|
1560 |
|
1561 // In this loop, we skip CIEs. We only parse them fully when we |
|
1562 // parse an FDE that refers to them. This limits our memory |
|
1563 // consumption (beyond the buffer itself) to that needed to |
|
1564 // process the largest single entry. |
|
1565 if (fde.kind != kFDE) { |
|
1566 ok = true; |
|
1567 continue; |
|
1568 } |
|
1569 |
|
1570 // Validate the CIE pointer. |
|
1571 if (fde.id > buffer_length_) { |
|
1572 reporter_->CIEPointerOutOfRange(fde.offset, fde.id); |
|
1573 continue; |
|
1574 } |
|
1575 |
|
1576 CIE cie; |
|
1577 |
|
1578 // Parse this FDE's CIE header. |
|
1579 if (!ReadEntryPrologue(buffer_ + fde.id, &cie)) |
|
1580 continue; |
|
1581 // This had better be an actual CIE. |
|
1582 if (cie.kind != kCIE) { |
|
1583 reporter_->BadCIEId(fde.offset, fde.id); |
|
1584 continue; |
|
1585 } |
|
1586 if (!ReadCIEFields(&cie)) |
|
1587 continue; |
|
1588 |
|
1589 // We now have the values that govern both the CIE and the FDE. |
|
1590 cie.cie = &cie; |
|
1591 fde.cie = &cie; |
|
1592 |
|
1593 // Parse the FDE's header. |
|
1594 if (!ReadFDEFields(&fde)) |
|
1595 continue; |
|
1596 |
|
1597 // Call Entry to ask the consumer if they're interested. |
|
1598 if (!handler_->Entry(fde.offset, fde.address, fde.size, |
|
1599 cie.version, cie.augmentation, |
|
1600 cie.return_address_register)) { |
|
1601 // The handler isn't interested in this entry. That's not an error. |
|
1602 ok = true; |
|
1603 continue; |
|
1604 } |
|
1605 |
|
1606 if (cie.has_z_augmentation) { |
|
1607 // Report the personality routine address, if we have one. |
|
1608 if (cie.has_z_personality) { |
|
1609 if (!handler_ |
|
1610 ->PersonalityRoutine(cie.personality_address, |
|
1611 IsIndirectEncoding(cie.personality_encoding))) |
|
1612 continue; |
|
1613 } |
|
1614 |
|
1615 // Report the language-specific data area address, if we have one. |
|
1616 if (cie.has_z_lsda) { |
|
1617 if (!handler_ |
|
1618 ->LanguageSpecificDataArea(fde.lsda_address, |
|
1619 IsIndirectEncoding(cie.lsda_encoding))) |
|
1620 continue; |
|
1621 } |
|
1622 |
|
1623 // If this is a signal-handling frame, report that. |
|
1624 if (cie.has_z_signal_frame) { |
|
1625 if (!handler_->SignalHandler()) |
|
1626 continue; |
|
1627 } |
|
1628 } |
|
1629 |
|
1630 // Interpret the CIE's instructions, and then the FDE's instructions. |
|
1631 State state(reader_, handler_, reporter_, fde.address); |
|
1632 ok = state.InterpretCIE(cie) && state.InterpretFDE(fde); |
|
1633 |
|
1634 // Tell the ByteReader that the function start address from the |
|
1635 // FDE header is no longer valid. |
|
1636 reader_->ClearFunctionBase(); |
|
1637 |
|
1638 // Report the end of the entry. |
|
1639 handler_->End(); |
|
1640 } |
|
1641 |
|
1642 return all_ok; |
|
1643 } |
|
1644 |
|
1645 const char *CallFrameInfo::KindName(EntryKind kind) { |
|
1646 if (kind == CallFrameInfo::kUnknown) |
|
1647 return "entry"; |
|
1648 else if (kind == CallFrameInfo::kCIE) |
|
1649 return "common information entry"; |
|
1650 else if (kind == CallFrameInfo::kFDE) |
|
1651 return "frame description entry"; |
|
1652 else { |
|
1653 MOZ_ASSERT (kind == CallFrameInfo::kTerminator); |
|
1654 return ".eh_frame sequence terminator"; |
|
1655 } |
|
1656 } |
|
1657 |
|
1658 bool CallFrameInfo::ReportIncomplete(Entry *entry) { |
|
1659 reporter_->Incomplete(entry->offset, entry->kind); |
|
1660 return false; |
|
1661 } |
|
1662 |
|
1663 void CallFrameInfo::Reporter::Incomplete(uint64 offset, |
|
1664 CallFrameInfo::EntryKind kind) { |
|
1665 char buf[300]; |
|
1666 snprintf(buf, sizeof(buf), |
|
1667 "%s: CFI %s at offset 0x%llx in '%s': entry ends early\n", |
|
1668 filename_.c_str(), CallFrameInfo::KindName(kind), offset, |
|
1669 section_.c_str()); |
|
1670 log_(buf); |
|
1671 } |
|
1672 |
|
1673 void CallFrameInfo::Reporter::EarlyEHTerminator(uint64 offset) { |
|
1674 char buf[300]; |
|
1675 snprintf(buf, sizeof(buf), |
|
1676 "%s: CFI at offset 0x%llx in '%s': saw end-of-data marker" |
|
1677 " before end of section contents\n", |
|
1678 filename_.c_str(), offset, section_.c_str()); |
|
1679 log_(buf); |
|
1680 } |
|
1681 |
|
1682 void CallFrameInfo::Reporter::CIEPointerOutOfRange(uint64 offset, |
|
1683 uint64 cie_offset) { |
|
1684 char buf[300]; |
|
1685 snprintf(buf, sizeof(buf), |
|
1686 "%s: CFI frame description entry at offset 0x%llx in '%s':" |
|
1687 " CIE pointer is out of range: 0x%llx\n", |
|
1688 filename_.c_str(), offset, section_.c_str(), cie_offset); |
|
1689 log_(buf); |
|
1690 } |
|
1691 |
|
1692 void CallFrameInfo::Reporter::BadCIEId(uint64 offset, uint64 cie_offset) { |
|
1693 char buf[300]; |
|
1694 snprintf(buf, sizeof(buf), |
|
1695 "%s: CFI frame description entry at offset 0x%llx in '%s':" |
|
1696 " CIE pointer does not point to a CIE: 0x%llx\n", |
|
1697 filename_.c_str(), offset, section_.c_str(), cie_offset); |
|
1698 log_(buf); |
|
1699 } |
|
1700 |
|
1701 void CallFrameInfo::Reporter::UnrecognizedVersion(uint64 offset, int version) { |
|
1702 char buf[300]; |
|
1703 snprintf(buf, sizeof(buf), |
|
1704 "%s: CFI frame description entry at offset 0x%llx in '%s':" |
|
1705 " CIE specifies unrecognized version: %d\n", |
|
1706 filename_.c_str(), offset, section_.c_str(), version); |
|
1707 log_(buf); |
|
1708 } |
|
1709 |
|
1710 void CallFrameInfo::Reporter::UnrecognizedAugmentation(uint64 offset, |
|
1711 const string &aug) { |
|
1712 char buf[300]; |
|
1713 snprintf(buf, sizeof(buf), |
|
1714 "%s: CFI frame description entry at offset 0x%llx in '%s':" |
|
1715 " CIE specifies unrecognized augmentation: '%s'\n", |
|
1716 filename_.c_str(), offset, section_.c_str(), aug.c_str()); |
|
1717 log_(buf); |
|
1718 } |
|
1719 |
|
1720 void CallFrameInfo::Reporter::InvalidPointerEncoding(uint64 offset, |
|
1721 uint8 encoding) { |
|
1722 char buf[300]; |
|
1723 snprintf(buf, sizeof(buf), |
|
1724 "%s: CFI common information entry at offset 0x%llx in '%s':" |
|
1725 " 'z' augmentation specifies invalid pointer encoding: 0x%02x\n", |
|
1726 filename_.c_str(), offset, section_.c_str(), encoding); |
|
1727 log_(buf); |
|
1728 } |
|
1729 |
|
1730 void CallFrameInfo::Reporter::UnusablePointerEncoding(uint64 offset, |
|
1731 uint8 encoding) { |
|
1732 char buf[300]; |
|
1733 snprintf(buf, sizeof(buf), |
|
1734 "%s: CFI common information entry at offset 0x%llx in '%s':" |
|
1735 " 'z' augmentation specifies a pointer encoding for which" |
|
1736 " we have no base address: 0x%02x\n", |
|
1737 filename_.c_str(), offset, section_.c_str(), encoding); |
|
1738 log_(buf); |
|
1739 } |
|
1740 |
|
1741 void CallFrameInfo::Reporter::RestoreInCIE(uint64 offset, uint64 insn_offset) { |
|
1742 char buf[300]; |
|
1743 snprintf(buf, sizeof(buf), |
|
1744 "%s: CFI common information entry at offset 0x%llx in '%s':" |
|
1745 " the DW_CFA_restore instruction at offset 0x%llx" |
|
1746 " cannot be used in a common information entry\n", |
|
1747 filename_.c_str(), offset, section_.c_str(), insn_offset); |
|
1748 log_(buf); |
|
1749 } |
|
1750 |
|
1751 void CallFrameInfo::Reporter::BadInstruction(uint64 offset, |
|
1752 CallFrameInfo::EntryKind kind, |
|
1753 uint64 insn_offset) { |
|
1754 char buf[300]; |
|
1755 snprintf(buf, sizeof(buf), |
|
1756 "%s: CFI %s at offset 0x%llx in section '%s':" |
|
1757 " the instruction at offset 0x%llx is unrecognized\n", |
|
1758 filename_.c_str(), CallFrameInfo::KindName(kind), |
|
1759 offset, section_.c_str(), insn_offset); |
|
1760 log_(buf); |
|
1761 } |
|
1762 |
|
1763 void CallFrameInfo::Reporter::NoCFARule(uint64 offset, |
|
1764 CallFrameInfo::EntryKind kind, |
|
1765 uint64 insn_offset) { |
|
1766 char buf[300]; |
|
1767 snprintf(buf, sizeof(buf), |
|
1768 "%s: CFI %s at offset 0x%llx in section '%s':" |
|
1769 " the instruction at offset 0x%llx assumes that a CFA rule has" |
|
1770 " been set, but none has been set\n", |
|
1771 filename_.c_str(), CallFrameInfo::KindName(kind), offset, |
|
1772 section_.c_str(), insn_offset); |
|
1773 log_(buf); |
|
1774 } |
|
1775 |
|
1776 void CallFrameInfo::Reporter::EmptyStateStack(uint64 offset, |
|
1777 CallFrameInfo::EntryKind kind, |
|
1778 uint64 insn_offset) { |
|
1779 char buf[300]; |
|
1780 snprintf(buf, sizeof(buf), |
|
1781 "%s: CFI %s at offset 0x%llx in section '%s':" |
|
1782 " the DW_CFA_restore_state instruction at offset 0x%llx" |
|
1783 " should pop a saved state from the stack, but the stack is empty\n", |
|
1784 filename_.c_str(), CallFrameInfo::KindName(kind), offset, |
|
1785 section_.c_str(), insn_offset); |
|
1786 log_(buf); |
|
1787 } |
|
1788 |
|
1789 void CallFrameInfo::Reporter::ClearingCFARule(uint64 offset, |
|
1790 CallFrameInfo::EntryKind kind, |
|
1791 uint64 insn_offset) { |
|
1792 char buf[300]; |
|
1793 snprintf(buf, sizeof(buf), |
|
1794 "%s: CFI %s at offset 0x%llx in section '%s':" |
|
1795 " the DW_CFA_restore_state instruction at offset 0x%llx" |
|
1796 " would clear the CFA rule in effect\n", |
|
1797 filename_.c_str(), CallFrameInfo::KindName(kind), offset, |
|
1798 section_.c_str(), insn_offset); |
|
1799 log_(buf); |
|
1800 } |
|
1801 |
|
1802 |
|
1803 const unsigned int DwarfCFIToModule::RegisterNames::I386() { |
|
1804 /* |
|
1805 8 "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi", |
|
1806 3 "$eip", "$eflags", "$unused1", |
|
1807 8 "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7", |
|
1808 2 "$unused2", "$unused3", |
|
1809 8 "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7", |
|
1810 8 "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7", |
|
1811 3 "$fcw", "$fsw", "$mxcsr", |
|
1812 8 "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5", |
|
1813 2 "$tr", "$ldtr" |
|
1814 */ |
|
1815 return 8 + 3 + 8 + 2 + 8 + 8 + 3 + 8 + 2; |
|
1816 } |
|
1817 |
|
1818 const unsigned int DwarfCFIToModule::RegisterNames::X86_64() { |
|
1819 /* |
|
1820 8 "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp", |
|
1821 8 "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", |
|
1822 1 "$rip", |
|
1823 8 "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7", |
|
1824 8 "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15", |
|
1825 8 "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7", |
|
1826 8 "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7", |
|
1827 1 "$rflags", |
|
1828 8 "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused1", "$unused2", |
|
1829 4 "$fs.base", "$gs.base", "$unused3", "$unused4", |
|
1830 2 "$tr", "$ldtr", |
|
1831 3 "$mxcsr", "$fcw", "$fsw" |
|
1832 */ |
|
1833 return 8 + 8 + 1 + 8 + 8 + 8 + 8 + 1 + 8 + 4 + 2 + 3; |
|
1834 } |
|
1835 |
|
1836 // Per ARM IHI 0040A, section 3.1 |
|
1837 const unsigned int DwarfCFIToModule::RegisterNames::ARM() { |
|
1838 /* |
|
1839 8 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
|
1840 8 "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", |
|
1841 8 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
|
1842 8 "fps", "cpsr", "", "", "", "", "", "", |
|
1843 8 "", "", "", "", "", "", "", "", |
|
1844 8 "", "", "", "", "", "", "", "", |
|
1845 8 "", "", "", "", "", "", "", "", |
|
1846 8 "", "", "", "", "", "", "", "", |
|
1847 8 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", |
|
1848 8 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", |
|
1849 8 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", |
|
1850 8 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", |
|
1851 8 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7" |
|
1852 */ |
|
1853 return 13 * 8; |
|
1854 } |
|
1855 |
|
1856 bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length, |
|
1857 uint8 version, const string &augmentation, |
|
1858 unsigned return_address) { |
|
1859 if (DEBUG_DWARF) |
|
1860 printf("LUL.DW DwarfCFIToModule::Entry 0x%llx,+%lld\n", address, length); |
|
1861 |
|
1862 summ_->Entry(address, length); |
|
1863 |
|
1864 // If dwarf2reader::CallFrameInfo can handle this version and |
|
1865 // augmentation, then we should be okay with that, so there's no |
|
1866 // need to check them here. |
|
1867 |
|
1868 // Get ready to collect entries. |
|
1869 return_address_ = return_address; |
|
1870 |
|
1871 // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI |
|
1872 // may not establish any rule for .ra if the return address column |
|
1873 // is an ordinary register, and that register holds the return |
|
1874 // address on entry to the function. So establish an initial .ra |
|
1875 // rule citing the return address register. |
|
1876 if (return_address_ < num_dw_regs_) { |
|
1877 summ_->Rule(address, return_address_, return_address, 0, false); |
|
1878 } |
|
1879 |
|
1880 return true; |
|
1881 } |
|
1882 |
|
1883 const UniqueString* DwarfCFIToModule::RegisterName(int i) { |
|
1884 if (i < 0) { |
|
1885 MOZ_ASSERT(i == kCFARegister); |
|
1886 return ustr__ZDcfa(); |
|
1887 } |
|
1888 unsigned reg = i; |
|
1889 if (reg == return_address_) |
|
1890 return ustr__ZDra(); |
|
1891 |
|
1892 char buf[30]; |
|
1893 sprintf(buf, "dwarf_reg_%u", reg); |
|
1894 return ToUniqueString(buf); |
|
1895 } |
|
1896 |
|
1897 bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) { |
|
1898 reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg)); |
|
1899 // Treat this as a non-fatal error. |
|
1900 return true; |
|
1901 } |
|
1902 |
|
1903 bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) { |
|
1904 if (DEBUG_DWARF) |
|
1905 printf("LUL.DW 0x%llx: old r%d = Same\n", address, reg); |
|
1906 // reg + 0 |
|
1907 summ_->Rule(address, reg, reg, 0, false); |
|
1908 return true; |
|
1909 } |
|
1910 |
|
1911 bool DwarfCFIToModule::OffsetRule(uint64 address, int reg, |
|
1912 int base_register, long offset) { |
|
1913 if (DEBUG_DWARF) |
|
1914 printf("LUL.DW 0x%llx: old r%d = *(r%d + %ld)\n", |
|
1915 address, reg, base_register, offset); |
|
1916 // *(base_register + offset) |
|
1917 summ_->Rule(address, reg, base_register, offset, true); |
|
1918 return true; |
|
1919 } |
|
1920 |
|
1921 bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg, |
|
1922 int base_register, long offset) { |
|
1923 if (DEBUG_DWARF) |
|
1924 printf("LUL.DW 0x%llx: old r%d = r%d + %ld\n", |
|
1925 address, reg, base_register, offset); |
|
1926 // base_register + offset |
|
1927 summ_->Rule(address, reg, base_register, offset, false); |
|
1928 return true; |
|
1929 } |
|
1930 |
|
1931 bool DwarfCFIToModule::RegisterRule(uint64 address, int reg, |
|
1932 int base_register) { |
|
1933 if (DEBUG_DWARF) |
|
1934 printf("LUL.DW 0x%llx: old r%d = r%d\n", address, reg, base_register); |
|
1935 // base_register + 0 |
|
1936 summ_->Rule(address, reg, base_register, 0, false); |
|
1937 return true; |
|
1938 } |
|
1939 |
|
1940 bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg, |
|
1941 const string &expression) { |
|
1942 reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg)); |
|
1943 // Treat this as a non-fatal error. |
|
1944 return true; |
|
1945 } |
|
1946 |
|
1947 bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg, |
|
1948 const string &expression) { |
|
1949 reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg)); |
|
1950 // Treat this as a non-fatal error. |
|
1951 return true; |
|
1952 } |
|
1953 |
|
1954 bool DwarfCFIToModule::End() { |
|
1955 //module_->AddStackFrameEntry(entry_); |
|
1956 if (DEBUG_DWARF) |
|
1957 printf("LUL.DW DwarfCFIToModule::End()\n"); |
|
1958 summ_->End(); |
|
1959 return true; |
|
1960 } |
|
1961 |
|
1962 void DwarfCFIToModule::Reporter::UndefinedNotSupported( |
|
1963 size_t offset, |
|
1964 const UniqueString* reg) { |
|
1965 char buf[300]; |
|
1966 snprintf(buf, sizeof(buf), |
|
1967 "DwarfCFIToModule::Reporter::UndefinedNotSupported()\n"); |
|
1968 log_(buf); |
|
1969 //BPLOG(INFO) << file_ << ", section '" << section_ |
|
1970 // << "': the call frame entry at offset 0x" |
|
1971 // << std::setbase(16) << offset << std::setbase(10) |
|
1972 // << " sets the rule for register '" << FromUniqueString(reg) |
|
1973 // << "' to 'undefined', but the Breakpad symbol file format cannot " |
|
1974 // << " express this"; |
|
1975 } |
|
1976 |
|
1977 // FIXME: move this somewhere sensible |
|
1978 static bool is_power_of_2(uint64_t n) |
|
1979 { |
|
1980 int i, nSetBits = 0; |
|
1981 for (i = 0; i < 8*(int)sizeof(n); i++) { |
|
1982 if ((n & ((uint64_t)1) << i) != 0) |
|
1983 nSetBits++; |
|
1984 } |
|
1985 return nSetBits <= 1; |
|
1986 } |
|
1987 |
|
1988 void DwarfCFIToModule::Reporter::ExpressionsNotSupported( |
|
1989 size_t offset, |
|
1990 const UniqueString* reg) { |
|
1991 static uint64_t n_complaints = 0; // This isn't threadsafe |
|
1992 n_complaints++; |
|
1993 if (!is_power_of_2(n_complaints)) |
|
1994 return; |
|
1995 char buf[300]; |
|
1996 snprintf(buf, sizeof(buf), |
|
1997 "DwarfCFIToModule::Reporter::" |
|
1998 "ExpressionsNotSupported(shown %llu times)\n", |
|
1999 (unsigned long long int)n_complaints); |
|
2000 log_(buf); |
|
2001 //BPLOG(INFO) << file_ << ", section '" << section_ |
|
2002 // << "': the call frame entry at offset 0x" |
|
2003 // << std::setbase(16) << offset << std::setbase(10) |
|
2004 // << " uses a DWARF expression to describe how to recover register '" |
|
2005 // << FromUniqueString(reg) << "', but this translator cannot yet " |
|
2006 // << "translate DWARF expressions to Breakpad postfix expressions (shown " |
|
2007 // << n_complaints << " times)"; |
|
2008 } |
|
2009 |
|
2010 } // namespace lul |