| ... | @@ -415,16 +415,19 @@ const AllocateSegmentOpts = struct { | ... | @@ -415,16 +415,19 @@ const AllocateSegmentOpts = struct { |
| 415 | flags: u32 = elf.PF_R, | 415 | flags: u32 = elf.PF_R, |
| 416 | }; | 416 | }; |
| 417 | | 417 | |
| 418 | fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) !u16 { | 418 | fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory}!u16 { |
| 419 | const index = @as(u16, @intCast(self.phdrs.items.len)); | 419 | const index = @as(u16, @intCast(self.phdrs.items.len)); |
| 420 | try self.phdrs.ensureUnusedCapacity(self.base.allocator, 1); | 420 | try self.phdrs.ensureUnusedCapacity(self.base.allocator, 1); |
| 421 | const off = self.findFreeSpace(opts.size, opts.alignment); | 421 | const off = self.findFreeSpace(opts.size, opts.alignment); |
| 422 | log.debug("found PHDR {c}{c}{c} free space 0x{x} to 0x{x}", .{ | 422 | log.debug("allocating phdr({d})({c}{c}{c}) from 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ |
| | 423 | index, |
| 423 | if (opts.flags & elf.PF_R != 0) @as(u8, 'R') else '_', | 424 | if (opts.flags & elf.PF_R != 0) @as(u8, 'R') else '_', |
| 424 | if (opts.flags & elf.PF_W != 0) @as(u8, 'W') else '_', | 425 | if (opts.flags & elf.PF_W != 0) @as(u8, 'W') else '_', |
| 425 | if (opts.flags & elf.PF_X != 0) @as(u8, 'X') else '_', | 426 | if (opts.flags & elf.PF_X != 0) @as(u8, 'X') else '_', |
| 426 | off, | 427 | off, |
| 427 | off + opts.size, | 428 | off + opts.size, |
| | 429 | opts.addr, |
| | 430 | opts.addr + opts.size, |
| 428 | }); | 431 | }); |
| 429 | self.phdrs.appendAssumeCapacity(.{ | 432 | self.phdrs.appendAssumeCapacity(.{ |
| 430 | .p_type = elf.PT_LOAD, | 433 | .p_type = elf.PT_LOAD, |
| ... | @@ -440,6 +443,45 @@ fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) !u16 { | ... | @@ -440,6 +443,45 @@ fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) !u16 { |
| 440 | return index; | 443 | return index; |
| 441 | } | 444 | } |
| 442 | | 445 | |
| | 446 | const AllocateAllocSectionOpts = struct { |
| | 447 | name: [:0]const u8, |
| | 448 | phdr_index: u16, |
| | 449 | alignment: u16 = 1, |
| | 450 | flags: u16 = elf.SHF_ALLOC, |
| | 451 | type: u32 = elf.SHT_PROGBITS, |
| | 452 | }; |
| | 453 | |
| | 454 | fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{OutOfMemory}!u16 { |
| | 455 | const gpa = self.base.allocator; |
| | 456 | const phdr = &self.phdrs.items[opts.phdr_index]; |
| | 457 | const index = @as(u16, @intCast(self.shdrs.items.len)); |
| | 458 | try self.shdrs.ensureUnusedCapacity(gpa, 1); |
| | 459 | const sh_name = try self.shstrtab.insert(gpa, opts.name); |
| | 460 | try self.phdr_to_shdr_table.putNoClobber(gpa, index, opts.phdr_index); |
| | 461 | log.debug("allocating '{s}' in PHDR({d}) from 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ |
| | 462 | opts.name, |
| | 463 | opts.phdr_index, |
| | 464 | phdr.p_offset, |
| | 465 | phdr.p_offset + phdr.p_filesz, |
| | 466 | phdr.p_vaddr, |
| | 467 | phdr.p_vaddr + phdr.p_memsz, |
| | 468 | }); |
| | 469 | self.shdrs.appendAssumeCapacity(.{ |
| | 470 | .sh_name = sh_name, |
| | 471 | .sh_type = opts.type, |
| | 472 | .sh_flags = opts.flags, |
| | 473 | .sh_addr = phdr.p_vaddr, |
| | 474 | .sh_offset = phdr.p_offset, |
| | 475 | .sh_size = phdr.p_filesz, |
| | 476 | .sh_link = 0, |
| | 477 | .sh_info = 0, |
| | 478 | .sh_addralign = opts.alignment, |
| | 479 | .sh_entsize = 0, |
| | 480 | }); |
| | 481 | self.shdr_table_dirty = true; |
| | 482 | return index; |
| | 483 | } |
| | 484 | |
| 443 | pub fn populateMissingMetadata(self: *Elf) !void { | 485 | pub fn populateMissingMetadata(self: *Elf) !void { |
| 444 | const gpa = self.base.allocator; | 486 | const gpa = self.base.allocator; |
| 445 | const small_ptr = switch (self.ptr_width) { | 487 | const small_ptr = switch (self.ptr_width) { |
| ... | @@ -545,6 +587,8 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -545,6 +587,8 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 545 | .alignment = alignment, | 587 | .alignment = alignment, |
| 546 | .flags = elf.PF_R | elf.PF_W, | 588 | .flags = elf.PF_R | elf.PF_W, |
| 547 | }); | 589 | }); |
| | 590 | const phdr = &self.phdrs.items[self.phdr_load_zerofill_index.?]; |
| | 591 | phdr.p_offset = self.phdrs.items[self.phdr_load_rw_index.?].p_offset; // .bss overlaps .data |
| 548 | } | 592 | } |
| 549 | | 593 | |
| 550 | if (self.shstrtab_section_index == null) { | 594 | if (self.shstrtab_section_index == null) { |
| ... | @@ -592,102 +636,49 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -592,102 +636,49 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 592 | } | 636 | } |
| 593 | | 637 | |
| 594 | if (self.text_section_index == null) { | 638 | if (self.text_section_index == null) { |
| 595 | self.text_section_index = @intCast(self.shdrs.items.len); | 639 | self.text_section_index = try self.allocateAllocSection(.{ |
| 596 | const phdr = &self.phdrs.items[self.phdr_load_re_index.?]; | 640 | .name = ".text", |
| 597 | try self.shdrs.append(gpa, .{ | 641 | .phdr_index = self.phdr_load_re_index.?, |
| 598 | .sh_name = try self.shstrtab.insert(gpa, ".text"), | 642 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| 599 | .sh_type = elf.SHT_PROGBITS, | | |
| 600 | .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | | |
| 601 | .sh_addr = phdr.p_vaddr, | | |
| 602 | .sh_offset = phdr.p_offset, | | |
| 603 | .sh_size = phdr.p_filesz, | | |
| 604 | .sh_link = 0, | | |
| 605 | .sh_info = 0, | | |
| 606 | .sh_addralign = 1, | | |
| 607 | .sh_entsize = 0, | | |
| 608 | }); | 643 | }); |
| 609 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.text_section_index.?, self.phdr_load_re_index.?); | | |
| 610 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.text_section_index.?, .{}); | 644 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.text_section_index.?, .{}); |
| 611 | self.shdr_table_dirty = true; | | |
| 612 | } | 645 | } |
| 613 | | 646 | |
| 614 | if (self.got_section_index == null) { | 647 | if (self.got_section_index == null) { |
| 615 | self.got_section_index = @intCast(self.shdrs.items.len); | 648 | self.got_section_index = try self.allocateAllocSection(.{ |
| 616 | const phdr = &self.phdrs.items[self.phdr_got_index.?]; | 649 | .name = ".got", |
| 617 | try self.shdrs.append(gpa, .{ | 650 | .phdr_index = self.phdr_got_index.?, |
| 618 | .sh_name = try self.shstrtab.insert(gpa, ".got"), | 651 | .alignment = ptr_size, |
| 619 | .sh_type = elf.SHT_PROGBITS, | | |
| 620 | .sh_flags = elf.SHF_ALLOC, | | |
| 621 | .sh_addr = phdr.p_vaddr, | | |
| 622 | .sh_offset = phdr.p_offset, | | |
| 623 | .sh_size = phdr.p_filesz, | | |
| 624 | .sh_link = 0, | | |
| 625 | .sh_info = 0, | | |
| 626 | .sh_addralign = @as(u16, ptr_size), | | |
| 627 | .sh_entsize = 0, | | |
| 628 | }); | 652 | }); |
| 629 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.got_section_index.?, self.phdr_got_index.?); | | |
| 630 | self.shdr_table_dirty = true; | | |
| 631 | } | 653 | } |
| 632 | | 654 | |
| 633 | if (self.rodata_section_index == null) { | 655 | if (self.rodata_section_index == null) { |
| 634 | self.rodata_section_index = @intCast(self.shdrs.items.len); | 656 | self.rodata_section_index = try self.allocateAllocSection(.{ |
| 635 | const phdr = &self.phdrs.items[self.phdr_load_ro_index.?]; | 657 | .name = ".rodata", |
| 636 | try self.shdrs.append(gpa, .{ | 658 | .phdr_index = self.phdr_load_ro_index.?, |
| 637 | .sh_name = try self.shstrtab.insert(gpa, ".rodata"), | | |
| 638 | .sh_type = elf.SHT_PROGBITS, | | |
| 639 | .sh_flags = elf.SHF_ALLOC, | | |
| 640 | .sh_addr = phdr.p_vaddr, | | |
| 641 | .sh_offset = phdr.p_offset, | | |
| 642 | .sh_size = phdr.p_filesz, | | |
| 643 | .sh_link = 0, | | |
| 644 | .sh_info = 0, | | |
| 645 | .sh_addralign = 1, | | |
| 646 | .sh_entsize = 0, | | |
| 647 | }); | 659 | }); |
| 648 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.rodata_section_index.?, self.phdr_load_ro_index.?); | | |
| 649 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.rodata_section_index.?, .{}); | 660 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.rodata_section_index.?, .{}); |
| 650 | self.shdr_table_dirty = true; | | |
| 651 | } | 661 | } |
| 652 | | 662 | |
| 653 | if (self.data_section_index == null) { | 663 | if (self.data_section_index == null) { |
| 654 | self.data_section_index = @intCast(self.shdrs.items.len); | 664 | self.data_section_index = try self.allocateAllocSection(.{ |
| 655 | const phdr = &self.phdrs.items[self.phdr_load_rw_index.?]; | 665 | .name = ".data", |
| 656 | try self.shdrs.append(gpa, .{ | 666 | .phdr_index = self.phdr_load_rw_index.?, |
| 657 | .sh_name = try self.shstrtab.insert(gpa, ".data"), | 667 | .alignment = ptr_size, |
| 658 | .sh_type = elf.SHT_PROGBITS, | 668 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 659 | .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC, | | |
| 660 | .sh_addr = phdr.p_vaddr, | | |
| 661 | .sh_offset = phdr.p_offset, | | |
| 662 | .sh_size = phdr.p_filesz, | | |
| 663 | .sh_link = 0, | | |
| 664 | .sh_info = 0, | | |
| 665 | .sh_addralign = @as(u16, ptr_size), | | |
| 666 | .sh_entsize = 0, | | |
| 667 | }); | 669 | }); |
| 668 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.data_section_index.?, self.phdr_load_rw_index.?); | | |
| 669 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.data_section_index.?, .{}); | 670 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.data_section_index.?, .{}); |
| 670 | self.shdr_table_dirty = true; | | |
| 671 | } | 671 | } |
| 672 | | 672 | |
| 673 | if (self.bss_section_index == null) { | 673 | if (self.bss_section_index == null) { |
| 674 | self.bss_section_index = @intCast(self.shdrs.items.len); | 674 | self.bss_section_index = try self.allocateAllocSection(.{ |
| 675 | const phdr = &self.phdrs.items[self.phdr_load_zerofill_index.?]; | 675 | .name = ".bss", |
| 676 | try self.shdrs.append(gpa, .{ | 676 | .phdr_index = self.phdr_load_zerofill_index.?, |
| 677 | .sh_name = try self.shstrtab.insert(gpa, ".bss"), | 677 | .alignment = ptr_size, |
| 678 | .sh_type = elf.SHT_NOBITS, | 678 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 679 | .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC, | 679 | .type = elf.SHT_NOBITS, |
| 680 | .sh_addr = phdr.p_vaddr, | | |
| 681 | .sh_offset = phdr.p_offset, | | |
| 682 | .sh_size = phdr.p_filesz, | | |
| 683 | .sh_link = 0, | | |
| 684 | .sh_info = 0, | | |
| 685 | .sh_addralign = @as(u16, ptr_size), | | |
| 686 | .sh_entsize = 0, | | |
| 687 | }); | 680 | }); |
| 688 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.bss_section_index.?, self.phdr_load_zerofill_index.?); | | |
| 689 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.bss_section_index.?, .{}); | 681 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.bss_section_index.?, .{}); |
| 690 | self.shdr_table_dirty = true; | | |
| 691 | } | 682 | } |
| 692 | | 683 | |
| 693 | if (self.symtab_section_index == null) { | 684 | if (self.symtab_section_index == null) { |
| ... | @@ -1154,7 +1145,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1154,7 +1145,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1154 | for (self.file(index).?.zig_module.atoms.keys()) |atom_index| { | 1145 | for (self.file(index).?.zig_module.atoms.keys()) |atom_index| { |
| 1155 | const atom_ptr = self.atom(atom_index).?; | 1146 | const atom_ptr = self.atom(atom_index).?; |
| 1156 | if (!atom_ptr.alive) continue; | 1147 | if (!atom_ptr.alive) continue; |
| 1157 | const shdr = &self.shdrs.items[atom_ptr.output_section_index]; | 1148 | const shdr = &self.shdrs.items[atom_ptr.outputShndx().?]; |
| 1158 | const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; | 1149 | const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; |
| 1159 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | 1150 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| 1160 | const code = try gpa.alloc(u8, size); | 1151 | const code = try gpa.alloc(u8, size); |
| ... | @@ -1184,6 +1175,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1184,6 +1175,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1184 | try self.updateSymtabSize(); | 1175 | try self.updateSymtabSize(); |
| 1185 | try self.writeSymtab(); | 1176 | try self.writeSymtab(); |
| 1186 | | 1177 | |
| | 1178 | // .bss always overlaps .data in file offset, but is zero-sized in file so it doesn't |
| | 1179 | // get mapped by the loader |
| | 1180 | if (self.data_section_index) |data_shndx| blk: { |
| | 1181 | const bss_shndx = self.bss_section_index orelse break :blk; |
| | 1182 | const data_phndx = self.phdr_to_shdr_table.get(data_shndx).?; |
| | 1183 | const bss_phndx = self.phdr_to_shdr_table.get(bss_shndx).?; |
| | 1184 | self.shdrs.items[bss_shndx].sh_offset = self.shdrs.items[data_shndx].sh_offset; |
| | 1185 | self.phdrs.items[bss_phndx].p_offset = self.phdrs.items[data_phndx].p_offset; |
| | 1186 | } |
| | 1187 | |
| 1187 | // Dump the state for easy debugging. | 1188 | // Dump the state for easy debugging. |
| 1188 | // State can be dumped via `--debug-log link_state`. | 1189 | // State can be dumped via `--debug-log link_state`. |
| 1189 | if (build_options.enable_logging) { | 1190 | if (build_options.enable_logging) { |
| ... | @@ -1683,7 +1684,7 @@ fn writeObjects(self: *Elf) !void { | ... | @@ -1683,7 +1684,7 @@ fn writeObjects(self: *Elf) !void { |
| 1683 | const atom_ptr = self.atom(atom_index) orelse continue; | 1684 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 1684 | if (!atom_ptr.alive) continue; | 1685 | if (!atom_ptr.alive) continue; |
| 1685 | | 1686 | |
| 1686 | const shdr = &self.shdrs.items[atom_ptr.output_section_index]; | 1687 | const shdr = &self.shdrs.items[atom_ptr.outputShndx().?]; |
| 1687 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 1688 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 1688 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; // TODO we don't yet know how to handle non-alloc sections | 1689 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; // TODO we don't yet know how to handle non-alloc sections |
| 1689 | | 1690 | |
| ... | @@ -2557,15 +2558,15 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { | ... | @@ -2557,15 +2558,15 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2557 | } | 2558 | } |
| 2558 | } | 2559 | } |
| 2559 | | 2560 | |
| 2560 | pub fn getOrCreateMetadataForLazySymbol(self: *Elf, sym: link.File.LazySymbol) !Symbol.Index { | 2561 | pub fn getOrCreateMetadataForLazySymbol(self: *Elf, lazy_sym: link.File.LazySymbol) !Symbol.Index { |
| 2561 | const mod = self.base.options.module.?; | 2562 | const mod = self.base.options.module.?; |
| 2562 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod)); | 2563 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, lazy_sym.getDecl(mod)); |
| 2563 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); | 2564 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); |
| 2564 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 2565 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 2565 | const metadata: struct { | 2566 | const metadata: struct { |
| 2566 | symbol_index: *Symbol.Index, | 2567 | symbol_index: *Symbol.Index, |
| 2567 | state: *LazySymbolMetadata.State, | 2568 | state: *LazySymbolMetadata.State, |
| 2568 | } = switch (sym.kind) { | 2569 | } = switch (lazy_sym.kind) { |
| 2569 | .code => .{ | 2570 | .code => .{ |
| 2570 | .symbol_index = &gop.value_ptr.text_symbol_index, | 2571 | .symbol_index = &gop.value_ptr.text_symbol_index, |
| 2571 | .state = &gop.value_ptr.text_state, | 2572 | .state = &gop.value_ptr.text_state, |
| ... | @@ -2577,17 +2578,14 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, sym: link.File.LazySymbol) ! | ... | @@ -2577,17 +2578,14 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, sym: link.File.LazySymbol) ! |
| 2577 | }; | 2578 | }; |
| 2578 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; | 2579 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 2579 | switch (metadata.state.*) { | 2580 | switch (metadata.state.*) { |
| 2580 | .unused => metadata.symbol_index.* = try zig_module.addAtom(switch (sym.kind) { | 2581 | .unused => metadata.symbol_index.* = try zig_module.addAtom(self), |
| 2581 | .code => self.text_section_index.?, | | |
| 2582 | .const_data => self.rodata_section_index.?, | | |
| 2583 | }, self), | | |
| 2584 | .pending_flush => return metadata.symbol_index.*, | 2582 | .pending_flush => return metadata.symbol_index.*, |
| 2585 | .flushed => {}, | 2583 | .flushed => {}, |
| 2586 | } | 2584 | } |
| 2587 | metadata.state.* = .pending_flush; | 2585 | metadata.state.* = .pending_flush; |
| 2588 | const symbol_index = metadata.symbol_index.*; | 2586 | const symbol_index = metadata.symbol_index.*; |
| 2589 | // anyerror needs to be deferred until flushModule | 2587 | // anyerror needs to be deferred until flushModule |
| 2590 | if (sym.getDecl(mod) != .none) try self.updateLazySymbol(sym, symbol_index); | 2588 | if (lazy_sym.getDecl(mod) != .none) try self.updateLazySymbol(lazy_sym, symbol_index); |
| 2591 | return symbol_index; | 2589 | return symbol_index; |
| 2592 | } | 2590 | } |
| 2593 | | 2591 | |
| ... | @@ -2596,35 +2594,37 @@ pub fn getOrCreateMetadataForDecl(self: *Elf, decl_index: Module.Decl.Index) !Sy | ... | @@ -2596,35 +2594,37 @@ pub fn getOrCreateMetadataForDecl(self: *Elf, decl_index: Module.Decl.Index) !Sy |
| 2596 | if (!gop.found_existing) { | 2594 | if (!gop.found_existing) { |
| 2597 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; | 2595 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 2598 | gop.value_ptr.* = .{ | 2596 | gop.value_ptr.* = .{ |
| 2599 | .symbol_index = try zig_module.addAtom(self.getDeclShdrIndex(decl_index), self), | 2597 | .symbol_index = try zig_module.addAtom(self), |
| 2600 | .exports = .{}, | 2598 | .exports = .{}, |
| 2601 | }; | 2599 | }; |
| 2602 | } | 2600 | } |
| 2603 | return gop.value_ptr.symbol_index; | 2601 | return gop.value_ptr.symbol_index; |
| 2604 | } | 2602 | } |
| 2605 | | 2603 | |
| 2606 | fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 { | 2604 | fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index, code: []const u8) u16 { |
| 2607 | const mod = self.base.options.module.?; | 2605 | const mod = self.base.options.module.?; |
| 2608 | const decl = mod.declPtr(decl_index); | 2606 | const decl = mod.declPtr(decl_index); |
| 2609 | const ty = decl.ty; | 2607 | const shdr_index = switch (decl.ty.zigTypeTag(mod)) { |
| 2610 | const zig_ty = ty.zigTypeTag(mod); | 2608 | // TODO: what if this is a function pointer? |
| 2611 | const val = decl.val; | 2609 | .Fn => self.text_section_index.?, |
| 2612 | const shdr_index: u16 = blk: { | 2610 | else => blk: { |
| 2613 | if (val.isUndefDeep(mod)) { | 2611 | if (decl.getOwnedVariable(mod)) |variable| { |
| 2614 | // TODO in release-fast and release-small, we should put undef in .bss | 2612 | if (variable.is_const) break :blk self.rodata_section_index.?; |
| 2615 | break :blk self.data_section_index.?; | 2613 | if (variable.init.toValue().isUndefDeep(mod)) { |
| 2616 | } | 2614 | const mode = self.base.options.optimize_mode; |
| 2617 | | 2615 | if (mode == .Debug or mode == .ReleaseSafe) break :blk self.data_section_index.?; |
| 2618 | switch (zig_ty) { | 2616 | break :blk self.bss_section_index.?; |
| 2619 | // TODO: what if this is a function pointer? | | |
| 2620 | .Fn => break :blk self.text_section_index.?, | | |
| 2621 | else => { | | |
| 2622 | if (val.getVariable(mod)) |_| { | | |
| 2623 | break :blk self.data_section_index.?; | | |
| 2624 | } | 2617 | } |
| 2625 | break :blk self.rodata_section_index.?; | 2618 | // TODO I blatantly copied the logic from the Wasm linker, but is there a less |
| 2626 | }, | 2619 | // intrusive check for all zeroes than this? |
| 2627 | } | 2620 | const is_all_zeroes = for (code) |byte| { |
| | 2621 | if (byte != 0) break false; |
| | 2622 | } else true; |
| | 2623 | if (is_all_zeroes) break :blk self.bss_section_index.?; |
| | 2624 | break :blk self.data_section_index.?; |
| | 2625 | } |
| | 2626 | break :blk self.rodata_section_index.?; |
| | 2627 | }, |
| 2628 | }; | 2628 | }; |
| 2629 | return shdr_index; | 2629 | return shdr_index; |
| 2630 | } | 2630 | } |
| ... | @@ -2649,7 +2649,10 @@ fn updateDeclCode( | ... | @@ -2649,7 +2649,10 @@ fn updateDeclCode( |
| 2649 | const sym = self.symbol(sym_index); | 2649 | const sym = self.symbol(sym_index); |
| 2650 | const esym = &zig_module.local_esyms.items[sym.esym_index]; | 2650 | const esym = &zig_module.local_esyms.items[sym.esym_index]; |
| 2651 | const atom_ptr = sym.atom(self).?; | 2651 | const atom_ptr = sym.atom(self).?; |
| 2652 | const shdr_index = sym.output_section_index; | 2652 | |
| | 2653 | const shdr_index = self.getDeclShdrIndex(decl_index, code); |
| | 2654 | sym.output_section_index = shdr_index; |
| | 2655 | atom_ptr.output_section_index = shdr_index; |
| 2653 | | 2656 | |
| 2654 | sym.name_offset = try self.strtab.insert(gpa, decl_name); | 2657 | sym.name_offset = try self.strtab.insert(gpa, decl_name); |
| 2655 | atom_ptr.alive = true; | 2658 | atom_ptr.alive = true; |
| ... | @@ -2902,9 +2905,14 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. | ... | @@ -2902,9 +2905,14 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. |
| 2902 | }, | 2905 | }, |
| 2903 | }; | 2906 | }; |
| 2904 | | 2907 | |
| | 2908 | const output_section_index = switch (sym.kind) { |
| | 2909 | .code => self.text_section_index.?, |
| | 2910 | .const_data => self.rodata_section_index.?, |
| | 2911 | }; |
| 2905 | const local_sym = self.symbol(symbol_index); | 2912 | const local_sym = self.symbol(symbol_index); |
| 2906 | const phdr_index = self.phdr_to_shdr_table.get(local_sym.output_section_index).?; | 2913 | const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?; |
| 2907 | local_sym.name_offset = name_str_index; | 2914 | local_sym.name_offset = name_str_index; |
| | 2915 | local_sym.output_section_index = output_section_index; |
| 2908 | const local_esym = &zig_module.local_esyms.items[local_sym.esym_index]; | 2916 | const local_esym = &zig_module.local_esyms.items[local_sym.esym_index]; |
| 2909 | local_esym.st_name = name_str_index; | 2917 | local_esym.st_name = name_str_index; |
| 2910 | local_esym.st_info |= elf.STT_OBJECT; | 2918 | local_esym.st_info |= elf.STT_OBJECT; |
| ... | @@ -2914,6 +2922,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. | ... | @@ -2914,6 +2922,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. |
| 2914 | atom_ptr.name_offset = name_str_index; | 2922 | atom_ptr.name_offset = name_str_index; |
| 2915 | atom_ptr.alignment = required_alignment; | 2923 | atom_ptr.alignment = required_alignment; |
| 2916 | atom_ptr.size = code.len; | 2924 | atom_ptr.size = code.len; |
| | 2925 | atom_ptr.output_section_index = output_section_index; |
| 2917 | | 2926 | |
| 2918 | try atom_ptr.allocate(self); | 2927 | try atom_ptr.allocate(self); |
| 2919 | errdefer self.freeDeclMetadata(symbol_index); | 2928 | errdefer self.freeDeclMetadata(symbol_index); |
| ... | @@ -2932,7 +2941,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. | ... | @@ -2932,7 +2941,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. |
| 2932 | try self.got.writeEntry(self, gop.index); | 2941 | try self.got.writeEntry(self, gop.index); |
| 2933 | | 2942 | |
| 2934 | const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr; | 2943 | const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr; |
| 2935 | const file_offset = self.shdrs.items[local_sym.output_section_index].sh_offset + section_offset; | 2944 | const file_offset = self.shdrs.items[output_section_index].sh_offset + section_offset; |
| 2936 | try self.base.file.?.pwriteAll(code, file_offset); | 2945 | try self.base.file.?.pwriteAll(code, file_offset); |
| 2937 | } | 2946 | } |
| 2938 | | 2947 | |
| ... | @@ -2960,7 +2969,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module | ... | @@ -2960,7 +2969,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2960 | const name = self.strtab.get(name_str_index).?; | 2969 | const name = self.strtab.get(name_str_index).?; |
| 2961 | | 2970 | |
| 2962 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; | 2971 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 2963 | const sym_index = try zig_module.addAtom(self.rodata_section_index.?, self); | 2972 | const sym_index = try zig_module.addAtom(self); |
| 2964 | | 2973 | |
| 2965 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .{ | 2974 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .{ |
| 2966 | .none = {}, | 2975 | .none = {}, |
| ... | @@ -2982,6 +2991,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module | ... | @@ -2982,6 +2991,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2982 | const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?; | 2991 | const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?; |
| 2983 | const local_sym = self.symbol(sym_index); | 2992 | const local_sym = self.symbol(sym_index); |
| 2984 | local_sym.name_offset = name_str_index; | 2993 | local_sym.name_offset = name_str_index; |
| | 2994 | local_sym.output_section_index = self.rodata_section_index.?; |
| 2985 | const local_esym = &zig_module.local_esyms.items[local_sym.esym_index]; | 2995 | const local_esym = &zig_module.local_esyms.items[local_sym.esym_index]; |
| 2986 | local_esym.st_name = name_str_index; | 2996 | local_esym.st_name = name_str_index; |
| 2987 | local_esym.st_info |= elf.STT_OBJECT; | 2997 | local_esym.st_info |= elf.STT_OBJECT; |
| ... | @@ -2991,6 +3001,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module | ... | @@ -2991,6 +3001,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2991 | atom_ptr.name_offset = name_str_index; | 3001 | atom_ptr.name_offset = name_str_index; |
| 2992 | atom_ptr.alignment = required_alignment; | 3002 | atom_ptr.alignment = required_alignment; |
| 2993 | atom_ptr.size = code.len; | 3003 | atom_ptr.size = code.len; |
| | 3004 | atom_ptr.output_section_index = self.rodata_section_index.?; |
| 2994 | | 3005 | |
| 2995 | try atom_ptr.allocate(self); | 3006 | try atom_ptr.allocate(self); |
| 2996 | errdefer self.freeDeclMetadata(sym_index); | 3007 | errdefer self.freeDeclMetadata(sym_index); |
| ... | @@ -4008,6 +4019,54 @@ fn reportParseError( | ... | @@ -4008,6 +4019,54 @@ fn reportParseError( |
| 4008 | }); | 4019 | }); |
| 4009 | } | 4020 | } |
| 4010 | | 4021 | |
| | 4022 | fn fmtShdrs(self: *Elf) std.fmt.Formatter(formatShdrs) { |
| | 4023 | return .{ .data = self }; |
| | 4024 | } |
| | 4025 | |
| | 4026 | fn formatShdrs( |
| | 4027 | self: *Elf, |
| | 4028 | comptime unused_fmt_string: []const u8, |
| | 4029 | options: std.fmt.FormatOptions, |
| | 4030 | writer: anytype, |
| | 4031 | ) !void { |
| | 4032 | _ = options; |
| | 4033 | _ = unused_fmt_string; |
| | 4034 | for (self.shdrs.items, 0..) |shdr, i| { |
| | 4035 | try writer.print("shdr({d}) : phdr({?d}) : {s} : @{x} ({x}) : align({x}) : size({x})\n", .{ |
| | 4036 | i, self.phdr_to_shdr_table.get(@intCast(i)), |
| | 4037 | self.shstrtab.getAssumeExists(shdr.sh_name), shdr.sh_offset, |
| | 4038 | shdr.sh_addr, shdr.sh_addralign, |
| | 4039 | shdr.sh_size, |
| | 4040 | }); |
| | 4041 | } |
| | 4042 | } |
| | 4043 | |
| | 4044 | fn fmtPhdrs(self: *Elf) std.fmt.Formatter(formatPhdrs) { |
| | 4045 | return .{ .data = self }; |
| | 4046 | } |
| | 4047 | |
| | 4048 | fn formatPhdrs( |
| | 4049 | self: *Elf, |
| | 4050 | comptime unused_fmt_string: []const u8, |
| | 4051 | options: std.fmt.FormatOptions, |
| | 4052 | writer: anytype, |
| | 4053 | ) !void { |
| | 4054 | _ = options; |
| | 4055 | _ = unused_fmt_string; |
| | 4056 | for (self.phdrs.items, 0..) |phdr, i| { |
| | 4057 | const write = phdr.p_flags & elf.PF_W != 0; |
| | 4058 | const read = phdr.p_flags & elf.PF_R != 0; |
| | 4059 | const exec = phdr.p_flags & elf.PF_X != 0; |
| | 4060 | var flags: [3]u8 = [_]u8{'_'} ** 3; |
| | 4061 | if (exec) flags[0] = 'X'; |
| | 4062 | if (write) flags[1] = 'W'; |
| | 4063 | if (read) flags[2] = 'R'; |
| | 4064 | try writer.print("phdr({d}) : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})\n", .{ |
| | 4065 | i, flags, phdr.p_offset, phdr.p_vaddr, phdr.p_align, phdr.p_filesz, phdr.p_memsz, |
| | 4066 | }); |
| | 4067 | } |
| | 4068 | } |
| | 4069 | |
| 4011 | fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { | 4070 | fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { |
| 4012 | return .{ .data = self }; | 4071 | return .{ .data = self }; |
| 4013 | } | 4072 | } |
| ... | @@ -4047,6 +4106,10 @@ fn fmtDumpState( | ... | @@ -4047,6 +4106,10 @@ fn fmtDumpState( |
| 4047 | try writer.print("{}\n", .{linker_defined.fmtSymtab(self)}); | 4106 | try writer.print("{}\n", .{linker_defined.fmtSymtab(self)}); |
| 4048 | } | 4107 | } |
| 4049 | try writer.print("{}\n", .{self.got.fmt(self)}); | 4108 | try writer.print("{}\n", .{self.got.fmt(self)}); |
| | 4109 | try writer.writeAll("Output shdrs\n"); |
| | 4110 | try writer.print("{}\n", .{self.fmtShdrs()}); |
| | 4111 | try writer.writeAll("Output phdrs\n"); |
| | 4112 | try writer.print("{}\n", .{self.fmtPhdrs()}); |
| 4050 | } | 4113 | } |
| 4051 | | 4114 | |
| 4052 | /// Binary search | 4115 | /// Binary search |