| ... | ... | @@ -236,11 +236,11 @@ const LineNumberProgram = struct { |
| 236 | 236 | } |
| 237 | 237 | }; |
| 238 | 238 | |
| 239 | | fn readInitialLength(in_stream: var, is_64: *bool) !u64 { |
| 240 | | const first_32_bits = try in_stream.readIntLittle(u32); |
| 239 | fn readUnitLength(in_stream: var, endian: builtin.Endian, is_64: *bool) !u64 { |
| 240 | const first_32_bits = try in_stream.readInt(u32, endian); |
| 241 | 241 | is_64.* = (first_32_bits == 0xffffffff); |
| 242 | 242 | if (is_64.*) { |
| 243 | | return in_stream.readIntLittle(u64); |
| 243 | return in_stream.readInt(u64, endian); |
| 244 | 244 | } else { |
| 245 | 245 | if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; |
| 246 | 246 | // TODO this cast should not be needed |
| ... | ... | @@ -256,28 +256,36 @@ fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 |
| 256 | 256 | return buf; |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | // TODO the noasyncs here are workarounds |
| 260 | fn readAddress(in_stream: var, endian: builtin.Endian, is_64: bool) !u64 { |
| 261 | return noasync if (is_64) |
| 262 | try in_stream.readInt(u64, endian) |
| 263 | else |
| 264 | @as(u64, try in_stream.readInt(u32, endian)); |
| 265 | } |
| 266 | |
| 259 | 267 | fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { |
| 260 | 268 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 261 | 269 | return FormValue{ .Block = buf }; |
| 262 | 270 | } |
| 263 | 271 | |
| 264 | 272 | // TODO the noasyncs here are workarounds |
| 265 | | fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { |
| 266 | | const block_len = try noasync in_stream.readVarInt(usize, builtin.Endian.Little, size); |
| 273 | fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: usize) !FormValue { |
| 274 | const block_len = try noasync in_stream.readVarInt(usize, endian, size); |
| 267 | 275 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 268 | 276 | } |
| 269 | 277 | |
| 270 | | fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, comptime size: i32) !FormValue { |
| 278 | fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, endian: builtin.Endian, comptime size: i32) !FormValue { |
| 271 | 279 | // TODO: Please forgive me, I've worked around zig not properly spilling some intermediate values here. |
| 272 | 280 | // `noasync` should be removed from all the function calls once it is fixed. |
| 273 | 281 | return FormValue{ |
| 274 | 282 | .Const = Constant{ |
| 275 | 283 | .signed = signed, |
| 276 | 284 | .payload = switch (size) { |
| 277 | | 1 => try noasync in_stream.readIntLittle(u8), |
| 278 | | 2 => try noasync in_stream.readIntLittle(u16), |
| 279 | | 4 => try noasync in_stream.readIntLittle(u32), |
| 280 | | 8 => try noasync in_stream.readIntLittle(u64), |
| 285 | 1 => try noasync in_stream.readInt(u8, endian), |
| 286 | 2 => try noasync in_stream.readInt(u16, endian), |
| 287 | 4 => try noasync in_stream.readInt(u32, endian), |
| 288 | 8 => try noasync in_stream.readInt(u64, endian), |
| 281 | 289 | -1 => blk: { |
| 282 | 290 | if (signed) { |
| 283 | 291 | const x = try noasync leb.readILEB128(i64, in_stream); |
| ... | ... | @@ -294,30 +302,13 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo |
| 294 | 302 | } |
| 295 | 303 | |
| 296 | 304 | // TODO the noasyncs here are workarounds |
| 297 | | fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 { |
| 298 | | return if (is_64) try noasync in_stream.readIntLittle(u64) else @as(u64, try noasync in_stream.readIntLittle(u32)); |
| 299 | | } |
| 300 | | |
| 301 | | // TODO the noasyncs here are workarounds |
| 302 | | fn parseFormValueTargetAddrSize(in_stream: var) !u64 { |
| 303 | | if (@sizeOf(usize) == 4) { |
| 304 | | // TODO this cast should not be needed |
| 305 | | return @as(u64, try noasync in_stream.readIntLittle(u32)); |
| 306 | | } else if (@sizeOf(usize) == 8) { |
| 307 | | return noasync in_stream.readIntLittle(u64); |
| 308 | | } else { |
| 309 | | unreachable; |
| 310 | | } |
| 311 | | } |
| 312 | | |
| 313 | | // TODO the noasyncs here are workarounds |
| 314 | | fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue { |
| 305 | fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: i32) !FormValue { |
| 315 | 306 | return FormValue{ |
| 316 | 307 | .Ref = switch (size) { |
| 317 | | 1 => try noasync in_stream.readIntLittle(u8), |
| 318 | | 2 => try noasync in_stream.readIntLittle(u16), |
| 319 | | 4 => try noasync in_stream.readIntLittle(u32), |
| 320 | | 8 => try noasync in_stream.readIntLittle(u64), |
| 308 | 1 => try noasync in_stream.readInt(u8, endian), |
| 309 | 2 => try noasync in_stream.readInt(u16, endian), |
| 310 | 4 => try noasync in_stream.readInt(u32, endian), |
| 311 | 8 => try noasync in_stream.readInt(u64, endian), |
| 321 | 312 | -1 => try noasync leb.readULEB128(u64, in_stream), |
| 322 | 313 | else => unreachable, |
| 323 | 314 | }, |
| ... | ... | @@ -325,23 +316,23 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !Form |
| 325 | 316 | } |
| 326 | 317 | |
| 327 | 318 | // TODO the noasyncs here are workarounds |
| 328 | | fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue { |
| 319 | fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, endian: builtin.Endian, is_64: bool) anyerror!FormValue { |
| 329 | 320 | return switch (form_id) { |
| 330 | | FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, |
| 331 | | FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), |
| 332 | | FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), |
| 333 | | FORM_block4 => parseFormValueBlock(allocator, in_stream, 4), |
| 321 | FORM_addr => FormValue{ .Address = try readAddress(in_stream, endian, @sizeOf(usize) == 8) }, |
| 322 | FORM_block1 => parseFormValueBlock(allocator, in_stream, endian, 1), |
| 323 | FORM_block2 => parseFormValueBlock(allocator, in_stream, endian, 2), |
| 324 | FORM_block4 => parseFormValueBlock(allocator, in_stream, endian, 4), |
| 334 | 325 | FORM_block => x: { |
| 335 | 326 | const block_len = try noasync leb.readULEB128(usize, in_stream); |
| 336 | 327 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 337 | 328 | }, |
| 338 | | FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1), |
| 339 | | FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2), |
| 340 | | FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4), |
| 341 | | FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8), |
| 329 | FORM_data1 => parseFormValueConstant(allocator, in_stream, false, endian, 1), |
| 330 | FORM_data2 => parseFormValueConstant(allocator, in_stream, false, endian, 2), |
| 331 | FORM_data4 => parseFormValueConstant(allocator, in_stream, false, endian, 4), |
| 332 | FORM_data8 => parseFormValueConstant(allocator, in_stream, false, endian, 8), |
| 342 | 333 | FORM_udata, FORM_sdata => { |
| 343 | 334 | const signed = form_id == FORM_sdata; |
| 344 | | return parseFormValueConstant(allocator, in_stream, signed, -1); |
| 335 | return parseFormValueConstant(allocator, in_stream, signed, endian, -1); |
| 345 | 336 | }, |
| 346 | 337 | FORM_exprloc => { |
| 347 | 338 | const size = try noasync leb.readULEB128(usize, in_stream); |
| ... | ... | @@ -350,25 +341,25 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 350 | 341 | }, |
| 351 | 342 | FORM_flag => FormValue{ .Flag = (try noasync in_stream.readByte()) != 0 }, |
| 352 | 343 | FORM_flag_present => FormValue{ .Flag = true }, |
| 353 | | FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 344 | FORM_sec_offset => FormValue{ .SecOffset = try readAddress(in_stream, endian, is_64) }, |
| 354 | 345 | |
| 355 | | FORM_ref1 => parseFormValueRef(allocator, in_stream, 1), |
| 356 | | FORM_ref2 => parseFormValueRef(allocator, in_stream, 2), |
| 357 | | FORM_ref4 => parseFormValueRef(allocator, in_stream, 4), |
| 358 | | FORM_ref8 => parseFormValueRef(allocator, in_stream, 8), |
| 359 | | FORM_ref_udata => parseFormValueRef(allocator, in_stream, -1), |
| 346 | FORM_ref1 => parseFormValueRef(allocator, in_stream, endian, 1), |
| 347 | FORM_ref2 => parseFormValueRef(allocator, in_stream, endian, 2), |
| 348 | FORM_ref4 => parseFormValueRef(allocator, in_stream, endian, 4), |
| 349 | FORM_ref8 => parseFormValueRef(allocator, in_stream, endian, 8), |
| 350 | FORM_ref_udata => parseFormValueRef(allocator, in_stream, endian, -1), |
| 360 | 351 | |
| 361 | | FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 362 | | FORM_ref_sig8 => FormValue{ .Ref = try noasync in_stream.readIntLittle(u64) }, |
| 352 | FORM_ref_addr => FormValue{ .RefAddr = try readAddress(in_stream, endian, is_64) }, |
| 353 | FORM_ref_sig8 => FormValue{ .Ref = try noasync in_stream.readInt(u64, endian) }, |
| 363 | 354 | |
| 364 | 355 | FORM_string => FormValue{ .String = try in_stream.readUntilDelimiterAlloc(allocator, 0, math.maxInt(usize)) }, |
| 365 | | FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 356 | FORM_strp => FormValue{ .StrPtr = try readAddress(in_stream, endian, is_64) }, |
| 366 | 357 | FORM_indirect => { |
| 367 | 358 | const child_form_id = try noasync leb.readULEB128(u64, in_stream); |
| 368 | | const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, is_64)); |
| 359 | const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, endian, is_64)); |
| 369 | 360 | var frame = try allocator.create(F); |
| 370 | 361 | defer allocator.destroy(frame); |
| 371 | | return await @asyncCall(frame, {}, parseFormValue, allocator, in_stream, child_form_id, is_64); |
| 362 | return await @asyncCall(frame, {}, parseFormValue, allocator, in_stream, child_form_id, endian, is_64); |
| 372 | 363 | }, |
| 373 | 364 | else => error.InvalidDebugInfo, |
| 374 | 365 | }; |
| ... | ... | @@ -423,7 +414,7 @@ pub const DwarfInfo = struct { |
| 423 | 414 | }; |
| 424 | 415 | |
| 425 | 416 | var is_64: bool = undefined; |
| 426 | | const unit_length = try readInitialLength(in, &is_64); |
| 417 | const unit_length = try readUnitLength(in, di.endian, &is_64); |
| 427 | 418 | if (unit_length == 0) return; |
| 428 | 419 | const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4)); |
| 429 | 420 | |
| ... | ... | @@ -530,7 +521,7 @@ pub const DwarfInfo = struct { |
| 530 | 521 | }; |
| 531 | 522 | |
| 532 | 523 | var is_64: bool = undefined; |
| 533 | | const unit_length = try readInitialLength(in, &is_64); |
| 524 | const unit_length = try readUnitLength(in, di.endian, &is_64); |
| 534 | 525 | if (unit_length == 0) return; |
| 535 | 526 | const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4)); |
| 536 | 527 | |
| ... | ... | @@ -610,8 +601,8 @@ pub const DwarfInfo = struct { |
| 610 | 601 | try seekable.seekTo(ranges_offset); |
| 611 | 602 | |
| 612 | 603 | while (true) { |
| 613 | | const begin_addr = try in.readIntLittle(usize); |
| 614 | | const end_addr = try in.readIntLittle(usize); |
| 604 | const begin_addr = try in.readInt(usize, di.endian); |
| 605 | const end_addr = try in.readInt(usize, di.endian); |
| 615 | 606 | if (begin_addr == 0 and end_addr == 0) { |
| 616 | 607 | break; |
| 617 | 608 | } |
| ... | ... | @@ -693,7 +684,7 @@ pub const DwarfInfo = struct { |
| 693 | 684 | for (table_entry.attrs.span()) |attr, i| { |
| 694 | 685 | result.attrs.items[i] = Die.Attr{ |
| 695 | 686 | .id = attr.attr_id, |
| 696 | | .value = try parseFormValue(di.allocator(), in_stream, attr.form_id, is_64), |
| 687 | .value = try parseFormValue(di.allocator(), in_stream, attr.form_id, di.endian, is_64), |
| 697 | 688 | }; |
| 698 | 689 | } |
| 699 | 690 | return result; |
| ... | ... | @@ -710,7 +701,7 @@ pub const DwarfInfo = struct { |
| 710 | 701 | try seekable.seekTo(line_info_offset); |
| 711 | 702 | |
| 712 | 703 | var is_64: bool = undefined; |
| 713 | | const unit_length = try readInitialLength(in, &is_64); |
| 704 | const unit_length = try readUnitLength(in, di.endian, &is_64); |
| 714 | 705 | if (unit_length == 0) { |
| 715 | 706 | return error.MissingDebugInfo; |
| 716 | 707 | } |