| ... | ... | @@ -247,8 +247,7 @@ pub fn writeCurrentStackTraceWindows( |
| 247 | 247 | start_addr: ?usize, |
| 248 | 248 | ) !void { |
| 249 | 249 | var addr_buf: [1024]usize = undefined; |
| 250 | | const casted_len = @intCast(u32, addr_buf.len); // TODO shouldn't need this cast |
| 251 | | const n = windows.RtlCaptureStackBackTrace(0, casted_len, @ptrCast(**c_void, &addr_buf), null); |
| 250 | const n = windows.RtlCaptureStackBackTrace(0, addr_buf.len, @ptrCast(**c_void, &addr_buf), null); |
| 252 | 251 | const addrs = addr_buf[0..n]; |
| 253 | 252 | var start_i: usize = if (start_addr) |saddr| blk: { |
| 254 | 253 | for (addrs) |addr, i| { |
| ... | ... | @@ -338,50 +337,74 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 338 | 337 | |
| 339 | 338 | switch (subsect_hdr.Kind) { |
| 340 | 339 | pdb.DebugSubsectionKind.Lines => { |
| 341 | | var line_index: usize = sect_offset; |
| 340 | var line_index = sect_offset; |
| 342 | 341 | |
| 343 | 342 | const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]); |
| 344 | 343 | if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo; |
| 345 | 344 | line_index += @sizeOf(pdb.LineFragmentHeader); |
| 346 | | |
| 347 | | const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]); |
| 348 | | line_index += @sizeOf(pdb.LineBlockFragmentHeader); |
| 349 | | |
| 350 | | const has_column = line_hdr.Flags.LF_HaveColumns; |
| 351 | | |
| 352 | 345 | const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset; |
| 353 | 346 | const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize; |
| 354 | | if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) { |
| 355 | | var line_i: usize = 0; |
| 347 | |
| 348 | // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records) |
| 349 | // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in, |
| 350 | // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection. |
| 351 | const subsection_end_index = sect_offset + subsect_hdr.Length; |
| 352 | while (line_index < subsection_end_index) { |
| 353 | const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]); |
| 354 | line_index += @sizeOf(pdb.LineBlockFragmentHeader); |
| 356 | 355 | const start_line_index = line_index; |
| 357 | | while (line_i < block_hdr.NumLines) : (line_i += 1) { |
| 358 | | const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]); |
| 359 | | line_index += @sizeOf(pdb.LineNumberEntry); |
| 360 | | const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags); |
| 361 | | const vaddr_start = frag_vaddr_start + line_num_entry.Offset; |
| 362 | | const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End; |
| 363 | | if (relative_address >= vaddr_start and relative_address < vaddr_end) { |
| 356 | |
| 357 | const has_column = line_hdr.Flags.LF_HaveColumns; |
| 358 | |
| 359 | if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) { |
| 360 | // All line entries are stored inside their line block by ascending start address. |
| 361 | // Heuristic: we want to find the last line entry that has a vaddr_start <= relative_address. |
| 362 | // This is done with a simple linear search. |
| 363 | var line_i: u32 = 0; |
| 364 | while (line_i < block_hdr.NumLines) : (line_i += 1) { |
| 365 | const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]); |
| 366 | line_index += @sizeOf(pdb.LineNumberEntry); |
| 367 | |
| 368 | const vaddr_start = frag_vaddr_start + line_num_entry.Offset; |
| 369 | if (relative_address <= vaddr_start) { |
| 370 | break; |
| 371 | } |
| 372 | } |
| 373 | |
| 374 | // line_i == 0 would mean that no matching LineNumberEntry was found. |
| 375 | if (line_i > 0) { |
| 364 | 376 | const subsect_index = checksum_offset + block_hdr.NameIndex; |
| 365 | 377 | const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]); |
| 366 | 378 | const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset; |
| 367 | 379 | try di.pdb.string_table.seekTo(strtab_offset); |
| 368 | 380 | const source_file_name = try di.pdb.string_table.readNullTermString(allocator); |
| 369 | | const line = flags.Start; |
| 381 | |
| 382 | const line_entry_idx = line_i - 1; |
| 383 | |
| 370 | 384 | const column = if (has_column) blk: { |
| 371 | | line_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines; |
| 372 | | line_index += @sizeOf(pdb.ColumnNumberEntry) * line_i; |
| 373 | | const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[line_index]); |
| 385 | const start_col_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines; |
| 386 | const col_index = start_col_index + @sizeOf(pdb.ColumnNumberEntry) * line_entry_idx; |
| 387 | const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[col_index]); |
| 374 | 388 | break :blk col_num_entry.StartColumn; |
| 375 | 389 | } else 0; |
| 390 | |
| 391 | const found_line_index = start_line_index + line_entry_idx * @sizeOf(pdb.LineNumberEntry); |
| 392 | const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[found_line_index]); |
| 393 | const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags); |
| 394 | |
| 376 | 395 | break :subsections LineInfo{ |
| 377 | 396 | .allocator = allocator, |
| 378 | 397 | .file_name = source_file_name, |
| 379 | | .line = line, |
| 398 | .line = flags.Start, |
| 380 | 399 | .column = column, |
| 381 | 400 | }; |
| 382 | 401 | } |
| 383 | 402 | } |
| 384 | | break :subsections null; |
| 403 | } |
| 404 | |
| 405 | // Checking that we are not reading garbage after the (possibly) multiple block fragments. |
| 406 | if (line_index != subsection_end_index) { |
| 407 | return error.InvalidDebugInfo; |
| 385 | 408 | } |
| 386 | 409 | }, |
| 387 | 410 | else => {}, |