(entries, func_ranges, code_section_offset, options)
| 498 | |
| 499 | |
| 500 | def build_sourcemap(entries, func_ranges, code_section_offset, options): |
| 501 | base_path = options.basepath |
| 502 | collect_sources = options.sources |
| 503 | prefixes = SourceMapPrefixes(options.prefix, options.load_prefix, base_path) |
| 504 | |
| 505 | # Add code section offset to the low/high pc in the function PC ranges |
| 506 | for func_range in func_ranges: |
| 507 | func_range.low_pc += code_section_offset |
| 508 | func_range.high_pc += code_section_offset |
| 509 | |
| 510 | sources = [] |
| 511 | sources_content = [] |
| 512 | # There can be duplicate names in case an original source function has |
| 513 | # multiple disjoint PC ranges or is inlined to multiple callsites. Make the |
| 514 | # 'names' list a unique list of names, and map the function ranges to the |
| 515 | # indices in that list. |
| 516 | names = sorted({item.name for item in func_ranges}) |
| 517 | name_to_id = {name: i for i, name in enumerate(names)} |
| 518 | mappings = [] |
| 519 | sources_map = {} |
| 520 | last_address = 0 |
| 521 | last_source_id = 0 |
| 522 | last_line = 1 |
| 523 | last_column = 1 |
| 524 | last_func_id = 0 |
| 525 | |
| 526 | active_funcs = [] |
| 527 | next_func_range_id = 0 |
| 528 | |
| 529 | # Get the function name ID that the given address falls into |
| 530 | def get_function_id(address): |
| 531 | nonlocal active_funcs |
| 532 | nonlocal next_func_range_id |
| 533 | |
| 534 | # Maintain a list of "active functions" whose ranges currently cover the |
| 535 | # address. As the address advances, it adds new functions that start and |
| 536 | # removes functions that end. The last function remaining in the active list |
| 537 | # at any point is the innermost function. |
| 538 | while next_func_range_id < len(func_ranges) and func_ranges[next_func_range_id].low_pc <= address: |
| 539 | # active_funcs contains (high_pc, id) pair |
| 540 | active_funcs.append((func_ranges[next_func_range_id].high_pc, next_func_range_id)) |
| 541 | next_func_range_id += 1 |
| 542 | active_funcs = [f for f in active_funcs if f[0] > address] |
| 543 | |
| 544 | if active_funcs: |
| 545 | func_range_id = active_funcs[-1][1] |
| 546 | name = func_ranges[func_range_id].name |
| 547 | return name_to_id[name] |
| 548 | return None |
| 549 | |
| 550 | for entry in entries: |
| 551 | line = entry['line'] |
| 552 | column = entry['column'] |
| 553 | # ignore entries with line 0 |
| 554 | if line == 0: |
| 555 | continue |
| 556 | # start at least at column 1 |
| 557 | if column == 0: |
no test coverage detected