Add libdynDwarf, libdynElf, and libsymLite. Removes multiple copies of Elf_X and...
[dyninst.git] / dwarf / src / dwarfFrameParser.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 "dwarf/h/dwarfFrameParser.h"
32 #include "dwarf/h/dwarfExprParser.h"
33 #include "dwarf/h/dwarfResult.h"
34 #include "dynutil/h/VariableLocation.h"
35 #include "common/h/Types.h"
36 #include "libdwarf.h"
37 #include <stdio.h>
38 #include <iostream>
39
40 using namespace Dyninst;
41 using namespace Dwarf;
42 using namespace std;
43
44 std::map<Dwarf_Debug, DwarfFrameParser::Ptr> DwarfFrameParser::frameParsers;
45
46 DwarfFrameParser::Ptr DwarfFrameParser::create(Dwarf_Debug dbg, Architecture arch) {
47    std::map<Dwarf_Debug, DwarfFrameParser::Ptr>::iterator iter = frameParsers.find(dbg);
48    if (iter == frameParsers.end()) {
49       Ptr newParser = Ptr(new DwarfFrameParser(dbg, arch));
50       frameParsers[dbg] = newParser;
51       return newParser;
52    }
53    else {
54       assert(iter->second->arch == arch);
55       return iter->second;
56    }
57 }
58
59
60 DwarfFrameParser::DwarfFrameParser(Dwarf_Debug dbg_, Architecture arch_) :
61    dbg(dbg_),
62    arch(arch_),
63    fde_dwarf_status(dwarf_status_uninitialized)
64 {
65 }
66
67 DwarfFrameParser::~DwarfFrameParser()
68 {
69    if (fde_dwarf_status != dwarf_status_ok) 
70       return;
71    for (unsigned i=0; i<fde_data.size(); i++)
72    {
73       dwarf_fde_cie_list_dealloc(dbg, 
74                                  fde_data[i].cie_data, fde_data[i].cie_count, 
75                                  fde_data[i].fde_data, fde_data[i].fde_count);
76    }
77 }
78
79 bool DwarfFrameParser::hasFrameDebugInfo()
80 {
81    setupFdeData();
82    return fde_dwarf_status == dwarf_status_ok;
83 }
84
85 bool DwarfFrameParser::getRegValueAtFrame(Address pc, 
86                                  Dyninst::MachRegister reg,
87                                  Dyninst::MachRegisterVal &reg_result,
88                                  ProcessReader *reader,
89                                  FrameErrors_t &err_result)
90 {
91    ConcreteDwarfResult cons(reader, arch, pc, dbg);
92
93    if (!getRegAtFrame(pc, reg, cons, err_result))
94       return false;
95    
96    if (cons.err()) {
97       return false;
98    }
99
100    reg_result = cons.val();
101
102    return true;
103 }
104
105 bool DwarfFrameParser::getRegRepAtFrame(Address pc,
106                                Dyninst::MachRegister reg,
107                                VariableLocation &loc,
108                                FrameErrors_t &err_result) {
109    SymbolicDwarfResult cons(loc, arch);
110
111    if (!getRegAtFrame(pc, reg, cons, err_result))
112       return false;
113    
114    if (cons.err()) {
115       err_result = FE_Frame_Eval_Error;
116       return false;
117    }
118
119    loc = cons.val();
120
121    return true;
122 }
123
124 bool DwarfFrameParser::getRegsForFunction(Address entryPC,
125                                           Dyninst::MachRegister reg,
126                                           std::vector<VariableLocation> &locs,
127                                           FrameErrors_t &err_result) {
128    locs.clear();
129
130    err_result = FE_No_Error;
131
132    /**
133     * Initialize the FDE and CIE data.  This is only really done once, 
134     * after which setupFdeData will immediately return.
135     **/
136    setupFdeData();
137    if (!fde_data.size()) {
138       err_result = FE_Bad_Frame_Data;
139       return false;
140    }
141
142    /**
143     * Get the FDE at this PC.  The FDE contains the rules for getting
144     * registers at the given PC in this frame.
145     **/
146    Dwarf_Fde fde;
147    Address low, high;
148    if (!getFDE(entryPC, fde, low, high, err_result)) {
149       return false;
150    }
151    
152    Dwarf_Half dwarf_reg;
153    if (!getDwarfReg(reg, fde, dwarf_reg, err_result)) {
154       return false;
155    }
156
157    Address worker = high;
158    while (worker > low) {
159       VariableLocation loc;
160       SymbolicDwarfResult cons(loc, arch);
161       Address next;
162       if (!getRegAtFrame_aux(worker, fde, dwarf_reg, reg, cons, next, err_result)) {
163          return false;
164       }
165       loc.lowPC = next;
166       loc.hiPC = worker;
167
168       worker = next - 1;
169       locs.push_back(cons.val());
170    }
171
172    std::reverse(locs.begin(), locs.end());
173    return true;
174 }
175
176 bool DwarfFrameParser::getRegAtFrame(Address pc,
177                                      Dyninst::MachRegister reg,
178                                      DwarfResult &cons,
179                                      FrameErrors_t &err_result) {
180
181    err_result = FE_No_Error;
182
183    /**
184     * Initialize the FDE and CIE data.  This is only really done once, 
185     * after which setupFdeData will immediately return.
186     **/
187    setupFdeData();
188    if (!fde_data.size()) {
189       err_result = FE_Bad_Frame_Data;
190       return false;
191    }
192
193    /**
194     * Get the FDE at this PC.  The FDE contains the rules for getting
195     * registers at the given PC in this frame.
196     **/
197    Dwarf_Fde fde;
198    Address u1, u2;
199    if (!getFDE(pc, fde, u1, u2, err_result)) {
200       return false;
201    }
202
203    Dwarf_Half dwarf_reg;
204    if (!getDwarfReg(reg, fde, dwarf_reg, err_result)) {
205       return false;
206    }
207
208    Address ignored;
209    return getRegAtFrame_aux(pc, fde, dwarf_reg, reg, cons, ignored, err_result);
210 }
211
212 bool DwarfFrameParser::getRegAtFrame_aux(Address pc,
213                                          Dwarf_Fde fde,
214                                          Dwarf_Half dwarf_reg,
215                                          MachRegister orig_reg,
216                                          DwarfResult &cons,
217                                          Address &lowpc,
218                                          FrameErrors_t &err_result) {
219    int result;
220    Dwarf_Error err;
221
222    int width = getArchAddressWidth(arch);
223
224    Dwarf_Small value_type;
225    Dwarf_Signed offset_relevant, register_num, offset_or_block_len;
226    Dwarf_Ptr block_ptr;
227    Dwarf_Addr row_pc;
228
229    /**
230     * Decode the rule that describes how to get dwarf_reg at pc.
231     **/
232    if (dwarf_reg != DW_FRAME_CFA_COL3) {
233       result = dwarf_get_fde_info_for_reg3(fde, dwarf_reg, pc, &value_type, 
234                                            &offset_relevant, &register_num,
235                                            &offset_or_block_len,
236                                            &block_ptr, &row_pc, &err);
237    }
238    else {
239       result = dwarf_get_fde_info_for_cfa_reg3(fde, pc, &value_type, 
240                                                &offset_relevant, &register_num,
241                                                &offset_or_block_len,
242                                                &block_ptr, &row_pc, &err);
243    }
244    if (result == DW_DLV_ERROR) {
245       err_result = FE_Bad_Frame_Data;
246       return false;
247    }
248
249    lowpc = (Address) row_pc;
250
251    /**
252     * Interpret the rule and turn it into a real value.
253     **/
254    
255    if (value_type == DW_EXPR_OFFSET || value_type == DW_EXPR_VAL_OFFSET)
256    {
257       bool done;
258       if (!handleExpression(pc, register_num, orig_reg,
259                             arch, cons, done, err_result)) return false;
260       if (done) return true;
261    }
262
263    bool indirect = false;
264
265    switch(value_type) {
266       // For a val offset, the value of the register is (other_reg + const)
267       case DW_EXPR_VAL_OFFSET:
268       case DW_EXPR_OFFSET:
269          if (offset_relevant) {
270             cons.pushSignedVal(offset_or_block_len);
271             cons.pushOp(DwarfResult::Add);
272          }
273          
274          if (offset_relevant && 
275              dwarf_reg != DW_FRAME_CFA_COL3) {
276             indirect = true;
277          }
278          break;
279       case DW_EXPR_VAL_EXPRESSION:
280       case DW_EXPR_EXPRESSION: {
281          Dwarf_Locdesc *llbuf = NULL;
282          Dwarf_Signed listlen = 0;
283          result = dwarf_loclist_from_expr(dbg, block_ptr, offset_or_block_len, &llbuf, &listlen, &err);
284          if (result != DW_DLV_OK) {
285             return false;
286          }
287          
288          if (!decodeDwarfExpression(llbuf, NULL, 
289                                     cons,
290                                     arch)) {
291             return false;
292          }
293
294          dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
295          dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
296          
297          if (value_type == DW_EXPR_EXPRESSION) {
298             indirect = true;
299          }
300          break;
301       }
302       default:
303          err_result = FE_Bad_Frame_Data;
304          return false;
305    }
306    
307    if (indirect) {
308       cons.pushOp(DwarfResult::Deref, width);
309    }
310
311    return true;
312 }
313
314 void DwarfFrameParser::setupFdeData()
315 {
316    Dwarf_Error err;
317    
318    if (fde_dwarf_status == dwarf_status_ok || 
319        fde_dwarf_status == dwarf_status_error)
320       return;
321
322    if (!dbg) {
323       fde_dwarf_status = dwarf_status_error;
324       return;
325    }
326
327 #if defined(dwarf_has_setframe)
328    dwarf_set_frame_cfa_value(dbg, DW_FRAME_CFA_COL3);
329 #endif
330
331    fde_cie_data fc;
332    int result = dwarf_get_fde_list(dbg, 
333                                    &fc.cie_data, &fc.cie_count,
334                                    &fc.fde_data, &fc.fde_count,
335                                    &err);
336    if (result == DW_DLV_OK) {
337       fde_data.push_back(fc);
338    }
339
340    result = dwarf_get_fde_list_eh(dbg, 
341                                   &fc.cie_data, &fc.cie_count,
342                                   &fc.fde_data, &fc.fde_count,
343                                   &err);
344    if (result == DW_DLV_OK) {
345       fde_data.push_back(fc);
346    }
347    
348
349    if (!fde_data.size()) {
350       fde_dwarf_status = dwarf_status_error;
351    }
352    
353    fde_dwarf_status = dwarf_status_ok;
354 }
355
356 bool DwarfFrameParser::getFDE(Address pc, Dwarf_Fde &fde, 
357                               Address &low, Address &high, 
358                               FrameErrors_t &err_result) {
359    Dwarf_Addr lowpc = 0, hipc = 0;
360
361    bool found = false;
362    unsigned cur_fde;
363    for (cur_fde=0; cur_fde<fde_data.size(); cur_fde++) {
364       int result = dwarf_get_fde_at_pc(fde_data[cur_fde].fde_data, 
365                                        (Dwarf_Addr) pc, &fde, &lowpc, &hipc, NULL);
366       if (result == DW_DLV_ERROR) {
367          err_result = FE_Bad_Frame_Data;
368          return false;
369       }
370       else if (result == DW_DLV_OK) {
371          low = (Address) lowpc;
372          high = (Address) hipc;
373          found = true;
374          break;
375       }
376    }
377    if (!found)
378    {
379       err_result = FE_No_Frame_Entry;
380       return false;
381    }
382    return true;
383 }
384
385 bool DwarfFrameParser::getDwarfReg(Dyninst::MachRegister reg,
386                                    Dwarf_Fde &fde,
387                                    Dwarf_Half &dwarf_reg,
388                                    FrameErrors_t &err_result) {
389    Dwarf_Error err;
390    if (reg == Dyninst::ReturnAddr) {
391       /**
392        * We should be getting the return address for the stack frame.  
393        * This is treated as a virtual register in the
394        * FDE.  We can look up the virtual register in the CIE.
395        **/
396       Dwarf_Cie cie;
397       int result = dwarf_get_cie_of_fde(fde, &cie, &err);
398       if (result != DW_DLV_OK) {
399          err_result = FE_Bad_Frame_Data;
400          return false;
401       }
402
403       Dwarf_Unsigned bytes_in_cie;
404       result = dwarf_get_cie_info(cie, &bytes_in_cie, NULL, NULL, NULL, NULL, 
405                                   &dwarf_reg, NULL, NULL, &err);
406       if (result != DW_DLV_OK) {
407          err_result = FE_Bad_Frame_Data;
408          return false;
409       }
410    }
411    else if (reg == Dyninst::FrameBase || reg == Dyninst::CFA) {
412       dwarf_reg = DW_FRAME_CFA_COL3;
413    }
414    else {
415       dwarf_reg = reg.getDwarfEnc(); 
416    }
417    return true;
418 }
419
420 bool DwarfFrameParser::handleExpression(Address pc,
421                                Dwarf_Signed registerNum,
422                                Dyninst::MachRegister origReg,
423                                Dyninst::Architecture arch,
424                                DwarfResult &cons,
425                                bool &done,
426                                FrameErrors_t &err_result) {
427    done = false;
428    switch (registerNum) {
429       case DW_FRAME_CFA_COL3:
430          err_result = FE_No_Error;
431          if (!getRegAtFrame(pc, Dyninst::FrameBase,
432                             cons, err_result)) {
433             return false;
434          }
435          break;
436       case DW_FRAME_SAME_VAL:
437          cons.readReg(origReg);
438          done = true;
439          break;
440       default: {
441          Dyninst::MachRegister dyn_register = MachRegister::DwarfEncToReg(registerNum, arch);
442          cons.readReg(dyn_register);
443          break;
444       }
445    }
446    return true;
447 }  
448