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 // module.h: Define google_breakpad::Module. A Module holds debugging
35 // information, and can write that information out as a Breakpad
36 // symbol file.
37 
38 #ifndef COMMON_LINUX_MODULE_H__
39 #define COMMON_LINUX_MODULE_H__
40 
41 #include <iostream>
42 #include <map>
43 #include <set>
44 #include <string>
45 #include <vector>
46 
47 #include "common/symbol_data.h"
48 #include "common/using_std_string.h"
49 #include "google_breakpad/common/breakpad_types.h"
50 
51 namespace google_breakpad {
52 
53 using std::set;
54 using std::vector;
55 using std::map;
56 
57 // A Module represents the contents of a module, and supports methods
58 // for adding information produced by parsing STABS or DWARF data
59 // --- possibly both from the same file --- and then writing out the
60 // unified contents as a Breakpad-format symbol file.
61 class Module {
62  public:
63   // The type of addresses and sizes in a symbol table.
64   typedef uint64_t Address;
65   struct File;
66   struct Function;
67   struct Line;
68   struct Extern;
69 
70   // Addresses appearing in File, Function, and Line structures are
71   // absolute, not relative to the the module's load address.  That
72   // is, if the module were loaded at its nominal load address, the
73   // addresses would be correct.
74 
75   // A source file.
76   struct File {
FileFile77     explicit File(const string &name_input) : name(name_input), source_id(0) {}
78 
79     // The name of the source file.
80     const string name;
81 
82     // The file's source id.  The Write member function clears this
83     // field and assigns source ids a fresh, so any value placed here
84     // before calling Write will be lost.
85     int source_id;
86   };
87 
88   // A function.
89   struct Function {
FunctionFunction90     Function(const string &name_input, const Address &address_input) :
91         name(name_input), address(address_input), size(0), parameter_size(0) {}
92 
93     // For sorting by address.  (Not style-guide compliant, but it's
94     // stupid not to put this in the struct.)
CompareByAddressFunction95     static bool CompareByAddress(const Function *x, const Function *y) {
96       return x->address < y->address;
97     }
98 
99     // The function's name.
100     const string name;
101 
102     // The start address and length of the function's code.
103     const Address address;
104     Address size;
105 
106     // The function's parameter size.
107     Address parameter_size;
108 
109     // Source lines belonging to this function, sorted by increasing
110     // address.
111     vector<Line> lines;
112   };
113 
114   // A source line.
115   struct Line {
116     // For sorting by address.  (Not style-guide compliant, but it's
117     // stupid not to put this in the struct.)
CompareByAddressLine118     static bool CompareByAddress(const Module::Line &x, const Module::Line &y) {
119       return x.address < y.address;
120     }
121 
122     Address address, size;    // The address and size of the line's code.
123     File *file;                // The source file.
124     int number;                // The source line number.
125   };
126 
127   // An exported symbol.
128   struct Extern {
ExternExtern129     explicit Extern(const Address &address_input) : address(address_input) {}
130     const Address address;
131     string name;
132   };
133 
134   // A map from register names to postfix expressions that recover
135   // their their values. This can represent a complete set of rules to
136   // follow at some address, or a set of changes to be applied to an
137   // extant set of rules.
138   typedef map<string, string> RuleMap;
139 
140   // A map from addresses to RuleMaps, representing changes that take
141   // effect at given addresses.
142   typedef map<Address, RuleMap> RuleChangeMap;
143 
144   // A range of 'STACK CFI' stack walking information. An instance of
145   // this structure corresponds to a 'STACK CFI INIT' record and the
146   // subsequent 'STACK CFI' records that fall within its range.
147   struct StackFrameEntry {
148     // The starting address and number of bytes of machine code this
149     // entry covers.
150     Address address, size;
151 
152     // The initial register recovery rules, in force at the starting
153     // address.
154     RuleMap initial_rules;
155 
156     // A map from addresses to rule changes. To find the rules in
157     // force at a given address, start with initial_rules, and then
158     // apply the changes given in this map for all addresses up to and
159     // including the address you're interested in.
160     RuleChangeMap rule_changes;
161   };
162 
163   struct FunctionCompare {
operatorFunctionCompare164     bool operator() (const Function *lhs,
165                      const Function *rhs) const {
166       if (lhs->address == rhs->address)
167         return lhs->name < rhs->name;
168       return lhs->address < rhs->address;
169     }
170   };
171 
172   struct ExternCompare {
operatorExternCompare173     bool operator() (const Extern *lhs,
174                      const Extern *rhs) const {
175       return lhs->address < rhs->address;
176     }
177   };
178 
179   // Create a new module with the given name, operating system,
180   // architecture, and ID string.
181   Module(const string &name, const string &os, const string &architecture,
182          const string &id);
183   ~Module();
184 
185   // Set the module's load address to LOAD_ADDRESS; addresses given
186   // for functions and lines will be written to the Breakpad symbol
187   // file as offsets from this address.  Construction initializes this
188   // module's load address to zero: addresses written to the symbol
189   // file will be the same as they appear in the Function, Line, and
190   // StackFrameEntry structures.
191   //
192   // Note that this member function has no effect on addresses stored
193   // in the data added to this module; the Write member function
194   // simply subtracts off the load address from addresses before it
195   // prints them. Only the last load address given before calling
196   // Write is used.
197   void SetLoadAddress(Address load_address);
198 
199   // Add FUNCTION to the module. FUNCTION's name must not be empty.
200   // This module owns all Function objects added with this function:
201   // destroying the module destroys them as well.
202   void AddFunction(Function *function);
203 
204   // Add all the functions in [BEGIN,END) to the module.
205   // This module owns all Function objects added with this function:
206   // destroying the module destroys them as well.
207   void AddFunctions(vector<Function *>::iterator begin,
208                     vector<Function *>::iterator end);
209 
210   // Add STACK_FRAME_ENTRY to the module.
211   // This module owns all StackFrameEntry objects added with this
212   // function: destroying the module destroys them as well.
213   void AddStackFrameEntry(StackFrameEntry *stack_frame_entry);
214 
215   // Add PUBLIC to the module.
216   // This module owns all Extern objects added with this function:
217   // destroying the module destroys them as well.
218   void AddExtern(Extern *ext);
219 
220   // If this module has a file named NAME, return a pointer to it. If
221   // it has none, then create one and return a pointer to the new
222   // file. This module owns all File objects created using these
223   // functions; destroying the module destroys them as well.
224   File *FindFile(const string &name);
225   File *FindFile(const char *name);
226 
227   // If this module has a file named NAME, return a pointer to it.
228   // Otherwise, return NULL.
229   File *FindExistingFile(const string &name);
230 
231   // Insert pointers to the functions added to this module at I in
232   // VEC. The pointed-to Functions are still owned by this module.
233   // (Since this is effectively a copy of the function list, this is
234   // mostly useful for testing; other uses should probably get a more
235   // appropriate interface.)
236   void GetFunctions(vector<Function *> *vec, vector<Function *>::iterator i);
237 
238   // Insert pointers to the externs added to this module at I in
239   // VEC. The pointed-to Externs are still owned by this module.
240   // (Since this is effectively a copy of the extern list, this is
241   // mostly useful for testing; other uses should probably get a more
242   // appropriate interface.)
243   void GetExterns(vector<Extern *> *vec, vector<Extern *>::iterator i);
244 
245   // Clear VEC and fill it with pointers to the Files added to this
246   // module, sorted by name. The pointed-to Files are still owned by
247   // this module. (Since this is effectively a copy of the file list,
248   // this is mostly useful for testing; other uses should probably get
249   // a more appropriate interface.)
250   void GetFiles(vector<File *> *vec);
251 
252   // Clear VEC and fill it with pointers to the StackFrameEntry
253   // objects that have been added to this module. (Since this is
254   // effectively a copy of the stack frame entry list, this is mostly
255   // useful for testing; other uses should probably get
256   // a more appropriate interface.)
257   void GetStackFrameEntries(vector<StackFrameEntry *> *vec) const;
258 
259   // Find those files in this module that are actually referred to by
260   // functions' line number data, and assign them source id numbers.
261   // Set the source id numbers for all other files --- unused by the
262   // source line data --- to -1.  We do this before writing out the
263   // symbol file, at which point we omit any unused files.
264   void AssignSourceIds();
265 
266   // Call AssignSourceIds, and write this module to STREAM in the
267   // breakpad symbol format. Return true if all goes well, or false if
268   // an error occurs. This method writes out:
269   // - a header based on the values given to the constructor,
270   // If symbol_data is not ONLY_CFI then:
271   // - the source files added via FindFile,
272   // - the functions added via AddFunctions, each with its lines,
273   // - all public records,
274   // If symbol_data is not NO_CFI then:
275   // - all CFI records.
276   // Addresses in the output are all relative to the load address
277   // established by SetLoadAddress.
278   bool Write(std::ostream &stream, SymbolData symbol_data);
279 
name()280   string name() const { return name_; }
os()281   string os() const { return os_; }
architecture()282   string architecture() const { return architecture_; }
identifier()283   string identifier() const { return id_; }
284 
285  private:
286   // Report an error that has occurred writing the symbol file, using
287   // errno to find the appropriate cause.  Return false.
288   static bool ReportError();
289 
290   // Write RULE_MAP to STREAM, in the form appropriate for 'STACK CFI'
291   // records, without a final newline. Return true if all goes well;
292   // if an error occurs, return false, and leave errno set.
293   static bool WriteRuleMap(const RuleMap &rule_map, std::ostream &stream);
294 
295   // Module header entries.
296   string name_, os_, architecture_, id_;
297 
298   // The module's nominal load address.  Addresses for functions and
299   // lines are absolute, assuming the module is loaded at this
300   // address.
301   Address load_address_;
302 
303   // Relation for maps whose keys are strings shared with some other
304   // structure.
305   struct CompareStringPtrs {
operatorCompareStringPtrs306     bool operator()(const string *x, const string *y) const { return *x < *y; }
307   };
308 
309   // A map from filenames to File structures.  The map's keys are
310   // pointers to the Files' names.
311   typedef map<const string *, File *, CompareStringPtrs> FileByNameMap;
312 
313   // A set containing Function structures, sorted by address.
314   typedef set<Function *, FunctionCompare> FunctionSet;
315 
316   // A set containing Extern structures, sorted by address.
317   typedef set<Extern *, ExternCompare> ExternSet;
318 
319   // The module owns all the files and functions that have been added
320   // to it; destroying the module frees the Files and Functions these
321   // point to.
322   FileByNameMap files_;    // This module's source files.
323   FunctionSet functions_;  // This module's functions.
324 
325   // The module owns all the call frame info entries that have been
326   // added to it.
327   vector<StackFrameEntry *> stack_frame_entries_;
328 
329   // The module owns all the externs that have been added to it;
330   // destroying the module frees the Externs these point to.
331   ExternSet externs_;
332 };
333 
334 }  // namespace google_breakpad
335 
336 #endif  // COMMON_LINUX_MODULE_H__
337