| ... | ... | @@ -65,8 +65,6 @@ section_merge_pending_index: u32, |
| 65 | 65 | symbols: std.ArrayList(Symbol), |
| 66 | 66 | globals: std.array_hash_map.Auto(GlobalName, Symbol.Index), |
| 67 | 67 | global_pending_index: u32, |
| 68 | | late_globals: std.ArrayList(Node.GlobalMapIndex), |
| 69 | | late_globals_pending_index: u32, |
| 70 | 68 | navs: std.array_hash_map.Auto(InternPool.Nav.Index, Symbol.Index), |
| 71 | 69 | uavs: std.array_hash_map.Auto(InternPool.Index, Symbol.Index), |
| 72 | 70 | lazy: std.EnumArray(link.File.LazySymbol.Kind, struct { |
| ... | ... | @@ -188,17 +186,16 @@ pub const Node = union(enum) { |
| 188 | 186 | archive_member: Member.Index, |
| 189 | 187 | |
| 190 | 188 | coff_header, |
| 189 | |
| 191 | 190 | /// Image only |
| 192 | 191 | optional_header, |
| 193 | | /// Image only |
| 194 | 192 | data_directories, |
| 195 | 193 | |
| 196 | 194 | section_table, |
| 197 | | // Archives and objects only |
| 195 | |
| 196 | /// Archives and objects only |
| 198 | 197 | symbol_table, |
| 199 | | // Archives and objects only |
| 200 | 198 | string_table, |
| 201 | | // Archives and objects only |
| 202 | 199 | relocation_table: Symbol.SectionNumber, |
| 203 | 200 | relocation_table_entry: Reloc.Index, |
| 204 | 201 | |
| ... | ... | @@ -220,11 +217,12 @@ pub const Node = union(enum) { |
| 220 | 217 | pseudo_section: PseudoSectionMapIndex, |
| 221 | 218 | object_section: ObjectSectionMapIndex, |
| 222 | 219 | input_section: InputSection.Index, |
| 223 | | import_thunk: GlobalMapIndex, // TODO: Rename to import_thunk |
| 220 | import_thunk: GlobalMapIndex, |
| 224 | 221 | nav: NavMapIndex, |
| 225 | 222 | uav: UavMapIndex, |
| 226 | 223 | lazy_code: LazyMapRef.Index(.code), |
| 227 | 224 | lazy_const_data: LazyMapRef.Index(.const_data), |
| 225 | builtin: Symbol.Index, |
| 228 | 226 | |
| 229 | 227 | /// Takes the place of a known node index when that node is not present in the output |
| 230 | 228 | placeholder, |
| ... | ... | @@ -945,7 +943,7 @@ pub const Symbol = struct { |
| 945 | 943 | // The size of the symbol |
| 946 | 944 | size: u32, |
| 947 | 945 | /// Only valid when .ni == .input_section and .value_tag == .node_offset |
| 948 | | /// TODO: This is only used for name lookups, could just be String? |
| 946 | /// TODO: This is only used for name lookups, could just be String, remove `input_symbols`? |
| 949 | 947 | isli: Node.InputSection.LocalIndex, |
| 950 | 948 | /// The next symbol in the list of aliases of this symbol. |
| 951 | 949 | next_alias_si: Symbol.Index, |
| ... | ... | @@ -1322,7 +1320,8 @@ pub const Reloc = extern struct { |
| 1322 | 1320 | switch (target_machine) { |
| 1323 | 1321 | else => |machine| @panic(@tagName(machine)), |
| 1324 | 1322 | .AMD64 => switch (reloc.type.AMD64) { |
| 1325 | | // TODO: Report these later, in reportUndefs -> reportRelocErrs ? |
| 1323 | // TODO: Could wait to report these later, in reportUndefs -> reportRelocErrs, |
| 1324 | // so that this function doesn't return an err |
| 1326 | 1325 | else => |kind| return coff.base.comp.link_diags.fail( |
| 1327 | 1326 | "absolute symbol '{s}' targeted by invalid relocation type: {t}", |
| 1328 | 1327 | .{ target_sym.gmi.globalName(coff).name.toSlice(coff), kind }, |
| ... | ... | @@ -1475,8 +1474,10 @@ pub const Reloc = extern struct { |
| 1475 | 1474 | pub fn delete(reloc: *Reloc, coff: *Coff) void { |
| 1476 | 1475 | if (reloc.sri != .none) { |
| 1477 | 1476 | // TODO: Need to remove this from the COFF relocation table (maybe removeswap?) |
| 1478 | | // TODO: If this was the last reloc causing something to be in the symbol table, we should remove the sti |
| 1479 | | // That will require flushSymbolTableIndex on the swapped symbol if we exchange indices |
| 1477 | // TODO: If this was the last reloc causing something to be in the symbol table, we should remove |
| 1478 | // the symbol table entry (and unset sti). That will require flushSymbolTableIndex on the |
| 1479 | // swapped symbol if we exchange indices |
| 1480 | unreachable; |
| 1480 | 1481 | } |
| 1481 | 1482 | |
| 1482 | 1483 | switch (reloc.prev) { |
| ... | ... | @@ -1623,8 +1624,6 @@ fn create( |
| 1623 | 1624 | .symbols = .empty, |
| 1624 | 1625 | .globals = .empty, |
| 1625 | 1626 | .global_pending_index = 0, |
| 1626 | | .late_globals = .empty, |
| 1627 | | .late_globals_pending_index = 0, |
| 1628 | 1627 | .navs = .empty, |
| 1629 | 1628 | .uavs = .empty, |
| 1630 | 1629 | .lazy = .initFill(.{ |
| ... | ... | @@ -1698,7 +1697,6 @@ pub fn deinit(coff: *Coff) void { |
| 1698 | 1697 | coff.object_section_table.deinit(gpa); |
| 1699 | 1698 | coff.symbols.deinit(gpa); |
| 1700 | 1699 | coff.globals.deinit(gpa); |
| 1701 | | coff.late_globals.deinit(gpa); |
| 1702 | 1700 | coff.navs.deinit(gpa); |
| 1703 | 1701 | coff.uavs.deinit(gpa); |
| 1704 | 1702 | for (&coff.lazy.values) |*lazy| lazy.map.deinit(gpa); |
| ... | ... | @@ -2109,7 +2107,7 @@ fn initHeaders( |
| 2109 | 2107 | }); |
| 2110 | 2108 | } |
| 2111 | 2109 | |
| 2112 | | // TODO: Lazily initialize this instead? |
| 2110 | // TODO: Lazily initialize this instead, avoid the extra logic for this in flushMoved / flushResized |
| 2113 | 2111 | coff.import_table.ni = try coff.mf.addLastChildNode( |
| 2114 | 2112 | gpa, |
| 2115 | 2113 | (try coff.objectSectionMapIndex( |
| ... | ... | @@ -2225,18 +2223,27 @@ pub fn initBuiltins(coff: *Coff) !void { |
| 2225 | 2223 | sym.ni = Node.known.header; |
| 2226 | 2224 | } |
| 2227 | 2225 | |
| 2226 | defer coff.flushSectionMerges() catch unreachable; |
| 2228 | 2227 | if (coff.isImage() and target.isMinGW() and comp.config.link_libc) { |
| 2229 | | try coff.symbols.ensureUnusedCapacity(gpa, 6); |
| 2228 | try coff.symbols.ensureUnusedCapacity(gpa, 8); |
| 2230 | 2229 | try coff.globals.ensureUnusedCapacity(gpa, 2); |
| 2231 | | try coff.nodes.ensureUnusedCapacity(gpa, 6); |
| 2230 | try coff.nodes.ensureUnusedCapacity(gpa, 8); |
| 2231 | try coff.section_merges.ensureUnusedCapacity(gpa, 2); |
| 2232 | 2232 | |
| 2233 | 2233 | const lists: []const struct { global: []const u8, start: String, end: String } = &.{ |
| 2234 | 2234 | .{ .global = "__CTOR_LIST__", .start = .@".ctors", .end = .@".ctors$ZZZ" }, |
| 2235 | 2235 | .{ .global = "__DTOR_LIST__", .start = .@".dtors", .end = .@".dtors$ZZZ" }, |
| 2236 | 2236 | }; |
| 2237 | 2237 | |
| 2238 | // We need to explicitly merge these into .rdata as in objects they can be marked |
| 2239 | // as MEM_WRITE, and would have mismatced section flags. |
| 2240 | try coff.section_merges.put(gpa, .@".ctors", .@".rdata"); |
| 2241 | try coff.section_merges.put(gpa, .@".dtors", .@".rdata"); |
| 2242 | |
| 2238 | 2243 | for (lists) |list| { |
| 2239 | 2244 | const addr_info = coff.targetAddrInfo(); |
| 2245 | |
| 2246 | // Any .(c|d)tor$(.*) input sections will merge in between these sections |
| 2240 | 2247 | const start_osmi = try coff.objectSectionMapIndex( |
| 2241 | 2248 | list.start, |
| 2242 | 2249 | addr_info.alignment, |
| ... | ... | @@ -2248,32 +2255,46 @@ pub fn initBuiltins(coff: *Coff) !void { |
| 2248 | 2255 | .{ .read = true, .initialized = true }, |
| 2249 | 2256 | ); |
| 2250 | 2257 | |
| 2258 | // Additional nodes are used here, instead of just adding the sentinel |
| 2259 | // directly to the section data, since once input sections are added |
| 2260 | // as children, they would overwrite that data. |
| 2251 | 2261 | const start_sym = start_osmi.symbol(coff).get(coff); |
| 2252 | | try start_sym.ni.resize(&coff.mf, gpa, addr_info.size); |
| 2253 | | const start_slice = start_sym.ni.slice(&coff.mf); |
| 2262 | const list_len_si = try coff.globalSymbol(.{ .name = list.global, .type = .data }); |
| 2263 | const list_len_sym = list_len_si.get(coff); |
| 2264 | list_len_sym.setExtra(.{ .size = addr_info.size }); |
| 2265 | list_len_sym.ni = try coff.mf.addFirstChildNode(gpa, start_sym.ni, .{ |
| 2266 | .size = addr_info.size, |
| 2267 | .fixed = true, |
| 2268 | }); |
| 2269 | coff.nodes.appendAssumeCapacity(.{ .builtin = list_len_si }); |
| 2270 | list_len_sym.section_number = start_sym.section_number; |
| 2271 | |
| 2272 | const start_slice = list_len_sym.ni.slice(&coff.mf); |
| 2254 | 2273 | switch (addr_info.magic) { |
| 2255 | 2274 | _ => unreachable, |
| 2256 | 2275 | inline .PE32, .@"PE32+" => |t| { |
| 2257 | 2276 | const addr: *TargetAddr(t) = @ptrCast(@alignCast(start_slice)); |
| 2258 | 2277 | // For __CTOR_LIST__ -1 indicates that the list is null terminated. |
| 2259 | | // For __DTOR_LIST__, this value is ignored. |
| 2278 | // For __DTOR_LIST__, this value is ignored, the list is always null terminated |
| 2260 | 2279 | coff.targetStore(addr, std.math.maxInt(TargetAddr(t))); |
| 2261 | 2280 | }, |
| 2262 | 2281 | } |
| 2263 | 2282 | |
| 2264 | | // Any .(c|d)tor$(.*) input sections will merge in between these sections |
| 2265 | | // TODO: is it guaranteed that there will be no padding between those nodes? |
| 2266 | | |
| 2267 | 2283 | const end_sym = end_osmi.symbol(coff).get(coff); |
| 2268 | | try end_sym.ni.resize(&coff.mf, gpa, addr_info.size); |
| 2269 | | @memset(end_sym.ni.slice(&coff.mf), 0); |
| 2284 | const list_end_si = coff.addSymbolAssumeCapacity(); |
| 2285 | const list_end_sym = list_end_si.get(coff); |
| 2286 | list_end_sym.setExtra(.{ .size = addr_info.size }); |
| 2287 | list_end_sym.ni = try coff.mf.addFirstChildNode(gpa, end_sym.ni, .{ |
| 2288 | .size = addr_info.size, |
| 2289 | .fixed = true, |
| 2290 | }); |
| 2291 | coff.nodes.appendAssumeCapacity(.{ .builtin = list_end_si }); |
| 2292 | list_end_sym.section_number = start_sym.section_number; |
| 2270 | 2293 | |
| 2271 | | const list_si = try coff.globalSymbol(.{ .name = list.global, .type = .data }); |
| 2272 | | const list_sym = list_si.get(coff); |
| 2273 | | list_sym.ni = start_sym.ni; |
| 2274 | | list_sym.section_number = start_sym.section_number; |
| 2294 | @memset(list_end_sym.ni.slice(&coff.mf), 0); |
| 2275 | 2295 | |
| 2276 | | start_sym.setExtra(.{ .next_alias_si = list_si }); |
| 2296 | try list_len_si.flushMoved(coff); |
| 2297 | try list_end_si.flushMoved(coff); |
| 2277 | 2298 | } |
| 2278 | 2299 | } |
| 2279 | 2300 | } |
| ... | ... | @@ -2284,7 +2305,6 @@ pub fn startProgress(coff: *Coff, prog_node: std.Progress.Node) void { |
| 2284 | 2305 | coff.synth_prog_node = prog_node.start("Synthetics", count: { |
| 2285 | 2306 | var count = |
| 2286 | 2307 | coff.globals.count() - coff.global_pending_index + |
| 2287 | | coff.late_globals.items.len - coff.late_globals_pending_index + |
| 2288 | 2308 | coff.section_merges.count() - coff.section_merge_pending_index; |
| 2289 | 2309 | |
| 2290 | 2310 | for (&coff.lazy.values) |*lazy| count += lazy.map.count() - lazy.pending_index; |
| ... | ... | @@ -2344,6 +2364,7 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 2344 | 2364 | .relocation_table, |
| 2345 | 2365 | .relocation_table_entry, |
| 2346 | 2366 | .input_section, |
| 2367 | .builtin, |
| 2347 | 2368 | => unreachable, |
| 2348 | 2369 | .image_section => |si| si, |
| 2349 | 2370 | .import_directory_table => break :parent_rva coff.targetLoad( |
| ... | ... | @@ -2404,7 +2425,7 @@ pub inline fn targetEndian(_: *const Coff) std.lang.Endian { |
| 2404 | 2425 | } |
| 2405 | 2426 | |
| 2406 | 2427 | fn targetAddrInfo(coff: *Coff) struct { |
| 2407 | | size: u64, |
| 2428 | size: u8, |
| 2408 | 2429 | alignment: std.mem.Alignment, |
| 2409 | 2430 | magic: std.coff.OptionalHeader.Magic, |
| 2410 | 2431 | } { |
| ... | ... | @@ -3450,9 +3471,9 @@ fn pseudoSectionMapIndex( |
| 3450 | 3471 | } else pseudo_section_gop.value_ptr.get(coff).section_number; |
| 3451 | 3472 | |
| 3452 | 3473 | try coff.verifyParentSectionAttributes( |
| 3453 | | .pseudo, |
| 3454 | | parent_sn.name(coff), |
| 3474 | parent_sn, |
| 3455 | 3475 | name, |
| 3476 | .pseudo, |
| 3456 | 3477 | .fromFlags(parent_sn.header(coff).flags), |
| 3457 | 3478 | attributes, |
| 3458 | 3479 | ); |
| ... | ... | @@ -3478,6 +3499,7 @@ fn objectSectionMapIndex( |
| 3478 | 3499 | ) !Node.ObjectSectionMapIndex { |
| 3479 | 3500 | const gpa = coff.base.comp.gpa; |
| 3480 | 3501 | const name_slice = name.toSlice(coff); |
| 3502 | // TODO: Should this be a section merge instead? |
| 3481 | 3503 | const effective_attributes = if (coff.isImage() and std.mem.startsWith(u8, name_slice, ".tls")) attr: { |
| 3482 | 3504 | // In images, the .tls section is a read-only template |
| 3483 | 3505 | var attr = attributes; |
| ... | ... | @@ -3541,9 +3563,9 @@ fn objectSectionMapIndex( |
| 3541 | 3563 | } |
| 3542 | 3564 | |
| 3543 | 3565 | try coff.verifyParentSectionAttributes( |
| 3544 | | .object, |
| 3545 | | sym.section_number.name(coff), |
| 3566 | sym.section_number, |
| 3546 | 3567 | name, |
| 3568 | .object, |
| 3547 | 3569 | .fromFlags(sym.section_number.header(coff).flags), |
| 3548 | 3570 | effective_attributes, |
| 3549 | 3571 | ); |
| ... | ... | @@ -3554,21 +3576,34 @@ fn objectSectionMapIndex( |
| 3554 | 3576 | // TODO: Include align in attrs and verify the current align is >= requested |
| 3555 | 3577 | fn verifyParentSectionAttributes( |
| 3556 | 3578 | coff: *Coff, |
| 3557 | | kind: enum { pseudo, object }, |
| 3558 | | parent_name: String, |
| 3579 | parent: Symbol.SectionNumber, |
| 3559 | 3580 | child_name: String, |
| 3581 | child_kind: enum { pseudo, object }, |
| 3560 | 3582 | parent_attrs: ObjectSectionAttributes, |
| 3561 | 3583 | child_attrs: ObjectSectionAttributes, |
| 3562 | 3584 | ) !void { |
| 3563 | 3585 | if (parent_attrs == child_attrs) return; |
| 3564 | 3586 | |
| 3587 | const was_merged = switch (child_kind) { |
| 3588 | .pseudo => coff.section_merges.contains(child_name), |
| 3589 | .object => if (coff.getString( |
| 3590 | coff.objectSectionParentName(child_name.toSlice(coff)), |
| 3591 | ).unwrap()) |pseudo_name| |
| 3592 | coff.section_merges.contains(pseudo_name) |
| 3593 | else |
| 3594 | false, |
| 3595 | }; |
| 3596 | |
| 3597 | // The section was intentionally merged by the user or builtin rule |
| 3598 | if (was_merged) return; |
| 3599 | |
| 3565 | 3600 | const BackingT = @typeInfo(ObjectSectionAttributes).@"struct".backing_integer.?; |
| 3566 | 3601 | const num_notes = @popCount(@as(BackingT, @bitCast(parent_attrs)) ^ @as(BackingT, @bitCast(child_attrs))); |
| 3567 | 3602 | var err = try coff.base.comp.link_diags.addErrorWithNotes(num_notes); |
| 3568 | 3603 | try err.addMsg("{t} section '{s}' was placed in parent section '{s}' with mismatched flags", .{ |
| 3569 | | kind, |
| 3604 | child_kind, |
| 3570 | 3605 | child_name.toSlice(coff), |
| 3571 | | parent_name.toSlice(coff), |
| 3606 | parent.name(coff).toSlice(coff), |
| 3572 | 3607 | }); |
| 3573 | 3608 | |
| 3574 | 3609 | inline for (comptime std.meta.fieldNames(ObjectSectionAttributes)) |field| { |
| ... | ... | @@ -3578,7 +3613,7 @@ fn verifyParentSectionAttributes( |
| 3578 | 3613 | @intFromBool(@field(child_attrs, field)), |
| 3579 | 3614 | child_name.toSlice(coff), |
| 3580 | 3615 | @intFromBool(@field(parent_attrs, field)), |
| 3581 | | parent_name.toSlice(coff), |
| 3616 | parent.name(coff).toSlice(coff), |
| 3582 | 3617 | }); |
| 3583 | 3618 | } |
| 3584 | 3619 | } |
| ... | ... | @@ -4094,6 +4129,7 @@ fn loadObject( |
| 4094 | 4129 | |
| 4095 | 4130 | // Discover symbol names and COMDAT symbol mappings |
| 4096 | 4131 | var symbol_i: u32 = 0; |
| 4132 | var num_included_symbols: u32 = 0; |
| 4097 | 4133 | while (symbol_i < header.number_of_symbols) { |
| 4098 | 4134 | var symbol: std.coff.Symbol = undefined; |
| 4099 | 4135 | @memcpy(std.mem.asBytes(&symbol)[0..symbol_size], try r.take(symbol_size)); |
| ... | ... | @@ -4275,6 +4311,9 @@ fn loadObject( |
| 4275 | 4311 | }; |
| 4276 | 4312 | |
| 4277 | 4313 | for (values, 0..) |value, i| { |
| 4314 | if (section_number == .ABSOLUTE) |
| 4315 | num_included_symbols += 1; |
| 4316 | |
| 4278 | 4317 | switch (value) { |
| 4279 | 4318 | .section => {}, |
| 4280 | 4319 | .static, |
| ... | ... | @@ -4545,12 +4584,10 @@ fn loadObject( |
| 4545 | 4584 | }; |
| 4546 | 4585 | } |
| 4547 | 4586 | |
| 4548 | | while (coff.section_merge_pending_index < coff.section_merges.count()) : (coff.section_merge_pending_index += 1) |
| 4549 | | try coff.flushSectionMerge(coff.section_merge_pending_index); |
| 4587 | try coff.flushSectionMerges(); |
| 4550 | 4588 | |
| 4551 | 4589 | // Resolve pending associations, create parent sections |
| 4552 | 4590 | var num_included_sections: u16 = 0; |
| 4553 | | var num_included_symbols: u32 = 0; |
| 4554 | 4591 | var num_included_relocs: u32 = 0; |
| 4555 | 4592 | for (sections) |*section| { |
| 4556 | 4593 | comdat: switch (section.comdat_result) { |
| ... | ... | @@ -5916,22 +5953,6 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5916 | 5953 | }) coff.global_pending_index += 1; |
| 5917 | 5954 | break :task; |
| 5918 | 5955 | } |
| 5919 | | if (coff.exports_complete and coff.late_globals_pending_index < coff.late_globals.items.len) { |
| 5920 | | const gmi: Node.GlobalMapIndex = coff.late_globals.items[coff.late_globals_pending_index]; |
| 5921 | | const sub_prog_node = coff.synth_prog_node.start( |
| 5922 | | gmi.globalName(coff).name.toSlice(coff), |
| 5923 | | 0, |
| 5924 | | ); |
| 5925 | | defer sub_prog_node.end(); |
| 5926 | | if (coff.flushGlobal(gmi) catch |err| switch (err) { |
| 5927 | | error.OutOfMemory => |e| return e, |
| 5928 | | else => |e| return comp.link_diags.fail( |
| 5929 | | "linker failed to lower constant: {t}", |
| 5930 | | .{e}, |
| 5931 | | ), |
| 5932 | | }) coff.late_globals_pending_index += 1; |
| 5933 | | break :task; |
| 5934 | | } |
| 5935 | 5956 | if (coff.exports_complete and coff.pending_special_symbol != .none) { |
| 5936 | 5957 | coff.pending_special_symbol = coff.flushSpecialSymbol(coff.pending_special_symbol) catch |err| |
| 5937 | 5958 | switch (err) { |
| ... | ... | @@ -6002,7 +6023,6 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 6002 | 6023 | if (coff.pending_input != null) return true; |
| 6003 | 6024 | if (coff.exports_complete and coff.globals.count() > coff.global_pending_index) return true; |
| 6004 | 6025 | assert(!coff.exports_complete or coff.inputs_complete); |
| 6005 | | if (coff.exports_complete and coff.late_globals.items.len > coff.late_globals_pending_index) return true; |
| 6006 | 6026 | if (coff.exports_complete and coff.pending_special_symbol != .none) return true; |
| 6007 | 6027 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; |
| 6008 | 6028 | if (coff.symbol_table.pending_symbol_index < coff.symbol_table.symbols.count()) return true; |
| ... | ... | @@ -6223,11 +6243,10 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6223 | 6243 | const gpa = comp.gpa; |
| 6224 | 6244 | const gn = gmi.globalName(coff); |
| 6225 | 6245 | const si = gmi.symbol(coff); |
| 6226 | | const is_late = gmi.unwrap().? < coff.global_pending_index; |
| 6227 | 6246 | |
| 6228 | 6247 | log.debug( |
| 6229 | | "flushGlobal({s}, {?s}, {}) = n{d} {d}@{d}", |
| 6230 | | .{ gn.name.toSlice(coff), gn.lib_name.toSlice(coff), is_late, si.get(coff).ni, si, si.get(coff).section_number }, |
| 6248 | "flushGlobal({s}, {?s}) = n{d} {d}@{d}", |
| 6249 | .{ gn.name.toSlice(coff), gn.lib_name.toSlice(coff), si.get(coff).ni, si, si.get(coff).section_number }, |
| 6231 | 6250 | ); |
| 6232 | 6251 | |
| 6233 | 6252 | if (!coff.isImage()) { |
| ... | ... | @@ -6271,7 +6290,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6271 | 6290 | }; |
| 6272 | 6291 | |
| 6273 | 6292 | const opt_alt_search_name = coff.alternate_names.get(search_name); |
| 6274 | | const search_libs = if (is_late) switch (sym.flags.value_tag) { |
| 6293 | const search_libs = switch (sym.flags.value_tag) { |
| 6275 | 6294 | .weak_alias_si, .weak_alias_name => switch (sym.flags.weak_external_strat) { |
| 6276 | 6295 | .none => unreachable, |
| 6277 | 6296 | .no_library => false, |
| ... | ... | @@ -6285,18 +6304,6 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6285 | 6304 | ), |
| 6286 | 6305 | }, |
| 6287 | 6306 | else => true, |
| 6288 | | } else search_libs: { |
| 6289 | | if (switch (sym.flags.value_tag) { |
| 6290 | | .weak_alias_si, .weak_alias_name => true, |
| 6291 | | else => opt_alt_search_name != null, |
| 6292 | | }) { |
| 6293 | | // We need to wait until all exports are known before resolving these |
| 6294 | | coff.synth_prog_node.increaseEstimatedTotalItems(1); |
| 6295 | | (try coff.late_globals.addOne(gpa)).* = gmi; |
| 6296 | | return true; |
| 6297 | | } |
| 6298 | | |
| 6299 | | break :search_libs true; |
| 6300 | 6307 | }; |
| 6301 | 6308 | |
| 6302 | 6309 | const opt_indices_lists: []const ?InputArchive.SearchList = if (search_libs) &.{ |
| ... | ... | @@ -6381,12 +6388,10 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6381 | 6388 | |
| 6382 | 6389 | switch (sym.flags.value_tag) { |
| 6383 | 6390 | .weak_alias_si => { |
| 6384 | | assert(is_late); |
| 6385 | 6391 | try coff.aliasGlobal(gmi, sym.value.weak_alias_si); |
| 6386 | 6392 | return true; |
| 6387 | 6393 | }, |
| 6388 | 6394 | .weak_alias_name => { |
| 6389 | | assert(is_late); |
| 6390 | 6395 | // Convert an unresolved weak external that itself refers to an undef external |
| 6391 | 6396 | // into a (possibly new) global, so it can be resolved separately. |
| 6392 | 6397 | const alias_gop = try coff.getOrPutGlobalSymbol(.{ |
| ... | ... | @@ -6400,7 +6405,6 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6400 | 6405 | |
| 6401 | 6406 | // If there was an object that had the alternate name, we've attempted to load it |
| 6402 | 6407 | if (opt_alt_search_name) |alt_search_name| { |
| 6403 | | assert(is_late); |
| 6404 | 6408 | if (coff.globals.get(.{ .name = alt_search_name, .lib_name = .none })) |alias_si| { |
| 6405 | 6409 | try coff.aliasGlobal(gmi, alias_si); |
| 6406 | 6410 | return true; |
| ... | ... | @@ -6986,6 +6990,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 6986 | 6990 | .lazy_code, |
| 6987 | 6991 | .lazy_const_data, |
| 6988 | 6992 | => |mi| try mi.symbol(coff).flushMoved(coff), |
| 6993 | .builtin => |si| try si.flushMoved(coff), |
| 6989 | 6994 | } |
| 6990 | 6995 | try ni.childrenMoved(coff.base.comp.gpa, &coff.mf); |
| 6991 | 6996 | } |
| ... | ... | @@ -7126,8 +7131,10 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 7126 | 7131 | .uav, |
| 7127 | 7132 | .lazy_code, |
| 7128 | 7133 | .lazy_const_data, |
| 7134 | .builtin, |
| 7129 | 7135 | => {}, |
| 7130 | | .placeholder => unreachable, |
| 7136 | .placeholder, |
| 7137 | => unreachable, |
| 7131 | 7138 | } |
| 7132 | 7139 | } |
| 7133 | 7140 | |
| ... | ... | @@ -7217,6 +7224,11 @@ fn flushExportsSort(coff: *Coff) void { |
| 7217 | 7224 | }); |
| 7218 | 7225 | } |
| 7219 | 7226 | |
| 7227 | fn flushSectionMerges(coff: *Coff) !void { |
| 7228 | while (coff.section_merge_pending_index < coff.section_merges.count()) : (coff.section_merge_pending_index += 1) |
| 7229 | try coff.flushSectionMerge(coff.section_merge_pending_index); |
| 7230 | } |
| 7231 | |
| 7220 | 7232 | fn flushSectionMerge(coff: *Coff, index: u32) !void { |
| 7221 | 7233 | assert(coff.isImage()); |
| 7222 | 7234 | const from = coff.section_merges.keys()[index]; |
| ... | ... | @@ -7237,7 +7249,6 @@ fn flushSectionMerge(coff: *Coff, index: u32) !void { |
| 7237 | 7249 | // This is non-trivial as we can't leave holes in the section table. |
| 7238 | 7250 | // TODO: Merge section flags |
| 7239 | 7251 | _ = to_sym; |
| 7240 | | |
| 7241 | 7252 | return coff.base.comp.link_diags.fail("TODO implement section to section merge", .{}); |
| 7242 | 7253 | } else if (coff.pseudo_section_table.get(to)) |to_ps_si| { |
| 7243 | 7254 | const to_sym = to_ps_si.get(coff); |
| ... | ... | @@ -7265,7 +7276,6 @@ fn flushSectionMerge(coff: *Coff, index: u32) !void { |
| 7265 | 7276 | // TODO: Move from_psmi's node into to_sec |
| 7266 | 7277 | // TODO: Update .section_number for all contained syms |
| 7267 | 7278 | // TODO: Merge section flags |
| 7268 | | |
| 7269 | 7279 | return coff.base.comp.link_diags.fail("TODO implement pseudosection to section merge", .{}); |
| 7270 | 7280 | } else if (coff.pseudo_section_table.get(to)) |to_ps_si| { |
| 7271 | 7281 | const to_sym = to_ps_si.get(coff); |
| ... | ... | @@ -7273,7 +7283,6 @@ fn flushSectionMerge(coff: *Coff, index: u32) !void { |
| 7273 | 7283 | return; |
| 7274 | 7284 | |
| 7275 | 7285 | // TODO: Same as above, but move from_psmi's node after to_psmi's node in its parent |
| 7276 | | |
| 7277 | 7286 | return coff.base.comp.link_diags.fail("TODO implement pseudosection to pseudosection merge", .{}); |
| 7278 | 7287 | } |
| 7279 | 7288 | |
| ... | ... | @@ -7626,7 +7635,8 @@ fn printNodeName( |
| 7626 | 7635 | inline .pseudo_section, .object_section => |smi| try w.print("({s})", .{ |
| 7627 | 7636 | smi.name(coff).toSlice(coff), |
| 7628 | 7637 | }), |
| 7629 | | .import_thunk => |gmi| { |
| 7638 | .import_thunk, |
| 7639 | => |gmi| { |
| 7630 | 7640 | const gn = gmi.globalName(coff); |
| 7631 | 7641 | try w.writeByte('('); |
| 7632 | 7642 | if (gn.lib_name.toSlice(coff)) |lib_name| try w.print("{s}.dll, ", .{lib_name}); |
| ... | ... | @@ -7655,6 +7665,15 @@ fn printNodeName( |
| 7655 | 7665 | .tid = tid, |
| 7656 | 7666 | }), |
| 7657 | 7667 | }), |
| 7668 | .builtin => |si| { |
| 7669 | const sym = si.get(coff); |
| 7670 | if (sym.gmi != .none) { |
| 7671 | const gn = sym.gmi.globalName(coff); |
| 7672 | try w.writeByte('('); |
| 7673 | if (gn.lib_name.toSlice(coff)) |lib_name| try w.print("{s}.dll, ", .{lib_name}); |
| 7674 | try w.print("{s})", .{gn.name.toSlice(coff)}); |
| 7675 | } |
| 7676 | }, |
| 7658 | 7677 | } |
| 7659 | 7678 | } |
| 7660 | 7679 | |