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 {
236236 }
237237};
238238
239fn readInitialLength(in_stream: var, is_64: *bool) !u64 {
240 const first_32_bits = try in_stream.readIntLittle(u32);
239fn readUnitLength(in_stream: var, endian: builtin.Endian, is_64: *bool) !u64 {
240 const first_32_bits = try in_stream.readInt(u32, endian);
241241 is_64.* = (first_32_bits == 0xffffffff);
242242 if (is_64.*) {
243 return in_stream.readIntLittle(u64);
243 return in_stream.readInt(u64, endian);
244244 } else {
245245 if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
246246 // TODO this cast should not be needed
......@@ -256,28 +256,36 @@ fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8
256256 return buf;
257257}
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
259267fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
260268 const buf = try readAllocBytes(allocator, in_stream, size);
261269 return FormValue{ .Block = buf };
262270}
263271
264272// TODO the noasyncs here are workarounds
265fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
266 const block_len = try noasync in_stream.readVarInt(usize, builtin.Endian.Little, size);
273fn 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);
267275 return parseFormValueBlockLen(allocator, in_stream, block_len);
268276}
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 {
271279 // TODO: Please forgive me, I've worked around zig not properly spilling some intermediate values here.
272280 // `noasync` should be removed from all the function calls once it is fixed.
273281 return FormValue{
274282 .Const = Constant{
275283 .signed = signed,
276284 .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),
281289 -1 => blk: {
282290 if (signed) {
283291 const x = try noasync leb.readILEB128(i64, in_stream);
......@@ -294,30 +302,13 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
294302}
295303
296304// TODO the noasyncs here are workarounds
297fn 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
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 {
305fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: i32) !FormValue {
315306 return FormValue{
316307 .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),
321312 -1 => try noasync leb.readULEB128(u64, in_stream),
322313 else => unreachable,
323314 },
......@@ -325,23 +316,23 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !Form
325316}
326317
327318// 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 {
329320 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),
334325 FORM_block => x: {
335326 const block_len = try noasync leb.readULEB128(usize, in_stream);
336327 return parseFormValueBlockLen(allocator, in_stream, block_len);
337328 },
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),
342333 FORM_udata, FORM_sdata => {
343334 const signed = form_id == FORM_sdata;
344 return parseFormValueConstant(allocator, in_stream, signed, -1);
335 return parseFormValueConstant(allocator, in_stream, signed, endian, -1);
345336 },
346337 FORM_exprloc => {
347338 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
350341 },
351342 FORM_flag => FormValue{ .Flag = (try noasync in_stream.readByte()) != 0 },
352343 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),
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),
360351
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) },
363354
364355 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) },
366357 FORM_indirect => {
367358 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));
369360 var frame = try allocator.create(F);
370361 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);
372363 },
373364 else => error.InvalidDebugInfo,
374365 };
......@@ -423,7 +414,7 @@ pub const DwarfInfo = struct {
423414 };
424415
425416 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);
427418 if (unit_length == 0) return;
428419 const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
429420
......@@ -530,7 +521,7 @@ pub const DwarfInfo = struct {
530521 };
531522
532523 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);
534525 if (unit_length == 0) return;
535526 const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
536527
......@@ -610,8 +601,8 @@ pub const DwarfInfo = struct {
610601 try seekable.seekTo(ranges_offset);
611602
612603 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);
615606 if (begin_addr == 0 and end_addr == 0) {
616607 break;
617608 }
......@@ -693,7 +684,7 @@ pub const DwarfInfo = struct {
693684 for (table_entry.attrs.span()) |attr, i| {
694685 result.attrs.items[i] = Die.Attr{
695686 .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),
697688 };
698689 }
699690 return result;
......@@ -710,7 +701,7 @@ pub const DwarfInfo = struct {
710701 try seekable.seekTo(line_info_offset);
711702
712703 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);
714705 if (unit_length == 0) {
715706 return error.MissingDebugInfo;
716707 }