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