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 {...@@ -36,10 +36,6 @@ comptime {
36 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {36 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
37 @export(main2, .{ .name = "main" });37 @export(main2, .{ .name = "main" });
38 }38 }
39 } else if (builtin.os.tag == .windows) {
40 if (!@hasDecl(root, "wWinMainCRTStartup") and !@hasDecl(root, "mainCRTStartup")) {
41 @export(wWinMainCRTStartup2, .{ .name = "wWinMainCRTStartup" });
42 }
43 } else if (builtin.os.tag == .wasi and @hasDecl(root, "main")) {39 } else if (builtin.os.tag == .wasi and @hasDecl(root, "main")) {
44 @export(wasiMain2, .{ .name = "_start" });40 @export(wasiMain2, .{ .name = "_start" });
45 } else {41 } else {
src/link/Coff.zig+88-5
...@@ -1130,6 +1130,10 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -1130,6 +1130,10 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
1130 sub_prog_node.activate();1130 sub_prog_node.activate();
1131 defer sub_prog_node.end();1131 defer sub_prog_node.end();
11321132
1133 if (build_options.enable_logging) {
1134 self.logSymtab();
1135 }
1136
1133 if (self.getEntryPoint()) |entry_sym_loc| {1137 if (self.getEntryPoint()) |entry_sym_loc| {
1134 self.entry_addr = self.getSymbol(entry_sym_loc).value;1138 self.entry_addr = self.getSymbol(entry_sym_loc).value;
1135 }1139 }
...@@ -1428,7 +1432,7 @@ inline fn getSizeOfImage(self: Coff) u32 {...@@ -1428,7 +1432,7 @@ inline fn getSizeOfImage(self: Coff) u32 {
14281432
1429/// Returns symbol location corresponding to the set entrypoint (if any).1433/// Returns symbol location corresponding to the set entrypoint (if any).
1430pub fn getEntryPoint(self: Coff) ?SymbolWithLoc {1434pub fn getEntryPoint(self: Coff) ?SymbolWithLoc {
1431 const entry_name = self.base.options.entry orelse "mainCRTStartup"; // TODO this is incomplete1435 const entry_name = self.base.options.entry orelse "_start"; // TODO this is incomplete
1432 return self.globals.get(entry_name);1436 return self.globals.get(entry_name);
1433}1437}
14341438
...@@ -1439,14 +1443,15 @@ pub fn getSymbolPtr(self: *Coff, sym_loc: SymbolWithLoc) *coff.Symbol {...@@ -1439,14 +1443,15 @@ pub fn getSymbolPtr(self: *Coff, sym_loc: SymbolWithLoc) *coff.Symbol {
1439}1443}
14401444
1441/// Returns symbol described by `sym_with_loc` descriptor.1445/// Returns symbol described by `sym_with_loc` descriptor.
1442pub fn getSymbol(self: *Coff, sym_loc: SymbolWithLoc) coff.Symbol {1446pub fn getSymbol(self: *const Coff, sym_loc: SymbolWithLoc) *const coff.Symbol {
1443 return self.getSymbolPtr(sym_loc).*;1447 assert(sym_loc.file == null); // TODO linking object files
1448 return &self.locals.items[sym_loc.sym_index];
1444}1449}
14451450
1446/// Returns name of the symbol described by `sym_with_loc` descriptor.1451/// 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 {
1448 assert(sym_loc.file == null); // TODO linking object files1453 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);
1450 const offset = sym.getNameOffset() orelse return sym.getName().?;1455 const offset = sym.getNameOffset() orelse return sym.getName().?;
1451 return self.strtab.get(offset).?;1456 return self.strtab.get(offset).?;
1452}1457}
...@@ -1486,3 +1491,81 @@ fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {...@@ -1486,3 +1491,81 @@ fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {
1486 mem.set(u8, symbol.name[0..4], 0);1491 mem.set(u8, symbol.name[0..4], 0);
1487 mem.writeIntLittle(u32, symbol.name[4..8], offset);1492 mem.writeIntLittle(u32, symbol.name[4..8], offset);
1488}1493}
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}