| ... | @@ -1,25 +1,73 @@ | ... | @@ -1,25 +1,73 @@ |
| | 1 | debug_info: []u8 = &[0]u8{}, |
| | 2 | debug_abbrev: []u8 = &[0]u8{}, |
| | 3 | debug_str: []u8 = &[0]u8{}, |
| | 4 | debug_str_offsets: []u8 = &[0]u8{}, |
| | 5 | |
| | 6 | pub fn deinit(dwarf: *Dwarf, allocator: Allocator) void { |
| | 7 | allocator.free(dwarf.debug_info); |
| | 8 | allocator.free(dwarf.debug_abbrev); |
| | 9 | allocator.free(dwarf.debug_str); |
| | 10 | allocator.free(dwarf.debug_str_offsets); |
| | 11 | } |
| | 12 | |
| | 13 | /// Pulls an offset into __debug_str section from a __debug_str_offs section. |
| | 14 | /// This is new in DWARFv5 and requires the producer to specify DW_FORM_strx* (`index` arg) |
| | 15 | /// but also DW_AT_str_offsets_base with DW_FORM_sec_offset (`base` arg) in the opening header |
| | 16 | /// of a "referencing entity" such as DW_TAG_compile_unit. |
| | 17 | fn getOffset(debug_str_offsets: []const u8, base: u64, index: u64, dw_fmt: DwarfFormat) u64 { |
| | 18 | return switch (dw_fmt) { |
| | 19 | .dwarf32 => @as(*align(1) const u32, @ptrCast(debug_str_offsets.ptr + base + index * @sizeOf(u32))).*, |
| | 20 | .dwarf64 => @as(*align(1) const u64, @ptrCast(debug_str_offsets.ptr + base + index * @sizeOf(u64))).*, |
| | 21 | }; |
| | 22 | } |
| | 23 | |
| 1 | pub const InfoReader = struct { | 24 | pub const InfoReader = struct { |
| 2 | bytes: []const u8, | 25 | ctx: Dwarf, |
| 3 | strtab: []const u8, | | |
| 4 | pos: usize = 0, | 26 | pos: usize = 0, |
| 5 | | 27 | |
| 6 | pub fn readCompileUnitHeader(p: *InfoReader) !CompileUnitHeader { | 28 | fn bytes(p: InfoReader) []const u8 { |
| | 29 | return p.ctx.debug_info; |
| | 30 | } |
| | 31 | |
| | 32 | pub fn readCompileUnitHeader(p: *InfoReader, macho_file: *MachO) !CompileUnitHeader { |
| | 33 | _ = macho_file; |
| 7 | var length: u64 = try p.readInt(u32); | 34 | var length: u64 = try p.readInt(u32); |
| 8 | const is_64bit = length == 0xffffffff; | 35 | const is_64bit = length == 0xffffffff; |
| 9 | if (is_64bit) { | 36 | if (is_64bit) { |
| 10 | length = try p.readInt(u64); | 37 | length = try p.readInt(u64); |
| 11 | } | 38 | } |
| 12 | const dw_fmt: DwarfFormat = if (is_64bit) .dwarf64 else .dwarf32; | 39 | const dw_fmt: DwarfFormat = if (is_64bit) .dwarf64 else .dwarf32; |
| | 40 | const version = try p.readInt(Version); |
| | 41 | const rest: struct { |
| | 42 | debug_abbrev_offset: u64, |
| | 43 | address_size: u8, |
| | 44 | unit_type: u8, |
| | 45 | } = switch (version) { |
| | 46 | 4 => .{ |
| | 47 | .debug_abbrev_offset = try p.readOffset(dw_fmt), |
| | 48 | .address_size = try p.readByte(), |
| | 49 | .unit_type = 0, |
| | 50 | }, |
| | 51 | 5 => .{ |
| | 52 | // According to the spec, version 5 introduced .unit_type field in the header, and |
| | 53 | // it reordered .debug_abbrev_offset with .address_size fields. |
| | 54 | .unit_type = try p.readByte(), |
| | 55 | .address_size = try p.readByte(), |
| | 56 | .debug_abbrev_offset = try p.readOffset(dw_fmt), |
| | 57 | }, |
| | 58 | else => return error.InvalidVersion, |
| | 59 | }; |
| 13 | return .{ | 60 | return .{ |
| 14 | .format = dw_fmt, | 61 | .format = dw_fmt, |
| 15 | .length = length, | 62 | .length = length, |
| 16 | .version = try p.readInt(u16), | 63 | .version = version, |
| 17 | .debug_abbrev_offset = try p.readOffset(dw_fmt), | 64 | .debug_abbrev_offset = rest.debug_abbrev_offset, |
| 18 | .address_size = try p.readByte(), | 65 | .address_size = rest.address_size, |
| | 66 | .unit_type = rest.unit_type, |
| 19 | }; | 67 | }; |
| 20 | } | 68 | } |
| 21 | | 69 | |
| 22 | pub fn seekToDie(p: *InfoReader, code: Code, cuh: CompileUnitHeader, abbrev_reader: *AbbrevReader) !void { | 70 | pub fn seekToDie(p: *InfoReader, code: Code, cuh: CompileUnitHeader, abbrev_reader: *AbbrevReader, macho_file: *MachO) !void { |
| 23 | const cuh_length = math.cast(usize, cuh.length) orelse return error.Overflow; | 71 | const cuh_length = math.cast(usize, cuh.length) orelse return error.Overflow; |
| 24 | const end_pos = p.pos + switch (cuh.format) { | 72 | const end_pos = p.pos + switch (cuh.format) { |
| 25 | .dwarf32 => @as(usize, 4), | 73 | .dwarf32 => @as(usize, 4), |
| ... | @@ -27,72 +75,100 @@ pub const InfoReader = struct { | ... | @@ -27,72 +75,100 @@ pub const InfoReader = struct { |
| 27 | } + cuh_length; | 75 | } + cuh_length; |
| 28 | while (p.pos < end_pos) { | 76 | while (p.pos < end_pos) { |
| 29 | const di_code = try p.readUleb128(u64); | 77 | const di_code = try p.readUleb128(u64); |
| 30 | if (di_code == 0) return error.Eof; | 78 | if (di_code == 0) return error.UnexpectedEndOfFile; |
| 31 | if (di_code == code) return; | 79 | if (di_code == code) return; |
| 32 | | 80 | |
| 33 | while (try abbrev_reader.readAttr()) |attr| switch (attr.at) { | 81 | while (try abbrev_reader.readAttr()) |attr| { |
| 34 | dwarf.FORM.sec_offset, | 82 | try p.skip(attr.form, cuh, macho_file); |
| 35 | dwarf.FORM.ref_addr, | 83 | } |
| 36 | => { | 84 | } |
| 37 | _ = try p.readOffset(cuh.format); | 85 | return error.UnexpectedEndOfFile; |
| 38 | }, | 86 | } |
| 39 | | 87 | |
| 40 | dwarf.FORM.addr => { | 88 | /// When skipping attributes, we don't really need to be able to handle them all |
| 41 | _ = try p.readNBytes(cuh.address_size); | 89 | /// since we only ever care about the DW_TAG_compile_unit. |
| 42 | }, | 90 | pub fn skip(p: *InfoReader, form: Form, cuh: CompileUnitHeader, macho_file: *MachO) !void { |
| | 91 | _ = macho_file; |
| | 92 | switch (form) { |
| | 93 | dw.FORM.sec_offset, |
| | 94 | dw.FORM.ref_addr, |
| | 95 | => { |
| | 96 | _ = try p.readOffset(cuh.format); |
| | 97 | }, |
| 43 | | 98 | |
| 44 | dwarf.FORM.block1, | 99 | dw.FORM.addr => { |
| 45 | dwarf.FORM.block2, | 100 | _ = try p.readNBytes(cuh.address_size); |
| 46 | dwarf.FORM.block4, | 101 | }, |
| 47 | dwarf.FORM.block, | | |
| 48 | => { | | |
| 49 | _ = try p.readBlock(attr.form); | | |
| 50 | }, | | |
| 51 | | 102 | |
| 52 | dwarf.FORM.exprloc => { | 103 | dw.FORM.block1, |
| 53 | _ = try p.readExprLoc(); | 104 | dw.FORM.block2, |
| 54 | }, | 105 | dw.FORM.block4, |
| | 106 | dw.FORM.block, |
| | 107 | => { |
| | 108 | _ = try p.readBlock(form); |
| | 109 | }, |
| | 110 | |
| | 111 | dw.FORM.exprloc => { |
| | 112 | _ = try p.readExprLoc(); |
| | 113 | }, |
| 55 | | 114 | |
| 56 | dwarf.FORM.flag_present => {}, | 115 | dw.FORM.flag_present => {}, |
| 57 | | 116 | |
| 58 | dwarf.FORM.data1, | 117 | dw.FORM.data1, |
| 59 | dwarf.FORM.ref1, | 118 | dw.FORM.ref1, |
| 60 | dwarf.FORM.flag, | 119 | dw.FORM.flag, |
| 61 | dwarf.FORM.data2, | 120 | dw.FORM.data2, |
| 62 | dwarf.FORM.ref2, | 121 | dw.FORM.ref2, |
| 63 | dwarf.FORM.data4, | 122 | dw.FORM.data4, |
| 64 | dwarf.FORM.ref4, | 123 | dw.FORM.ref4, |
| 65 | dwarf.FORM.data8, | 124 | dw.FORM.data8, |
| 66 | dwarf.FORM.ref8, | 125 | dw.FORM.ref8, |
| 67 | dwarf.FORM.ref_sig8, | 126 | dw.FORM.ref_sig8, |
| 68 | dwarf.FORM.udata, | 127 | dw.FORM.udata, |
| 69 | dwarf.FORM.ref_udata, | 128 | dw.FORM.ref_udata, |
| 70 | dwarf.FORM.sdata, | 129 | dw.FORM.sdata, |
| | 130 | => { |
| | 131 | _ = try p.readConstant(form); |
| | 132 | }, |
| | 133 | |
| | 134 | dw.FORM.strp, |
| | 135 | dw.FORM.string, |
| | 136 | => { |
| | 137 | _ = try p.readString(form, cuh); |
| | 138 | }, |
| | 139 | |
| | 140 | else => if (cuh.version >= 5) switch (form) { |
| | 141 | dw.FORM.strx, |
| | 142 | dw.FORM.strx1, |
| | 143 | dw.FORM.strx2, |
| | 144 | dw.FORM.strx3, |
| | 145 | dw.FORM.strx4, |
| 71 | => { | 146 | => { |
| 72 | _ = try p.readConstant(attr.form); | 147 | // We are just iterating over the __debug_info data, so we don't care about an actual |
| | 148 | // string, therefore we set the `base = 0`. |
| | 149 | _ = try p.readStringIndexed(form, cuh, 0); |
| 73 | }, | 150 | }, |
| 74 | | 151 | |
| 75 | dwarf.FORM.strp, | 152 | dw.FORM.addrx, |
| 76 | dwarf.FORM.string, | 153 | dw.FORM.addrx1, |
| | 154 | dw.FORM.addrx2, |
| | 155 | dw.FORM.addrx3, |
| | 156 | dw.FORM.addrx4, |
| 77 | => { | 157 | => { |
| 78 | _ = try p.readString(attr.form, cuh); | 158 | _ = try p.readIndex(form); |
| 79 | }, | 159 | }, |
| 80 | | 160 | |
| 81 | else => { | 161 | else => return error.UnknownForm, |
| 82 | // TODO better errors | 162 | } else return error.UnknownForm, |
| 83 | log.err("unhandled DW_FORM_* value with identifier {x}", .{attr.form}); | | |
| 84 | return error.UnhandledDwFormValue; | | |
| 85 | }, | | |
| 86 | }; | | |
| 87 | } | 163 | } |
| 88 | } | 164 | } |
| 89 | | 165 | |
| 90 | pub fn readBlock(p: *InfoReader, form: Form) ![]const u8 { | 166 | pub fn readBlock(p: *InfoReader, form: Form) ![]const u8 { |
| 91 | const len: u64 = switch (form) { | 167 | const len: u64 = switch (form) { |
| 92 | dwarf.FORM.block1 => try p.readByte(), | 168 | dw.FORM.block1 => try p.readByte(), |
| 93 | dwarf.FORM.block2 => try p.readInt(u16), | 169 | dw.FORM.block2 => try p.readInt(u16), |
| 94 | dwarf.FORM.block4 => try p.readInt(u32), | 170 | dw.FORM.block4 => try p.readInt(u32), |
| 95 | dwarf.FORM.block => try p.readUleb128(u64), | 171 | dw.FORM.block => try p.readUleb128(u64), |
| 96 | else => unreachable, | 172 | else => unreachable, |
| 97 | }; | 173 | }; |
| 98 | return p.readNBytes(len); | 174 | return p.readNBytes(len); |
| ... | @@ -105,52 +181,79 @@ pub const InfoReader = struct { | ... | @@ -105,52 +181,79 @@ pub const InfoReader = struct { |
| 105 | | 181 | |
| 106 | pub fn readConstant(p: *InfoReader, form: Form) !u64 { | 182 | pub fn readConstant(p: *InfoReader, form: Form) !u64 { |
| 107 | return switch (form) { | 183 | return switch (form) { |
| 108 | dwarf.FORM.data1, dwarf.FORM.ref1, dwarf.FORM.flag => try p.readByte(), | 184 | dw.FORM.data1, dw.FORM.ref1, dw.FORM.flag => try p.readByte(), |
| 109 | dwarf.FORM.data2, dwarf.FORM.ref2 => try p.readInt(u16), | 185 | dw.FORM.data2, dw.FORM.ref2 => try p.readInt(u16), |
| 110 | dwarf.FORM.data4, dwarf.FORM.ref4 => try p.readInt(u32), | 186 | dw.FORM.data4, dw.FORM.ref4 => try p.readInt(u32), |
| 111 | dwarf.FORM.data8, dwarf.FORM.ref8, dwarf.FORM.ref_sig8 => try p.readInt(u64), | 187 | dw.FORM.data8, dw.FORM.ref8, dw.FORM.ref_sig8 => try p.readInt(u64), |
| 112 | dwarf.FORM.udata, dwarf.FORM.ref_udata => try p.readUleb128(u64), | 188 | dw.FORM.udata, dw.FORM.ref_udata => try p.readUleb128(u64), |
| 113 | dwarf.FORM.sdata => @bitCast(try p.readIleb128(i64)), | 189 | dw.FORM.sdata => @bitCast(try p.readIleb128(i64)), |
| 114 | else => return error.UnhandledConstantForm, | 190 | else => return error.UnhandledConstantForm, |
| 115 | }; | 191 | }; |
| 116 | } | 192 | } |
| 117 | | 193 | |
| | 194 | pub fn readIndex(p: *InfoReader, form: Form) !u64 { |
| | 195 | return switch (form) { |
| | 196 | dw.FORM.strx1, dw.FORM.addrx1 => try p.readByte(), |
| | 197 | dw.FORM.strx2, dw.FORM.addrx2 => try p.readInt(u16), |
| | 198 | dw.FORM.strx3, dw.FORM.addrx3 => error.UnhandledDwForm, |
| | 199 | dw.FORM.strx4, dw.FORM.addrx4 => try p.readInt(u32), |
| | 200 | dw.FORM.strx, dw.FORM.addrx => try p.readUleb128(u64), |
| | 201 | else => return error.UnhandledIndexForm, |
| | 202 | }; |
| | 203 | } |
| | 204 | |
| 118 | pub fn readString(p: *InfoReader, form: Form, cuh: CompileUnitHeader) ![:0]const u8 { | 205 | pub fn readString(p: *InfoReader, form: Form, cuh: CompileUnitHeader) ![:0]const u8 { |
| 119 | switch (form) { | 206 | switch (form) { |
| 120 | dwarf.FORM.strp => { | 207 | dw.FORM.strp => { |
| 121 | const off = try p.readOffset(cuh.format); | 208 | const off = try p.readOffset(cuh.format); |
| 122 | const off_u = math.cast(usize, off) orelse return error.Overflow; | 209 | const off_u = math.cast(usize, off) orelse return error.Overflow; |
| 123 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(p.strtab.ptr + off_u)), 0); | 210 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(p.ctx.debug_str.ptr + off_u)), 0); |
| 124 | }, | 211 | }, |
| 125 | dwarf.FORM.string => { | 212 | dw.FORM.string => { |
| 126 | const start = p.pos; | 213 | const start = p.pos; |
| 127 | while (p.pos < p.bytes.len) : (p.pos += 1) { | 214 | while (p.pos < p.bytes().len) : (p.pos += 1) { |
| 128 | if (p.bytes[p.pos] == 0) break; | 215 | if (p.bytes()[p.pos] == 0) break; |
| 129 | } | 216 | } |
| 130 | if (p.bytes[p.pos] != 0) return error.Eof; | 217 | if (p.bytes()[p.pos] != 0) return error.UnexpectedEndOfFile; |
| 131 | return p.bytes[start..p.pos :0]; | 218 | return p.bytes()[start..p.pos :0]; |
| | 219 | }, |
| | 220 | else => unreachable, |
| | 221 | } |
| | 222 | } |
| | 223 | |
| | 224 | pub fn readStringIndexed(p: *InfoReader, form: Form, cuh: CompileUnitHeader, base: u64) ![:0]const u8 { |
| | 225 | switch (form) { |
| | 226 | dw.FORM.strx, |
| | 227 | dw.FORM.strx1, |
| | 228 | dw.FORM.strx2, |
| | 229 | dw.FORM.strx3, |
| | 230 | dw.FORM.strx4, |
| | 231 | => { |
| | 232 | const index = try p.readIndex(form); |
| | 233 | const off = getOffset(p.ctx.debug_str_offsets, base, index, cuh.format); |
| | 234 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(p.ctx.debug_str.ptr + off)), 0); |
| 132 | }, | 235 | }, |
| 133 | else => unreachable, | 236 | else => unreachable, |
| 134 | } | 237 | } |
| 135 | } | 238 | } |
| 136 | | 239 | |
| 137 | pub fn readByte(p: *InfoReader) !u8 { | 240 | pub fn readByte(p: *InfoReader) !u8 { |
| 138 | if (p.pos + 1 > p.bytes.len) return error.Eof; | 241 | if (p.pos + 1 > p.bytes().len) return error.UnexpectedEndOfFile; |
| 139 | defer p.pos += 1; | 242 | defer p.pos += 1; |
| 140 | return p.bytes[p.pos]; | 243 | return p.bytes()[p.pos]; |
| 141 | } | 244 | } |
| 142 | | 245 | |
| 143 | pub fn readNBytes(p: *InfoReader, num: u64) ![]const u8 { | 246 | pub fn readNBytes(p: *InfoReader, num: u64) ![]const u8 { |
| 144 | const num_usize = math.cast(usize, num) orelse return error.Overflow; | 247 | const num_usize = math.cast(usize, num) orelse return error.Overflow; |
| 145 | if (p.pos + num_usize > p.bytes.len) return error.Eof; | 248 | if (p.pos + num_usize > p.bytes().len) return error.UnexpectedEndOfFile; |
| 146 | defer p.pos += num_usize; | 249 | defer p.pos += num_usize; |
| 147 | return p.bytes[p.pos..][0..num_usize]; | 250 | return p.bytes()[p.pos..][0..num_usize]; |
| 148 | } | 251 | } |
| 149 | | 252 | |
| 150 | pub fn readInt(p: *InfoReader, comptime Int: type) !Int { | 253 | pub fn readInt(p: *InfoReader, comptime Int: type) !Int { |
| 151 | if (p.pos + @sizeOf(Int) > p.bytes.len) return error.Eof; | 254 | if (p.pos + @sizeOf(Int) > p.bytes().len) return error.UnexpectedEndOfFile; |
| 152 | defer p.pos += @sizeOf(Int); | 255 | defer p.pos += @sizeOf(Int); |
| 153 | return mem.readInt(Int, p.bytes[p.pos..][0..@sizeOf(Int)], .little); | 256 | return mem.readInt(Int, p.bytes()[p.pos..][0..@sizeOf(Int)], .little); |
| 154 | } | 257 | } |
| 155 | | 258 | |
| 156 | pub fn readOffset(p: *InfoReader, dw_fmt: DwarfFormat) !u64 { | 259 | pub fn readOffset(p: *InfoReader, dw_fmt: DwarfFormat) !u64 { |
| ... | @@ -161,7 +264,7 @@ pub const InfoReader = struct { | ... | @@ -161,7 +264,7 @@ pub const InfoReader = struct { |
| 161 | } | 264 | } |
| 162 | | 265 | |
| 163 | pub fn readUleb128(p: *InfoReader, comptime Type: type) !Type { | 266 | pub fn readUleb128(p: *InfoReader, comptime Type: type) !Type { |
| 164 | var stream = std.io.fixedBufferStream(p.bytes[p.pos..]); | 267 | var stream = std.io.fixedBufferStream(p.bytes()[p.pos..]); |
| 165 | var creader = std.io.countingReader(stream.reader()); | 268 | var creader = std.io.countingReader(stream.reader()); |
| 166 | const value: Type = try leb.readUleb128(Type, creader.reader()); | 269 | const value: Type = try leb.readUleb128(Type, creader.reader()); |
| 167 | p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; | 270 | p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; |
| ... | @@ -169,7 +272,7 @@ pub const InfoReader = struct { | ... | @@ -169,7 +272,7 @@ pub const InfoReader = struct { |
| 169 | } | 272 | } |
| 170 | | 273 | |
| 171 | pub fn readIleb128(p: *InfoReader, comptime Type: type) !Type { | 274 | pub fn readIleb128(p: *InfoReader, comptime Type: type) !Type { |
| 172 | var stream = std.io.fixedBufferStream(p.bytes[p.pos..]); | 275 | var stream = std.io.fixedBufferStream(p.bytes()[p.pos..]); |
| 173 | var creader = std.io.countingReader(stream.reader()); | 276 | var creader = std.io.countingReader(stream.reader()); |
| 174 | const value: Type = try leb.readIleb128(Type, creader.reader()); | 277 | const value: Type = try leb.readIleb128(Type, creader.reader()); |
| 175 | p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; | 278 | p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; |
| ... | @@ -182,11 +285,15 @@ pub const InfoReader = struct { | ... | @@ -182,11 +285,15 @@ pub const InfoReader = struct { |
| 182 | }; | 285 | }; |
| 183 | | 286 | |
| 184 | pub const AbbrevReader = struct { | 287 | pub const AbbrevReader = struct { |
| 185 | bytes: []const u8, | 288 | ctx: Dwarf, |
| 186 | pos: usize = 0, | 289 | pos: usize = 0, |
| 187 | | 290 | |
| | 291 | fn bytes(p: AbbrevReader) []const u8 { |
| | 292 | return p.ctx.debug_abbrev; |
| | 293 | } |
| | 294 | |
| 188 | pub fn hasMore(p: AbbrevReader) bool { | 295 | pub fn hasMore(p: AbbrevReader) bool { |
| 189 | return p.pos < p.bytes.len; | 296 | return p.pos < p.bytes().len; |
| 190 | } | 297 | } |
| 191 | | 298 | |
| 192 | pub fn readDecl(p: *AbbrevReader) !?AbbrevDecl { | 299 | pub fn readDecl(p: *AbbrevReader) !?AbbrevDecl { |
| ... | @@ -218,13 +325,13 @@ pub const AbbrevReader = struct { | ... | @@ -218,13 +325,13 @@ pub const AbbrevReader = struct { |
| 218 | } | 325 | } |
| 219 | | 326 | |
| 220 | pub fn readByte(p: *AbbrevReader) !u8 { | 327 | pub fn readByte(p: *AbbrevReader) !u8 { |
| 221 | if (p.pos + 1 > p.bytes.len) return error.Eof; | 328 | if (p.pos + 1 > p.bytes().len) return error.Eof; |
| 222 | defer p.pos += 1; | 329 | defer p.pos += 1; |
| 223 | return p.bytes[p.pos]; | 330 | return p.bytes()[p.pos]; |
| 224 | } | 331 | } |
| 225 | | 332 | |
| 226 | pub fn readUleb128(p: *AbbrevReader, comptime Type: type) !Type { | 333 | pub fn readUleb128(p: *AbbrevReader, comptime Type: type) !Type { |
| 227 | var stream = std.io.fixedBufferStream(p.bytes[p.pos..]); | 334 | var stream = std.io.fixedBufferStream(p.bytes()[p.pos..]); |
| 228 | var creader = std.io.countingReader(stream.reader()); | 335 | var creader = std.io.countingReader(stream.reader()); |
| 229 | const value: Type = try leb.readUleb128(Type, creader.reader()); | 336 | const value: Type = try leb.readUleb128(Type, creader.reader()); |
| 230 | p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; | 337 | p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; |
| ... | @@ -254,9 +361,10 @@ const AbbrevAttr = struct { | ... | @@ -254,9 +361,10 @@ const AbbrevAttr = struct { |
| 254 | const CompileUnitHeader = struct { | 361 | const CompileUnitHeader = struct { |
| 255 | format: DwarfFormat, | 362 | format: DwarfFormat, |
| 256 | length: u64, | 363 | length: u64, |
| 257 | version: u16, | 364 | version: Version, |
| 258 | debug_abbrev_offset: u64, | 365 | debug_abbrev_offset: u64, |
| 259 | address_size: u8, | 366 | address_size: u8, |
| | 367 | unit_type: u8, |
| 260 | }; | 368 | }; |
| 261 | | 369 | |
| 262 | const Die = struct { | 370 | const Die = struct { |
| ... | @@ -269,18 +377,24 @@ const DwarfFormat = enum { | ... | @@ -269,18 +377,24 @@ const DwarfFormat = enum { |
| 269 | dwarf64, | 377 | dwarf64, |
| 270 | }; | 378 | }; |
| 271 | | 379 | |
| 272 | const dwarf = std.dwarf; | 380 | const dw = std.dwarf; |
| 273 | const leb = std.leb; | 381 | const leb = std.leb; |
| 274 | const log = std.log.scoped(.link); | 382 | const log = std.log.scoped(.link); |
| 275 | const math = std.math; | 383 | const math = std.math; |
| 276 | const mem = std.mem; | 384 | const mem = std.mem; |
| 277 | const std = @import("std"); | 385 | const std = @import("std"); |
| 278 | | 386 | const Allocator = mem.Allocator; |
| 279 | const At = u64; | 387 | const Dwarf = @This(); |
| 280 | const Code = u64; | 388 | const File = @import("file.zig").File; |
| 281 | const Form = u64; | 389 | const MachO = @import("../MachO.zig"); |
| 282 | const Tag = u64; | 390 | const Object = @import("Object.zig"); |
| 283 | | 391 | |
| 284 | pub const AT = dwarf.AT; | 392 | pub const At = u64; |
| 285 | pub const FORM = dwarf.FORM; | 393 | pub const Code = u64; |
| 286 | pub const TAG = dwarf.TAG; | 394 | pub const Form = u64; |
| | 395 | pub const Tag = u64; |
| | 396 | pub const Version = u16; |
| | 397 | |
| | 398 | pub const AT = dw.AT; |
| | 399 | pub const FORM = dw.FORM; |
| | 400 | pub const TAG = dw.TAG; |