| ... | ... | @@ -13,6 +13,8 @@ const ArrayList = std.ArrayList; |
| 13 | 13 | const builtin = @import("builtin"); |
| 14 | 14 | const maxInt = std.math.maxInt; |
| 15 | 15 | |
| 16 | const leb = @import("debug/leb128.zig"); |
| 17 | |
| 16 | 18 | pub const FailingAllocator = @import("debug/failing_allocator.zig").FailingAllocator; |
| 17 | 19 | pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator; |
| 18 | 20 | |
| ... | ... | @@ -1460,7 +1462,7 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo |
| 1460 | 1462 | 2 => try in_stream.readIntLittle(u16), |
| 1461 | 1463 | 4 => try in_stream.readIntLittle(u32), |
| 1462 | 1464 | 8 => try in_stream.readIntLittle(u64), |
| 1463 | | -1 => if (signed) @bitCast(u64, try readILeb128(in_stream)) else try readULeb128(in_stream), |
| 1465 | -1 => if (signed) @bitCast(u64, try leb.readILEB128(i64, in_stream)) else try leb.readULEB128(u64, in_stream), |
| 1464 | 1466 | else => @compileError("Invalid size"), |
| 1465 | 1467 | }, |
| 1466 | 1468 | }, |
| ... | ... | @@ -1482,7 +1484,7 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !Form |
| 1482 | 1484 | 2 => try in_stream.readIntLittle(u16), |
| 1483 | 1485 | 4 => try in_stream.readIntLittle(u32), |
| 1484 | 1486 | 8 => try in_stream.readIntLittle(u64), |
| 1485 | | -1 => try readULeb128(in_stream), |
| 1487 | -1 => try leb.readULEB128(u64, in_stream), |
| 1486 | 1488 | else => unreachable, |
| 1487 | 1489 | }, |
| 1488 | 1490 | }; |
| ... | ... | @@ -1495,7 +1497,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1495 | 1497 | DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), |
| 1496 | 1498 | DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4), |
| 1497 | 1499 | DW.FORM_block => x: { |
| 1498 | | const block_len = try readULeb128(in_stream); |
| 1500 | const block_len = try leb.readULEB128(usize, in_stream); |
| 1499 | 1501 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 1500 | 1502 | }, |
| 1501 | 1503 | DW.FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1), |
| ... | ... | @@ -1507,7 +1509,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1507 | 1509 | return parseFormValueConstant(allocator, in_stream, signed, -1); |
| 1508 | 1510 | }, |
| 1509 | 1511 | DW.FORM_exprloc => { |
| 1510 | | const size = try readULeb128(in_stream); |
| 1512 | const size = try leb.readULEB128(usize, in_stream); |
| 1511 | 1513 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 1512 | 1514 | return FormValue{ .ExprLoc = buf }; |
| 1513 | 1515 | }, |
| ... | ... | @@ -1527,7 +1529,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1527 | 1529 | DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, |
| 1528 | 1530 | DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 1529 | 1531 | DW.FORM_indirect => { |
| 1530 | | const child_form_id = try readULeb128(in_stream); |
| 1532 | const child_form_id = try leb.readULEB128(u64, in_stream); |
| 1531 | 1533 | return parseFormValue(allocator, in_stream, child_form_id, is_64); |
| 1532 | 1534 | }, |
| 1533 | 1535 | else => error.InvalidDebugInfo, |
| ... | ... | @@ -1537,19 +1539,19 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1537 | 1539 | fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable { |
| 1538 | 1540 | var result = AbbrevTable.init(di.allocator()); |
| 1539 | 1541 | while (true) { |
| 1540 | | const abbrev_code = try readULeb128(di.dwarf_in_stream); |
| 1542 | const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream); |
| 1541 | 1543 | if (abbrev_code == 0) return result; |
| 1542 | 1544 | try result.append(AbbrevTableEntry{ |
| 1543 | 1545 | .abbrev_code = abbrev_code, |
| 1544 | | .tag_id = try readULeb128(di.dwarf_in_stream), |
| 1546 | .tag_id = try leb.readULEB128(u64, di.dwarf_in_stream), |
| 1545 | 1547 | .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes, |
| 1546 | 1548 | .attrs = ArrayList(AbbrevAttr).init(di.allocator()), |
| 1547 | 1549 | }); |
| 1548 | 1550 | const attrs = &result.items[result.len - 1].attrs; |
| 1549 | 1551 | |
| 1550 | 1552 | while (true) { |
| 1551 | | const attr_id = try readULeb128(di.dwarf_in_stream); |
| 1552 | | const form_id = try readULeb128(di.dwarf_in_stream); |
| 1553 | const attr_id = try leb.readULEB128(u64, di.dwarf_in_stream); |
| 1554 | const form_id = try leb.readULEB128(u64, di.dwarf_in_stream); |
| 1553 | 1555 | if (attr_id == 0 and form_id == 0) break; |
| 1554 | 1556 | try attrs.append(AbbrevAttr{ |
| 1555 | 1557 | .attr_id = attr_id, |
| ... | ... | @@ -1583,7 +1585,7 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con |
| 1583 | 1585 | } |
| 1584 | 1586 | |
| 1585 | 1587 | fn parseDie1(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Die { |
| 1586 | | const abbrev_code = try readULeb128(di.dwarf_in_stream); |
| 1588 | const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream); |
| 1587 | 1589 | if (abbrev_code == 0) return null; |
| 1588 | 1590 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; |
| 1589 | 1591 | |
| ... | ... | @@ -1603,7 +1605,7 @@ fn parseDie1(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Di |
| 1603 | 1605 | } |
| 1604 | 1606 | |
| 1605 | 1607 | fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { |
| 1606 | | const abbrev_code = try readULeb128(di.dwarf_in_stream); |
| 1608 | const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream); |
| 1607 | 1609 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; |
| 1608 | 1610 | |
| 1609 | 1611 | var result = Die{ |
| ... | ... | @@ -1716,9 +1718,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1716 | 1718 | while (true) { |
| 1717 | 1719 | const file_name = readStringMem(&ptr); |
| 1718 | 1720 | if (file_name.len == 0) break; |
| 1719 | | const dir_index = try readULeb128Mem(&ptr); |
| 1720 | | const mtime = try readULeb128Mem(&ptr); |
| 1721 | | const len_bytes = try readULeb128Mem(&ptr); |
| 1721 | const dir_index = try leb.readULEB128Mem(usize, &ptr); |
| 1722 | const mtime = try leb.readULEB128Mem(usize, &ptr); |
| 1723 | const len_bytes = try leb.readULEB128Mem(usize, &ptr); |
| 1722 | 1724 | try file_entries.append(FileEntry{ |
| 1723 | 1725 | .file_name = file_name, |
| 1724 | 1726 | .dir_index = dir_index, |
| ... | ... | @@ -1732,7 +1734,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1732 | 1734 | const opcode = readByteMem(&ptr); |
| 1733 | 1735 | |
| 1734 | 1736 | if (opcode == DW.LNS_extended_op) { |
| 1735 | | const op_size = try readULeb128Mem(&ptr); |
| 1737 | const op_size = try leb.readULEB128Mem(u64, &ptr); |
| 1736 | 1738 | if (op_size < 1) return error.InvalidDebugInfo; |
| 1737 | 1739 | var sub_op = readByteMem(&ptr); |
| 1738 | 1740 | switch (sub_op) { |
| ... | ... | @@ -1747,9 +1749,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1747 | 1749 | }, |
| 1748 | 1750 | DW.LNE_define_file => { |
| 1749 | 1751 | const file_name = readStringMem(&ptr); |
| 1750 | | const dir_index = try readULeb128Mem(&ptr); |
| 1751 | | const mtime = try readULeb128Mem(&ptr); |
| 1752 | | const len_bytes = try readULeb128Mem(&ptr); |
| 1752 | const dir_index = try leb.readULEB128Mem(usize, &ptr); |
| 1753 | const mtime = try leb.readULEB128Mem(usize, &ptr); |
| 1754 | const len_bytes = try leb.readULEB128Mem(usize, &ptr); |
| 1753 | 1755 | try file_entries.append(FileEntry{ |
| 1754 | 1756 | .file_name = file_name, |
| 1755 | 1757 | .dir_index = dir_index, |
| ... | ... | @@ -1777,19 +1779,19 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1777 | 1779 | prog.basic_block = false; |
| 1778 | 1780 | }, |
| 1779 | 1781 | DW.LNS_advance_pc => { |
| 1780 | | const arg = try readULeb128Mem(&ptr); |
| 1782 | const arg = try leb.readULEB128Mem(u64, &ptr); |
| 1781 | 1783 | prog.address += arg * minimum_instruction_length; |
| 1782 | 1784 | }, |
| 1783 | 1785 | DW.LNS_advance_line => { |
| 1784 | | const arg = try readILeb128Mem(&ptr); |
| 1786 | const arg = try leb.readILEB128Mem(i64, &ptr); |
| 1785 | 1787 | prog.line += arg; |
| 1786 | 1788 | }, |
| 1787 | 1789 | DW.LNS_set_file => { |
| 1788 | | const arg = try readULeb128Mem(&ptr); |
| 1790 | const arg = try leb.readULEB128Mem(u64, &ptr); |
| 1789 | 1791 | prog.file = arg; |
| 1790 | 1792 | }, |
| 1791 | 1793 | DW.LNS_set_column => { |
| 1792 | | const arg = try readULeb128Mem(&ptr); |
| 1794 | const arg = try leb.readULEB128Mem(u64, &ptr); |
| 1793 | 1795 | prog.column = arg; |
| 1794 | 1796 | }, |
| 1795 | 1797 | DW.LNS_negate_stmt => { |
| ... | ... | @@ -1880,9 +1882,9 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr |
| 1880 | 1882 | while (true) { |
| 1881 | 1883 | const file_name = try di.readString(); |
| 1882 | 1884 | if (file_name.len == 0) break; |
| 1883 | | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1884 | | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1885 | | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1885 | const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream); |
| 1886 | const mtime = try leb.readULEB128(usize, di.dwarf_in_stream); |
| 1887 | const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream); |
| 1886 | 1888 | try file_entries.append(FileEntry{ |
| 1887 | 1889 | .file_name = file_name, |
| 1888 | 1890 | .dir_index = dir_index, |
| ... | ... | @@ -1897,7 +1899,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr |
| 1897 | 1899 | const opcode = try di.dwarf_in_stream.readByte(); |
| 1898 | 1900 | |
| 1899 | 1901 | if (opcode == DW.LNS_extended_op) { |
| 1900 | | const op_size = try readULeb128(di.dwarf_in_stream); |
| 1902 | const op_size = try leb.readULEB128(u64, di.dwarf_in_stream); |
| 1901 | 1903 | if (op_size < 1) return error.InvalidDebugInfo; |
| 1902 | 1904 | var sub_op = try di.dwarf_in_stream.readByte(); |
| 1903 | 1905 | switch (sub_op) { |
| ... | ... | @@ -1912,9 +1914,9 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr |
| 1912 | 1914 | }, |
| 1913 | 1915 | DW.LNE_define_file => { |
| 1914 | 1916 | const file_name = try di.readString(); |
| 1915 | | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1916 | | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1917 | | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1917 | const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream); |
| 1918 | const mtime = try leb.readULEB128(usize, di.dwarf_in_stream); |
| 1919 | const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream); |
| 1918 | 1920 | try file_entries.append(FileEntry{ |
| 1919 | 1921 | .file_name = file_name, |
| 1920 | 1922 | .dir_index = dir_index, |
| ... | ... | @@ -1943,19 +1945,19 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr |
| 1943 | 1945 | prog.basic_block = false; |
| 1944 | 1946 | }, |
| 1945 | 1947 | DW.LNS_advance_pc => { |
| 1946 | | const arg = try readULeb128(di.dwarf_in_stream); |
| 1948 | const arg = try leb.readULEB128(u64, di.dwarf_in_stream); |
| 1947 | 1949 | prog.address += arg * minimum_instruction_length; |
| 1948 | 1950 | }, |
| 1949 | 1951 | DW.LNS_advance_line => { |
| 1950 | | const arg = try readILeb128(di.dwarf_in_stream); |
| 1952 | const arg = try leb.readILEB128(i64, di.dwarf_in_stream); |
| 1951 | 1953 | prog.line += arg; |
| 1952 | 1954 | }, |
| 1953 | 1955 | DW.LNS_set_file => { |
| 1954 | | const arg = try readULeb128(di.dwarf_in_stream); |
| 1956 | const arg = try leb.readULEB128(u64, di.dwarf_in_stream); |
| 1955 | 1957 | prog.file = arg; |
| 1956 | 1958 | }, |
| 1957 | 1959 | DW.LNS_set_column => { |
| 1958 | | const arg = try readULeb128(di.dwarf_in_stream); |
| 1960 | const arg = try leb.readULEB128(u64, di.dwarf_in_stream); |
| 1959 | 1961 | prog.column = arg; |
| 1960 | 1962 | }, |
| 1961 | 1963 | DW.LNS_negate_stmt => { |
| ... | ... | @@ -2240,53 +2242,6 @@ fn readStringMem(ptr: *[*]const u8) []const u8 { |
| 2240 | 2242 | return result; |
| 2241 | 2243 | } |
| 2242 | 2244 | |
| 2243 | | fn readULeb128Mem(ptr: *[*]const u8) !u64 { |
| 2244 | | var result: u64 = 0; |
| 2245 | | var shift: usize = 0; |
| 2246 | | var i: usize = 0; |
| 2247 | | |
| 2248 | | while (true) { |
| 2249 | | const byte = ptr.*[i]; |
| 2250 | | i += 1; |
| 2251 | | |
| 2252 | | var operand: u64 = undefined; |
| 2253 | | |
| 2254 | | if (@shlWithOverflow(u64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo; |
| 2255 | | |
| 2256 | | result |= operand; |
| 2257 | | |
| 2258 | | if ((byte & 0b10000000) == 0) { |
| 2259 | | ptr.* += i; |
| 2260 | | return result; |
| 2261 | | } |
| 2262 | | |
| 2263 | | shift += 7; |
| 2264 | | } |
| 2265 | | } |
| 2266 | | fn readILeb128Mem(ptr: *[*]const u8) !i64 { |
| 2267 | | var result: i64 = 0; |
| 2268 | | var shift: usize = 0; |
| 2269 | | var i: usize = 0; |
| 2270 | | |
| 2271 | | while (true) { |
| 2272 | | const byte = ptr.*[i]; |
| 2273 | | i += 1; |
| 2274 | | |
| 2275 | | if (shift > @sizeOf(i64) * 8) return error.InvalidDebugInfo; |
| 2276 | | |
| 2277 | | result |= i64(byte & 0b01111111) << @intCast(u6, shift); |
| 2278 | | shift += 7; |
| 2279 | | |
| 2280 | | if ((byte & 0b10000000) == 0) { |
| 2281 | | if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) { |
| 2282 | | result |= -(i64(1) << @intCast(u6, shift)); |
| 2283 | | } |
| 2284 | | ptr.* += i; |
| 2285 | | return result; |
| 2286 | | } |
| 2287 | | } |
| 2288 | | } |
| 2289 | | |
| 2290 | 2245 | fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 { |
| 2291 | 2246 | const first_32_bits = try in_stream.readIntLittle(u32); |
| 2292 | 2247 | is_64.* = (first_32_bits == 0xffffffff); |
| ... | ... | @@ -2298,46 +2253,6 @@ fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) |
| 2298 | 2253 | } |
| 2299 | 2254 | } |
| 2300 | 2255 | |
| 2301 | | fn readULeb128(in_stream: var) !u64 { |
| 2302 | | var result: u64 = 0; |
| 2303 | | var shift: usize = 0; |
| 2304 | | |
| 2305 | | while (true) { |
| 2306 | | const byte = try in_stream.readByte(); |
| 2307 | | |
| 2308 | | var operand: u64 = undefined; |
| 2309 | | |
| 2310 | | if (@shlWithOverflow(u64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo; |
| 2311 | | |
| 2312 | | result |= operand; |
| 2313 | | |
| 2314 | | if ((byte & 0b10000000) == 0) return result; |
| 2315 | | |
| 2316 | | shift += 7; |
| 2317 | | } |
| 2318 | | } |
| 2319 | | |
| 2320 | | fn readILeb128(in_stream: var) !i64 { |
| 2321 | | var result: i64 = 0; |
| 2322 | | var shift: usize = 0; |
| 2323 | | |
| 2324 | | while (true) { |
| 2325 | | const byte = try in_stream.readByte(); |
| 2326 | | |
| 2327 | | if (shift > @sizeOf(i64) * 8) return error.InvalidDebugInfo; |
| 2328 | | |
| 2329 | | result |= i64(byte & 0b01111111) << @intCast(u6, shift); |
| 2330 | | shift += 7; |
| 2331 | | |
| 2332 | | if ((byte & 0b10000000) == 0) { |
| 2333 | | if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) { |
| 2334 | | result |= -(i64(1) << @intCast(u6, shift)); |
| 2335 | | } |
| 2336 | | return result; |
| 2337 | | } |
| 2338 | | } |
| 2339 | | } |
| 2340 | | |
| 2341 | 2256 | /// This should only be used in temporary test programs. |
| 2342 | 2257 | pub const global_allocator = &global_fixed_allocator.allocator; |
| 2343 | 2258 | var global_fixed_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(global_allocator_mem[0..]); |