blob: 49a6d8520320623bd4e326fc4ecad3a4e5dcdb73 [file] [log] [blame]
jimblandy3e768ed2010-03-16 16:31:49 +00001// -*- 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
jimblandy87855242010-04-05 19:40:17 +000039#include "common/dwarf_cfi_to_module.h"
jimblandy3e768ed2010-03-16 16:31:49 +000040
41namespace google_breakpad {
42
43using std::ostringstream;
44
45bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length,
46 uint8 version, const string &augmentation,
47 unsigned return_address) {
48 assert(!entry_);
jimblandya76aaa12010-03-16 16:37:50 +000049
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.
jimblandy3e768ed2010-03-16 16:31:49 +000053
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
72string 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
91void 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
102bool 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
108bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) {
109 ostringstream s;
110 s << RegisterName(reg);
111 Record(address, reg, s.str());
112 return true;
113}
114
115bool 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
123bool 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
131bool 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
139bool 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
146bool 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
153bool DwarfCFIToModule::End() {
154 module_->AddStackFrameEntry(entry_);
155 entry_ = NULL;
156 return true;
157}
158
159void 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
166void DwarfCFIToModule::Reporter::UndefinedNotSupported(size_t offset,
167 const string &reg) {
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
175void DwarfCFIToModule::Reporter::ExpressionsNotSupported(size_t offset,
176 const string &reg) {
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