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 = .{},...@@ -47,8 +47,13 @@ got: GotSection = .{},
4747
48text_section_index: ?u16 = null,48text_section_index: ?u16 = null,
49rodata_section_index: ?u16 = null,49rodata_section_index: ?u16 = null,
50got_section_index: ?u16 = null,
51data_section_index: ?u16 = null,50data_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,
52debug_info_section_index: ?u16 = null,57debug_info_section_index: ?u16 = null,
53debug_abbrev_section_index: ?u16 = null,58debug_abbrev_section_index: ?u16 = null,
54debug_str_section_index: ?u16 = null,59debug_str_section_index: ?u16 = null,
...@@ -74,6 +79,7 @@ gnu_eh_frame_hdr_index: ?Symbol.Index = null,...@@ -74,6 +79,7 @@ gnu_eh_frame_hdr_index: ?Symbol.Index = null,
74dso_handle_index: ?Symbol.Index = null,79dso_handle_index: ?Symbol.Index = null,
75rela_iplt_start_index: ?Symbol.Index = null,80rela_iplt_start_index: ?Symbol.Index = null,
76rela_iplt_end_index: ?Symbol.Index = null,81rela_iplt_end_index: ?Symbol.Index = null,
82start_stop_indexes: std.ArrayListUnmanaged(u32) = .{},
7783
78symbols: std.ArrayListUnmanaged(Symbol) = .{},84symbols: std.ArrayListUnmanaged(Symbol) = .{},
79symbols_extra: std.ArrayListUnmanaged(u32) = .{},85symbols_extra: std.ArrayListUnmanaged(u32) = .{},
...@@ -264,6 +270,7 @@ pub fn deinit(self: *Elf) void {...@@ -264,6 +270,7 @@ pub fn deinit(self: *Elf) void {
264 self.got.deinit(gpa);270 self.got.deinit(gpa);
265 self.resolver.deinit(gpa);271 self.resolver.deinit(gpa);
266 self.unresolved.deinit(gpa);272 self.unresolved.deinit(gpa);
273 self.start_stop_indexes.deinit(gpa);
267274
268 {275 {
269 var it = self.decls.iterator();276 var it = self.decls.iterator();
...@@ -385,6 +392,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -385,6 +392,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
385 .p64 => false,392 .p64 => false,
386 };393 };
387 const ptr_size: u8 = self.ptrWidthBytes();394 const ptr_size: u8 = self.ptrWidthBytes();
395 const image_base = self.calcImageBase();
388396
389 if (self.phdr_table_index == null) {397 if (self.phdr_table_index == null) {
390 self.phdr_table_index = @as(u16, @intCast(self.phdrs.items.len));398 self.phdr_table_index = @as(u16, @intCast(self.phdrs.items.len));
...@@ -396,8 +404,8 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -396,8 +404,8 @@ pub fn populateMissingMetadata(self: *Elf) !void {
396 .p_type = elf.PT_PHDR,404 .p_type = elf.PT_PHDR,
397 .p_offset = 0,405 .p_offset = 0,
398 .p_filesz = 0,406 .p_filesz = 0,
399 .p_vaddr = 0,407 .p_vaddr = image_base,
400 .p_paddr = 0,408 .p_paddr = image_base,
401 .p_memsz = 0,409 .p_memsz = 0,
402 .p_align = p_align,410 .p_align = p_align,
403 .p_flags = elf.PF_R,411 .p_flags = elf.PF_R,
...@@ -408,16 +416,14 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -408,16 +416,14 @@ pub fn populateMissingMetadata(self: *Elf) !void {
408 if (self.phdr_table_load_index == null) {416 if (self.phdr_table_load_index == null) {
409 self.phdr_table_load_index = @as(u16, @intCast(self.phdrs.items.len));417 self.phdr_table_load_index = @as(u16, @intCast(self.phdrs.items.len));
410 // TODO Same as for GOT418 // 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;
413 try self.phdrs.append(gpa, .{419 try self.phdrs.append(gpa, .{
414 .p_type = elf.PT_LOAD,420 .p_type = elf.PT_LOAD,
415 .p_offset = 0,421 .p_offset = 0,
416 .p_filesz = 0,422 .p_filesz = 0,
417 .p_vaddr = phdr_addr,423 .p_vaddr = image_base,
418 .p_paddr = phdr_addr,424 .p_paddr = image_base,
419 .p_memsz = 0,425 .p_memsz = 0,
420 .p_align = p_align,426 .p_align = self.page_size,
421 .p_flags = elf.PF_R,427 .p_flags = elf.PF_R,
422 });428 });
423 self.phdr_table_dirty = true;429 self.phdr_table_dirty = true;
...@@ -429,7 +435,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -429,7 +435,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
429 const p_align = self.page_size;435 const p_align = self.page_size;
430 const off = self.findFreeSpace(file_size, p_align);436 const off = self.findFreeSpace(file_size, p_align);
431 log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size });437 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();
433 try self.phdrs.append(gpa, .{439 try self.phdrs.append(gpa, .{
434 .p_type = elf.PT_LOAD,440 .p_type = elf.PT_LOAD,
435 .p_offset = off,441 .p_offset = off,
...@@ -1055,6 +1061,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1055,6 +1061,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10551061
1056 try self.addLinkerDefinedSymbols();1062 try self.addLinkerDefinedSymbols();
10571063
1064 self.allocateLinkerDefinedSymbols();
1065
1058 // Beyond this point, everything has been allocated a virtual address and we can resolve1066 // Beyond this point, everything has been allocated a virtual address and we can resolve
1059 // the relocations.1067 // the relocations.
1060 {1068 {
...@@ -2764,6 +2772,129 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {...@@ -2764,6 +2772,129 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
2764 linker_defined.resolveSymbols(self);2772 linker_defined.resolveSymbols(self);
2765}2773}
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
2767fn updateSymtabSize(self: *Elf) !void {2898fn updateSymtabSize(self: *Elf) !void {
2768 var sizes = SymtabSize{};2899 var sizes = SymtabSize{};
27692900
...@@ -2774,17 +2905,17 @@ fn updateSymtabSize(self: *Elf) !void {...@@ -2774,17 +2905,17 @@ fn updateSymtabSize(self: *Elf) !void {
2774 sizes.nglobals += zig_module.output_symtab_size.nglobals;2905 sizes.nglobals += zig_module.output_symtab_size.nglobals;
2775 }2906 }
27762907
2908 if (self.got_section_index) |_| {
2909 self.got.updateSymtabSize(self);
2910 sizes.nlocals += self.got.output_symtab_size.nlocals;
2911 }
2912
2777 if (self.linker_defined_index) |index| {2913 if (self.linker_defined_index) |index| {
2778 const linker_defined = self.file(index).?.linker_defined;2914 const linker_defined = self.file(index).?.linker_defined;
2779 linker_defined.updateSymtabSize(self);2915 linker_defined.updateSymtabSize(self);
2780 sizes.nlocals += linker_defined.output_symtab_size.nlocals;2916 sizes.nlocals += linker_defined.output_symtab_size.nlocals;
2781 }2917 }
27822918
2783 if (self.got_section_index) |_| {
2784 self.got.updateSymtabSize(self);
2785 sizes.nlocals += self.got.output_symtab_size.nlocals;
2786 }
2787
2788 const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?];2919 const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?];
2789 shdr.sh_info = sizes.nlocals + 1;2920 shdr.sh_info = sizes.nlocals + 1;
2790 self.markDirty(self.symtab_section_index.?, null);2921 self.markDirty(self.symtab_section_index.?, null);
...@@ -2829,17 +2960,17 @@ fn writeSymtab(self: *Elf) !void {...@@ -2829,17 +2960,17 @@ fn writeSymtab(self: *Elf) !void {
2829 ctx.iglobal += zig_module.output_symtab_size.nglobals;2960 ctx.iglobal += zig_module.output_symtab_size.nglobals;
2830 }2961 }
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
2832 if (self.linker_defined_index) |index| {2968 if (self.linker_defined_index) |index| {
2833 const linker_defined = self.file(index).?.linker_defined;2969 const linker_defined = self.file(index).?.linker_defined;
2834 linker_defined.writeSymtab(self, ctx);2970 linker_defined.writeSymtab(self, ctx);
2835 ctx.ilocal += linker_defined.output_symtab_size.nlocals;2971 ctx.ilocal += linker_defined.output_symtab_size.nlocals;
2836 }2972 }
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
2843 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();2974 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
2844 switch (self.ptr_width) {2975 switch (self.ptr_width) {
2845 .p32 => {2976 .p32 => {
...@@ -3179,6 +3310,34 @@ const CsuObjects = struct {...@@ -3179,6 +3310,34 @@ const CsuObjects = struct {
3179 }3310 }
3180};3311};
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
3182pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom {3341pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom {
3183 if (atom_index == 0) return null;3342 if (atom_index == 0) return null;
3184 assert(atom_index < self.atoms.items.len);3343 assert(atom_index < self.atoms.items.len);