authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-04-10 10:08:48+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-10 14:59:19-04:00
log72dca05f5c60cbb492825f61b5308ff925ce9275
tree93d8ae95564cf590f051249d2f86d504ec795451
parent1b1cbd93587642ea281dadc6f8b5e33104f38320

debug: Fix parsing of DWARF info for BE machines

Tested with ppc32

1 files changed, 50 insertions(+), 59 deletions(-)

lib/std/dwarf.zig+50-59
...@@ -236,11 +236,11 @@ const LineNumberProgram = struct {...@@ -236,11 +236,11 @@ const LineNumberProgram = struct {
236 }236 }
237};237};
238238
239fn readInitialLength(in_stream: var, is_64: *bool) !u64 {239fn 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 needed246 // 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}
258258
259// TODO the noasyncs here are workarounds
260fn 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
259fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {267fn 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}
263271
264// TODO the noasyncs here are workarounds272// TODO the noasyncs here are workarounds
265fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {273fn 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}
269277
270fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, comptime size: i32) !FormValue {278fn 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}
295303
296// TODO the noasyncs here are workarounds304// TODO the noasyncs here are workarounds
297fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {305fn 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
302fn 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
314fn 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}
326317
327// TODO the noasyncs here are workarounds318// TODO the noasyncs here are workarounds
328fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {319fn 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) },
354345
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),
360351
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) },
363354
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 };
424415
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));
429420
...@@ -530,7 +521,7 @@ pub const DwarfInfo = struct {...@@ -530,7 +521,7 @@ pub const DwarfInfo = struct {
530 };521 };
531522
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));
536527
...@@ -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);
611602
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);
711702
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 }