dwarfFrameParser.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #include "dwarf/h/dwarfFrameParser.h"
00032 #include "dwarf/h/dwarfExprParser.h"
00033 #include "dwarf/h/dwarfResult.h"
00034 #include "dynutil/h/VariableLocation.h"
00035 #include "common/h/Types.h"
00036 #include "libdwarf.h"
00037 #include <stdio.h>
00038 #include <iostream>
00039 #include "common/h/debug_common.h" // dwarf_printf
00040 
00041 using namespace Dyninst;
00042 using namespace Dwarf;
00043 using namespace std;
00044 
00045 std::map<Dwarf_Debug, DwarfFrameParser::Ptr> DwarfFrameParser::frameParsers;
00046 
00047 DwarfFrameParser::Ptr DwarfFrameParser::create(Dwarf_Debug dbg, Architecture arch) {
00048    std::map<Dwarf_Debug, DwarfFrameParser::Ptr>::iterator iter = frameParsers.find(dbg);
00049    if (iter == frameParsers.end()) {
00050       Ptr newParser = Ptr(new DwarfFrameParser(dbg, arch));
00051       frameParsers[dbg] = newParser;
00052       return newParser;
00053    }
00054    else {
00055       assert(iter->second->arch == arch);
00056       return iter->second;
00057    }
00058 }
00059 
00060 
00061 DwarfFrameParser::DwarfFrameParser(Dwarf_Debug dbg_, Architecture arch_) :
00062    dbg(dbg_),
00063    arch(arch_),
00064    fde_dwarf_status(dwarf_status_uninitialized)
00065 {
00066 }
00067 
00068 DwarfFrameParser::~DwarfFrameParser()
00069 {
00070    if (fde_dwarf_status != dwarf_status_ok) 
00071       return;
00072    for (unsigned i=0; i<fde_data.size(); i++)
00073    {
00074       dwarf_fde_cie_list_dealloc(dbg, 
00075                                  fde_data[i].cie_data, fde_data[i].cie_count, 
00076                                  fde_data[i].fde_data, fde_data[i].fde_count);
00077    }
00078 }
00079 
00080 bool DwarfFrameParser::hasFrameDebugInfo()
00081 {
00082    setupFdeData();
00083    return fde_dwarf_status == dwarf_status_ok;
00084 }
00085 
00086 bool DwarfFrameParser::getRegValueAtFrame(Address pc, 
00087                                  Dyninst::MachRegister reg,
00088                                  Dyninst::MachRegisterVal &reg_result,
00089                                  ProcessReader *reader,
00090                                  FrameErrors_t &err_result)
00091 {
00092    ConcreteDwarfResult cons(reader, arch, pc, dbg);
00093 
00094    dwarf_printf("Getting concrete value for %s at 0x%lx\n",
00095                 reg.name().c_str(), pc);
00096    if (!getRegAtFrame(pc, reg, cons, err_result)) {
00097      assert(err_result != FE_No_Error);
00098      dwarf_printf("\t Returning error from getRegValueAtFrame\n");
00099      return false;
00100    }
00101    if (cons.err()) {
00102       dwarf_printf("\t Computed dwarf result to an error\n");
00103       err_result = FE_Frame_Eval_Error;
00104       return false;
00105    }
00106 
00107    reg_result = cons.val();
00108    dwarf_printf("Returning result 0x%lx for reg %s at 0x%lx\n", 
00109                 reg_result, reg.name().c_str(), pc);
00110    return true;
00111 }
00112 
00113 bool DwarfFrameParser::getRegRepAtFrame(Address pc,
00114                                Dyninst::MachRegister reg,
00115                                VariableLocation &loc,
00116                                FrameErrors_t &err_result) {
00117    SymbolicDwarfResult cons(loc, arch);
00118    
00119    dwarf_printf("Getting symbolic value for %s at 0x%lx\n",
00120                 reg.name().c_str(), pc);
00121    if (!getRegAtFrame(pc, reg, cons, err_result)) {
00122      dwarf_printf("\t Returning error from getRegRepAtFrame\n");
00123      assert(err_result != FE_No_Error);
00124      return false;
00125    }
00126    
00127    if (cons.err()) {
00128       dwarf_printf("\t Computed dwarf result to an error\n");
00129       err_result = FE_Frame_Eval_Error;
00130       return false;
00131    }
00132 
00133    loc = cons.val();
00134 
00135    dwarf_printf("Returning symbolic result for reg %s at 0x%lx\n", 
00136                 reg.name().c_str(), pc);
00137 
00138    return true;
00139 }
00140 
00141 bool DwarfFrameParser::getRegsForFunction(Address entryPC,
00142                                           Dyninst::MachRegister reg,
00143                                           std::vector<VariableLocation> &locs,
00144                                           FrameErrors_t &err_result) {
00145    locs.clear();
00146    dwarf_printf("Entry to getRegsForFunction at 0x%lx, reg %s\n", entryPC, reg.name().c_str());
00147    err_result = FE_No_Error;
00148 
00149    /**
00150     * Initialize the FDE and CIE data.  This is only really done once, 
00151     * after which setupFdeData will immediately return.
00152     **/
00153    setupFdeData();
00154    if (!fde_data.size()) {
00155       err_result = FE_Bad_Frame_Data;
00156       dwarf_printf("\t No FDE data, returning error\n");
00157       return false;
00158    }
00159 
00160    /**
00161     * Get the FDE at this PC.  The FDE contains the rules for getting
00162     * registers at the given PC in this frame.
00163     **/
00164    Dwarf_Fde fde;
00165    Address low, high;
00166    if (!getFDE(entryPC, fde, low, high, err_result)) {
00167       dwarf_printf("\t Failed to find FDE for 0x%lx, returning error\n", entryPC);
00168      assert(err_result != FE_No_Error);
00169      return false;
00170    }
00171 
00172    dwarf_printf("\t Got FDE range 0x%lx..0x%lx\n", low, high);
00173    
00174    Dwarf_Half dwarf_reg;
00175    if (!getDwarfReg(reg, fde, dwarf_reg, err_result)) {
00176      assert(err_result != FE_No_Error);
00177      dwarf_printf("\t Failed to get dwarf register for %s\n", reg.name().c_str());
00178      return false;
00179    }
00180 
00181    Address worker = high;
00182    while (worker > low) {
00183       dwarf_printf("\t Getting register representation for 0x%lx (reg %s)\n", worker, reg.name().c_str());
00184       VariableLocation loc;
00185       SymbolicDwarfResult cons(loc, arch);
00186       Address next;
00187       if (!getRegAtFrame_aux(worker, fde, dwarf_reg, reg, cons, next, err_result)) {
00188     assert(err_result != FE_No_Error);
00189         dwarf_printf("\t Failed to get register representation, ret false\n");
00190          return false;
00191       }
00192       loc.lowPC = next;
00193       loc.hiPC = worker;
00194 
00195       worker = next - 1;
00196       locs.push_back(cons.val());
00197    }
00198 
00199    std::reverse(locs.begin(), locs.end());
00200    return true;
00201 }
00202 
00203 bool DwarfFrameParser::getRegAtFrame(Address pc,
00204                                      Dyninst::MachRegister reg,
00205                                      DwarfResult &cons,
00206                                      FrameErrors_t &err_result) {
00207 
00208    err_result = FE_No_Error;
00209 
00210    dwarf_printf("getRegAtFrame for 0x%lx, %s\n", pc, reg.name().c_str());
00211    /**
00212     * Initialize the FDE and CIE data.  This is only really done once, 
00213     * after which setupFdeData will immediately return.
00214     **/
00215    setupFdeData();
00216    if (!fde_data.size()) {
00217       dwarf_printf("\t No FDE data, ret false\n");
00218       err_result = FE_Bad_Frame_Data;
00219       return false;
00220    }
00221 
00222    /**
00223     * Get the FDE at this PC.  The FDE contains the rules for getting
00224     * registers at the given PC in this frame.
00225     **/
00226    Dwarf_Fde fde;
00227    Address u1, u2;
00228    if (!getFDE(pc, fde, u1, u2, err_result)) {
00229       dwarf_printf("\t No FDE at 0x%lx, ret false\n", pc);
00230       assert(err_result != FE_No_Error);
00231       return false;
00232    }
00233 
00234    Dwarf_Half dwarf_reg;
00235    if (!getDwarfReg(reg, fde, dwarf_reg, err_result)) {
00236       dwarf_printf("\t Failed to convert %s to dwarf reg, ret false\n",
00237                    reg.name().c_str());
00238       assert(err_result != FE_No_Error);
00239       return false;
00240    }
00241 
00242    Address ignored;
00243    return getRegAtFrame_aux(pc, fde, dwarf_reg, reg, cons, ignored, err_result);
00244 }
00245 
00246 bool DwarfFrameParser::getRegAtFrame_aux(Address pc,
00247                                          Dwarf_Fde fde,
00248                                          Dwarf_Half dwarf_reg,
00249                                          MachRegister orig_reg,
00250                                          DwarfResult &cons,
00251                                          Address &lowpc,
00252                                          FrameErrors_t &err_result) {
00253    int result;
00254    Dwarf_Error err;
00255    
00256    int width = getArchAddressWidth(arch);
00257    dwarf_printf("getRegAtFrame_aux for 0x%lx, addr width %d\n",
00258                 pc, width);
00259 
00260    Dwarf_Small value_type;
00261    Dwarf_Signed offset_relevant, register_num, offset_or_block_len;
00262    Dwarf_Ptr block_ptr;
00263    Dwarf_Addr row_pc;
00264 
00265    /**
00266     * Decode the rule that describes how to get dwarf_reg at pc.
00267     **/
00268    if (dwarf_reg != DW_FRAME_CFA_COL3) {
00269       dwarf_printf("\tNot col3 reg, using default\n");
00270       result = dwarf_get_fde_info_for_reg3(fde, dwarf_reg, pc, &value_type, 
00271                                            &offset_relevant, &register_num,
00272                                            &offset_or_block_len,
00273                                            &block_ptr, &row_pc, &err);
00274    }
00275    else {
00276       dwarf_printf("\tcol3 reg, using CFA\n");
00277       result = dwarf_get_fde_info_for_cfa_reg3(fde, pc, &value_type, 
00278                                                &offset_relevant, &register_num,
00279                                                &offset_or_block_len,
00280                                                &block_ptr, &row_pc, &err);
00281    }
00282    if (result == DW_DLV_ERROR) {
00283       err_result = FE_Bad_Frame_Data;
00284       return false;
00285    }
00286 
00287    lowpc = (Address) row_pc;
00288    dwarf_printf("\t Got FDE data starting at 0x%lx; value_type %d, offset_relevant %d, offset/block len %d\n", 
00289                 lowpc, (int) value_type, (int) offset_relevant, offset_or_block_len);
00290 
00291    /**
00292     * Interpret the rule and turn it into a real value.
00293     **/
00294    
00295    if (value_type == DW_EXPR_OFFSET || value_type == DW_EXPR_VAL_OFFSET)
00296    {
00297       
00298       bool done;
00299       dwarf_printf("\tHandling returned FDE as expression\n");
00300       if (!handleExpression(pc, register_num, orig_reg,
00301                             arch, cons, done, err_result)) {
00302          dwarf_printf("\t Error handling expression, ret false\n");
00303     assert(err_result != FE_No_Error);
00304     return false;
00305       }
00306       if (done) {
00307          dwarf_printf("\t Handled expression, indicated done, returning\n");
00308          return true;
00309       }
00310    }
00311 
00312    bool indirect = false;
00313 
00314    switch(value_type) {
00315       // For a val offset, the value of the register is (other_reg + const)
00316       case DW_EXPR_VAL_OFFSET:
00317       case DW_EXPR_OFFSET:
00318          dwarf_printf("\tHandling val_offset or offset\n");
00319          if (offset_relevant) {
00320             dwarf_printf("\t Offset relevant, adding %d\n", offset_or_block_len);
00321             cons.pushSignedVal(offset_or_block_len);
00322             cons.pushOp(DwarfResult::Add);
00323          }
00324          
00325          if (offset_relevant && 
00326              dwarf_reg != DW_FRAME_CFA_COL3) {
00327             dwarf_printf("\t Reg not CFA and offset relevant: indirect\n");
00328             indirect = true;
00329          }
00330          dwarf_printf("\t Done handling val_offset or offset\n");
00331          break;
00332       case DW_EXPR_VAL_EXPRESSION:
00333       case DW_EXPR_EXPRESSION: {
00334          dwarf_printf("\t Handling val_expression or expression\n");
00335          Dwarf_Locdesc *llbuf = NULL;
00336          Dwarf_Signed listlen = 0;
00337          result = dwarf_loclist_from_expr(dbg, block_ptr, offset_or_block_len, &llbuf, &listlen, &err);
00338          if (result != DW_DLV_OK) {
00339             dwarf_printf("\t Failed to get loclist, ret false\n");
00340             err_result = FE_Frame_Read_Error;
00341             return false;
00342          }
00343          
00344          if (!decodeDwarfExpression(llbuf, NULL, 
00345                                     cons,
00346                                     arch)) {
00347             dwarf_printf("\t Failed to decode dwarf expr, ret false\n");
00348             err_result = FE_Frame_Eval_Error;
00349             return false;
00350          }
00351 
00352          dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
00353          dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
00354          
00355          if (value_type == DW_EXPR_EXPRESSION) {
00356             dwarf_printf("\t Handling expression, adding indirect\n");
00357             indirect = true;
00358          }
00359          break;
00360       }
00361       default:
00362          err_result = FE_Bad_Frame_Data;
00363          return false;
00364    }
00365    
00366    if (indirect) {
00367       dwarf_printf("\t Adding a dereference to handle \"address of\" operator\n");
00368       cons.pushOp(DwarfResult::Deref, width);
00369    }
00370 
00371    return true;
00372 }
00373 
00374 void DwarfFrameParser::setupFdeData()
00375 {
00376    Dwarf_Error err;
00377    
00378    if (fde_dwarf_status == dwarf_status_ok || 
00379        fde_dwarf_status == dwarf_status_error)
00380       return;
00381 
00382    if (!dbg) {
00383       fde_dwarf_status = dwarf_status_error;
00384       return;
00385    }
00386 
00387 #if defined(dwarf_has_setframe)
00388    dwarf_set_frame_cfa_value(dbg, DW_FRAME_CFA_COL3);
00389 #endif
00390 
00391    fde_cie_data fc;
00392    int result = dwarf_get_fde_list(dbg, 
00393                                    &fc.cie_data, &fc.cie_count,
00394                                    &fc.fde_data, &fc.fde_count,
00395                                    &err);
00396    if (result == DW_DLV_OK) {
00397       fde_data.push_back(fc);
00398    }
00399 
00400    result = dwarf_get_fde_list_eh(dbg, 
00401                                   &fc.cie_data, &fc.cie_count,
00402                                   &fc.fde_data, &fc.fde_count,
00403                                   &err);
00404    if (result == DW_DLV_OK) {
00405       fde_data.push_back(fc);
00406    }
00407    
00408 
00409    if (!fde_data.size()) {
00410       fde_dwarf_status = dwarf_status_error;
00411    }
00412    
00413    fde_dwarf_status = dwarf_status_ok;
00414 }
00415 
00416 bool DwarfFrameParser::getFDE(Address pc, Dwarf_Fde &fde, 
00417                               Address &low, Address &high, 
00418                               FrameErrors_t &err_result) {
00419    Dwarf_Addr lowpc = 0, hipc = 0;
00420    dwarf_printf("Getting FDE for 0x%lx\n", pc);
00421    bool found = false;
00422    unsigned cur_fde;
00423    for (cur_fde=0; cur_fde<fde_data.size(); cur_fde++) {
00424       int result = dwarf_get_fde_at_pc(fde_data[cur_fde].fde_data, 
00425                                        (Dwarf_Addr) pc, &fde, &lowpc, &hipc, NULL);
00426       if (result == DW_DLV_ERROR) {
00427          dwarf_printf("\t Got ERROR return\n");
00428          err_result = FE_Bad_Frame_Data;
00429          return false;
00430       }
00431       else if (pc < lowpc || pc > hipc) 
00432       {
00433     continue;
00434       }
00435       else if (result == DW_DLV_OK) {
00436          dwarf_printf("\t Got range 0x%lx..0x%lx\n", 
00437                       lowpc, hipc);
00438          low = (Address) lowpc;
00439          high = (Address) hipc;
00440          found = true;
00441          break;
00442       }
00443    }
00444    if (!found)
00445    {
00446       dwarf_printf("\tEntry not found, ret false\n");
00447       err_result = FE_No_Frame_Entry;
00448       return false;
00449    }
00450    return true;
00451 }
00452 
00453 bool DwarfFrameParser::getDwarfReg(Dyninst::MachRegister reg,
00454                                    Dwarf_Fde &fde,
00455                                    Dwarf_Half &dwarf_reg,
00456                                    FrameErrors_t &err_result) {
00457    Dwarf_Error err;
00458    if (reg == Dyninst::ReturnAddr) {
00459       /**
00460        * We should be getting the return address for the stack frame.  
00461        * This is treated as a virtual register in the
00462        * FDE.  We can look up the virtual register in the CIE.
00463        **/
00464       Dwarf_Cie cie;
00465       int result = dwarf_get_cie_of_fde(fde, &cie, &err);
00466       if (result != DW_DLV_OK) {
00467          err_result = FE_Bad_Frame_Data;
00468          return false;
00469       }
00470 
00471       Dwarf_Unsigned bytes_in_cie;
00472       result = dwarf_get_cie_info(cie, &bytes_in_cie, NULL, NULL, NULL, NULL, 
00473                                   &dwarf_reg, NULL, NULL, &err);
00474       if (result != DW_DLV_OK) {
00475          err_result = FE_Bad_Frame_Data;
00476          return false;
00477       }
00478    }
00479    else if (reg == Dyninst::FrameBase || reg == Dyninst::CFA) {
00480       dwarf_reg = DW_FRAME_CFA_COL3;
00481    }
00482    else {
00483       dwarf_reg = reg.getDwarfEnc(); 
00484    }
00485    return true;
00486 }
00487 
00488 bool DwarfFrameParser::handleExpression(Address pc,
00489                                Dwarf_Signed registerNum,
00490                                Dyninst::MachRegister origReg,
00491                                Dyninst::Architecture arch,
00492                                DwarfResult &cons,
00493                                bool &done,
00494                                FrameErrors_t &err_result) {
00495   dwarf_printf("HandleExpression\n");
00496   
00497    done = false;
00498    switch (registerNum) {
00499       case DW_FRAME_CFA_COL3:
00500     dwarf_printf("\t Getting frame base\n");
00501     
00502          err_result = FE_No_Error;
00503          if (!getRegAtFrame(pc, Dyninst::FrameBase,
00504                             cons, err_result)) {
00505        assert(err_result != FE_No_Error);
00506             return false;
00507          }
00508          break;
00509       case DW_FRAME_SAME_VAL:
00510     dwarf_printf("\t Getting %s\n", origReg.name().c_str());
00511     
00512          cons.readReg(origReg);
00513          done = true;
00514          break;
00515       default: {
00516          Dyninst::MachRegister dyn_register = MachRegister::DwarfEncToReg(registerNum, arch);
00517      dwarf_printf("\t Getting %s\n", dyn_register.name().c_str());
00518      
00519          cons.readReg(dyn_register);
00520          break;
00521       }
00522    }
00523    return true;
00524 }  
00525 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1