1 | // -*- mode: C++ -*- |
2 | |
3 | // Copyright (c) 2010, Google Inc. |
4 | // 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 | // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> |
33 | |
34 | // cfi_frame_info-inl.h: Definitions for cfi_frame_info.h inlined functions. |
35 | |
36 | #ifndef PROCESSOR_CFI_FRAME_INFO_INL_H_ |
37 | #define PROCESSOR_CFI_FRAME_INFO_INL_H_ |
38 | |
39 | #include <string.h> |
40 | |
41 | namespace google_breakpad { |
42 | |
43 | template <typename RegisterType, class RawContextType> |
44 | bool SimpleCFIWalker<RegisterType, RawContextType>::FindCallerRegisters( |
45 | const MemoryRegion& memory, |
46 | const CFIFrameInfo& cfi_frame_info, |
47 | const RawContextType& callee_context, |
48 | int callee_validity, |
49 | RawContextType* caller_context, |
50 | int* caller_validity) const { |
51 | typedef CFIFrameInfo::RegisterValueMap<RegisterType> ValueMap; |
52 | ValueMap callee_registers; |
53 | ValueMap caller_registers; |
54 | // Just for brevity. |
55 | typename ValueMap::const_iterator caller_none = caller_registers.end(); |
56 | |
57 | // Populate callee_registers with register values from callee_context. |
58 | for (size_t i = 0; i < map_size_; i++) { |
59 | const RegisterSet& r = register_map_[i]; |
60 | if (callee_validity & r.validity_flag) |
61 | callee_registers[r.name] = callee_context.*r.context_member; |
62 | } |
63 | |
64 | // Apply the rules, and see what register values they yield. |
65 | if (!cfi_frame_info.FindCallerRegs<RegisterType>(callee_registers, memory, |
66 | &caller_registers)) |
67 | return false; |
68 | |
69 | // Populate *caller_context with the values the rules placed in |
70 | // caller_registers. |
71 | memset(caller_context, 0xda, sizeof(*caller_context)); |
72 | *caller_validity = 0; |
73 | for (size_t i = 0; i < map_size_; i++) { |
74 | const RegisterSet& r = register_map_[i]; |
75 | typename ValueMap::const_iterator caller_entry; |
76 | |
77 | // Did the rules provide a value for this register by its name? |
78 | caller_entry = caller_registers.find(r.name); |
79 | if (caller_entry != caller_none) { |
80 | caller_context->*r.context_member = caller_entry->second; |
81 | *caller_validity |= r.validity_flag; |
82 | continue; |
83 | } |
84 | |
85 | // Did the rules provide a value for this register under its |
86 | // alternate name? |
87 | if (r.alternate_name) { |
88 | caller_entry = caller_registers.find(r.alternate_name); |
89 | if (caller_entry != caller_none) { |
90 | caller_context->*r.context_member = caller_entry->second; |
91 | *caller_validity |= r.validity_flag; |
92 | continue; |
93 | } |
94 | } |
95 | |
96 | // Is this a callee-saves register? The walker assumes that these |
97 | // still hold the caller's value if the CFI doesn't mention them. |
98 | // |
99 | // Note that other frame walkers may fail to recover callee-saves |
100 | // registers; for example, the x86 "traditional" strategy only |
101 | // recovers %eip, %esp, and %ebp, even though %ebx, %esi, and %edi |
102 | // are callee-saves, too. It is not correct to blindly set the |
103 | // valid bit for all callee-saves registers, without first |
104 | // checking its validity bit in the callee. |
105 | if (r.callee_saves && (callee_validity & r.validity_flag) != 0) { |
106 | caller_context->*r.context_member = callee_context.*r.context_member; |
107 | *caller_validity |= r.validity_flag; |
108 | continue; |
109 | } |
110 | |
111 | // Otherwise, the register's value is unknown. |
112 | } |
113 | |
114 | return true; |
115 | } |
116 | |
117 | } // namespace google_breakpad |
118 | |
119 | #endif // PROCESSOR_CFI_FRAME_INFO_INL_H_ |
120 | |