authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-29 14:12:39+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-30 10:42:21+02:00
logdb1a3bb0e70338dc5261adf148284c1408d3df87
treeeeac34fa97b3d03116b6df5ad5a7f1f59732600b
parentb4e3b87a526378c33d4158ccc622a5183eadfb3f

coff: fallback to _start as default entry point for now

This is not technically correct, but given that we are not yet able to link against the CRT, it's a good default until then. Add basic logging of generated symbol table in the linker.

2 files changed, 88 insertions(+), 9 deletions(-)

lib/std/start.zig-4
......@@ -36,10 +36,6 @@ comptime {
3636 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
3737 @export(main2, .{ .name = "main" });
3838 }
39 } else if (builtin.os.tag == .windows) {
40 if (!@hasDecl(root, "wWinMainCRTStartup") and !@hasDecl(root, "mainCRTStartup")) {
41 @export(wWinMainCRTStartup2, .{ .name = "wWinMainCRTStartup" });
42 }
4339 } else if (builtin.os.tag == .wasi and @hasDecl(root, "main")) {
4440 @export(wasiMain2, .{ .name = "_start" });
4541 } else {
src/link/Coff.zig+88-5
......@@ -1130,6 +1130,10 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
11301130 sub_prog_node.activate();
11311131 defer sub_prog_node.end();
11321132
1133 if (build_options.enable_logging) {
1134 self.logSymtab();
1135 }
1136
11331137 if (self.getEntryPoint()) |entry_sym_loc| {
11341138 self.entry_addr = self.getSymbol(entry_sym_loc).value;
11351139 }
......@@ -1428,7 +1432,7 @@ inline fn getSizeOfImage(self: Coff) u32 {
14281432
14291433/// Returns symbol location corresponding to the set entrypoint (if any).
14301434pub fn getEntryPoint(self: Coff) ?SymbolWithLoc {
1431 const entry_name = self.base.options.entry orelse "mainCRTStartup"; // TODO this is incomplete
1435 const entry_name = self.base.options.entry orelse "_start"; // TODO this is incomplete
14321436 return self.globals.get(entry_name);
14331437}
14341438
......@@ -1439,14 +1443,15 @@ pub fn getSymbolPtr(self: *Coff, sym_loc: SymbolWithLoc) *coff.Symbol {
14391443}
14401444
14411445/// Returns symbol described by `sym_with_loc` descriptor.
1442pub fn getSymbol(self: *Coff, sym_loc: SymbolWithLoc) coff.Symbol {
1443 return self.getSymbolPtr(sym_loc).*;
1446pub fn getSymbol(self: *const Coff, sym_loc: SymbolWithLoc) *const coff.Symbol {
1447 assert(sym_loc.file == null); // TODO linking object files
1448 return &self.locals.items[sym_loc.sym_index];
14441449}
14451450
14461451/// Returns name of the symbol described by `sym_with_loc` descriptor.
1447pub fn getSymbolName(self: *Coff, sym_loc: SymbolWithLoc) []const u8 {
1452pub fn getSymbolName(self: *const Coff, sym_loc: SymbolWithLoc) []const u8 {
14481453 assert(sym_loc.file == null); // TODO linking object files
1449 const sym = self.locals.items[sym_loc.sym_index];
1454 const sym = self.getSymbol(sym_loc);
14501455 const offset = sym.getNameOffset() orelse return sym.getName().?;
14511456 return self.strtab.get(offset).?;
14521457}
......@@ -1486,3 +1491,81 @@ fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {
14861491 mem.set(u8, symbol.name[0..4], 0);
14871492 mem.writeIntLittle(u32, symbol.name[4..8], offset);
14881493}
1494
1495fn logSymAttributes(sym: *const coff.Symbol, buf: *[4]u8) []const u8 {
1496 mem.set(u8, buf[0..4], '_');
1497 switch (sym.section_number) {
1498 .UNDEFINED => {
1499 buf[3] = 'u';
1500 switch (sym.storage_class) {
1501 .EXTERNAL => buf[1] = 'e',
1502 .WEAK_EXTERNAL => buf[1] = 'w',
1503 .NULL => {},
1504 else => unreachable,
1505 }
1506 },
1507 .ABSOLUTE => unreachable, // handle ABSOLUTE
1508 .DEBUG => unreachable,
1509 else => {
1510 buf[0] = 's';
1511 switch (sym.storage_class) {
1512 .EXTERNAL => buf[1] = 'e',
1513 .WEAK_EXTERNAL => buf[1] = 'w',
1514 .NULL => {},
1515 else => unreachable,
1516 }
1517 },
1518 }
1519 return buf[0..];
1520}
1521
1522fn logSymtab(self: *Coff) void {
1523 var buf: [4]u8 = undefined;
1524
1525 log.debug("symtab:", .{});
1526 log.debug(" object(null)", .{});
1527 for (self.locals.items) |*sym, sym_id| {
1528 const where = if (sym.section_number == .UNDEFINED) "ord" else "sect";
1529 const def_index: u16 = switch (sym.section_number) {
1530 .UNDEFINED => 0, // TODO
1531 .ABSOLUTE => unreachable, // TODO
1532 .DEBUG => unreachable, // TODO
1533 else => @enumToInt(sym.section_number),
1534 };
1535 log.debug(" %{d}: {?s} @{x} in {s}({d}), {s}", .{
1536 sym_id,
1537 self.getSymbolName(.{ .sym_index = @intCast(u32, sym_id), .file = null }),
1538 sym.value,
1539 where,
1540 def_index,
1541 logSymAttributes(sym, &buf),
1542 });
1543 }
1544
1545 log.debug("globals table:", .{});
1546 for (self.globals.keys()) |name, id| {
1547 const value = self.globals.values()[id];
1548 log.debug(" {s} => %{d} in object({?d})", .{ name, value.sym_index, value.file });
1549 }
1550
1551 log.debug("GOT entries:", .{});
1552 for (self.got_entries.keys()) |target, i| {
1553 const got_sym = self.getSymbol(.{ .sym_index = self.got_entries.values()[i], .file = null });
1554 const target_sym = self.getSymbol(target);
1555 if (target_sym.section_number == .UNDEFINED) {
1556 log.debug(" {d}@{x} => import('{s}')", .{
1557 i,
1558 got_sym.value,
1559 self.getSymbolName(target),
1560 });
1561 } else {
1562 log.debug(" {d}@{x} => local(%{d}) in object({?d}) {s}", .{
1563 i,
1564 got_sym.value,
1565 target.sym_index,
1566 target.file,
1567 logSymAttributes(target_sym, &buf),
1568 });
1569 }
1570 }
1571}