Function getLineNumberInfo [src]

Prototype

pub fn getLineNumberInfo(self: *Pdb, module: *Module, address: u64) !std.debug.SourceLocation

Parameters

self: *Pdbmodule: *Moduleaddress: u64

Source

pub fn getLineNumberInfo(self: *Pdb, module: *Module, address: u64) !std.debug.SourceLocation { std.debug.assert(module.populated); const subsect_info = module.subsect_info; var sect_offset: usize = 0; var skip_len: usize = undefined; const checksum_offset = module.checksum_offset orelse return error.MissingDebugInfo; while (sect_offset != subsect_info.len) : (sect_offset += skip_len) { const subsect_hdr: *align(1) pdb.DebugSubsectionHeader = @ptrCast(&subsect_info[sect_offset]); skip_len = subsect_hdr.length; sect_offset += @sizeOf(pdb.DebugSubsectionHeader); switch (subsect_hdr.kind) { .lines => { var line_index = sect_offset; const line_hdr: *align(1) pdb.LineFragmentHeader = @ptrCast(&subsect_info[line_index]); if (line_hdr.reloc_segment == 0) return error.MissingDebugInfo; line_index += @sizeOf(pdb.LineFragmentHeader); const frag_vaddr_start = line_hdr.reloc_offset; const frag_vaddr_end = frag_vaddr_start + line_hdr.code_size; if (address >= frag_vaddr_start and address < frag_vaddr_end) { // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records) // from now on. We will iterate through them, and eventually find a SourceLocation that we're interested in, // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection. const subsection_end_index = sect_offset + subsect_hdr.length; while (line_index < subsection_end_index) { const block_hdr: *align(1) pdb.LineBlockFragmentHeader = @ptrCast(&subsect_info[line_index]); line_index += @sizeOf(pdb.LineBlockFragmentHeader); const start_line_index = line_index; const has_column = line_hdr.flags.have_columns; // All line entries are stored inside their line block by ascending start address. // Heuristic: we want to find the last line entry // that has a vaddr_start <= address. // This is done with a simple linear search. var line_i: u32 = 0; while (line_i < block_hdr.num_lines) : (line_i += 1) { const line_num_entry: *align(1) pdb.LineNumberEntry = @ptrCast(&subsect_info[line_index]); line_index += @sizeOf(pdb.LineNumberEntry); const vaddr_start = frag_vaddr_start + line_num_entry.offset; if (address < vaddr_start) { break; } } // line_i == 0 would mean that no matching pdb.LineNumberEntry was found. if (line_i > 0) { const subsect_index = checksum_offset + block_hdr.name_index; const chksum_hdr: *align(1) pdb.FileChecksumEntryHeader = @ptrCast(&module.subsect_info[subsect_index]); const strtab_offset = @sizeOf(pdb.StringTableHeader) + chksum_hdr.file_name_offset; try self.string_table.?.seekTo(strtab_offset); const source_file_name = try self.string_table.?.reader().readUntilDelimiterAlloc(self.allocator, 0, 1024); const line_entry_idx = line_i - 1; const column = if (has_column) blk: { const start_col_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.num_lines; const col_index = start_col_index + @sizeOf(pdb.ColumnNumberEntry) * line_entry_idx; const col_num_entry: *align(1) pdb.ColumnNumberEntry = @ptrCast(&subsect_info[col_index]); break :blk col_num_entry.start_column; } else 0; const found_line_index = start_line_index + line_entry_idx * @sizeOf(pdb.LineNumberEntry); const line_num_entry: *align(1) pdb.LineNumberEntry = @ptrCast(&subsect_info[found_line_index]); return .{ .file_name = source_file_name, .line = line_num_entry.flags.start, .column = column, }; } } // Checking that we are not reading garbage after the (possibly) multiple block fragments. if (line_index != subsection_end_index) { return error.InvalidDebugInfo; } } }, else => {}, } if (sect_offset > subsect_info.len) return error.InvalidDebugInfo; } return error.MissingDebugInfo; }