| ... | ... | @@ -838,9 +838,13 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo { |
| 838 | 838 | } |
| 839 | 839 | } |
| 840 | 840 | |
| 841 | | fn openCoffDebugInfo(allocator: *mem.Allocator, self_file: fs.File) !ObjectDebugInfo { |
| 841 | /// TODO resources https://github.com/ziglang/zig/issues/4353 |
| 842 | fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !ObjectDebugInfo { |
| 843 | const coff_file = try std.fs.openFileAbsoluteW(coff_file_path.ptr, .{}); |
| 844 | errdefer coff_file.close(); |
| 845 | |
| 842 | 846 | const coff_obj = try allocator.create(coff.Coff); |
| 843 | | coff_obj.* = coff.Coff.init(allocator, self_file); |
| 847 | coff_obj.* = coff.Coff.init(allocator, coff_file); |
| 844 | 848 | |
| 845 | 849 | var di = ObjectDebugInfo{ |
| 846 | 850 | .base_address = undefined, |
| ... | ... | @@ -1007,14 +1011,6 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { |
| 1007 | 1011 | return list.toOwnedSlice(); |
| 1008 | 1012 | } |
| 1009 | 1013 | |
| 1010 | | fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DW.DwarfInfo.Section { |
| 1011 | | const elf_header = (try elf_file.findSection(name)) orelse return null; |
| 1012 | | return DW.DwarfInfo.Section{ |
| 1013 | | .offset = elf_header.sh_offset, |
| 1014 | | .size = elf_header.sh_size, |
| 1015 | | }; |
| 1016 | | } |
| 1017 | | |
| 1018 | 1014 | fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 { |
| 1019 | 1015 | const start = try math.cast(usize, offset); |
| 1020 | 1016 | const end = start + try math.cast(usize, size); |
| ... | ... | @@ -1022,11 +1018,10 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 { |
| 1022 | 1018 | } |
| 1023 | 1019 | |
| 1024 | 1020 | /// TODO resources https://github.com/ziglang/zig/issues/4353 |
| 1025 | | pub fn openElfDebugInfo( |
| 1026 | | allocator: *mem.Allocator, |
| 1027 | | data: []const u8, |
| 1028 | | ) !DW.DwarfInfo { |
| 1029 | | var seekable_stream = io.SliceSeekableInStream.init(data); |
| 1021 | pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !ObjectDebugInfo { |
| 1022 | const mapped_mem = mapWholeFile(elf_file_path) catch |_| return error.InvalidDebugInfo; |
| 1023 | |
| 1024 | var seekable_stream = io.SliceSeekableInStream.init(mapped_mem); |
| 1030 | 1025 | var efile = try elf.Elf.openStream( |
| 1031 | 1026 | allocator, |
| 1032 | 1027 | @ptrCast(*DW.DwarfSeekableStream, &seekable_stream.seekable_stream), |
| ... | ... | @@ -1046,26 +1041,32 @@ pub fn openElfDebugInfo( |
| 1046 | 1041 | |
| 1047 | 1042 | var di = DW.DwarfInfo{ |
| 1048 | 1043 | .endian = efile.endian, |
| 1049 | | .debug_info = try chopSlice(data, debug_info.sh_offset, debug_info.sh_size), |
| 1050 | | .debug_abbrev = try chopSlice(data, debug_abbrev.sh_offset, debug_abbrev.sh_size), |
| 1051 | | .debug_str = try chopSlice(data, debug_str.sh_offset, debug_str.sh_size), |
| 1052 | | .debug_line = try chopSlice(data, debug_line.sh_offset, debug_line.sh_size), |
| 1044 | .debug_info = try chopSlice(mapped_mem, debug_info.sh_offset, debug_info.sh_size), |
| 1045 | .debug_abbrev = try chopSlice(mapped_mem, debug_abbrev.sh_offset, debug_abbrev.sh_size), |
| 1046 | .debug_str = try chopSlice(mapped_mem, debug_str.sh_offset, debug_str.sh_size), |
| 1047 | .debug_line = try chopSlice(mapped_mem, debug_line.sh_offset, debug_line.sh_size), |
| 1053 | 1048 | .debug_ranges = if (opt_debug_ranges) |debug_ranges| |
| 1054 | | try chopSlice(data, debug_ranges.sh_offset, debug_ranges.sh_size) |
| 1049 | try chopSlice(mapped_mem, debug_ranges.sh_offset, debug_ranges.sh_size) |
| 1055 | 1050 | else |
| 1056 | 1051 | null, |
| 1057 | 1052 | }; |
| 1058 | 1053 | |
| 1059 | 1054 | try DW.openDwarfDebugInfo(&di, allocator); |
| 1060 | | return di; |
| 1055 | |
| 1056 | return ObjectDebugInfo{ |
| 1057 | .base_address = undefined, |
| 1058 | .dwarf = di, |
| 1059 | .mapped_memory = mapped_mem, |
| 1060 | }; |
| 1061 | 1061 | } |
| 1062 | 1062 | |
| 1063 | 1063 | /// TODO resources https://github.com/ziglang/zig/issues/4353 |
| 1064 | | fn openMachODebugInfo(allocator: *mem.Allocator, memmo: []const u8) !ObjectDebugInfo { |
| 1065 | | // const hdr = &std.c._mh_execute_header; |
| 1064 | fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !ObjectDebugInfo { |
| 1065 | const mapped_mem = mapWholeFile(macho_file_path) catch |_| return error.InvalidDebugInfo; |
| 1066 | |
| 1066 | 1067 | const hdr = @ptrCast( |
| 1067 | 1068 | *const macho.mach_header_64, |
| 1068 | | @alignCast(@alignOf(macho.mach_header_64), memmo.ptr), |
| 1069 | @alignCast(@alignOf(macho.mach_header_64), mapped_mem.ptr), |
| 1069 | 1070 | ); |
| 1070 | 1071 | assert(hdr.magic == std.macho.MH_MAGIC_64); |
| 1071 | 1072 | |
| ... | ... | @@ -1137,7 +1138,7 @@ fn openMachODebugInfo(allocator: *mem.Allocator, memmo: []const u8) !ObjectDebug |
| 1137 | 1138 | |
| 1138 | 1139 | return ObjectDebugInfo{ |
| 1139 | 1140 | .base_address = undefined, |
| 1140 | | .mapped_memory = undefined, |
| 1141 | .mapped_memory = mapped_mem, |
| 1141 | 1142 | .ofiles = ObjectDebugInfo.OFileTable.init(allocator), |
| 1142 | 1143 | .symbols = symbols, |
| 1143 | 1144 | .strings = strings, |
| ... | ... | @@ -1191,6 +1192,24 @@ const MachoSymbol = struct { |
| 1191 | 1192 | } |
| 1192 | 1193 | }; |
| 1193 | 1194 | |
| 1195 | fn mapWholeFile(path: []const u8) ![]const u8 { |
| 1196 | const file = try fs.openFileAbsolute(path, .{}); |
| 1197 | defer file.close(); |
| 1198 | |
| 1199 | const file_len = try math.cast(usize, try file.getEndPos()); |
| 1200 | const mapped_mem = try os.mmap( |
| 1201 | null, |
| 1202 | file_len, |
| 1203 | os.PROT_READ, |
| 1204 | os.MAP_SHARED, |
| 1205 | file.handle, |
| 1206 | 0, |
| 1207 | ); |
| 1208 | errdefer os.munmap(mapped_mem); |
| 1209 | |
| 1210 | return mapped_mem; |
| 1211 | } |
| 1212 | |
| 1194 | 1213 | pub const DebugInfo = struct { |
| 1195 | 1214 | allocator: *mem.Allocator, |
| 1196 | 1215 | address_map: std.AutoHashMap(usize, *ObjectDebugInfo), |
| ... | ... | @@ -1253,30 +1272,14 @@ pub const DebugInfo = struct { |
| 1253 | 1272 | return obj_di; |
| 1254 | 1273 | } |
| 1255 | 1274 | |
| 1256 | | const image_name = std.c._dyld_get_image_name(i); |
| 1257 | | const exe_file = try fs.openFileAbsoluteC(image_name, .{}); |
| 1258 | | errdefer exe_file.close(); |
| 1259 | | |
| 1260 | | const exe_len = math.cast(usize, try exe_file.getEndPos()) catch |
| 1261 | | return error.DebugInfoTooLarge; |
| 1262 | | const exe_mmap = try os.mmap( |
| 1263 | | null, |
| 1264 | | exe_len, |
| 1265 | | os.PROT_READ, |
| 1266 | | os.MAP_SHARED, |
| 1267 | | exe_file.handle, |
| 1268 | | 0, |
| 1269 | | ); |
| 1270 | | errdefer os.munmap(exe_mmap); |
| 1271 | | |
| 1272 | 1275 | const obj_di = try self.allocator.create(ObjectDebugInfo); |
| 1273 | 1276 | errdefer self.allocator.destroy(obj_di); |
| 1274 | 1277 | |
| 1275 | 1278 | try self.address_map.putNoClobber(base_address, obj_di); |
| 1276 | 1279 | |
| 1277 | | obj_di.* = try openMachODebugInfo(self.allocator, exe_mmap); |
| 1280 | const macho_path = mem.toSliceConst(u8, std.c._dyld_get_image_name(i)); |
| 1281 | obj_di.* = try openMachODebugInfo(self.allocator, macho_path); |
| 1278 | 1282 | obj_di.base_address = base_address; |
| 1279 | | obj_di.mapped_memory = exe_mmap; |
| 1280 | 1283 | |
| 1281 | 1284 | return obj_di; |
| 1282 | 1285 | } |
| ... | ... | @@ -1348,18 +1351,12 @@ pub const DebugInfo = struct { |
| 1348 | 1351 | ); |
| 1349 | 1352 | assert(len > 0); |
| 1350 | 1353 | |
| 1351 | | // The compiler segfaults if the slicing is done as a parameter |
| 1352 | | // (#4423) |
| 1353 | | const tmp = name_buffer[0..:0]; |
| 1354 | | const file_obj = try fs.openFileAbsoluteW(tmp, .{}); |
| 1355 | | errdefer file_obj.close(); |
| 1356 | | |
| 1357 | 1354 | const obj_di = try self.allocator.create(ObjectDebugInfo); |
| 1358 | 1355 | errdefer self.allocator.destroy(obj_di); |
| 1359 | 1356 | |
| 1360 | 1357 | try self.address_map.putNoClobber(seg_start, obj_di); |
| 1361 | 1358 | |
| 1362 | | obj_di.* = try openCoffDebugInfo(self.allocator, file_obj); |
| 1359 | obj_di.* = try openCoffDebugInfo(self.allocator, name_buffer[0..:0]); |
| 1363 | 1360 | obj_di.base_address = seg_start; |
| 1364 | 1361 | |
| 1365 | 1362 | return obj_di; |
| ... | ... | @@ -1407,45 +1404,29 @@ pub const DebugInfo = struct { |
| 1407 | 1404 | } |
| 1408 | 1405 | }.callback)) { |
| 1409 | 1406 | return error.DebugInfoNotFound; |
| 1410 | | } else |err| { |
| 1411 | | switch (err) { |
| 1412 | | error.Found => {}, |
| 1413 | | else => return error.DebugInfoNotFound, |
| 1414 | | } |
| 1407 | } else |err| switch (err) { |
| 1408 | error.Found => {}, |
| 1409 | else => return error.DebugInfoNotFound, |
| 1415 | 1410 | } |
| 1416 | 1411 | |
| 1417 | 1412 | if (self.address_map.getValue(ctx.base_address)) |obj_di| { |
| 1418 | 1413 | return obj_di; |
| 1419 | 1414 | } |
| 1420 | 1415 | |
| 1421 | | const exe_file = if (ctx.name.len > 0) |
| 1422 | | try fs.openFileAbsolute(ctx.name, .{}) |
| 1423 | | else |
| 1424 | | try fs.openSelfExe(); |
| 1425 | | defer exe_file.close(); |
| 1426 | | |
| 1427 | | const exe_len = math.cast(usize, try exe_file.getEndPos()) catch |
| 1428 | | return error.DebugInfoTooLarge; |
| 1429 | | const exe_mmap = try os.mmap( |
| 1430 | | null, |
| 1431 | | exe_len, |
| 1432 | | os.PROT_READ, |
| 1433 | | os.MAP_SHARED, |
| 1434 | | exe_file.handle, |
| 1435 | | 0, |
| 1436 | | ); |
| 1437 | | errdefer os.munmap(exe_mmap); |
| 1416 | const elf_path = if (ctx.name.len > 0) |
| 1417 | ctx.name |
| 1418 | else blk: { |
| 1419 | var buf: [fs.MAX_PATH_BYTES]u8 = undefined; |
| 1420 | break :blk try fs.selfExePath(&buf); |
| 1421 | }; |
| 1438 | 1422 | |
| 1439 | 1423 | const obj_di = try self.allocator.create(ObjectDebugInfo); |
| 1440 | 1424 | errdefer self.allocator.destroy(obj_di); |
| 1441 | 1425 | |
| 1442 | 1426 | try self.address_map.putNoClobber(ctx.base_address, obj_di); |
| 1443 | 1427 | |
| 1444 | | obj_di.* = .{ |
| 1445 | | .dwarf = try openElfDebugInfo(self.allocator, exe_mmap), |
| 1446 | | .mapped_memory = exe_mmap, |
| 1447 | | .base_address = ctx.base_address, |
| 1448 | | }; |
| 1428 | obj_di.* = try openElfDebugInfo(self.allocator, elf_path); |
| 1429 | obj_di.base_address = ctx.base_address; |
| 1449 | 1430 | |
| 1450 | 1431 | return obj_di; |
| 1451 | 1432 | } |
| ... | ... | @@ -1454,7 +1435,7 @@ pub const DebugInfo = struct { |
| 1454 | 1435 | pub const ObjectDebugInfo = switch (builtin.os) { |
| 1455 | 1436 | .macosx, .ios, .watchos, .tvos => struct { |
| 1456 | 1437 | base_address: usize, |
| 1457 | | mapped_memory: []u8, |
| 1438 | mapped_memory: []const u8, |
| 1458 | 1439 | symbols: []const MachoSymbol, |
| 1459 | 1440 | strings: []const u8, |
| 1460 | 1441 | ofiles: OFileTable, |
| ... | ... | @@ -1480,7 +1461,7 @@ pub const ObjectDebugInfo = switch (builtin.os) { |
| 1480 | 1461 | .linux, .freebsd => struct { |
| 1481 | 1462 | base_address: usize, |
| 1482 | 1463 | dwarf: DW.DwarfInfo, |
| 1483 | | mapped_memory: []u8, |
| 1464 | mapped_memory: []const u8, |
| 1484 | 1465 | }, |
| 1485 | 1466 | else => DW.DwarfInfo, |
| 1486 | 1467 | }; |