authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-10 13:18:28+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-20 19:41:29+01:00
log99649794e965ce76c81cb91a7ff78f3a42d533bc
tree35dad55143aea2e65df6b317b07b1edd4e999b36
parentb0b60cd46854f05c830b51693acd2f1ea7b1ee1a

win


2 files changed, 96 insertions(+), 17 deletions(-)

lib/std/debug.zig+94-17
...@@ -248,7 +248,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c...@@ -248,7 +248,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
248 }248 }
249249
250 switch (@atomicRmw(u8, &panicking, .Add, 1, .SeqCst)) {250 switch (@atomicRmw(u8, &panicking, .Add, 1, .SeqCst)) {
251 0 => {251 0, 1 => {
252 const stderr = getStderrStream();252 const stderr = getStderrStream();
253 noasync stderr.print(format ++ "\n", args) catch os.abort();253 noasync stderr.print(format ++ "\n", args) catch os.abort();
254 if (trace) |t| {254 if (trace) |t| {
...@@ -256,7 +256,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c...@@ -256,7 +256,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
256 }256 }
257 dumpCurrentStackTrace(first_trace_addr);257 dumpCurrentStackTrace(first_trace_addr);
258 },258 },
259 1 => {259 2 => {
260 // TODO detect if a different thread caused the panic, because in that case260 // TODO detect if a different thread caused the panic, because in that case
261 // we would want to return here instead of calling abort, so that the thread261 // we would want to return here instead of calling abort, so that the thread
262 // which first called panic can finish printing a stack trace.262 // which first called panic can finish printing a stack trace.
...@@ -404,13 +404,15 @@ pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: us...@@ -404,13 +404,15 @@ pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: us
404404
405/// TODO resources https://github.com/ziglang/zig/issues/4353405/// TODO resources https://github.com/ziglang/zig/issues/4353
406fn printSourceAtAddressWindows(406fn printSourceAtAddressWindows(
407 di: *DebugInfo,407 di1: *DebugInfo,
408 out_stream: var,408 out_stream: var,
409 relocated_address: usize,409 relocated_address: usize,
410 tty_config: TTY.Config,410 tty_config: TTY.Config,
411) !void {411) !void {
412 const di = try di1.lookupByAddress(relocated_address);
413
412 const allocator = getDebugInfoAllocator();414 const allocator = getDebugInfoAllocator();
413 const base_address = process.getBaseAddress();415 const base_address = di.base_address;
414 const relative_address = relocated_address - base_address;416 const relative_address = relocated_address - base_address;
415417
416 var coff_section: *coff.Section = undefined;418 var coff_section: *coff.Section = undefined;
...@@ -630,7 +632,7 @@ pub const TTY = struct {...@@ -630,7 +632,7 @@ pub const TTY = struct {
630};632};
631633
632/// TODO resources https://github.com/ziglang/zig/issues/4353634/// TODO resources https://github.com/ziglang/zig/issues/4353
633fn populateModule(di: *DebugInfo, mod: *Module) !void {635fn populateModule(di: *ObjectDebugInfo, mod: *Module) !void {
634 if (mod.populated)636 if (mod.populated)
635 return;637 return;
636 const allocator = getDebugInfoAllocator();638 const allocator = getDebugInfoAllocator();
...@@ -824,27 +826,28 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {...@@ -824,27 +826,28 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
824 if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {826 if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {
825 return noasync root.os.debug.openSelfDebugInfo(allocator);827 return noasync root.os.debug.openSelfDebugInfo(allocator);
826 }828 }
827 if (builtin.os == .windows) {
828 return noasync openSelfDebugInfoWindows(allocator);
829 }
830 if (comptime std.Target.current.isDarwin()) {829 if (comptime std.Target.current.isDarwin()) {
831 return noasync openSelfDebugInfoMacOs(allocator);830 return noasync openSelfDebugInfoMacOs(allocator);
832 }831 }
833 if (builtin.os == .linux) {832 if (builtin.os == .linux or builtin.os == .windows) {
834 _ = try allocator.create(u32);833 _ = try allocator.create(u32);
835 return DebugInfo.init(allocator);834 return DebugInfo.init(allocator);
836 }835 }
837 return noasync openSelfDebugInfoPosix(allocator);836 return noasync openSelfDebugInfoPosix(allocator);
838}837}
839838
840fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {839fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !ObjectDebugInfo {
841 const self_file = try fs.openSelfExe();840 const self_file = try fs.openSelfExe();
842 defer self_file.close();841 defer self_file.close();
842 return openCoffDebugInfo(allocator, self_file);
843}
843844
845fn openCoffDebugInfo(allocator: *mem.Allocator, self_file: fs.File) !ObjectDebugInfo {
844 const coff_obj = try allocator.create(coff.Coff);846 const coff_obj = try allocator.create(coff.Coff);
845 coff_obj.* = coff.Coff.init(allocator, self_file);847 coff_obj.* = coff.Coff.init(allocator, self_file);
846848
847 var di = DebugInfo{849 var di = ObjectDebugInfo{
850 .base_address = 0,
848 .coff = coff_obj,851 .coff = coff_obj,
849 .pdb = undefined,852 .pdb = undefined,
850 .sect_contribs = undefined,853 .sect_contribs = undefined,
...@@ -1202,24 +1205,97 @@ const MachoSymbol = struct {...@@ -1202,24 +1205,97 @@ const MachoSymbol = struct {
12021205
1203pub const DebugInfo = struct {1206pub const DebugInfo = struct {
1204 allocator: *mem.Allocator,1207 allocator: *mem.Allocator,
1205 address_map: std.StringHashMap(*ObjectDebugInfo),1208 address_map: std.AutoHashMap(usize, *ObjectDebugInfo),
12061209
1207 pub fn init(allocator: *mem.Allocator) DebugInfo {1210 pub fn init(allocator: *mem.Allocator) DebugInfo {
1208 return DebugInfo{1211 return DebugInfo{
1209 .allocator = allocator,1212 .allocator = allocator,
1210 .address_map = std.StringHashMap(*ObjectDebugInfo).init(allocator),1213 .address_map = std.AutoHashMap(usize, *ObjectDebugInfo).init(allocator),
1211 };1214 };
1212 }1215 }
12131216
1214 pub fn deinit(self: *DebugInfo) void {1217 pub fn deinit(self: *DebugInfo) void {
1218 // XXX Free the values
1215 self.address_map.deinit();1219 self.address_map.deinit();
1216 }1220 }
12171221
1218 pub fn lookupByAddress(self: *DebugInfo, address: usize) !*ObjectDebugInfo {1222 pub fn lookupByAddress(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1219 const obj_di = try self.lookupModuleDl(address);1223 const obj_di = if (builtin.os == .windows)
1224 try self.lookupModuleWin32(address)
1225 else
1226 try self.lookupModuleDl(address);
1220 return obj_di;1227 return obj_di;
1221 }1228 }
12221229
1230 fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1231 const process_handle = windows.kernel32.GetCurrentProcess();
1232
1233 var modules: [32]windows.HMODULE = undefined;
1234 var modules_needed: windows.DWORD = undefined;
1235 // XXX Ask for the number of modules by passing size zero
1236 if (windows.kernel32.K32EnumProcessModules(
1237 process_handle,
1238 @ptrCast([*]windows.HMODULE, &modules),
1239 @sizeOf(@TypeOf(modules)),
1240 &modules_needed,
1241 ) == 0)
1242 return error.DebugInfoNotFound;
1243
1244 for (modules[0..modules_needed]) |module| {
1245 var info: windows.MODULEINFO = undefined;
1246 if (windows.kernel32.K32GetModuleInformation(
1247 process_handle,
1248 module,
1249 &info,
1250 @sizeOf(@TypeOf(info)),
1251 ) == 0)
1252 return error.DebugInfoNotFound;
1253
1254 const seg_start = @ptrToInt(info.lpBaseOfDll);
1255 const seg_end = seg_start + info.SizeOfImage;
1256
1257 if (address >= seg_start and address < seg_end) {
1258 var name_buffer: [windows.PATH_MAX_WIDE]u16 = [_]u16{0} ** windows.PATH_MAX_WIDE;
1259 // XXX Use W variant
1260 const len = windows.kernel32.K32GetModuleFileNameExW(
1261 process_handle,
1262 module,
1263 @ptrCast(windows.LPWSTR, &name_buffer),
1264 @sizeOf(@TypeOf(name_buffer)) / @sizeOf(u16),
1265 );
1266 assert(len > 0);
1267 const name_slice = mem.toSlice(u16, name_buffer[0..:0]);
1268 warn("slice len {}\n", .{name_slice.len});
1269
1270 const x = try std.unicode.utf16leToUtf8Alloc(self.allocator, name_buffer[0..]);
1271 warn("ask for {s} len {}\n", .{ x, name_slice.len });
1272 self.allocator.free(x);
1273
1274 if (self.address_map.getValue(seg_start)) |obj_di| {
1275 warn("cache hit!\n", .{});
1276 return obj_di;
1277 }
1278
1279 warn("loading?\n", .{});
1280 const file_obj = try fs.openFileAbsoluteW(name_slice, .{});
1281 errdefer file_obj.close();
1282 warn("loaded!\n", .{});
1283
1284 const obj_di = try self.allocator.create(ObjectDebugInfo);
1285 errdefer self.allocator.destroy(obj_di);
1286
1287 try self.address_map.putNoClobber(seg_start, obj_di);
1288
1289 obj_di.* = try openCoffDebugInfo(self.allocator, file_obj);
1290 obj_di.base_address = seg_start;
1291
1292 return obj_di;
1293 }
1294 }
1295
1296 return error.DebugInfoNotFound;
1297 }
1298
1223 fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo {1299 fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1224 var ctx = DIPContext{ .address = address };1300 var ctx = DIPContext{ .address = address };
12251301
...@@ -1231,7 +1307,7 @@ pub const DebugInfo = struct {...@@ -1231,7 +1307,7 @@ pub const DebugInfo = struct {
12311307
1232 warn("found in \"{s}\"\n", .{ctx.name});1308 warn("found in \"{s}\"\n", .{ctx.name});
12331309
1234 if (self.address_map.getValue(ctx.name)) |obj_di| {1310 if (self.address_map.getValue(ctx.base_address)) |obj_di| {
1235 warn("cache hit!\n", .{});1311 warn("cache hit!\n", .{});
1236 return obj_di;1312 return obj_di;
1237 }1313 }
...@@ -1257,7 +1333,7 @@ pub const DebugInfo = struct {...@@ -1257,7 +1333,7 @@ pub const DebugInfo = struct {
1257 const obj_di = try self.allocator.create(ObjectDebugInfo);1333 const obj_di = try self.allocator.create(ObjectDebugInfo);
1258 errdefer self.allocator.destroy(obj_di);1334 errdefer self.allocator.destroy(obj_di);
12591335
1260 try self.address_map.putNoClobber(ctx.name, obj_di);1336 try self.address_map.putNoClobber(ctx.base_address, obj_di);
12611337
1262 obj_di.* = .{1338 obj_di.* = .{
1263 .dwarf = try openElfDebugInfo(self.allocator, exe_mmap),1339 .dwarf = try openElfDebugInfo(self.allocator, exe_mmap),
...@@ -1289,7 +1365,7 @@ fn dl_iterate_phdr_callback(info: *os.dl_phdr_info, size: usize, context: ?*DIPC...@@ -1289,7 +1365,7 @@ fn dl_iterate_phdr_callback(info: *os.dl_phdr_info, size: usize, context: ?*DIPC
1289 const seg_start = info.dlpi_addr + phdr.p_vaddr;1365 const seg_start = info.dlpi_addr + phdr.p_vaddr;
1290 const seg_end = seg_start + phdr.p_memsz;1366 const seg_end = seg_start + phdr.p_memsz;
12911367
1292 if (address > seg_start and address <= seg_end) {1368 if (address >= seg_start and address < seg_end) {
1293 // Android libc uses NULL instead of an empty string to mark the1369 // Android libc uses NULL instead of an empty string to mark the
1294 // main program1370 // main program
1295 context.?.name = if (info.dlpi_name) |dlpi_name|1371 context.?.name = if (info.dlpi_name) |dlpi_name|
...@@ -1324,6 +1400,7 @@ pub const ObjectDebugInfo = switch (builtin.os) {...@@ -1324,6 +1400,7 @@ pub const ObjectDebugInfo = switch (builtin.os) {
1324 }1400 }
1325 },1401 },
1326 .uefi, .windows => struct {1402 .uefi, .windows => struct {
1403 base_address: usize,
1327 pdb: pdb.Pdb,1404 pdb: pdb.Pdb,
1328 coff: *coff.Coff,1405 coff: *coff.Coff,
1329 sect_contribs: []pdb.SectionContribEntry,1406 sect_contribs: []pdb.SectionContribEntry,
lib/std/fs.zig+2
...@@ -859,6 +859,8 @@ pub const Dir = struct {...@@ -859,6 +859,8 @@ pub const Dir = struct {
859 null,859 null,
860 0,860 0,
861 );861 );
862 std.debug.warn("here? rc {x}\n", .{rc});
863
862 switch (rc) {864 switch (rc) {
863 .SUCCESS => return result,865 .SUCCESS => return result,
864 .OBJECT_NAME_INVALID => unreachable,866 .OBJECT_NAME_INVALID => unreachable,