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 : // dwarf_cfi_to_module.h: Define the DwarfCFIToModule class, which
35 : // accepts parsed DWARF call frame info and adds it to a
36 : // google_breakpad::Module object, which can write that information to
37 : // a Breakpad symbol file.
38 :
39 : #ifndef COMMON_LINUX_DWARF_CFI_TO_MODULE_H
40 : #define COMMON_LINUX_DWARF_CFI_TO_MODULE_H
41 :
42 : #include <assert.h>
43 : #include <stdio.h>
44 :
45 : #include <set>
46 : #include <string>
47 : #include <vector>
48 :
49 : #include "common/module.h"
50 : #include "common/dwarf/dwarf2reader.h"
51 :
52 : namespace google_breakpad {
53 :
54 : using dwarf2reader::CallFrameInfo;
55 : using google_breakpad::Module;
56 : using std::set;
57 : using std::string;
58 : using std::vector;
59 :
60 : // A class that accepts parsed call frame information from the DWARF
61 : // CFI parser and populates a google_breakpad::Module object with the
62 : // contents.
63 : class DwarfCFIToModule: public CallFrameInfo::Handler {
64 : public:
65 :
66 : // DwarfCFIToModule uses an instance of this class to report errors
67 : // detected while converting DWARF CFI to Breakpad STACK CFI records.
68 : class Reporter {
69 : public:
70 : // Create a reporter that writes messages to the standard error
71 : // stream. FILE is the name of the file we're processing, and
72 : // SECTION is the name of the section within that file that we're
73 : // looking at (.debug_frame, .eh_frame, etc.).
74 248 : Reporter(const string &file, const string §ion)
75 248 : : file_(file), section_(section) { }
76 248 : virtual ~Reporter() { }
77 :
78 : // The DWARF CFI entry at OFFSET cites register REG, but REG is not
79 : // covered by the vector of register names passed to the
80 : // DwarfCFIToModule constructor, nor does it match the return
81 : // address column number for this entry.
82 : virtual void UnnamedRegister(size_t offset, int reg);
83 :
84 : // The DWARF CFI entry at OFFSET says that REG is undefined, but the
85 : // Breakpad symbol file format cannot express this.
86 : virtual void UndefinedNotSupported(size_t offset, const string ®);
87 :
88 : // The DWARF CFI entry at OFFSET says that REG uses a DWARF
89 : // expression to find its value, but DwarfCFIToModule is not
90 : // capable of translating DWARF expressions to Breakpad postfix
91 : // expressions.
92 : virtual void ExpressionsNotSupported(size_t offset, const string ®);
93 :
94 : protected:
95 : string file_, section_;
96 : };
97 :
98 : // Register name tables. If TABLE is a vector returned by one of these
99 : // functions, then TABLE[R] is the name of the register numbered R in
100 : // DWARF call frame information.
101 : class RegisterNames {
102 : public:
103 : // Intel's "x86" or IA-32.
104 : static vector<string> I386();
105 :
106 : // AMD x86_64, AMD64, Intel EM64T, or Intel 64
107 : static vector<string> X86_64();
108 :
109 : // ARM.
110 : static vector<string> ARM();
111 :
112 : private:
113 : // Given STRINGS, an array of C strings with SIZE elements, return an
114 : // equivalent vector<string>.
115 : static vector<string> MakeVector(const char * const *strings, size_t size);
116 : };
117 :
118 : // Create a handler for the dwarf2reader::CallFrameInfo parser that
119 : // records the stack unwinding information it receives in MODULE.
120 : //
121 : // Use REGISTER_NAMES[I] as the name of register number I; *this
122 : // keeps a reference to the vector, so the vector should remain
123 : // alive for as long as the DwarfCFIToModule does.
124 : //
125 : // Use REPORTER for reporting problems encountered in the conversion
126 : // process.
127 248 : DwarfCFIToModule(Module *module, const vector<string> ®ister_names,
128 : Reporter *reporter)
129 : : module_(module), register_names_(register_names), reporter_(reporter),
130 248 : entry_(NULL), return_address_(-1), cfa_name_(".cfa"), ra_name_(".ra") {
131 248 : }
132 248 : virtual ~DwarfCFIToModule() { delete entry_; }
133 :
134 : virtual bool Entry(size_t offset, uint64 address, uint64 length,
135 : uint8 version, const string &augmentation,
136 : unsigned return_address);
137 : virtual bool UndefinedRule(uint64 address, int reg);
138 : virtual bool SameValueRule(uint64 address, int reg);
139 : virtual bool OffsetRule(uint64 address, int reg,
140 : int base_register, long offset);
141 : virtual bool ValOffsetRule(uint64 address, int reg,
142 : int base_register, long offset);
143 : virtual bool RegisterRule(uint64 address, int reg, int base_register);
144 : virtual bool ExpressionRule(uint64 address, int reg,
145 : const string &expression);
146 : virtual bool ValExpressionRule(uint64 address, int reg,
147 : const string &expression);
148 : virtual bool End();
149 :
150 : private:
151 : // Return the name to use for register REG.
152 : string RegisterName(int i);
153 :
154 : // Record RULE for register REG at ADDRESS.
155 : void Record(Module::Address address, int reg, const string &rule);
156 :
157 : // The module to which we should add entries.
158 : Module *module_;
159 :
160 : // Map from register numbers to register names.
161 : const vector<string> ®ister_names_;
162 :
163 : // The reporter to use to report problems.
164 : Reporter *reporter_;
165 :
166 : // The current entry we're constructing.
167 : Module::StackFrameEntry *entry_;
168 :
169 : // The section offset of the current frame description entry, for
170 : // use in error messages.
171 : size_t entry_offset_;
172 :
173 : // The return address column for that entry.
174 : unsigned return_address_;
175 :
176 : // The names of the return address and canonical frame address. Putting
177 : // these here instead of using string literals allows us to share their
178 : // texts in reference-counted std::string implementations (all the
179 : // popular ones). Many, many rules cite these strings.
180 : string cfa_name_, ra_name_;
181 :
182 : // A set of strings used by this CFI. Before storing a string in one of
183 : // our data structures, insert it into this set, and then use the string
184 : // from the set.
185 : //
186 : // Because std::string uses reference counting internally, simply using
187 : // strings from this set, even if passed by value, assigned, or held
188 : // directly in structures and containers (map<string, ...>, for example),
189 : // causes those strings to share a single instance of each distinct piece
190 : // of text.
191 : set<string> common_strings_;
192 : };
193 :
194 : } // namespace google_breakpad
195 :
196 : #endif // COMMON_LINUX_DWARF_CFI_TO_MODULE_H
|