| ... | ... | @@ -1494,18 +1494,34 @@ pub const DwarfInfo = struct { |
| 1494 | 1494 | } |
| 1495 | 1495 | |
| 1496 | 1496 | const id_len = @as(u8, if (is_64) 8 else 4); |
| 1497 | | const entry_bytes = eh_frame[stream.pos..][0..length - id_len]; |
| 1497 | const entry_bytes = eh_frame[stream.pos..][0 .. length - id_len]; |
| 1498 | 1498 | const id = try reader.readInt(u32, di.endian); |
| 1499 | 1499 | |
| 1500 | 1500 | // TODO: Get section_offset here (pass in from headers) |
| 1501 | 1501 | |
| 1502 | 1502 | if (id == 0) { |
| 1503 | | const cie = try CommonInformationEntry.parse(entry_bytes, @ptrToInt(eh_frame.ptr), 0, length_offset, @sizeOf(usize), di.endian); |
| 1503 | const cie = try CommonInformationEntry.parse( |
| 1504 | entry_bytes, |
| 1505 | @ptrToInt(eh_frame.ptr), |
| 1506 | 0, |
| 1507 | true, |
| 1508 | length_offset, |
| 1509 | @sizeOf(usize), |
| 1510 | di.endian, |
| 1511 | ); |
| 1504 | 1512 | try di.cie_map.put(allocator, length_offset, cie); |
| 1505 | 1513 | } else { |
| 1506 | 1514 | const cie_offset = stream.pos - 4 - id; |
| 1507 | 1515 | const cie = di.cie_map.get(cie_offset) orelse return badDwarf(); |
| 1508 | | const fde = try FrameDescriptionEntry.parse(entry_bytes, @ptrToInt(eh_frame.ptr), 0, cie, @sizeOf(usize), di.endian); |
| 1516 | const fde = try FrameDescriptionEntry.parse( |
| 1517 | entry_bytes, |
| 1518 | @ptrToInt(eh_frame.ptr), |
| 1519 | 0, |
| 1520 | true, |
| 1521 | cie, |
| 1522 | @sizeOf(usize), |
| 1523 | di.endian, |
| 1524 | ); |
| 1509 | 1525 | try di.fde_list.append(allocator, fde); |
| 1510 | 1526 | } |
| 1511 | 1527 | } |
| ... | ... | @@ -1557,6 +1573,11 @@ const EhPointerContext = struct { |
| 1557 | 1573 | // The address of the pointer field itself |
| 1558 | 1574 | pc_rel_base: u64, |
| 1559 | 1575 | |
| 1576 | // Whether or not to follow indirect pointers. This should only be |
| 1577 | // used when decoding pointers at runtime using the current process's |
| 1578 | // debug info. |
| 1579 | follow_indirect: bool, |
| 1580 | |
| 1560 | 1581 | // These relative addressing modes are only used in specific cases, and |
| 1561 | 1582 | // might not be available / required in all parsing contexts |
| 1562 | 1583 | data_rel_base: ?u64 = null, |
| ... | ... | @@ -1570,7 +1591,7 @@ fn readEhPointer(reader: anytype, enc: u8, addr_size_bytes: u8, ctx: EhPointerCo |
| 1570 | 1591 | const value: union(enum) { |
| 1571 | 1592 | signed: i64, |
| 1572 | 1593 | unsigned: u64, |
| 1573 | | } = switch (enc & 0x0f) { |
| 1594 | } = switch (enc & EH.PE.type_mask) { |
| 1574 | 1595 | EH.PE.absptr => .{ |
| 1575 | 1596 | .unsigned = switch (addr_size_bytes) { |
| 1576 | 1597 | 2 => try reader.readInt(u16, endian), |
| ... | ... | @@ -1590,33 +1611,31 @@ fn readEhPointer(reader: anytype, enc: u8, addr_size_bytes: u8, ctx: EhPointerCo |
| 1590 | 1611 | else => return badDwarf(), |
| 1591 | 1612 | }; |
| 1592 | 1613 | |
| 1593 | | const relative_to = enc & 0xf0; |
| 1594 | | var base = switch (relative_to) { |
| 1614 | var base = switch (enc & EH.PE.rel_mask) { |
| 1595 | 1615 | EH.PE.pcrel => ctx.pc_rel_base, |
| 1596 | 1616 | EH.PE.textrel => ctx.text_rel_base orelse return error.PointerBaseNotSpecified, |
| 1597 | 1617 | EH.PE.datarel => ctx.data_rel_base orelse return error.PointerBaseNotSpecified, |
| 1598 | 1618 | EH.PE.funcrel => ctx.function_rel_base orelse return error.PointerBaseNotSpecified, |
| 1599 | | EH.PE.indirect => { |
| 1600 | | switch (addr_size_bytes) { |
| 1601 | | 2 => return @intToPtr(*const u16, value.unsigned).*, |
| 1602 | | 4 => return @intToPtr(*const u32, value.unsigned).*, |
| 1603 | | 8 => return @intToPtr(*const u64, value.unsigned).*, |
| 1604 | | else => return error.UnsupportedAddrSize, |
| 1605 | | } |
| 1606 | | }, |
| 1607 | 1619 | else => null, |
| 1608 | 1620 | }; |
| 1609 | 1621 | |
| 1610 | | if (base) |b| { |
| 1611 | | return switch (value) { |
| 1612 | | .signed => |s| @intCast(u64, s + @intCast(i64, b)), |
| 1613 | | .unsigned => |u| u + b, |
| 1622 | const ptr = if (base) |b| switch (value) { |
| 1623 | .signed => |s| @intCast(u64, s + @intCast(i64, b)), |
| 1624 | .unsigned => |u| u + b, |
| 1625 | } else switch (value) { |
| 1626 | .signed => |s| @intCast(u64, s), |
| 1627 | .unsigned => |u| u, |
| 1628 | }; |
| 1629 | |
| 1630 | if ((enc & EH.PE.indirect) > 0 and ctx.follow_indirect) { |
| 1631 | return switch (addr_size_bytes) { |
| 1632 | 2 => return @intToPtr(*const u16, ptr).*, |
| 1633 | 4 => return @intToPtr(*const u32, ptr).*, |
| 1634 | 8 => return @intToPtr(*const u64, ptr).*, |
| 1635 | else => return error.UnsupportedAddrSize, |
| 1614 | 1636 | }; |
| 1615 | 1637 | } else { |
| 1616 | | return switch (value) { |
| 1617 | | .signed => |s| @intCast(u64, s), |
| 1618 | | .unsigned => |u| u, |
| 1619 | | }; |
| 1638 | return ptr; |
| 1620 | 1639 | } |
| 1621 | 1640 | } |
| 1622 | 1641 | |
| ... | ... | @@ -1668,6 +1687,7 @@ pub const CommonInformationEntry = struct { |
| 1668 | 1687 | cie_bytes: []const u8, |
| 1669 | 1688 | section_base: u64, |
| 1670 | 1689 | section_offset: u64, |
| 1690 | is_runtime: bool, |
| 1671 | 1691 | length_offset: u64, |
| 1672 | 1692 | addr_size_bytes: u8, |
| 1673 | 1693 | endian: std.builtin.Endian, |
| ... | ... | @@ -1735,7 +1755,10 @@ pub const CommonInformationEntry = struct { |
| 1735 | 1755 | reader, |
| 1736 | 1756 | personality_enc.?, |
| 1737 | 1757 | addr_size_bytes, |
| 1738 | | .{ .pc_rel_base = @ptrToInt(&cie_bytes[stream.pos]) - section_base + section_offset }, |
| 1758 | .{ |
| 1759 | .pc_rel_base = @ptrToInt(&cie_bytes[stream.pos]) - section_base + section_offset, |
| 1760 | .follow_indirect = is_runtime, |
| 1761 | }, |
| 1739 | 1762 | endian, |
| 1740 | 1763 | ); |
| 1741 | 1764 | }, |
| ... | ... | @@ -1785,6 +1808,7 @@ pub const FrameDescriptionEntry = struct { |
| 1785 | 1808 | fde_bytes: []const u8, |
| 1786 | 1809 | section_base: u64, |
| 1787 | 1810 | section_offset: u64, |
| 1811 | is_runtime: bool, |
| 1788 | 1812 | cie: CommonInformationEntry, |
| 1789 | 1813 | addr_size_bytes: u8, |
| 1790 | 1814 | endian: std.builtin.Endian, |
| ... | ... | @@ -1798,15 +1822,21 @@ pub const FrameDescriptionEntry = struct { |
| 1798 | 1822 | reader, |
| 1799 | 1823 | cie.fde_pointer_enc, |
| 1800 | 1824 | addr_size_bytes, |
| 1801 | | .{ .pc_rel_base = @ptrToInt(&fde_bytes[stream.pos]) - section_base + section_offset }, |
| 1825 | .{ |
| 1826 | .pc_rel_base = @ptrToInt(&fde_bytes[stream.pos]) - section_base + section_offset, |
| 1827 | .follow_indirect = is_runtime, |
| 1828 | }, |
| 1802 | 1829 | endian, |
| 1803 | 1830 | ) orelse return badDwarf(); |
| 1804 | 1831 | |
| 1805 | 1832 | const pc_range = try readEhPointer( |
| 1806 | 1833 | reader, |
| 1807 | | cie.fde_pointer_enc & 0x0f, |
| 1834 | cie.fde_pointer_enc, |
| 1808 | 1835 | addr_size_bytes, |
| 1809 | | .{ .pc_rel_base = @ptrToInt(&fde_bytes[stream.pos]) - section_base + section_offset }, |
| 1836 | .{ |
| 1837 | .pc_rel_base = 0, |
| 1838 | .follow_indirect = false, |
| 1839 | }, |
| 1810 | 1840 | endian, |
| 1811 | 1841 | ) orelse return badDwarf(); |
| 1812 | 1842 | |
| ... | ... | @@ -1819,9 +1849,12 @@ pub const FrameDescriptionEntry = struct { |
| 1819 | 1849 | const lsda_pointer = if (cie.lsda_pointer_enc != EH.PE.omit) |
| 1820 | 1850 | try readEhPointer( |
| 1821 | 1851 | reader, |
| 1822 | | cie.lsda_pointer_enc & 0x0f, |
| 1852 | cie.lsda_pointer_enc, |
| 1823 | 1853 | addr_size_bytes, |
| 1824 | | .{ .pc_rel_base = @ptrToInt(&fde_bytes[stream.pos]) }, |
| 1854 | .{ |
| 1855 | .pc_rel_base = @ptrToInt(&fde_bytes[stream.pos]) - section_base + section_offset, |
| 1856 | .follow_indirect = is_runtime, |
| 1857 | }, |
| 1825 | 1858 | endian, |
| 1826 | 1859 | ) |
| 1827 | 1860 | else |