authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-10 11:10:16+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-10 11:10:16+02:00
loga3ce011408802ba81cb52753c65dbcd2254b9e75
treed677462f3ff11d2118ddc03bd8ed4ac8fc4f065a
parent1c3fd16c3777d8bf61e681a49fbcff0803dd9609

elf: allocate linker defined symbols


1 files changed, 178 insertions(+), 19 deletions(-)

src/link/Elf.zig+178-19
......@@ -47,8 +47,13 @@ got: GotSection = .{},
4747
4848text_section_index: ?u16 = null,
4949rodata_section_index: ?u16 = null,
50got_section_index: ?u16 = null,
5150data_section_index: ?u16 = null,
51dynamic_section_index: ?u16 = null,
52got_section_index: ?u16 = null,
53got_plt_section_index: ?u16 = null,
54plt_section_index: ?u16 = null,
55eh_frame_hdr_section_index: ?u16 = null,
56rela_dyn_section_index: ?u16 = null,
5257debug_info_section_index: ?u16 = null,
5358debug_abbrev_section_index: ?u16 = null,
5459debug_str_section_index: ?u16 = null,
......@@ -74,6 +79,7 @@ gnu_eh_frame_hdr_index: ?Symbol.Index = null,
7479dso_handle_index: ?Symbol.Index = null,
7580rela_iplt_start_index: ?Symbol.Index = null,
7681rela_iplt_end_index: ?Symbol.Index = null,
82start_stop_indexes: std.ArrayListUnmanaged(u32) = .{},
7783
7884symbols: std.ArrayListUnmanaged(Symbol) = .{},
7985symbols_extra: std.ArrayListUnmanaged(u32) = .{},
......@@ -264,6 +270,7 @@ pub fn deinit(self: *Elf) void {
264270 self.got.deinit(gpa);
265271 self.resolver.deinit(gpa);
266272 self.unresolved.deinit(gpa);
273 self.start_stop_indexes.deinit(gpa);
267274
268275 {
269276 var it = self.decls.iterator();
......@@ -385,6 +392,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
385392 .p64 => false,
386393 };
387394 const ptr_size: u8 = self.ptrWidthBytes();
395 const image_base = self.calcImageBase();
388396
389397 if (self.phdr_table_index == null) {
390398 self.phdr_table_index = @as(u16, @intCast(self.phdrs.items.len));
......@@ -396,8 +404,8 @@ pub fn populateMissingMetadata(self: *Elf) !void {
396404 .p_type = elf.PT_PHDR,
397405 .p_offset = 0,
398406 .p_filesz = 0,
399 .p_vaddr = 0,
400 .p_paddr = 0,
407 .p_vaddr = image_base,
408 .p_paddr = image_base,
401409 .p_memsz = 0,
402410 .p_align = p_align,
403411 .p_flags = elf.PF_R,
......@@ -408,16 +416,14 @@ pub fn populateMissingMetadata(self: *Elf) !void {
408416 if (self.phdr_table_load_index == null) {
409417 self.phdr_table_load_index = @as(u16, @intCast(self.phdrs.items.len));
410418 // TODO Same as for GOT
411 const phdr_addr: u64 = if (self.base.options.target.ptrBitWidth() >= 32) 0x1000000 else 0x1000;
412 const p_align = self.page_size;
413419 try self.phdrs.append(gpa, .{
414420 .p_type = elf.PT_LOAD,
415421 .p_offset = 0,
416422 .p_filesz = 0,
417 .p_vaddr = phdr_addr,
418 .p_paddr = phdr_addr,
423 .p_vaddr = image_base,
424 .p_paddr = image_base,
419425 .p_memsz = 0,
420 .p_align = p_align,
426 .p_align = self.page_size,
421427 .p_flags = elf.PF_R,
422428 });
423429 self.phdr_table_dirty = true;
......@@ -429,7 +435,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
429435 const p_align = self.page_size;
430436 const off = self.findFreeSpace(file_size, p_align);
431437 log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size });
432 const entry_addr: u64 = self.entry_addr orelse if (self.base.options.target.cpu.arch == .spu_2) @as(u64, 0) else default_entry_addr;
438 const entry_addr = self.defaultEntryAddress();
433439 try self.phdrs.append(gpa, .{
434440 .p_type = elf.PT_LOAD,
435441 .p_offset = off,
......@@ -1055,6 +1061,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10551061
10561062 try self.addLinkerDefinedSymbols();
10571063
1064 self.allocateLinkerDefinedSymbols();
1065
10581066 // Beyond this point, everything has been allocated a virtual address and we can resolve
10591067 // the relocations.
10601068 {
......@@ -2764,6 +2772,129 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
27642772 linker_defined.resolveSymbols(self);
27652773}
27662774
2775fn allocateLinkerDefinedSymbols(self: *Elf) void {
2776 // _DYNAMIC
2777 if (self.dynamic_section_index) |shndx| {
2778 const shdr = self.sections.items(.shdr)[shndx];
2779 const symbol_ptr = self.symbol(self.dynamic_index.?);
2780 symbol_ptr.value = shdr.sh_addr;
2781 symbol_ptr.output_section_index = shndx;
2782 }
2783
2784 // __ehdr_start
2785 {
2786 const symbol_ptr = self.symbol(self.ehdr_start_index.?);
2787 symbol_ptr.value = self.calcImageBase();
2788 symbol_ptr.output_section_index = 1;
2789 }
2790
2791 // __init_array_start, __init_array_end
2792 if (self.sectionByName(".init_array")) |shndx| {
2793 const start_sym = self.symbol(self.init_array_start_index.?);
2794 const end_sym = self.symbol(self.init_array_end_index.?);
2795 const shdr = &self.sections.items(.shdr)[shndx];
2796 start_sym.output_section_index = shndx;
2797 start_sym.value = shdr.sh_addr;
2798 end_sym.output_section_index = shndx;
2799 end_sym.value = shdr.sh_addr + shdr.sh_size;
2800 }
2801
2802 // __fini_array_start, __fini_array_end
2803 if (self.sectionByName(".fini_array")) |shndx| {
2804 const start_sym = self.symbol(self.fini_array_start_index.?);
2805 const end_sym = self.symbol(self.fini_array_end_index.?);
2806 const shdr = &self.sections.items(.shdr)[shndx];
2807 start_sym.output_section_index = shndx;
2808 start_sym.value = shdr.sh_addr;
2809 end_sym.output_section_index = shndx;
2810 end_sym.value = shdr.sh_addr + shdr.sh_size;
2811 }
2812
2813 // __preinit_array_start, __preinit_array_end
2814 if (self.sectionByName(".preinit_array")) |shndx| {
2815 const start_sym = self.symbol(self.preinit_array_start_index.?);
2816 const end_sym = self.symbol(self.preinit_array_end_index.?);
2817 const shdr = &self.sections.items(.shdr)[shndx];
2818 start_sym.output_section_index = shndx;
2819 start_sym.value = shdr.sh_addr;
2820 end_sym.output_section_index = shndx;
2821 end_sym.value = shdr.sh_addr + shdr.sh_size;
2822 }
2823
2824 // _GLOBAL_OFFSET_TABLE_
2825 if (self.got_plt_section_index) |shndx| {
2826 const shdr = &self.sections.items(.shdr)[shndx];
2827 const symbol_ptr = self.symbol(self.got_index.?);
2828 symbol_ptr.value = shdr.sh_addr;
2829 symbol_ptr.output_section_index = shndx;
2830 }
2831
2832 // _PROCEDURE_LINKAGE_TABLE_
2833 if (self.plt_section_index) |shndx| {
2834 const shdr = &self.sections.items(.shdr)[shndx];
2835 const symbol_ptr = self.symbol(self.plt_index.?);
2836 symbol_ptr.value = shdr.sh_addr;
2837 symbol_ptr.output_section_index = shndx;
2838 }
2839
2840 // __dso_handle
2841 if (self.dso_handle_index) |index| {
2842 const shdr = &self.sections.items(.shdr)[1];
2843 const symbol_ptr = self.symbol(index);
2844 symbol_ptr.value = shdr.sh_addr;
2845 symbol_ptr.output_section_index = 0;
2846 }
2847
2848 // __GNU_EH_FRAME_HDR
2849 if (self.eh_frame_hdr_section_index) |shndx| {
2850 const shdr = &self.sections.items(.shdr)[shndx];
2851 const symbol_ptr = self.symbol(self.gnu_eh_frame_hdr_index.?);
2852 symbol_ptr.value = shdr.sh_addr;
2853 symbol_ptr.output_section_index = shndx;
2854 }
2855
2856 // __rela_iplt_start, __rela_iplt_end
2857 if (self.rela_dyn_section_index) |shndx| blk: {
2858 if (self.base.options.link_mode != .Static or self.base.options.pie) break :blk;
2859 const shdr = &self.sections.items(.shdr)[shndx];
2860 const end_addr = shdr.sh_addr + shdr.sh_size;
2861 const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
2862 const start_sym = self.symbol(self.rela_iplt_start_index.?);
2863 const end_sym = self.symbol(self.rela_iplt_end_index.?);
2864 start_sym.value = start_addr;
2865 start_sym.output_section_index = shndx;
2866 end_sym.value = end_addr;
2867 end_sym.output_section_index = shndx;
2868 }
2869
2870 // _end
2871 {
2872 const end_symbol = self.symbol(self.end_index.?);
2873 for (self.sections.items(.shdr), 0..) |shdr, shndx| {
2874 if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
2875 end_symbol.value = shdr.sh_addr + shdr.sh_size;
2876 end_symbol.output_section_index = @intCast(shndx);
2877 }
2878 }
2879 }
2880
2881 // __start_*, __stop_*
2882 {
2883 var index: usize = 0;
2884 while (index < self.start_stop_indexes.items.len) : (index += 2) {
2885 const start = self.symbol(self.start_stop_indexes.items[index]);
2886 const name = start.name(self);
2887 const stop = self.symbol(self.start_stop_indexes.items[index + 1]);
2888 const shndx = self.sectionByName(name["__start_".len..]).?;
2889 const shdr = self.sections.items(.shdr)[shndx];
2890 start.value = shdr.sh_addr;
2891 start.output_section_index = shndx;
2892 stop.value = shdr.sh_addr + shdr.sh_size;
2893 stop.output_section_index = shndx;
2894 }
2895 }
2896}
2897
27672898fn updateSymtabSize(self: *Elf) !void {
27682899 var sizes = SymtabSize{};
27692900
......@@ -2774,17 +2905,17 @@ fn updateSymtabSize(self: *Elf) !void {
27742905 sizes.nglobals += zig_module.output_symtab_size.nglobals;
27752906 }
27762907
2908 if (self.got_section_index) |_| {
2909 self.got.updateSymtabSize(self);
2910 sizes.nlocals += self.got.output_symtab_size.nlocals;
2911 }
2912
27772913 if (self.linker_defined_index) |index| {
27782914 const linker_defined = self.file(index).?.linker_defined;
27792915 linker_defined.updateSymtabSize(self);
27802916 sizes.nlocals += linker_defined.output_symtab_size.nlocals;
27812917 }
27822918
2783 if (self.got_section_index) |_| {
2784 self.got.updateSymtabSize(self);
2785 sizes.nlocals += self.got.output_symtab_size.nlocals;
2786 }
2787
27882919 const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?];
27892920 shdr.sh_info = sizes.nlocals + 1;
27902921 self.markDirty(self.symtab_section_index.?, null);
......@@ -2829,17 +2960,17 @@ fn writeSymtab(self: *Elf) !void {
28292960 ctx.iglobal += zig_module.output_symtab_size.nglobals;
28302961 }
28312962
2963 if (self.got_section_index) |_| {
2964 try self.got.writeSymtab(self, ctx);
2965 ctx.ilocal += self.got.output_symtab_size.nlocals;
2966 }
2967
28322968 if (self.linker_defined_index) |index| {
28332969 const linker_defined = self.file(index).?.linker_defined;
28342970 linker_defined.writeSymtab(self, ctx);
28352971 ctx.ilocal += linker_defined.output_symtab_size.nlocals;
28362972 }
28372973
2838 if (self.got_section_index) |_| {
2839 try self.got.writeSymtab(self, ctx);
2840 ctx.ilocal += self.got.output_symtab_size.nlocals;
2841 }
2842
28432974 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
28442975 switch (self.ptr_width) {
28452976 .p32 => {
......@@ -3179,6 +3310,34 @@ const CsuObjects = struct {
31793310 }
31803311};
31813312
3313pub fn calcImageBase(self: Elf) u64 {
3314 if (self.base.options.pic) return 0; // TODO flag an error if PIC and image_base_override
3315 return self.base.options.image_base_override orelse switch (self.ptr_width) {
3316 .p32 => 0x1000,
3317 .p64 => 0x1000000,
3318 };
3319}
3320
3321pub fn defaultEntryAddress(self: Elf) u64 {
3322 if (self.entry_addr) |addr| return addr;
3323 return switch (self.base.options.target.cpu.arch) {
3324 .spu_2 => 0,
3325 else => default_entry_addr,
3326 };
3327}
3328
3329pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 {
3330 for (self.sections.items(.shdr), 0..) |shdr, i| {
3331 const this_name = self.shstrtab.getAssumeExists(shdr.sh_name);
3332 if (mem.eql(u8, this_name, name)) return @as(u16, @intCast(i));
3333 } else return null;
3334}
3335
3336pub fn calcNumIRelativeRelocs(self: *Elf) u64 {
3337 _ = self;
3338 unreachable; // TODO
3339}
3340
31823341pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom {
31833342 if (atom_index == 0) return null;
31843343 assert(atom_index < self.atoms.items.len);