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