xref: /aosp_15_r20/external/google-breakpad/src/common/dwarf_cfi_to_module.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // -*- mode: c++ -*-
2 
3 // Copyright 2010 Google LLC
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google LLC nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Original author: Jim Blandy <[email protected]> <[email protected]>
32 
33 // dwarf_cfi_to_module.h: Define the DwarfCFIToModule class, which
34 // accepts parsed DWARF call frame info and adds it to a
35 // google_breakpad::Module object, which can write that information to
36 // a Breakpad symbol file.
37 
38 #ifndef COMMON_LINUX_DWARF_CFI_TO_MODULE_H
39 #define COMMON_LINUX_DWARF_CFI_TO_MODULE_H
40 
41 #include <assert.h>
42 #include <stdio.h>
43 
44 #include <set>
45 #include <string>
46 #include <memory>
47 #include <vector>
48 
49 #include "common/module.h"
50 #include "common/dwarf/dwarf2reader.h"
51 #include "common/using_std_string.h"
52 
53 namespace google_breakpad {
54 
55 using google_breakpad::Module;
56 using std::set;
57 using std::vector;
58 
59 // A class that accepts parsed call frame information from the DWARF
60 // CFI parser and populates a google_breakpad::Module object with the
61 // contents.
62 class DwarfCFIToModule: public CallFrameInfo::Handler {
63  public:
64 
65   // DwarfCFIToModule uses an instance of this class to report errors
66   // detected while converting DWARF CFI to Breakpad STACK CFI records.
67   class Reporter {
68    public:
69     // Create a reporter that writes messages to the standard error
70     // stream. FILE is the name of the file we're processing, and
71     // SECTION is the name of the section within that file that we're
72     // looking at (.debug_frame, .eh_frame, etc.).
Reporter(const string & file,const string & section)73     Reporter(const string& file, const string& section)
74       : file_(file), section_(section) { }
~Reporter()75     virtual ~Reporter() { }
76 
77     // The DWARF CFI entry at OFFSET cites register REG, but REG is not
78     // covered by the vector of register names passed to the
79     // DwarfCFIToModule constructor, nor does it match the return
80     // address column number for this entry.
81     virtual void UnnamedRegister(size_t offset, int reg);
82 
83     // The DWARF CFI entry at OFFSET says that REG is undefined, but the
84     // Breakpad symbol file format cannot express this.
85     virtual void UndefinedNotSupported(size_t offset, const string& reg);
86 
87     // The DWARF CFI entry at OFFSET says that REG uses a DWARF
88     // expression to find its value, but DwarfCFIToModule is not
89     // capable of translating DWARF expressions to Breakpad postfix
90     // expressions.
91     virtual void ExpressionsNotSupported(size_t offset, const string& reg);
92 
93   protected:
94     string file_, section_;
95   };
96 
97   // Register name tables. If TABLE is a vector returned by one of these
98   // functions, then TABLE[R] is the name of the register numbered R in
99   // DWARF call frame information.
100   class RegisterNames {
101    public:
102     // Intel's "x86" or IA-32.
103     static vector<string> I386();
104 
105     // AMD x86_64, AMD64, Intel EM64T, or Intel 64
106     static vector<string> X86_64();
107 
108     // ARM.
109     static vector<string> ARM();
110 
111     // ARM64, aka AARCH64.
112     static vector<string> ARM64();
113 
114     // MIPS.
115     static vector<string> MIPS();
116 
117     // RISC-V.
118     static vector<string> RISCV();
119 
120    private:
121     // Given STRINGS, an array of C strings with SIZE elements, return an
122     // equivalent vector<string>.
123     static vector<string> MakeVector(const char* const* strings, size_t size);
124   };
125 
126   // Create a handler for the CallFrameInfo parser that
127   // records the stack unwinding information it receives in MODULE.
128   //
129   // Use REGISTER_NAMES[I] as the name of register number I; *this
130   // keeps a reference to the vector, so the vector should remain
131   // alive for as long as the DwarfCFIToModule does.
132   //
133   // Use REPORTER for reporting problems encountered in the conversion
134   // process.
DwarfCFIToModule(Module * module,const vector<string> & register_names,Reporter * reporter)135   DwarfCFIToModule(Module* module, const vector<string>& register_names,
136                    Reporter* reporter)
137       : module_(module), register_names_(register_names), reporter_(reporter),
138         return_address_(-1), cfa_name_(".cfa"), ra_name_(".ra") {
139   }
140   virtual ~DwarfCFIToModule() = default;
141 
142   virtual bool Entry(size_t offset, uint64_t address, uint64_t length,
143                      uint8_t version, const string& augmentation,
144                      unsigned return_address);
145   virtual bool UndefinedRule(uint64_t address, int reg);
146   virtual bool SameValueRule(uint64_t address, int reg);
147   virtual bool OffsetRule(uint64_t address, int reg,
148                           int base_register, long offset);
149   virtual bool ValOffsetRule(uint64_t address, int reg,
150                              int base_register, long offset);
151   virtual bool RegisterRule(uint64_t address, int reg, int base_register);
152   virtual bool ExpressionRule(uint64_t address, int reg,
153                               const string& expression);
154   virtual bool ValExpressionRule(uint64_t address, int reg,
155                                  const string& expression);
156   virtual bool End();
157 
158   virtual string Architecture();
159 
160  private:
161   // Return the name to use for register REG.
162   string RegisterName(int i);
163 
164   // Record RULE for register REG at ADDRESS.
165   void Record(Module::Address address, int reg, const string& rule);
166 
167   // The module to which we should add entries.
168   Module* module_;
169 
170   // Map from register numbers to register names.
171   const vector<string>& register_names_;
172 
173   // The reporter to use to report problems.
174   Reporter* reporter_;
175 
176   // The current entry we're constructing.
177   std::unique_ptr<Module::StackFrameEntry> entry_;
178 
179   // The section offset of the current frame description entry, for
180   // use in error messages.
181   size_t entry_offset_;
182 
183   // The return address column for that entry.
184   unsigned return_address_;
185 
186   // The names of the return address and canonical frame address. Putting
187   // these here instead of using string literals allows us to share their
188   // texts in reference-counted string implementations (all the
189   // popular ones). Many, many rules cite these strings.
190   string cfa_name_, ra_name_;
191 
192   // A set of strings used by this CFI. Before storing a string in one of
193   // our data structures, insert it into this set, and then use the string
194   // from the set.
195   //
196   // Because string uses reference counting internally, simply using
197   // strings from this set, even if passed by value, assigned, or held
198   // directly in structures and containers (map<string, ...>, for example),
199   // causes those strings to share a single instance of each distinct piece
200   // of text.
201   set<string> common_strings_;
202 };
203 
204 } // namespace google_breakpad
205 
206 #endif // COMMON_LINUX_DWARF_CFI_TO_MODULE_H
207