00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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"
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 ®_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
00151
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
00162
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
00213
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
00224
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
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, ®ister_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, ®ister_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
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
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
00461
00462
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