xref: /aosp_15_r20/external/google-breakpad/src/common/dwarf/functioninfo.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2010 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle //     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle //     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle //     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle 
29*9712c20fSFrederick Mayle // This is a client for the dwarf2reader to extract function and line
30*9712c20fSFrederick Mayle // information from the debug info.
31*9712c20fSFrederick Mayle 
32*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
33*9712c20fSFrederick Mayle #include <config.h>  // Must come first
34*9712c20fSFrederick Mayle #endif
35*9712c20fSFrederick Mayle 
36*9712c20fSFrederick Mayle #include <assert.h>
37*9712c20fSFrederick Mayle #include <limits.h>
38*9712c20fSFrederick Mayle #include <stdio.h>
39*9712c20fSFrederick Mayle 
40*9712c20fSFrederick Mayle #include <map>
41*9712c20fSFrederick Mayle #include <queue>
42*9712c20fSFrederick Mayle #include <vector>
43*9712c20fSFrederick Mayle 
44*9712c20fSFrederick Mayle #include "common/dwarf/functioninfo.h"
45*9712c20fSFrederick Mayle #include "common/dwarf/bytereader.h"
46*9712c20fSFrederick Mayle #include "common/scoped_ptr.h"
47*9712c20fSFrederick Mayle #include "common/using_std_string.h"
48*9712c20fSFrederick Mayle 
49*9712c20fSFrederick Mayle namespace google_breakpad {
50*9712c20fSFrederick Mayle 
CULineInfoHandler(std::vector<SourceFileInfo> * files,std::vector<string> * dirs,LineMap * linemap)51*9712c20fSFrederick Mayle CULineInfoHandler::CULineInfoHandler(std::vector<SourceFileInfo>* files,
52*9712c20fSFrederick Mayle                                      std::vector<string>* dirs,
53*9712c20fSFrederick Mayle                                      LineMap* linemap):linemap_(linemap),
54*9712c20fSFrederick Mayle                                                        files_(files),
55*9712c20fSFrederick Mayle                                                        dirs_(dirs) {
56*9712c20fSFrederick Mayle   // In dwarf4, the dirs and files are 1 indexed, and in dwarf5 they are zero
57*9712c20fSFrederick Mayle   // indexed. This is handled in the LineInfo reader, so empty files are not
58*9712c20fSFrederick Mayle   // needed here.
59*9712c20fSFrederick Mayle }
60*9712c20fSFrederick Mayle 
DefineDir(const string & name,uint32_t dir_num)61*9712c20fSFrederick Mayle void CULineInfoHandler::DefineDir(const string& name, uint32_t dir_num) {
62*9712c20fSFrederick Mayle   // These should never come out of order, actually
63*9712c20fSFrederick Mayle   assert(dir_num == dirs_->size());
64*9712c20fSFrederick Mayle   dirs_->push_back(name);
65*9712c20fSFrederick Mayle }
66*9712c20fSFrederick Mayle 
DefineFile(const string & name,int32 file_num,uint32_t dir_num,uint64_t mod_time,uint64_t length)67*9712c20fSFrederick Mayle void CULineInfoHandler::DefineFile(const string& name,
68*9712c20fSFrederick Mayle                                    int32 file_num, uint32_t dir_num,
69*9712c20fSFrederick Mayle                                    uint64_t mod_time, uint64_t length) {
70*9712c20fSFrederick Mayle   assert(dir_num >= 0);
71*9712c20fSFrederick Mayle   assert(dir_num < dirs_->size());
72*9712c20fSFrederick Mayle 
73*9712c20fSFrederick Mayle   // These should never come out of order, actually.
74*9712c20fSFrederick Mayle   if (file_num == (int32)files_->size() || file_num == -1) {
75*9712c20fSFrederick Mayle     string dir = dirs_->at(dir_num);
76*9712c20fSFrederick Mayle 
77*9712c20fSFrederick Mayle     SourceFileInfo s;
78*9712c20fSFrederick Mayle     s.lowpc = ULLONG_MAX;
79*9712c20fSFrederick Mayle 
80*9712c20fSFrederick Mayle     if (dir == "") {
81*9712c20fSFrederick Mayle       s.name = name;
82*9712c20fSFrederick Mayle     } else {
83*9712c20fSFrederick Mayle       s.name = dir + "/" + name;
84*9712c20fSFrederick Mayle     }
85*9712c20fSFrederick Mayle 
86*9712c20fSFrederick Mayle     files_->push_back(s);
87*9712c20fSFrederick Mayle   } else {
88*9712c20fSFrederick Mayle     fprintf(stderr, "error in DefineFile");
89*9712c20fSFrederick Mayle   }
90*9712c20fSFrederick Mayle }
91*9712c20fSFrederick Mayle 
AddLine(uint64_t address,uint64_t length,uint32_t file_num,uint32_t line_num,uint32_t column_num)92*9712c20fSFrederick Mayle void CULineInfoHandler::AddLine(uint64_t address, uint64_t length,
93*9712c20fSFrederick Mayle                                 uint32_t file_num, uint32_t line_num,
94*9712c20fSFrederick Mayle                                 uint32_t column_num) {
95*9712c20fSFrederick Mayle   if (file_num < files_->size()) {
96*9712c20fSFrederick Mayle     linemap_->insert(
97*9712c20fSFrederick Mayle         std::make_pair(address,
98*9712c20fSFrederick Mayle                        std::make_pair(files_->at(file_num).name.c_str(),
99*9712c20fSFrederick Mayle                                       line_num)));
100*9712c20fSFrederick Mayle 
101*9712c20fSFrederick Mayle     if (address < files_->at(file_num).lowpc) {
102*9712c20fSFrederick Mayle       files_->at(file_num).lowpc = address;
103*9712c20fSFrederick Mayle     }
104*9712c20fSFrederick Mayle   } else {
105*9712c20fSFrederick Mayle     fprintf(stderr, "error in AddLine");
106*9712c20fSFrederick Mayle   }
107*9712c20fSFrederick Mayle }
108*9712c20fSFrederick Mayle 
StartCompilationUnit(uint64_t offset,uint8_t address_size,uint8_t offset_size,uint64_t cu_length,uint8_t dwarf_version)109*9712c20fSFrederick Mayle bool CUFunctionInfoHandler::StartCompilationUnit(uint64_t offset,
110*9712c20fSFrederick Mayle                                                  uint8_t address_size,
111*9712c20fSFrederick Mayle                                                  uint8_t offset_size,
112*9712c20fSFrederick Mayle                                                  uint64_t cu_length,
113*9712c20fSFrederick Mayle                                                  uint8_t dwarf_version) {
114*9712c20fSFrederick Mayle   current_compilation_unit_offset_ = offset;
115*9712c20fSFrederick Mayle   return true;
116*9712c20fSFrederick Mayle }
117*9712c20fSFrederick Mayle 
118*9712c20fSFrederick Mayle 
119*9712c20fSFrederick Mayle // For function info, we only care about subprograms and inlined
120*9712c20fSFrederick Mayle // subroutines. For line info, the DW_AT_stmt_list lives in the
121*9712c20fSFrederick Mayle // compile unit tag.
122*9712c20fSFrederick Mayle 
StartDIE(uint64_t offset,enum DwarfTag tag)123*9712c20fSFrederick Mayle bool CUFunctionInfoHandler::StartDIE(uint64_t offset, enum DwarfTag tag) {
124*9712c20fSFrederick Mayle   switch (tag) {
125*9712c20fSFrederick Mayle     case DW_TAG_subprogram:
126*9712c20fSFrederick Mayle     case DW_TAG_inlined_subroutine: {
127*9712c20fSFrederick Mayle       current_function_info_ = new FunctionInfo;
128*9712c20fSFrederick Mayle       current_function_info_->lowpc = current_function_info_->highpc = 0;
129*9712c20fSFrederick Mayle       current_function_info_->name = "";
130*9712c20fSFrederick Mayle       current_function_info_->line = 0;
131*9712c20fSFrederick Mayle       current_function_info_->file = "";
132*9712c20fSFrederick Mayle       offset_to_funcinfo_->insert(std::make_pair(offset,
133*9712c20fSFrederick Mayle                                                  current_function_info_));
134*9712c20fSFrederick Mayle     };
135*9712c20fSFrederick Mayle       // FALLTHROUGH
136*9712c20fSFrederick Mayle     case DW_TAG_compile_unit:
137*9712c20fSFrederick Mayle       return true;
138*9712c20fSFrederick Mayle     default:
139*9712c20fSFrederick Mayle       return false;
140*9712c20fSFrederick Mayle   }
141*9712c20fSFrederick Mayle   return false;
142*9712c20fSFrederick Mayle }
143*9712c20fSFrederick Mayle 
144*9712c20fSFrederick Mayle // Only care about the name attribute for functions
145*9712c20fSFrederick Mayle 
ProcessAttributeString(uint64_t offset,enum DwarfAttribute attr,enum DwarfForm form,const string & data)146*9712c20fSFrederick Mayle void CUFunctionInfoHandler::ProcessAttributeString(uint64_t offset,
147*9712c20fSFrederick Mayle                                                    enum DwarfAttribute attr,
148*9712c20fSFrederick Mayle                                                    enum DwarfForm form,
149*9712c20fSFrederick Mayle                                                    const string& data) {
150*9712c20fSFrederick Mayle   if (current_function_info_) {
151*9712c20fSFrederick Mayle     if (attr == DW_AT_name)
152*9712c20fSFrederick Mayle       current_function_info_->name = data;
153*9712c20fSFrederick Mayle     else if (attr == DW_AT_MIPS_linkage_name)
154*9712c20fSFrederick Mayle       current_function_info_->mangled_name = data;
155*9712c20fSFrederick Mayle   }
156*9712c20fSFrederick Mayle }
157*9712c20fSFrederick Mayle 
ProcessAttributeUnsigned(uint64_t offset,enum DwarfAttribute attr,enum DwarfForm form,uint64_t data)158*9712c20fSFrederick Mayle void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64_t offset,
159*9712c20fSFrederick Mayle                                                      enum DwarfAttribute attr,
160*9712c20fSFrederick Mayle                                                      enum DwarfForm form,
161*9712c20fSFrederick Mayle                                                      uint64_t data) {
162*9712c20fSFrederick Mayle   if (attr == DW_AT_stmt_list) {
163*9712c20fSFrederick Mayle     SectionMap::const_iterator iter =
164*9712c20fSFrederick Mayle         GetSectionByName(sections_, ".debug_line");
165*9712c20fSFrederick Mayle     assert(iter != sections_.end());
166*9712c20fSFrederick Mayle 
167*9712c20fSFrederick Mayle     scoped_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data,
168*9712c20fSFrederick Mayle                                                iter->second.second  - data,
169*9712c20fSFrederick Mayle                                                reader_, linehandler_));
170*9712c20fSFrederick Mayle     lireader->Start();
171*9712c20fSFrederick Mayle   } else if (current_function_info_) {
172*9712c20fSFrederick Mayle     switch (attr) {
173*9712c20fSFrederick Mayle       case DW_AT_low_pc:
174*9712c20fSFrederick Mayle         current_function_info_->lowpc = data;
175*9712c20fSFrederick Mayle         break;
176*9712c20fSFrederick Mayle       case DW_AT_high_pc:
177*9712c20fSFrederick Mayle         current_function_info_->highpc = data;
178*9712c20fSFrederick Mayle         break;
179*9712c20fSFrederick Mayle       case DW_AT_decl_line:
180*9712c20fSFrederick Mayle         current_function_info_->line = data;
181*9712c20fSFrederick Mayle         break;
182*9712c20fSFrederick Mayle       case DW_AT_decl_file:
183*9712c20fSFrederick Mayle         current_function_info_->file = files_->at(data).name;
184*9712c20fSFrederick Mayle         break;
185*9712c20fSFrederick Mayle       case DW_AT_ranges:
186*9712c20fSFrederick Mayle         current_function_info_->ranges = data;
187*9712c20fSFrederick Mayle         break;
188*9712c20fSFrederick Mayle       default:
189*9712c20fSFrederick Mayle         break;
190*9712c20fSFrederick Mayle     }
191*9712c20fSFrederick Mayle   }
192*9712c20fSFrederick Mayle }
193*9712c20fSFrederick Mayle 
ProcessAttributeReference(uint64_t offset,enum DwarfAttribute attr,enum DwarfForm form,uint64_t data)194*9712c20fSFrederick Mayle void CUFunctionInfoHandler::ProcessAttributeReference(uint64_t offset,
195*9712c20fSFrederick Mayle                                                       enum DwarfAttribute attr,
196*9712c20fSFrederick Mayle                                                       enum DwarfForm form,
197*9712c20fSFrederick Mayle                                                       uint64_t data) {
198*9712c20fSFrederick Mayle   if (current_function_info_) {
199*9712c20fSFrederick Mayle     switch (attr) {
200*9712c20fSFrederick Mayle       case DW_AT_specification: {
201*9712c20fSFrederick Mayle         // Some functions have a "specification" attribute
202*9712c20fSFrederick Mayle         // which means they were defined elsewhere. The name
203*9712c20fSFrederick Mayle         // attribute is not repeated, and must be taken from
204*9712c20fSFrederick Mayle         // the specification DIE. Here we'll assume that
205*9712c20fSFrederick Mayle         // any DIE referenced in this manner will already have
206*9712c20fSFrederick Mayle         // been seen, but that's not really required by the spec.
207*9712c20fSFrederick Mayle         FunctionMap::iterator iter = offset_to_funcinfo_->find(data);
208*9712c20fSFrederick Mayle         if (iter != offset_to_funcinfo_->end()) {
209*9712c20fSFrederick Mayle           current_function_info_->name = iter->second->name;
210*9712c20fSFrederick Mayle           current_function_info_->mangled_name = iter->second->mangled_name;
211*9712c20fSFrederick Mayle         } else {
212*9712c20fSFrederick Mayle           // If you hit this, this code probably needs to be rewritten.
213*9712c20fSFrederick Mayle           fprintf(stderr,
214*9712c20fSFrederick Mayle                   "Error: DW_AT_specification was seen before the referenced "
215*9712c20fSFrederick Mayle                   "DIE! (Looking for DIE at offset %08llx, in DIE at "
216*9712c20fSFrederick Mayle                   "offset %08llx)\n", data, offset);
217*9712c20fSFrederick Mayle         }
218*9712c20fSFrederick Mayle         break;
219*9712c20fSFrederick Mayle       }
220*9712c20fSFrederick Mayle       default:
221*9712c20fSFrederick Mayle         break;
222*9712c20fSFrederick Mayle     }
223*9712c20fSFrederick Mayle   }
224*9712c20fSFrederick Mayle }
225*9712c20fSFrederick Mayle 
EndDIE(uint64_t offset)226*9712c20fSFrederick Mayle void CUFunctionInfoHandler::EndDIE(uint64_t offset) {
227*9712c20fSFrederick Mayle   if (current_function_info_ && current_function_info_->lowpc)
228*9712c20fSFrederick Mayle     address_to_funcinfo_->insert(std::make_pair(current_function_info_->lowpc,
229*9712c20fSFrederick Mayle                                                 current_function_info_));
230*9712c20fSFrederick Mayle }
231*9712c20fSFrederick Mayle 
232*9712c20fSFrederick Mayle }  // namespace google_breakpad
233