| ... | ... | @@ -246,6 +246,7 @@ changed_symtab_index: std.array_hash_map.Auto(Symbol.Global.Index, void), |
| 246 | 246 | /// entry in the `.dynamic` section. This allows adding `DT_TEXTREL` to the output `.dynamic` |
| 247 | 247 | /// section in `flush` only when it is actually necessary. See also `nodeAllowsDynamicReloc`. |
| 248 | 248 | textrel_count: u32, |
| 249 | entry_gsi: Symbol.Global.Index.Optional, |
| 249 | 250 | |
| 250 | 251 | dwarf: Dwarf, |
| 251 | 252 | dwarf_shared: std.enums.EnumArray(Dwarf.SharedSection, dwarf_relocs.Shared), |
| ... | ... | @@ -3073,6 +3074,8 @@ fn addGlobalSymbol(elf: *Elf, opts: Symbol.Global.AddOptions) (error{ |
| 3073 | 3074 | } || Error)!Symbol.Global.Index { |
| 3074 | 3075 | _ = opts.lib_name; // TODO |
| 3075 | 3076 | |
| 3077 | log.debug("addGlobalSymbol({q})", .{opts.name}); |
| 3078 | |
| 3076 | 3079 | const gpa = elf.base.comp.gpa; |
| 3077 | 3080 | |
| 3078 | 3081 | try elf.symtab.ensureUnusedCapacity(gpa, 1); |
| ... | ... | @@ -5138,6 +5141,7 @@ fn create( |
| 5138 | 5141 | .section_by_name = .empty, |
| 5139 | 5142 | .changed_symtab_index = .empty, |
| 5140 | 5143 | .textrel_count = 0, |
| 5144 | .entry_gsi = undefined, |
| 5141 | 5145 | |
| 5142 | 5146 | .dwarf = .init(&elf.base, switch (comp.config.debug_format) { |
| 5143 | 5147 | .strip => .@"32", // for .eh_frame |
| ... | ... | @@ -6561,6 +6565,31 @@ fn initHeaders( |
| 6561 | 6565 | .code_view => unreachable, |
| 6562 | 6566 | } |
| 6563 | 6567 | |
| 6568 | // If we have an entry point symbol, create the undefined reference now. |
| 6569 | elf.entry_gsi = entry: switch (elf.options.entry) { |
| 6570 | .default => switch (comp.config.output_mode) { |
| 6571 | .Exe => continue :entry .enabled, |
| 6572 | .Lib, .Obj => continue :entry .disabled, |
| 6573 | }, |
| 6574 | .enabled => continue :entry .{ .named = "_start" }, |
| 6575 | .disabled => .none, |
| 6576 | .named => |sym_name| .wrap(elf.addGlobalSymbol(.{ |
| 6577 | .node = .none, |
| 6578 | .name = sym_name, |
| 6579 | .value = 0, |
| 6580 | .size = 0, |
| 6581 | .type = .NOTYPE, |
| 6582 | .bind = .strong, |
| 6583 | .visibility = .DEFAULT, |
| 6584 | .shndx = .UNDEF, |
| 6585 | }) catch |err| switch (err) { |
| 6586 | error.MultipleDefinitions => unreachable, // shndx is undef |
| 6587 | error.MultipleDefaultVersions => unreachable, // not a versioned symbol |
| 6588 | error.UndefinedDefaultVersion => unreachable, // not a versioned symbol |
| 6589 | else => |e| return e, |
| 6590 | }), |
| 6591 | }; |
| 6592 | |
| 6564 | 6593 | assert(elf.nodes.len == expected_nodes_len); |
| 6565 | 6594 | assert(elf.shdrs.items.len == shnum - 1); // -1 to exclude SHN_UNDEF |
| 6566 | 6595 | |
| ... | ... | @@ -10884,20 +10913,22 @@ fn flushInner( |
| 10884 | 10913 | elf.flushDynamic(); |
| 10885 | 10914 | |
| 10886 | 10915 | const entry_addr: u64 = entry: { |
| 10887 | | const sym_name: []const u8 = name: switch (elf.options.entry) { |
| 10888 | | .default => switch (comp.config.output_mode) { |
| 10889 | | .Exe => continue :name .enabled, |
| 10890 | | .Lib, .Obj => continue :name .disabled, |
| 10891 | | }, |
| 10892 | | .disabled => break :entry 0, |
| 10893 | | .enabled => "_start", |
| 10894 | | .named => |named| named, |
| 10895 | | }; |
| 10896 | | const gsi = elf.globalByName(.{ |
| 10897 | | .name = sym_name, |
| 10898 | | .version = null, |
| 10899 | | }) orelse break :entry 0; |
| 10900 | | break :entry Symbol.Id.global(gsi).value(elf); |
| 10916 | const entry_gsi = elf.entry_gsi.unwrap() orelse break :entry 0; |
| 10917 | |
| 10918 | // Even though we already reported undefined globals earlier, we also need to check here |
| 10919 | // whether the entry point is defined. There are two reasons for this: |
| 10920 | // |
| 10921 | // * If we are emitting something other than an executable, we skipped the undefined globals |
| 10922 | // check, but there could still be an entry point (e.g. due to `-fentry=foo` on the CLI). |
| 10923 | // |
| 10924 | // * The entry point might be defined in an input DSO, which would satisfy the undefined |
| 10925 | // symbol reference but is insufficient here: the entry point needs a local definition. |
| 10926 | |
| 10927 | if (!entry_gsi.resolveAlias(elf).defined(elf)) { |
| 10928 | return diags.fail("undefined entry point symbol '{s}'", .{entry_gsi.name(elf)}); |
| 10929 | } |
| 10930 | |
| 10931 | break :entry Symbol.Id.global(entry_gsi).value(elf); |
| 10901 | 10932 | }; |
| 10902 | 10933 | switch (elf.ehdrPtr()) { |
| 10903 | 10934 | inline else => |ehdr| elf.targetStore(&ehdr.entry, @intCast(entry_addr)), |