| 3266 | |
| 3267 | template <typename CB> |
| 3268 | static bool deep_first_search_by_pc( |
| 3269 | dwarf_fileobject& fobj, |
| 3270 | Dwarf_Die parent_die, |
| 3271 | Dwarf_Addr pc, |
| 3272 | std::vector<std::string>& ns, |
| 3273 | CB cb) |
| 3274 | { |
| 3275 | Dwarf_Die current_die = 0; |
| 3276 | Dwarf_Debug dwarf = fobj.dwarf_handle.get(); |
| 3277 | Dwarf_Error error = DW_DLE_NE; |
| 3278 | |
| 3279 | if (dwarf_child(parent_die, ¤t_die, &error) != DW_DLV_OK) { |
| 3280 | return false; |
| 3281 | } |
| 3282 | |
| 3283 | bool branch_has_pc = false; |
| 3284 | bool has_namespace = false; |
| 3285 | for (;;) { |
| 3286 | Dwarf_Die sibling_die = 0; |
| 3287 | |
| 3288 | Dwarf_Half tag; |
| 3289 | if (dwarf_tag(current_die, &tag, &error) == DW_DLV_OK) { |
| 3290 | if (tag == DW_TAG_namespace || tag == DW_TAG_class_type) { |
| 3291 | char* ns_name = NULL; |
| 3292 | if (dwarf_diename(current_die, &ns_name, &error) == DW_DLV_OK) { |
| 3293 | if (ns_name) { |
| 3294 | ns.push_back(std::string(ns_name)); |
| 3295 | } |
| 3296 | else { |
| 3297 | ns.push_back("<unknown>"); |
| 3298 | } |
| 3299 | dwarf_dealloc(dwarf, ns_name, DW_DLA_STRING); |
| 3300 | } |
| 3301 | else { |
| 3302 | ns.push_back("<unknown>"); |
| 3303 | } |
| 3304 | has_namespace = true; |
| 3305 | } |
| 3306 | } |
| 3307 | |
| 3308 | bool declaration = false; |
| 3309 | Dwarf_Attribute attr_mem; |
| 3310 | if (tag != DW_TAG_class_type && |
| 3311 | dwarf_attr(current_die, DW_AT_declaration, &attr_mem, &error) == DW_DLV_OK) { |
| 3312 | Dwarf_Bool flag = 0; |
| 3313 | if (dwarf_formflag(attr_mem, &flag, &error) == DW_DLV_OK) { |
| 3314 | declaration = flag != 0; |
| 3315 | } |
| 3316 | dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); |
| 3317 | } |
| 3318 | |
| 3319 | if (!declaration) { |
| 3320 | // let's be curious and look deeper in the tree, function are |
| 3321 | // not necessarily at the first level, but might be nested |
| 3322 | // inside a namespace, structure, a function, an inlined |
| 3323 | // function etc. |
| 3324 | branch_has_pc = deep_first_search_by_pc(fobj, current_die, pc, ns, cb); |
| 3325 | } |
no test coverage detected