libdynDwarf is compiling now.
[dyninst.git] / dwarf / src / dwarfHandle.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  *
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  *
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  *
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "libdw.h"
32 #include "Elf_X.h"
33 #include "dwarfHandle.h"
34 #include "dwarfFrameParser.h"
35 #include "debug_common.h"
36 #include <cstring>
37
38 using namespace Dyninst;
39 using namespace Dwarf;
40 using namespace std;
41
42 // Add definitions that may not be in all elf.h files
43 #if !defined(EM_K10M)
44 #define EM_K10M 180
45 #endif
46 #if !defined(EM_L10M)
47 #define EM_L10M 181
48 #endif
49 #if !defined(EM_AARCH64)
50 #define EM_AARCH64 183
51 #endif
52
53 /*void DwarfHandle::defaultDwarfError(Dwarf_Error err, Dwarf_Ptr p) {
54   dwarf_dealloc(*(Dwarf*)(p), err, DW_DLA_ERROR);
55   }
56
57   Dwarf_Handler DwarfHandle::defaultErrFunc = DwarfHandle::defaultDwarfError;*/
58
59 DwarfHandle::DwarfHandle(string filename_, Elf_X *file_,
60         void * /*Dwarf_Handler err_func_*/) :
61     init_dwarf_status(dwarf_status_uninitialized),
62     dbg_file_data(NULL),
63     file_data(NULL),
64     line_data(NULL),
65     type_data(NULL),
66     frame_data(NULL),
67     file(file_),
68     dbg_file(NULL),
69     //err_func(err_func_),
70     filename(filename_)
71 {
72
73     locate_dbg_file();
74 }
75
76 void DwarfHandle::locate_dbg_file()
77 {
78     char *buffer;
79     unsigned long buffer_size;
80     bool result = file->findDebugFile(filename, debug_filename, buffer, buffer_size);
81     if (!result)
82         return;
83     dbg_file = Elf_X::newElf_X(buffer, buffer_size, debug_filename);
84     if (!dbg_file->isValid()) {
85         dwarf_printf("Invalid ELF file for debug info: %s\n", debug_filename.c_str());
86         dbg_file->end();
87         dbg_file = NULL;
88     }
89 }
90
91 bool DwarfHandle::init_dbg()
92 {
93     //int status;
94     //Dwarf_Error err;
95     if (init_dwarf_status == dwarf_status_ok) {
96         return true;
97     }
98
99     if (init_dwarf_status == dwarf_status_error) {
100         return false;
101     }
102
103     //status = dwarf_elf_init(file->e_elfp(), DW_DLC_READ,
104     //                       err_func, &file_data, &file_data, &err);
105
106     file_data = dwarf_begin_elf(file->e_elfp(), DWARF_C_READ, NULL); 
107
108     if (!file_data) {
109         init_dwarf_status = dwarf_status_error;
110         return false;
111     }
112
113     if (dbg_file) {
114         dbg_file_data = dwarf_begin_elf(dbg_file->e_elfp(), DWARF_C_READ, NULL); 
115         //status = dwarf_elf_init(dbg_file->e_elfp(), DW_DLC_READ,
116         //        err_func, &dbg_file_data, &dbg_file_data, &err);
117
118         if (!dbg_file_data) {
119             init_dwarf_status = dwarf_status_error;
120             return false;
121         }
122
123         //Have(sic) a debug file, choose which file to use for different lookups.
124         line_data = &dbg_file_data;
125         type_data = &dbg_file_data;
126
127         if (hasFrameData(dbg_file))
128             frame_data = &dbg_file_data;
129         else
130             frame_data = &file_data;
131     }
132     else {
133         //No debug file, take everything from file
134         line_data = &file_data;
135         type_data = &file_data;
136         frame_data = &file_data;
137     }
138
139     Dyninst::Architecture arch;
140     switch (file->e_machine()) {
141         case EM_386:
142             arch = Arch_x86;
143             break;
144         case EM_X86_64:
145         case EM_K10M:
146         case EM_L10M:
147             arch = Arch_x86_64;
148             break;
149         case EM_PPC:
150             arch = Arch_ppc32;
151             break;
152         case EM_PPC64:
153             arch = Arch_ppc64;
154             break;
155         case EM_ARM:
156             arch = Arch_aarch32;
157             break;
158         case EM_AARCH64:
159             arch = Arch_aarch64;
160             break;
161         default:
162             assert(0 && "Unsupported archiecture in ELF file.");
163             return false;
164     }
165     sw = Dwarf::DwarfFrameParser::create(*frame_data, arch);
166
167     init_dwarf_status = dwarf_status_ok;
168     return true;
169 }
170
171 const char* frame_section_names[] = { ".debug_frame", ".eh_frame", NULL };
172 bool DwarfHandle::hasFrameData(Elf_X *e)
173 {
174     unsigned short shstrtab_idx = e->e_shstrndx();
175     Elf_X_Shdr &shstrtab = e->get_shdr(shstrtab_idx);
176     if (!shstrtab.isValid())
177         return false;
178     Elf_X_Data data = shstrtab.get_data();
179     if (!data.isValid())
180         return false;
181     const char *shnames = data.get_string();
182
183     unsigned short num_sections = e->e_shnum();
184     for (unsigned i = 0; i < num_sections; i++) {
185         Elf_X_Shdr &shdr = e->get_shdr(i);
186         if (!shdr.isValid())
187             continue;
188         if (shdr.sh_type() == SHT_NOBITS)
189             continue;
190         unsigned long name_idx = shdr.sh_name();
191         for (const char **s = frame_section_names; *s; s++) {
192             if (strcmp(*s, shnames + name_idx) == 0) {
193                 return true;
194             }
195         }
196     }
197     return false;
198 }
199
200 Elf_X *DwarfHandle::origFile()
201 {
202     return file;
203 }
204
205 Elf_X *DwarfHandle::debugLinkFile()
206 {
207     return dbg_file;
208 }
209
210 ::Dwarf **DwarfHandle::line_dbg()
211 {
212     if (!init_dbg())
213         return NULL;
214     return line_data;
215 }
216
217 ::Dwarf **DwarfHandle::type_dbg()
218 {
219     if (!init_dbg())
220         return NULL;
221     return type_data;
222 }
223
224 ::Dwarf **DwarfHandle::frame_dbg()
225 {
226     if (!init_dbg())
227         return NULL;
228     return frame_data;
229 }
230
231
232 DwarfHandle::~DwarfHandle()
233 {
234     if (init_dwarf_status != dwarf_status_ok)
235         return;
236
237     //Dwarf_Error err;
238     if (dbg_file_data)
239         dwarf_end(dbg_file_data);
240     if (file_data)
241         dwarf_end(file_data);
242 }
243
244 map<string, DwarfHandle::ptr> DwarfHandle::all_dwarf_handles;
245 DwarfHandle::ptr DwarfHandle::createDwarfHandle(string filename_, Elf_X *file_,
246         void* /*Dwarf_Handler err_func_*/)
247 {
248     map<string, DwarfHandle::ptr>::iterator i;
249     i = all_dwarf_handles.find(filename_);
250     if (i != all_dwarf_handles.end()) {
251         return i->second;
252     }
253
254     DwarfHandle::ptr ret = DwarfHandle::ptr(
255             new DwarfHandle(filename_, file_, NULL /* err_func_*/));
256     all_dwarf_handles.insert(make_pair(filename_, ret));
257     return ret;
258 }
259
260 DwarfFrameParserPtr DwarfHandle::frameParser() {
261     return sw;
262 }