stackwalker: added translation function for abstract
[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 "dwarfFrameParser.h"
32 #include "dwarfExprParser.h"
33 #include "dwarfResult.h"
34 #include "VariableLocation.h"
35 #include "Types.h"
36 #include "libdwarf.h"
37 #include <stdio.h>
38 #include <iostream>
39 #include "debug_common.h" // dwarf_printf
40
41 using namespace Dyninst;
42 using namespace Dwarf;
43 using namespace std;
44
45 struct frameParser_key
46 {
47   Dwarf_Debug dbg;
48   Architecture arch;
49   frameParser_key(Dwarf_Debug d, Architecture a) : dbg(d), arch(a)
50   {
51   }
52
53   bool operator< (const frameParser_key& rhs) const
54   {
55     return (dbg < rhs.dbg) || (dbg == rhs.dbg && arch < rhs.arch);
56   }
57
58 };
59
60
61
62 std::map<DwarfFrameParser::frameParser_key, DwarfFrameParser::Ptr> DwarfFrameParser::frameParsers;
63
64 DwarfFrameParser::Ptr DwarfFrameParser::create(Dwarf_Debug dbg, Architecture arch) {
65   frameParser_key k(dbg, arch);
66
67   auto iter = frameParsers.find(k);
68   if (iter == frameParsers.end()) {
69     Ptr newParser = Ptr(new DwarfFrameParser(dbg, arch));
70     frameParsers[k] = newParser;
71     return newParser;
72    }
73    else {
74       return iter->second;
75    }
76 }
77
78
79 DwarfFrameParser::DwarfFrameParser(Dwarf_Debug dbg_, Architecture arch_) :
80    dbg(dbg_),
81    arch(arch_),
82    fde_dwarf_status(dwarf_status_uninitialized)
83 {
84 }
85
86 DwarfFrameParser::~DwarfFrameParser()
87 {
88    if (fde_dwarf_status != dwarf_status_ok)
89       return;
90    for (unsigned i=0; i<fde_data.size(); i++)
91    {
92       dwarf_fde_cie_list_dealloc(dbg,
93                                  fde_data[i].cie_data, fde_data[i].cie_count,
94                                  fde_data[i].fde_data, fde_data[i].fde_count);
95    }
96 }
97
98 bool DwarfFrameParser::hasFrameDebugInfo()
99 {
100    setupFdeData();
101    return fde_dwarf_status == dwarf_status_ok;
102 }
103
104 bool DwarfFrameParser::getRegValueAtFrame(Address pc,
105                                  Dyninst::MachRegister reg,
106                                  Dyninst::MachRegisterVal &reg_result,
107                                  ProcessReader *reader,
108                                  FrameErrors_t &err_result)
109 {
110    ConcreteDwarfResult cons(reader, arch, pc, dbg);
111
112    dwarf_printf("Getting concrete value for %s at 0x%lx\n",
113                 reg.name().c_str(), pc);
114    if (!getRegAtFrame(pc, reg, cons, err_result)) {
115      assert(err_result != FE_No_Error);
116      dwarf_printf("\t Returning error from getRegValueAtFrame\n");
117      return false;
118    }
119    if (cons.err()) {
120       dwarf_printf("\t Computed dwarf result to an error\n");
121       err_result = FE_Frame_Eval_Error;
122       return false;
123    }
124
125    reg_result = cons.val();
126    dwarf_printf("Returning result 0x%lx for reg %s at 0x%lx\n",
127                 reg_result, reg.name().c_str(), pc);
128    return true;
129 }
130
131 bool DwarfFrameParser::getRegRepAtFrame(Address pc,
132                                Dyninst::MachRegister reg,
133                                VariableLocation &loc,
134                                FrameErrors_t &err_result) {
135    SymbolicDwarfResult cons(loc, arch);
136
137    dwarf_printf("Getting symbolic value for %s at 0x%lx\n",
138                 reg.name().c_str(), pc);
139    if (!getRegAtFrame(pc, reg, cons, err_result)) {
140      dwarf_printf("\t Returning error from getRegRepAtFrame\n");
141      assert(err_result != FE_No_Error);
142      return false;
143    }
144
145    if (cons.err()) {
146       dwarf_printf("\t Computed dwarf result to an error\n");
147       err_result = FE_Frame_Eval_Error;
148       return false;
149    }
150
151    loc = cons.val();
152
153    dwarf_printf("Returning symbolic result for reg %s at 0x%lx\n",
154                 reg.name().c_str(), pc);
155
156    return true;
157 }
158
159 bool DwarfFrameParser::getRegsForFunction(Address entryPC,
160                                           Dyninst::MachRegister reg,
161                                           std::vector<VariableLocation> &locs,
162                                           FrameErrors_t &err_result) {
163    locs.clear();
164    dwarf_printf("Entry to getRegsForFunction at 0x%lx, reg %s\n", entryPC, reg.name().c_str());
165    err_result = FE_No_Error;
166
167    /**
168     * Initialize the FDE and CIE data.  This is only really done once,
169     * after which setupFdeData will immediately return.
170     **/
171    setupFdeData();
172    if (!fde_data.size()) {
173       err_result = FE_Bad_Frame_Data;
174       dwarf_printf("\t No FDE data, returning error\n");
175       return false;
176    }
177
178    /**
179     * Get the FDE at this PC.  The FDE contains the rules for getting
180     * registers at the given PC in this frame.
181     **/
182    Dwarf_Fde fde;
183    Address low, high;
184    if (!getFDE(entryPC, fde, low, high, err_result)) {
185       dwarf_printf("\t Failed to find FDE for 0x%lx, returning error\n", entryPC);
186      assert(err_result != FE_No_Error);
187      return false;
188    }
189
190    dwarf_printf("\t Got FDE range 0x%lx..0x%lx\n", low, high);
191
192    Dwarf_Half dwarf_reg;
193    if (!getDwarfReg(reg, fde, dwarf_reg, err_result)) {
194      assert(err_result != FE_No_Error);
195      dwarf_printf("\t Failed to get dwarf register for %s\n", reg.name().c_str());
196      return false;
197    }
198
199    Address worker = high;
200    while (worker > low) {
201       dwarf_printf("\t Getting register representation for 0x%lx (reg %s)\n", worker, reg.name().c_str());
202       VariableLocation loc;
203       SymbolicDwarfResult cons(loc, arch);
204       Address next;
205       if (!getRegAtFrame_aux(worker, fde, dwarf_reg, reg, cons, next, err_result)) {
206         assert(err_result != FE_No_Error);
207         dwarf_printf("\t Failed to get register representation, ret false\n");
208          return false;
209       }
210       loc.lowPC = next;
211       loc.hiPC = worker;
212
213       worker = next - 1;
214       locs.push_back(cons.val());
215    }
216
217    std::reverse(locs.begin(), locs.end());
218    return true;
219 }
220
221 bool DwarfFrameParser::getRegAtFrame(Address pc,
222                                      Dyninst::MachRegister reg,
223                                      DwarfResult &cons,
224                                      FrameErrors_t &err_result) {
225
226    err_result = FE_No_Error;
227
228    dwarf_printf("getRegAtFrame for 0x%lx, %s\n", pc, reg.name().c_str());
229    /**
230     * Initialize the FDE and CIE data.  This is only really done once,
231     * after which setupFdeData will immediately return.
232     **/
233    setupFdeData();
234    if (!fde_data.size()) {
235       dwarf_printf("\t No FDE data, ret false\n");
236       err_result = FE_Bad_Frame_Data;
237       return false;
238    }
239
240    /**
241     * Get the FDE at this PC.  The FDE contains the rules for getting
242     * registers at the given PC in this frame.
243     **/
244    Dwarf_Fde fde;
245    Address u1, u2;
246    if (!getFDE(pc, fde, u1, u2, err_result)) {
247       dwarf_printf("\t No FDE at 0x%lx, ret false\n", pc);
248       assert(err_result != FE_No_Error);
249       return false;
250    }
251
252    Dwarf_Half dwarf_reg;
253    if (!getDwarfReg(reg, fde, dwarf_reg, err_result)) {
254       dwarf_printf("\t Failed to convert %s to dwarf reg, ret false\n",
255                    reg.name().c_str());
256       assert(err_result != FE_No_Error);
257       return false;
258    }
259
260    Address ignored;
261    return getRegAtFrame_aux(pc, fde, dwarf_reg, reg, cons, ignored, err_result);
262 }
263
264 bool DwarfFrameParser::getRegAtFrame_aux(Address pc,
265                                          Dwarf_Fde fde,
266                                          Dwarf_Half dwarf_reg,
267                                          MachRegister orig_reg,
268                                          DwarfResult &cons,
269                                          Address &lowpc,
270                                          FrameErrors_t &err_result) {
271    int result;
272    Dwarf_Error err;
273
274    int width = getArchAddressWidth(arch);
275    dwarf_printf("getRegAtFrame_aux for 0x%lx, addr width %d\n",
276                 pc, width);
277
278    Dwarf_Small value_type;
279    Dwarf_Signed offset_relevant, register_num, offset_or_block_len;
280    Dwarf_Ptr block_ptr;
281    Dwarf_Addr row_pc;
282
283    /**
284     * Decode the rule that describes how to get dwarf_reg at pc.
285     **/
286    if (dwarf_reg != DW_FRAME_CFA_COL3) {
287       dwarf_printf("\tNot col3 reg, using default\n");
288       result = dwarf_get_fde_info_for_reg3(fde, dwarf_reg, pc, &value_type,
289                                            &offset_relevant, &register_num,
290                                            &offset_or_block_len,
291                                            &block_ptr, &row_pc, &err);
292    }
293    else {
294       dwarf_printf("\tcol3 reg, using CFA\n");
295       result = dwarf_get_fde_info_for_cfa_reg3(fde, pc, &value_type,
296                                                &offset_relevant, &register_num,
297                                                &offset_or_block_len,
298                                                &block_ptr, &row_pc, &err);
299    }
300    if (result == DW_DLV_ERROR) {
301       err_result = FE_Bad_Frame_Data;
302       return false;
303    }
304
305    lowpc = (Address) row_pc;
306    dwarf_printf("\t Got FDE data starting at 0x%lx; value_type %d, offset_relevant %d, offset/block len %d\n",
307                 lowpc, (int) value_type, (int) offset_relevant, offset_or_block_len);
308
309    /**
310     * Interpret the rule and turn it into a real value.
311     **/
312
313    if (value_type == DW_EXPR_OFFSET || value_type == DW_EXPR_VAL_OFFSET)
314    {
315
316       bool done;
317       dwarf_printf("\tHandling returned FDE as expression\n");
318       if (!handleExpression(pc, register_num, orig_reg,
319                             arch, cons, done, err_result)) {
320          dwarf_printf("\t Error handling expression, ret false\n");
321         assert(err_result != FE_No_Error);
322         return false;
323       }
324       if (done) {
325          dwarf_printf("\t Handled expression, indicated done, returning\n");
326          return true;
327       }
328    }
329
330    bool indirect = false;
331
332    switch(value_type) {
333       // For a val offset, the value of the register is (other_reg + const)
334       case DW_EXPR_VAL_OFFSET:
335       case DW_EXPR_OFFSET:
336          dwarf_printf("\tHandling val_offset or offset\n");
337          if (offset_relevant) {
338             dwarf_printf("\t Offset relevant, adding %d\n", offset_or_block_len);
339             cons.pushSignedVal(offset_or_block_len);
340             cons.pushOp(DwarfResult::Add);
341          }
342
343          if (offset_relevant &&
344              dwarf_reg != DW_FRAME_CFA_COL3) {
345             dwarf_printf("\t Reg not CFA and offset relevant: indirect\n");
346             indirect = true;
347          }
348          dwarf_printf("\t Done handling val_offset or offset\n");
349          break;
350       case DW_EXPR_VAL_EXPRESSION:
351       case DW_EXPR_EXPRESSION: {
352          dwarf_printf("\t Handling val_expression or expression\n");
353          Dwarf_Locdesc *llbuf = NULL;
354          Dwarf_Signed listlen = 0;
355          result = dwarf_loclist_from_expr(dbg, block_ptr, offset_or_block_len, &llbuf, &listlen, &err);
356          if (result != DW_DLV_OK) {
357             dwarf_printf("\t Failed to get loclist, ret false\n");
358             err_result = FE_Frame_Read_Error;
359             return false;
360          }
361
362          if (!decodeDwarfExpression(llbuf, NULL,
363                                     cons,
364                                     arch)) {
365             dwarf_printf("\t Failed to decode dwarf expr, ret false\n");
366             err_result = FE_Frame_Eval_Error;
367             return false;
368          }
369
370          dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
371          dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
372
373          if (value_type == DW_EXPR_EXPRESSION) {
374             dwarf_printf("\t Handling expression, adding indirect\n");
375             indirect = true;
376          }
377          break;
378       }
379       default:
380          err_result = FE_Bad_Frame_Data;
381          return false;
382    }
383
384    if (indirect) {
385       dwarf_printf("\t Adding a dereference to handle \"address of\" operator\n");
386       cons.pushOp(DwarfResult::Deref, width);
387    }
388
389    return true;
390 }
391
392 void DwarfFrameParser::setupFdeData()
393 {
394    Dwarf_Error err;
395
396    if (fde_dwarf_status == dwarf_status_ok ||
397        fde_dwarf_status == dwarf_status_error)
398       return;
399
400    if (!dbg) {
401       fde_dwarf_status = dwarf_status_error;
402       return;
403    }
404
405 #if defined(dwarf_has_setframe)
406    dwarf_set_frame_cfa_value(dbg, DW_FRAME_CFA_COL3);
407 #endif
408
409    fde_cie_data fc;
410    int result = dwarf_get_fde_list(dbg,
411                                    &fc.cie_data, &fc.cie_count,
412                                    &fc.fde_data, &fc.fde_count,
413                                    &err);
414    if (result == DW_DLV_OK) {
415       fde_data.push_back(fc);
416    }
417
418    result = dwarf_get_fde_list_eh(dbg,
419                                   &fc.cie_data, &fc.cie_count,
420                                   &fc.fde_data, &fc.fde_count,
421                                   &err);
422    if (result == DW_DLV_OK) {
423       fde_data.push_back(fc);
424    }
425
426
427    if (!fde_data.size()) {
428       fde_dwarf_status = dwarf_status_error;
429    }
430
431    fde_dwarf_status = dwarf_status_ok;
432 }
433
434 bool DwarfFrameParser::getFDE(Address pc, Dwarf_Fde &fde,
435                               Address &low, Address &high,
436                               FrameErrors_t &err_result) {
437    Dwarf_Addr lowpc = 0, hipc = 0;
438    dwarf_printf("Getting FDE for 0x%lx\n", pc);
439    bool found = false;
440    unsigned cur_fde;
441    for (cur_fde=0; cur_fde<fde_data.size(); cur_fde++) {
442       int result = dwarf_get_fde_at_pc(fde_data[cur_fde].fde_data,
443                                        (Dwarf_Addr) pc, &fde, &lowpc, &hipc, NULL);
444       if (result == DW_DLV_ERROR) {
445          dwarf_printf("\t Got ERROR return\n");
446          err_result = FE_Bad_Frame_Data;
447          return false;
448       }
449       else if (pc < lowpc || pc > hipc)
450       {
451         continue;
452       }
453       else if (result == DW_DLV_OK) {
454          dwarf_printf("\t Got range 0x%lx..0x%lx\n",
455                       lowpc, hipc);
456          low = (Address) lowpc;
457          high = (Address) hipc;
458          found = true;
459          break;
460       }
461    }
462    if (!found)
463    {
464       dwarf_printf("\tEntry not found, ret false\n");
465       err_result = FE_No_Frame_Entry;
466       return false;
467    }
468    return true;
469 }
470
471 bool DwarfFrameParser::getDwarfReg(Dyninst::MachRegister reg,
472                                    Dwarf_Fde &fde,
473                                    Dwarf_Half &dwarf_reg,
474                                    FrameErrors_t &err_result) {
475    Dwarf_Error err;
476    if (reg == Dyninst::ReturnAddr) {
477       /**
478        * We should be getting the return address for the stack frame.
479        * This is treated as a virtual register in the
480        * FDE.  We can look up the virtual register in the CIE.
481        **/
482       Dwarf_Cie cie;
483       int result = dwarf_get_cie_of_fde(fde, &cie, &err);
484       if (result != DW_DLV_OK) {
485           dwarf_printf("ARM-ERROR: bad return value.\n");
486          err_result = FE_Bad_Frame_Data;
487          return false;
488       }
489
490       Dwarf_Unsigned bytes_in_cie;
491       result = dwarf_get_cie_info(cie, &bytes_in_cie, NULL, NULL, NULL, NULL,
492                                   &dwarf_reg, NULL, NULL, &err);
493       if (result != DW_DLV_OK) {
494           dwarf_printf("ARM-ERROR: bad return value.\n");
495          err_result = FE_Bad_Frame_Data;
496          return false;
497       }
498    }
499    else if (reg == Dyninst::FrameBase || reg == Dyninst::CFA) {
500       dwarf_reg = DW_FRAME_CFA_COL3;
501    }
502    else {
503       dwarf_reg = reg.getDwarfEnc();
504    }
505    return true;
506 }
507
508 bool DwarfFrameParser::handleExpression(Address pc,
509                                Dwarf_Signed registerNum,
510                                Dyninst::MachRegister origReg,
511                                Dyninst::Architecture arch,
512                                DwarfResult &cons,
513                                bool &done,
514                                FrameErrors_t &err_result) {
515   dwarf_printf("HandleExpression\n");
516
517    done = false;
518    dwarf_printf("register num %d\n", registerNum);
519    switch (registerNum) {
520       case DW_FRAME_CFA_COL3:
521         dwarf_printf("\t Getting frame base\n");
522
523          err_result = FE_No_Error;
524          if (!getRegAtFrame(pc, Dyninst::FrameBase,
525                             cons, err_result)) {
526            assert(err_result != FE_No_Error);
527             return false;
528          }
529          break;
530       case DW_FRAME_SAME_VAL:
531         dwarf_printf("\t Getting %s\n", origReg.name().c_str());
532 #if defined(arch_aarch64)
533          //if(origReg == Dyninst::ReturnAddr)
534          //    origReg = Dyninst::aarch64::x30;
535          origReg = MachRegister::getArchRegFromAbstractReg(origReg, arch);
536 #endif
537          cons.readReg(origReg);
538          done = true;
539          break;
540    case DW_FRAME_UNDEFINED_VAL:
541        dwarf_printf("\t Value not available for %s\n", origReg.name().c_str());
542        err_result = FE_No_Frame_Entry;
543        return false;
544
545       default: {
546          Dyninst::MachRegister dyn_register = MachRegister::DwarfEncToReg(registerNum, arch);
547          dwarf_printf("\t Getting %s\n", dyn_register.name().c_str());
548
549          cons.readReg(dyn_register);
550          break;
551       }
552    }
553    return true;
554 }
555