OLD | NEW |
| (Empty) |
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 // Implementation of google_breakpad::DwarfCFIToModule. | |
35 // See dwarf_cfi_to_module.h for details. | |
36 | |
37 #include <sstream> | |
38 | |
39 #include "common/dwarf_cfi_to_module.h" | |
40 | |
41 namespace google_breakpad { | |
42 | |
43 using std::ostringstream; | |
44 | |
45 bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length, | |
46 uint8 version, const string &augmentation, | |
47 unsigned return_address) { | |
48 assert(!entry_); | |
49 | |
50 // If dwarf2reader::CallFrameInfo can handle this version and | |
51 // augmentation, then we should be okay with that, so there's no | |
52 // need to check them here. | |
53 | |
54 // Get ready to collect entries. | |
55 entry_ = new Module::StackFrameEntry; | |
56 entry_->address = address; | |
57 entry_->size = length; | |
58 entry_offset_ = offset; | |
59 return_address_ = return_address; | |
60 | |
61 // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI | |
62 // may not establish any rule for .ra if the return address column | |
63 // is an ordinary register, and that register holds the return | |
64 // address on entry to the function. So establish an initial .ra | |
65 // rule citing the return address register. | |
66 if (return_address_ < register_names_.size()) | |
67 entry_->initial_rules[".ra"] = register_names_[return_address_]; | |
68 | |
69 return true; | |
70 } | |
71 | |
72 string DwarfCFIToModule::RegisterName(int i) { | |
73 assert(entry_); | |
74 if (i < 0) { | |
75 assert(i == kCFARegister); | |
76 return ".cfa"; | |
77 } | |
78 unsigned reg = i; | |
79 if (reg == return_address_) | |
80 return ".ra"; | |
81 | |
82 if (0 <= reg && reg < register_names_.size()) | |
83 return register_names_[reg]; | |
84 | |
85 reporter_->UnnamedRegister(entry_offset_, reg); | |
86 char buf[30]; | |
87 sprintf(buf, "unnamed_register%u", reg); | |
88 return buf; | |
89 } | |
90 | |
91 void DwarfCFIToModule::Record(Module::Address address, int reg, | |
92 const string &rule) { | |
93 assert(entry_); | |
94 // Is this one of this entry's initial rules? | |
95 if (address == entry_->address) | |
96 entry_->initial_rules[RegisterName(reg)] = rule; | |
97 // File it under the appropriate address. | |
98 else | |
99 entry_->rule_changes[address][RegisterName(reg)] = rule; | |
100 } | |
101 | |
102 bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) { | |
103 reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg)); | |
104 // Treat this as a non-fatal error. | |
105 return true; | |
106 } | |
107 | |
108 bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) { | |
109 ostringstream s; | |
110 s << RegisterName(reg); | |
111 Record(address, reg, s.str()); | |
112 return true; | |
113 } | |
114 | |
115 bool DwarfCFIToModule::OffsetRule(uint64 address, int reg, | |
116 int base_register, long offset) { | |
117 ostringstream s; | |
118 s << RegisterName(base_register) << " " << offset << " + ^"; | |
119 Record(address, reg, s.str()); | |
120 return true; | |
121 } | |
122 | |
123 bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg, | |
124 int base_register, long offset) { | |
125 ostringstream s; | |
126 s << RegisterName(base_register) << " " << offset << " +"; | |
127 Record(address, reg, s.str()); | |
128 return true; | |
129 } | |
130 | |
131 bool DwarfCFIToModule::RegisterRule(uint64 address, int reg, | |
132 int base_register) { | |
133 ostringstream s; | |
134 s << RegisterName(base_register); | |
135 Record(address, reg, s.str()); | |
136 return true; | |
137 } | |
138 | |
139 bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg, | |
140 const string &expression) { | |
141 reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg)); | |
142 // Treat this as a non-fatal error. | |
143 return true; | |
144 } | |
145 | |
146 bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg, | |
147 const string &expression) { | |
148 reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg)); | |
149 // Treat this as a non-fatal error. | |
150 return true; | |
151 } | |
152 | |
153 bool DwarfCFIToModule::End() { | |
154 module_->AddStackFrameEntry(entry_); | |
155 entry_ = NULL; | |
156 return true; | |
157 } | |
158 | |
159 void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) { | |
160 fprintf(stderr, "%s, section '%s': " | |
161 "the call frame entry at offset 0x%zx refers to register %d," | |
162 " whose name we don't know\n", | |
163 file_.c_str(), section_.c_str(), offset, reg); | |
164 } | |
165 | |
166 void DwarfCFIToModule::Reporter::UndefinedNotSupported(size_t offset, | |
167 const string ®) { | |
168 fprintf(stderr, "%s, section '%s': " | |
169 "the call frame entry at offset 0x%zx sets the rule for " | |
170 "register '%s' to 'undefined', but the Breakpad symbol file format" | |
171 " cannot express this\n", | |
172 file_.c_str(), section_.c_str(), offset, reg.c_str()); | |
173 } | |
174 | |
175 void DwarfCFIToModule::Reporter::ExpressionsNotSupported(size_t offset, | |
176 const string ®) { | |
177 fprintf(stderr, "%s, section '%s': " | |
178 "the call frame entry at offset 0x%zx uses a DWARF expression to" | |
179 " describe how to recover register '%s', " | |
180 " but this translator cannot yet translate DWARF expressions to" | |
181 " Breakpad postfix expressions\n", | |
182 file_.c_str(), section_.c_str(), offset, reg.c_str()); | |
183 } | |
184 | |
185 } // namespace google_breakpad | |
OLD | NEW |