| line | true | false | branch | 
 
| 27 | 527 | 17 | for (auto& so: so_map) { | 
 
| 28 | 527 | 0 | auto info = std::make_unique(so); | 
 
| 29 | 527 | 0 | string real_path(PANDA_PATH_MAX); | 
 
| 33 | 527 | 0 | file = fopen(so.name.c_str(), "rb"); | 
 
|  | 527 | 0 | file = fopen(so.name.c_str(), "rb"); | 
 
| 34 | 527 | 0 | DwarfInfo::file_guard_t file_guard (file, [](auto* f){ if (f) {fclose(f); }}); | 
 
|  | 527 | 0 | DwarfInfo::file_guard_t file_guard (file, [](auto* f){ if (f) {fclose(f); }}); | 
 
| 35 | 527 | 0 | int fd = file ? fileno(file) : 0; | 
 
| 36 | 527 | 0 | if (fd > 0) { | 
 
| 37 | 527 | 0 | auto err = dwarf_init_b(fd, DW_DLC_READ, DW_GROUPNUMBER_ANY, nullptr, &info->err_arg, &info->debug, &error); | 
 
| 39 | 527 | 0 | if (err == DW_DLV_OK) { | 
 
| 49 | 527 | 0 | result.emplace(so.name, std::move(info)); | 
 
| 54 | 0 | 17 | struct DwarfBackend: BacktraceBackend { | 
 
| 67 | 3436 | 0 | for(auto& it: info_map) { | 
 
| 69 | 267 | 3169 | if (it.second->resolve(ip_addr, frames)) return true; | 
 
| 86 | 527 | 0 | if (debug) { | 
 
| 90 | 0 | 527 | if (res != DW_DLV_OK) { | 
 
| 108 | 527 | 0 | if (res != DW_DLV_OK) { break; } | 
 
| 113 | 0 | 0 | if (res != DW_DLV_OK) { break; } | 
 
| 115 | 0 | 527 | dwarf::DieHolder cu_die_holder(cu_die, debug, nullptr); | 
 
| 124 | 499 | 2937 | if (ip < so_info.begin || ip >= so_info.end) { return false; } | 
 
|  | 232 | 267 | if (ip < so_info.begin || ip >= so_info.end) { return false; } | 
 
| 129 | 0 | 267 | for(auto it = CUs.begin(); it != CUs.end(); ++it){ | 
 
| 133 | 0 | 0 | if (r.is_complete()) { return r.get_frames(ip, so_info, frames); } | 
 
|  | 0 | 0 | if (r.is_complete()) { return r.get_frames(ip, so_info, frames); } | 
 
| 153 | 0 | 0 | bool LookupResult::is_complete() noexcept { return cu && subprogram; } | 
 
|  | 0 | 0 | bool LookupResult::is_complete() noexcept { return cu && subprogram; } | 
 
| 159 | 0 | 0 | auto frame = StackframeSP(new Stackframe()); | 
 
|  | 0 | 0 | auto frame = StackframeSP(new Stackframe()); | 
 
| 162 | 0 | 0 | frame->library = so.name; | 
 
| 164 | 0 | 0 | if (details.name)    frame->name    = details.name; | 
 
|  | 0 | 0 | if (details.name)    frame->name    = details.name; | 
 
| 165 | 0 | 0 | if (details.line_no) frame->line_no = details.line_no; | 
 
| 166 | 0 | 0 | if (details.source)  frame->file    = details.source; | 
 
|  | 0 | 0 | if (details.source)  frame->file    = details.source; | 
 
| 168 | 0 | 0 | frames.emplace_back(std::move(frame)); | 
 
| 171 | 0 | 0 | if (subprogram) { | 
 
| 177 | 0 | 0 | while(!location->context.empty()) { | 
 
| 196 | 0 | 0 | } | 
 
| 203 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 206 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 208 | 0 | 0 | if (res == DW_DLV_OK) { return r; } | 
 
| 216 | 0 | 0 | while (p->parent) { p = p->parent; } | 
 
| 225 | 0 | 0 | if(res == DW_DLV_OK) { | 
 
| 229 | 0 | 0 | assert(res == DW_DLV_OK); | 
 
| 240 | 0 | 0 | int res = dwarf_siblingof_b(node.debug, node.die, true, &child_die, &error); | 
 
| 241 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 242 | 0 | 0 | DieHolder child(child_die, node.debug, node.parent); | 
 
| 243 | 0 | 0 | auto found = fn(child); | 
 
| 244 | 0 | 0 | if (found) { return found; } | 
 
|  | 0 | 0 | if (found) { return found; } | 
 
| 248 | 0 | 0 | res = dwarf_child(node.die, &child_die, &error); | 
 
| 249 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 250 | 0 | 0 | DieHolder child(child_die, node.debug, &node); | 
 
| 251 | 0 | 0 | auto found = fn(child); | 
 
| 252 | 0 | 0 | if (found) { return found; } | 
 
|  | 0 | 0 | if (found) { return found; } | 
 
| 263 | 0 | 0 | assert(res == DW_DLV_OK); | 
 
| 264 | 0 | 0 | if (off == target_offset) { return node.detach(); } | 
 
| 265 | 0 | 0 | if (off > target_offset)  { return DieSP(); } /* do not lookup for fail branch */ | 
 
| 272 | 0 | 0 | if (!details.name) { | 
 
| 277 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 278 | 0 | 0 | iptr node = (it == die) ? iptr(this) : discover(it); | 
 
| 286 | 0 | 0 | if (die_spec) return refine_fn_spec(die_spec, details); | 
 
| 289 | 0 | 0 | if (die_ao) return refine_fn_name(die_ao, details); | 
 
| 299 | 0 | 0 | if (!source_die) { | 
 
| 300 | 0 | 0 | int res = dwarf_hasattr(it->die, DW_AT_decl_file, &has_source, &error); | 
 
| 301 | 0 | 0 | if (res == DW_DLV_OK && has_source) { | 
 
|  | 0 | 0 | if (res == DW_DLV_OK && has_source) { | 
 
| 302 | 0 | 0 | source_die = it; | 
 
| 310 | 0 | 0 | assert(res == DW_DLV_OK); | 
 
| 316 | 0 | 0 | while(p) { | 
 
| 319 | 0 | 0 | assert(res == DW_DLV_OK); | 
 
| 320 | 0 | 0 | if (tag == DW_TAG_structure_type || tag == DW_TAG_class_type || tag == DW_TAG_namespace) { | 
 
|  | 0 | 0 | if (tag == DW_TAG_structure_type || tag == DW_TAG_class_type || tag == DW_TAG_namespace) { | 
 
|  | 0 | 0 | if (tag == DW_TAG_structure_type || tag == DW_TAG_class_type || tag == DW_TAG_namespace) { | 
 
| 323 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 326 | 0 | 0 | assert(res == DW_DLV_OK); | 
 
| 344 | 0 | 0 | if (res != DW_DLV_OK) { return; } | 
 
| 351 | 0 | 0 | if (res != DW_DLV_OK) { return; } | 
 
| 352 | 0 | 0 | LineContextHolder line_context_guard(&line_context, [](auto it){ dwarf_srclines_dealloc_b(*it); }); | 
 
| 357 | 0 | 0 | if (res != DW_DLV_OK) { return; } | 
 
| 361 | 0 | 0 | for (Dwarf_Signed i = base_index; i < end_index; ++i) { | 
 
| 368 | 0 | 0 | if (res != DW_DLV_OK) { return; } | 
 
| 369 | 0 | 0 | if (cu_name.find(source_name) != string::npos) { | 
 
| 370 | 0 | 0 | if (dirindex) { | 
 
| 373 | 0 | 0 | if (res != DW_DLV_OK) { return; } | 
 
| 375 | 0 | 0 | if (cu_name.find(dir_name) != string::npos) { | 
 
| 386 | 0 | 0 | if (cu_index == -1) { return; } | 
 
| 391 | 0 | 0 | if (res != DW_DLV_OK) { return; } | 
 
| 396 | 0 | 0 | for(Dwarf_Signed i = 0; i < linecount; ++i) { | 
 
| 402 | 0 | 0 | if (res != DW_DLV_OK) { return; } | 
 
| 404 | 0 | 0 | if (res != DW_DLV_OK) { return; } | 
 
| 406 | 0 | 0 | if (res != DW_DLV_OK) { return; } | 
 
| 407 | 0 | 0 | if (file_index != static_cast(cu_index)) { continue; } | 
 
| 409 | 0 | 0 | if (lineaddr >=  offset) { found = true; break;  } | 
 
| 413 | 0 | 0 | if (found) { | 
 
| 414 | 0 | 0 | details.line_no = prev_lineno; | 
 
| 421 | 0 | 0 | if (!details.line_no) { | 
 
| 426 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 429 | 0 | 0 | if (res == DW_DLV_OK) { details.line_no = line + 1; } | 
 
| 439 | 0 | 0 | if (!r.line_no && r.name_die) refine_fn_line_fallback(r.name_die->die, r); | 
 
|  | 0 | 0 | if (!r.line_no && r.name_die) refine_fn_line_fallback(r.name_die->die, r); | 
 
|  | 0 | 0 | if (!r.line_no && r.name_die) refine_fn_line_fallback(r.name_die->die, r); | 
 
| 441 | 0 | 0 | if (r.name_die) refine_fn_source(r.name_die->die, r, *lr.root); | 
 
| 448 | 0 | 0 | if (!details.source) { | 
 
| 452 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 455 | 0 | 0 | if (res == DW_DLV_OK && file_index) { | 
 
|  | 0 | 0 | if (res == DW_DLV_OK && file_index) { | 
 
| 465 | 0 | 0 | if (!details.name) { | 
 
| 467 | 0 | 0 | if (die_spec) { refine_fn_spec(die_spec, details); } | 
 
| 482 | 0 | 0 | if (er == Scan::found) return er; | 
 
|  | 0 | 0 | if (er == Scan::found) return er; | 
 
|  | 0 | 0 | if (er == Scan::found) return er; | 
 
|  | 0 | 0 | if (er == Scan::found) return er; | 
 
| 493 | 0 | 0 | if (sr == Scan::found) return sr; | 
 
|  | 0 | 0 | if (sr == Scan::found) return sr; | 
 
| 494 | 0 | 0 | } else if (res == DW_DLV_NO_ENTRY) { | 
 
|  | 0 | 0 | } else if (res == DW_DLV_NO_ENTRY) { | 
 
|  | 0 | 0 | } else if (res == DW_DLV_NO_ENTRY) { | 
 
|  | 0 | 0 | } else if (res == DW_DLV_NO_ENTRY) { | 
 
| 501 | 0 | 0 | if (er != Scan::dead_end) { | 
 
|  | 0 | 0 | if (er != Scan::dead_end) { | 
 
|  | 0 | 0 | if (er != Scan::dead_end) { | 
 
|  | 0 | 0 | if (er != Scan::dead_end) { | 
 
| 506 | 0 | 0 | if (sr == Scan::found) return sr; | 
 
|  | 0 | 0 | if (sr == Scan::found) return sr; | 
 
| 514 | 0 | 0 | DieCollection context{{DieSP(this)}}; | 
 
| 520 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 526 | 0 | 0 | res = dwarf_tag(node.die, &tag, &error); | 
 
| 527 | 0 | 0 | if (res != DW_DLV_OK) { return Scan::dead_end; } | 
 
| 529 | 0 | 0 | if( tag == DW_TAG_subprogram || | 
 
|  | 0 | 0 | if( tag == DW_TAG_subprogram || | 
 
| 533 | 0 | 0 | case Match::yes: context.push_back(node.detach()); break; | 
 
|  | 0 | 0 | case Match::yes: context.push_back(node.detach()); break; | 
 
| 549 | 0 | 0 | assert(!owner || owner->die); | 
 
|  | 0 | 0 | assert(!owner || owner->die); | 
 
| 555 | 0 | 0 | if (!owner) { dwarf_dealloc(debug, die,DW_DLA_DIE); } | 
 
| 559 | 0 | 0 | if (!owner) { | 
 
| 560 | 0 | 0 | DieSP parent_ptr(parent ? parent->detach() : nullptr); | 
 
|  | 0 | 0 | DieSP parent_ptr(parent ? parent->detach() : nullptr); | 
 
| 561 | 0 | 0 | owner = DieSP(new DieRC(die, debug, parent_ptr)); | 
 
|  | 0 | 0 | owner = DieSP(new DieRC(die, debug, parent_ptr)); | 
 
| 572 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 576 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 577 | 0 | 0 | if (formclass == DW_FORM_CLASS_CONSTANT) { high += low; } | 
 
| 587 | 0 | 0 | if (addr) { | 
 
| 588 | 0 | 0 | if ((addr->high >= offset) || (addr->low < offset)) { | 
 
|  | 0 | 0 | if ((addr->high >= offset) || (addr->low < offset)) { | 
 
|  | 0 | 0 | if ((addr->high >= offset) || (addr->low < offset)) { | 
 
| 597 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 600 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 605 | 0 | 0 | if (res == DW_DLV_OK) { | 
 
| 607 | 0 | 0 | for(int i = 0; i < ranges_count; ++i) { | 
 
| 614 | 0 | 0 | auto matches = (low <= offset) && (high > offset); | 
 
|  | 0 | 0 | auto matches = (low <= offset) && (high > offset); | 
 
| 616 | 0 | 0 | if (matches) {return Match::yes; } | 
 
| 623 | 0 | 0 | if (ranges_count > 0) { return Match::no; } | 
 
| 638 | 0 | 527 | if (sources) { | 
 
| 639 | 0 | 0 | for(size_t i = 0; i < static_cast(sources_count); ++i) { | 
 
| 644 | 0 | 527 | } | 
 
| 647 | 0 | 0 | assert(cu_die); | 
 
| 661 | 0 | 0 | assert(die.die); | 
 
| 663 | 0 | 0 | if (res != DW_DLV_OK) { return Scan::dead_end; } | 
 
| 665 | 0 | 0 | if( tag == DW_TAG_subprogram || | 
 
|  | 0 | 0 | if( tag == DW_TAG_subprogram || | 
 
| 667 | 0 | 0 | switch (die.contains(offset)) { | 
 
| 676 | 0 | 0 | else if(tag == DW_TAG_compile_unit) { | 
 
| 680 | 0 | 0 | return lr.is_complete() ? Scan::found : Scan::not_found; | 
 
| 692 | 0 | 0 | if (!sources_count) { | 
 
| 694 | 0 | 0 | if (res != DW_DLV_OK) { sources_count = -1; } | 
 
| 696 | 0 | 0 | if (sources_count > 0 && index < static_cast(sources_count)) { | 
 
|  | 0 | 0 | if (sources_count > 0 && index < static_cast(sources_count)) { | 
 
| 704 | 6 | 0 | }}} | 
 
|  | 6 | 0 | }}} |