| ... | @@ -1754,7 +1754,7 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1754,7 +1754,7 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1754 | os.munmap(self.mapped_memory); | 1754 | os.munmap(self.mapped_memory); |
| 1755 | } | 1755 | } |
| 1756 | | 1756 | |
| 1757 | fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !OFileInfo { | 1757 | fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !*OFileInfo { |
| 1758 | const o_file = try fs.cwd().openFile(o_file_path, .{ .intended_io_mode = .blocking }); | 1758 | const o_file = try fs.cwd().openFile(o_file_path, .{ .intended_io_mode = .blocking }); |
| 1759 | const mapped_mem = try mapWholeFile(o_file); | 1759 | const mapped_mem = try mapWholeFile(o_file); |
| 1760 | | 1760 | |
| ... | @@ -1799,11 +1799,11 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1799,11 +1799,11 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1799 | | 1799 | |
| 1800 | var sections: DW.DwarfInfo.SectionArray = DW.DwarfInfo.null_section_array; | 1800 | var sections: DW.DwarfInfo.SectionArray = DW.DwarfInfo.null_section_array; |
| 1801 | for (segcmd.?.getSections()) |sect| { | 1801 | for (segcmd.?.getSections()) |sect| { |
| 1802 | const name = sect.sectName(); | 1802 | if (!std.mem.eql(u8, "__DWARF", sect.segName())) continue; |
| 1803 | | 1803 | |
| 1804 | var section_index: ?usize = null; | 1804 | var section_index: ?usize = null; |
| 1805 | inline for (@typeInfo(DW.DwarfSection).Enum.fields, 0..) |section, i| { | 1805 | inline for (@typeInfo(DW.DwarfSection).Enum.fields, 0..) |section, i| { |
| 1806 | if (mem.eql(u8, "__" ++ section.name, name)) section_index = i; | 1806 | if (mem.eql(u8, "__" ++ section.name, sect.sectName())) section_index = i; |
| 1807 | } | 1807 | } |
| 1808 | if (section_index == null) continue; | 1808 | if (section_index == null) continue; |
| 1809 | | 1809 | |
| ... | @@ -1834,65 +1834,31 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1834,65 +1834,31 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1834 | }; | 1834 | }; |
| 1835 | | 1835 | |
| 1836 | // Add the debug info to the cache | 1836 | // Add the debug info to the cache |
| 1837 | try self.ofiles.putNoClobber(o_file_path, info); | 1837 | const result = try self.ofiles.getOrPut(o_file_path); |
| | 1838 | assert(!result.found_existing); |
| | 1839 | result.value_ptr.* = info; |
| 1838 | | 1840 | |
| 1839 | return info; | 1841 | return result.value_ptr; |
| 1840 | } | | |
| 1841 | | | |
| 1842 | fn getOFileForAddress(self: *@This(), allocator: mem.Allocator, address: usize) !?*OFileInfo { | | |
| 1843 | nosuspend { | | |
| 1844 | const relocated_address = address - self.base_address; | | |
| 1845 | const symbol = machoSearchSymbols(self.symbols, relocated_address) orelse | | |
| 1846 | return null; | | |
| 1847 | | | |
| 1848 | const o_file_path = mem.sliceTo(self.strings[symbol.ofile..], 0); | | |
| 1849 | var o_file_info = self.ofiles.get(o_file_path) orelse | | |
| 1850 | (self.loadOFile(allocator, o_file_path) catch |err| switch (err) { | | |
| 1851 | error.FileNotFound, | | |
| 1852 | error.MissingDebugInfo, | | |
| 1853 | error.InvalidDebugInfo, | | |
| 1854 | => return null, | | |
| 1855 | else => return err, | | |
| 1856 | }); | | |
| 1857 | | | |
| 1858 | return &o_file_info.di; | | |
| 1859 | } | | |
| 1860 | } | 1842 | } |
| 1861 | | 1843 | |
| 1862 | pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo { | 1844 | pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo { |
| 1863 | nosuspend { | 1845 | nosuspend { |
| 1864 | // Translate the VA into an address into this object | 1846 | const result = try self.getOFileInfoForAddress(allocator, address); |
| 1865 | const relocated_address = address - self.base_address; | 1847 | if (result.symbol == null) return .{}; |
| 1866 | | | |
| 1867 | // Find the .o file where this symbol is defined | | |
| 1868 | const symbol = machoSearchSymbols(self.symbols, relocated_address) orelse | | |
| 1869 | return SymbolInfo{}; | | |
| 1870 | const addr_off = relocated_address - symbol.addr; | | |
| 1871 | | 1848 | |
| 1872 | // Take the symbol name from the N_FUN STAB entry, we're going to | 1849 | // Take the symbol name from the N_FUN STAB entry, we're going to |
| 1873 | // use it if we fail to find the DWARF infos | 1850 | // use it if we fail to find the DWARF infos |
| 1874 | const stab_symbol = mem.sliceTo(self.strings[symbol.strx..], 0); | 1851 | const stab_symbol = mem.sliceTo(self.strings[result.symbol.?.strx..], 0); |
| 1875 | const o_file_path = mem.sliceTo(self.strings[symbol.ofile..], 0); | 1852 | if (result.o_file_info == null) return .{ .symbol_name = stab_symbol }; |
| 1876 | | | |
| 1877 | // Check if its debug infos are already in the cache | | |
| 1878 | var o_file_info = self.ofiles.get(o_file_path) orelse | | |
| 1879 | (self.loadOFile(allocator, o_file_path) catch |err| switch (err) { | | |
| 1880 | error.FileNotFound, | | |
| 1881 | error.MissingDebugInfo, | | |
| 1882 | error.InvalidDebugInfo, | | |
| 1883 | => { | | |
| 1884 | return SymbolInfo{ .symbol_name = stab_symbol }; | | |
| 1885 | }, | | |
| 1886 | else => return err, | | |
| 1887 | }); | | |
| 1888 | const o_file_di = &o_file_info.di; | | |
| 1889 | | 1853 | |
| 1890 | // Translate again the address, this time into an address inside the | 1854 | // Translate again the address, this time into an address inside the |
| 1891 | // .o file | 1855 | // .o file |
| 1892 | const relocated_address_o = o_file_info.addr_table.get(stab_symbol) orelse return SymbolInfo{ | 1856 | const relocated_address_o = result.o_file_info.?.addr_table.get(stab_symbol) orelse return .{ |
| 1893 | .symbol_name = "???", | 1857 | .symbol_name = "???", |
| 1894 | }; | 1858 | }; |
| 1895 | | 1859 | |
| | 1860 | const addr_off = result.relocated_address - result.symbol.?.addr; |
| | 1861 | const o_file_di = &result.o_file_info.?.di; |
| 1896 | if (o_file_di.findCompileUnit(relocated_address_o)) |compile_unit| { | 1862 | if (o_file_di.findCompileUnit(relocated_address_o)) |compile_unit| { |
| 1897 | return SymbolInfo{ | 1863 | return SymbolInfo{ |
| 1898 | .symbol_name = o_file_di.getSymbolName(relocated_address_o) orelse "???", | 1864 | .symbol_name = o_file_di.getSymbolName(relocated_address_o) orelse "???", |
| ... | @@ -1919,30 +1885,48 @@ pub const ModuleDebugInfo = switch (native_os) { | ... | @@ -1919,30 +1885,48 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1919 | }, | 1885 | }, |
| 1920 | else => return err, | 1886 | else => return err, |
| 1921 | } | 1887 | } |
| 1922 | | | |
| 1923 | unreachable; | | |
| 1924 | } | 1888 | } |
| 1925 | } | 1889 | } |
| 1926 | | 1890 | |
| 1927 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: mem.Allocator, address: usize) !?*const DW.DwarfInfo { | 1891 | fn getOFileInfoForAddress(self: *@This(), allocator: mem.Allocator, address: usize) !struct { |
| | 1892 | relocated_address: usize, |
| | 1893 | symbol: ?*const MachoSymbol = null, |
| | 1894 | o_file_info: ?*OFileInfo = null, |
| | 1895 | } { |
| 1928 | nosuspend { | 1896 | nosuspend { |
| | 1897 | // Translate the VA into an address into this object |
| 1929 | const relocated_address = address - self.base_address; | 1898 | const relocated_address = address - self.base_address; |
| 1930 | const symbol = machoSearchSymbols(self.symbols, relocated_address) orelse | | |
| 1931 | return null; | | |
| 1932 | | 1899 | |
| | 1900 | // Find the .o file where this symbol is defined |
| | 1901 | const symbol = machoSearchSymbols(self.symbols, relocated_address) orelse return .{ |
| | 1902 | .relocated_address = relocated_address, |
| | 1903 | }; |
| | 1904 | |
| | 1905 | // Check if its debug infos are already in the cache |
| 1933 | const o_file_path = mem.sliceTo(self.strings[symbol.ofile..], 0); | 1906 | const o_file_path = mem.sliceTo(self.strings[symbol.ofile..], 0); |
| 1934 | var o_file_info = self.ofiles.get(o_file_path) orelse | 1907 | var o_file_info = self.ofiles.getPtr(o_file_path) orelse |
| 1935 | (self.loadOFile(allocator, o_file_path) catch |err| switch (err) { | 1908 | (self.loadOFile(allocator, o_file_path) catch |err| switch (err) { |
| 1936 | error.FileNotFound, | 1909 | error.FileNotFound, |
| 1937 | error.MissingDebugInfo, | 1910 | error.MissingDebugInfo, |
| 1938 | error.InvalidDebugInfo, | 1911 | error.InvalidDebugInfo, |
| 1939 | => return null, | 1912 | => return .{ |
| | 1913 | .relocated_address = relocated_address, |
| | 1914 | .symbol = symbol, |
| | 1915 | }, |
| 1940 | else => return err, | 1916 | else => return err, |
| 1941 | }); | 1917 | }); |
| 1942 | | 1918 | |
| 1943 | return &o_file_info.di; | 1919 | return .{ |
| | 1920 | .relocated_address = relocated_address, |
| | 1921 | .symbol = symbol, |
| | 1922 | .o_file_info = o_file_info, |
| | 1923 | }; |
| 1944 | } | 1924 | } |
| 1945 | } | 1925 | } |
| | 1926 | |
| | 1927 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: mem.Allocator, address: usize) !?*const DW.DwarfInfo { |
| | 1928 | return if ((try self.getOFileInfoForAddress(allocator, address)).o_file_info) |o_file_info| &o_file_info.di else null; |
| | 1929 | } |
| 1946 | }, | 1930 | }, |
| 1947 | .uefi, .windows => struct { | 1931 | .uefi, .windows => struct { |
| 1948 | base_address: usize, | 1932 | base_address: usize, |