(text)
| 283 | # each function in a list of FuncRanges. The result list will be sorted in the |
| 284 | # increasing order of low_pcs. |
| 285 | def extract_func_ranges(text): |
| 286 | # This function handles four cases: |
| 287 | # 1. DW_TAG_subprogram with DW_AT_name, DW_AT_low_pc, and DW_AT_high_pc. |
| 288 | # 0x000000ba: DW_TAG_subprogram |
| 289 | # DW_AT_low_pc (0x0000005f) |
| 290 | # DW_AT_high_pc (0x00000071) |
| 291 | # DW_AT_name ("foo") |
| 292 | # ... |
| 293 | # |
| 294 | # 2. DW_TAG_subprogram with DW_AT_linkage_name, DW_AT_low_pc, and |
| 295 | # DW_AT_high_pc. Applies to mangled C++ functions. |
| 296 | # (We parse DW_AT_linkage_name instead of DW_AT_name here.) |
| 297 | # 0x000000ba: DW_TAG_subprogram |
| 298 | # DW_AT_low_pc (0x0000005f) |
| 299 | # DW_AT_high_pc (0x00000071) |
| 300 | # DW_AT_linkage_name ("_ZN7MyClass3fooEv") |
| 301 | # DW_AT_name ("foo") |
| 302 | # ... |
| 303 | # |
| 304 | # 3. DW_TAG_subprogram with DW_AT_specification, DW_AT_low_pc, and |
| 305 | # DW_AT_high_pc. C++ function info can be split into two DIEs (one with |
| 306 | # DW_AT_linkage_name and DW_AT_declaration (true) and the other with |
| 307 | # DW_AT_specification). In this case we parse DW_AT_specification for the |
| 308 | # function name. |
| 309 | # 0x0000006d: DW_TAG_subprogram |
| 310 | # DW_AT_linkage_name ("_ZN7MyClass3fooEv") |
| 311 | # DW_AT_name ("foo") |
| 312 | # DW_AT_declaration (true) |
| 313 | # ... |
| 314 | # 0x00000097: DW_TAG_subprogram |
| 315 | # DW_AT_low_pc (0x00000007) |
| 316 | # DW_AT_high_pc (0x0000004c) |
| 317 | # DW_AT_specification (0x0000006d "_ZN7MyClass3fooEv") |
| 318 | # ... |
| 319 | # |
| 320 | # 4. DW_TAG_inlined_subroutine with DW_AT_abstract_origin, DW_AT_low_pc, and |
| 321 | # DW_AT_high_pc. This represents an inlined function. We parse |
| 322 | # DW_AT_abstract_origin for the original function name. |
| 323 | # 0x0000011a: DW_TAG_inlined_subroutine |
| 324 | # DW_AT_abstract_origin (0x000000da "_ZN7MyClass3barEv") |
| 325 | # DW_AT_low_pc (0x00000078) |
| 326 | # DW_AT_high_pc (0x00000083) |
| 327 | # ... |
| 328 | |
| 329 | # Pattern to find the start of the NEXT DWARF tag (boundary marker) |
| 330 | next_tag_pattern = re.compile(r'\n0x[0-9a-f]+:') |
| 331 | # Pattern to find DWARF tags for functions (Subprogram or Inlined) directly |
| 332 | func_pattern = re.compile(r'DW_TAG_(?:subprogram|inlined_subroutine)') |
| 333 | |
| 334 | low_pc_pattern = re.compile(r'DW_AT_low_pc\s+\(0x([0-9a-f]+)\)') |
| 335 | high_pc_pattern = re.compile(r'DW_AT_high_pc\s+\(0x([0-9a-f]+)\)') |
| 336 | abstract_origin_pattern = re.compile(r'DW_AT_abstract_origin\s+\(0x[0-9a-f]+\s+"([^"]+)"\)') |
| 337 | linkage_name_pattern = re.compile(r'DW_AT_linkage_name\s+\("([^"]+)"\)') |
| 338 | name_pattern = re.compile(r'DW_AT_name\s+\("([^"]+)"\)') |
| 339 | specification_pattern = re.compile(r'DW_AT_specification\s+\(0x[0-9a-f]+\s+"([^"]+)"\)') |
| 340 | |
| 341 | def get_name_from_tag(start, end): |
| 342 | m = linkage_name_pattern.search(text, start, end) |
no test coverage detected