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