Commit 72dca05f5c

LemonBoy <thatlemon@gmail.com>
2020-04-10 10:08:48
debug: Fix parsing of DWARF info for BE machines
Tested with ppc32
1 parent 1b1cbd9
Changed files (1)
lib
lib/std/dwarf.zig
@@ -236,11 +236,11 @@ const LineNumberProgram = struct {
     }
 };
 
-fn readInitialLength(in_stream: var, is_64: *bool) !u64 {
-    const first_32_bits = try in_stream.readIntLittle(u32);
+fn readUnitLength(in_stream: var, endian: builtin.Endian, is_64: *bool) !u64 {
+    const first_32_bits = try in_stream.readInt(u32, endian);
     is_64.* = (first_32_bits == 0xffffffff);
     if (is_64.*) {
-        return in_stream.readIntLittle(u64);
+        return in_stream.readInt(u64, endian);
     } else {
         if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
         // TODO this cast should not be needed
@@ -256,28 +256,36 @@ fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8
     return buf;
 }
 
+// TODO the noasyncs here are workarounds
+fn readAddress(in_stream: var, endian: builtin.Endian, is_64: bool) !u64 {
+    return noasync if (is_64)
+        try in_stream.readInt(u64, endian)
+    else
+        @as(u64, try in_stream.readInt(u32, endian));
+}
+
 fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
     const buf = try readAllocBytes(allocator, in_stream, size);
     return FormValue{ .Block = buf };
 }
 
 // TODO the noasyncs here are workarounds
-fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
-    const block_len = try noasync in_stream.readVarInt(usize, builtin.Endian.Little, size);
+fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: usize) !FormValue {
+    const block_len = try noasync in_stream.readVarInt(usize, endian, size);
     return parseFormValueBlockLen(allocator, in_stream, block_len);
 }
 
-fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, comptime size: i32) !FormValue {
+fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, endian: builtin.Endian, comptime size: i32) !FormValue {
     // TODO: Please forgive me, I've worked around zig not properly spilling some intermediate values here.
     // `noasync` should be removed from all the function calls once it is fixed.
     return FormValue{
         .Const = Constant{
             .signed = signed,
             .payload = switch (size) {
-                1 => try noasync in_stream.readIntLittle(u8),
-                2 => try noasync in_stream.readIntLittle(u16),
-                4 => try noasync in_stream.readIntLittle(u32),
-                8 => try noasync in_stream.readIntLittle(u64),
+                1 => try noasync in_stream.readInt(u8, endian),
+                2 => try noasync in_stream.readInt(u16, endian),
+                4 => try noasync in_stream.readInt(u32, endian),
+                8 => try noasync in_stream.readInt(u64, endian),
                 -1 => blk: {
                     if (signed) {
                         const x = try noasync leb.readILEB128(i64, in_stream);
@@ -294,30 +302,13 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
 }
 
 // TODO the noasyncs here are workarounds
-fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
-    return if (is_64) try noasync in_stream.readIntLittle(u64) else @as(u64, try noasync in_stream.readIntLittle(u32));
-}
-
-// TODO the noasyncs here are workarounds
-fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
-    if (@sizeOf(usize) == 4) {
-        // TODO this cast should not be needed
-        return @as(u64, try noasync in_stream.readIntLittle(u32));
-    } else if (@sizeOf(usize) == 8) {
-        return noasync in_stream.readIntLittle(u64);
-    } else {
-        unreachable;
-    }
-}
-
-// TODO the noasyncs here are workarounds
-fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue {
+fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: i32) !FormValue {
     return FormValue{
         .Ref = switch (size) {
-            1 => try noasync in_stream.readIntLittle(u8),
-            2 => try noasync in_stream.readIntLittle(u16),
-            4 => try noasync in_stream.readIntLittle(u32),
-            8 => try noasync in_stream.readIntLittle(u64),
+            1 => try noasync in_stream.readInt(u8, endian),
+            2 => try noasync in_stream.readInt(u16, endian),
+            4 => try noasync in_stream.readInt(u32, endian),
+            8 => try noasync in_stream.readInt(u64, endian),
             -1 => try noasync leb.readULEB128(u64, in_stream),
             else => unreachable,
         },
@@ -325,23 +316,23 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !Form
 }
 
 // TODO the noasyncs here are workarounds
-fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {
+fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, endian: builtin.Endian, is_64: bool) anyerror!FormValue {
     return switch (form_id) {
-        FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
-        FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
-        FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
-        FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
+        FORM_addr => FormValue{ .Address = try readAddress(in_stream, endian, @sizeOf(usize) == 8) },
+        FORM_block1 => parseFormValueBlock(allocator, in_stream, endian, 1),
+        FORM_block2 => parseFormValueBlock(allocator, in_stream, endian, 2),
+        FORM_block4 => parseFormValueBlock(allocator, in_stream, endian, 4),
         FORM_block => x: {
             const block_len = try noasync leb.readULEB128(usize, in_stream);
             return parseFormValueBlockLen(allocator, in_stream, block_len);
         },
-        FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1),
-        FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2),
-        FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),
-        FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),
+        FORM_data1 => parseFormValueConstant(allocator, in_stream, false, endian, 1),
+        FORM_data2 => parseFormValueConstant(allocator, in_stream, false, endian, 2),
+        FORM_data4 => parseFormValueConstant(allocator, in_stream, false, endian, 4),
+        FORM_data8 => parseFormValueConstant(allocator, in_stream, false, endian, 8),
         FORM_udata, FORM_sdata => {
             const signed = form_id == FORM_sdata;
-            return parseFormValueConstant(allocator, in_stream, signed, -1);
+            return parseFormValueConstant(allocator, in_stream, signed, endian, -1);
         },
         FORM_exprloc => {
             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
         },
         FORM_flag => FormValue{ .Flag = (try noasync in_stream.readByte()) != 0 },
         FORM_flag_present => FormValue{ .Flag = true },
-        FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
+        FORM_sec_offset => FormValue{ .SecOffset = try readAddress(in_stream, endian, is_64) },
 
-        FORM_ref1 => parseFormValueRef(allocator, in_stream, 1),
-        FORM_ref2 => parseFormValueRef(allocator, in_stream, 2),
-        FORM_ref4 => parseFormValueRef(allocator, in_stream, 4),
-        FORM_ref8 => parseFormValueRef(allocator, in_stream, 8),
-        FORM_ref_udata => parseFormValueRef(allocator, in_stream, -1),
+        FORM_ref1 => parseFormValueRef(allocator, in_stream, endian, 1),
+        FORM_ref2 => parseFormValueRef(allocator, in_stream, endian, 2),
+        FORM_ref4 => parseFormValueRef(allocator, in_stream, endian, 4),
+        FORM_ref8 => parseFormValueRef(allocator, in_stream, endian, 8),
+        FORM_ref_udata => parseFormValueRef(allocator, in_stream, endian, -1),
 
-        FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
-        FORM_ref_sig8 => FormValue{ .Ref = try noasync in_stream.readIntLittle(u64) },
+        FORM_ref_addr => FormValue{ .RefAddr = try readAddress(in_stream, endian, is_64) },
+        FORM_ref_sig8 => FormValue{ .Ref = try noasync in_stream.readInt(u64, endian) },
 
         FORM_string => FormValue{ .String = try in_stream.readUntilDelimiterAlloc(allocator, 0, math.maxInt(usize)) },
-        FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
+        FORM_strp => FormValue{ .StrPtr = try readAddress(in_stream, endian, is_64) },
         FORM_indirect => {
             const child_form_id = try noasync leb.readULEB128(u64, in_stream);
-            const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, is_64));
+            const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, endian, is_64));
             var frame = try allocator.create(F);
             defer allocator.destroy(frame);
-            return await @asyncCall(frame, {}, parseFormValue, allocator, in_stream, child_form_id, is_64);
+            return await @asyncCall(frame, {}, parseFormValue, allocator, in_stream, child_form_id, endian, is_64);
         },
         else => error.InvalidDebugInfo,
     };
@@ -423,7 +414,7 @@ pub const DwarfInfo = struct {
             };
 
             var is_64: bool = undefined;
-            const unit_length = try readInitialLength(in, &is_64);
+            const unit_length = try readUnitLength(in, di.endian, &is_64);
             if (unit_length == 0) return;
             const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
 
@@ -530,7 +521,7 @@ pub const DwarfInfo = struct {
             };
 
             var is_64: bool = undefined;
-            const unit_length = try readInitialLength(in, &is_64);
+            const unit_length = try readUnitLength(in, di.endian, &is_64);
             if (unit_length == 0) return;
             const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
 
@@ -610,8 +601,8 @@ pub const DwarfInfo = struct {
                     try seekable.seekTo(ranges_offset);
 
                     while (true) {
-                        const begin_addr = try in.readIntLittle(usize);
-                        const end_addr = try in.readIntLittle(usize);
+                        const begin_addr = try in.readInt(usize, di.endian);
+                        const end_addr = try in.readInt(usize, di.endian);
                         if (begin_addr == 0 and end_addr == 0) {
                             break;
                         }
@@ -693,7 +684,7 @@ pub const DwarfInfo = struct {
         for (table_entry.attrs.span()) |attr, i| {
             result.attrs.items[i] = Die.Attr{
                 .id = attr.attr_id,
-                .value = try parseFormValue(di.allocator(), in_stream, attr.form_id, is_64),
+                .value = try parseFormValue(di.allocator(), in_stream, attr.form_id, di.endian, is_64),
             };
         }
         return result;
@@ -710,7 +701,7 @@ pub const DwarfInfo = struct {
         try seekable.seekTo(line_info_offset);
 
         var is_64: bool = undefined;
-        const unit_length = try readInitialLength(in, &is_64);
+        const unit_length = try readUnitLength(in, di.endian, &is_64);
         if (unit_length == 0) {
             return error.MissingDebugInfo;
         }