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