| ... | ... | @@ -4037,107 +4037,19 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 4037 | 4037 | } |
| 4038 | 4038 | |
| 4039 | 4039 | fn writeAtoms(self: *Elf) !void { |
| 4040 | | const gpa = self.base.comp.gpa; |
| 4041 | | |
| 4042 | | var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa); |
| 4043 | | defer { |
| 4044 | | for (undefs.values()) |*refs| { |
| 4045 | | refs.deinit(); |
| 4046 | | } |
| 4047 | | undefs.deinit(); |
| 4048 | | } |
| 4049 | | |
| 4050 | | var has_reloc_errors = false; |
| 4051 | | const slice = self.sections.slice(); |
| 4052 | | for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { |
| 4053 | | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 4054 | | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 4055 | | if (atom_list.items.len == 0) continue; |
| 4056 | | |
| 4057 | | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); |
| 4058 | | |
| 4059 | | // TODO really, really handle debug section separately |
| 4060 | | const base_offset = if (self.zigObjectPtr()) |zo| base_offset: { |
| 4061 | | for ([_]?Symbol.Index{ |
| 4062 | | zo.text_index, |
| 4063 | | zo.rodata_index, |
| 4064 | | zo.data_relro_index, |
| 4065 | | zo.data_index, |
| 4066 | | zo.tdata_index, |
| 4067 | | zo.eh_frame_index, |
| 4068 | | zo.debug_info_index, |
| 4069 | | zo.debug_abbrev_index, |
| 4070 | | zo.debug_aranges_index, |
| 4071 | | zo.debug_str_index, |
| 4072 | | zo.debug_line_index, |
| 4073 | | zo.debug_line_str_index, |
| 4074 | | zo.debug_loclists_index, |
| 4075 | | zo.debug_rnglists_index, |
| 4076 | | }) |maybe_sym_index| { |
| 4077 | | const sym_index = maybe_sym_index orelse continue; |
| 4078 | | const sym = zo.symbol(sym_index); |
| 4079 | | const atom_ptr = sym.atom(self).?; |
| 4080 | | if (atom_ptr.output_section_index == shndx) break :base_offset atom_ptr.size; |
| 4081 | | } |
| 4082 | | break :base_offset 0; |
| 4083 | | } else 0; |
| 4084 | | const sh_offset = shdr.sh_offset + base_offset; |
| 4085 | | const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow; |
| 4086 | | |
| 4087 | | const buffer = try gpa.alloc(u8, sh_size); |
| 4088 | | defer gpa.free(buffer); |
| 4089 | | const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and |
| 4090 | | shdr.sh_flags & elf.SHF_EXECINSTR != 0 and self.getTarget().cpu.arch == .x86_64) |
| 4091 | | 0xcc // int3 |
| 4092 | | else |
| 4093 | | 0; |
| 4094 | | @memset(buffer, padding_byte); |
| 4095 | | |
| 4096 | | for (atom_list.items) |ref| { |
| 4097 | | const atom_ptr = self.atom(ref).?; |
| 4098 | | assert(atom_ptr.alive); |
| 4099 | | |
| 4100 | | const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(base_offset))) orelse |
| 4101 | | return error.Overflow; |
| 4102 | | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| 4103 | | |
| 4104 | | log.debug("writing atom({}) at 0x{x}", .{ ref, sh_offset + offset }); |
| 4105 | | |
| 4106 | | // TODO decompress directly into provided buffer |
| 4107 | | const out_code = buffer[offset..][0..size]; |
| 4108 | | const in_code = switch (atom_ptr.file(self).?) { |
| 4109 | | .object => |x| try x.codeDecompressAlloc(self, ref.index), |
| 4110 | | .zig_object => |x| try x.codeAlloc(self, ref.index), |
| 4111 | | else => unreachable, |
| 4112 | | }; |
| 4113 | | defer gpa.free(in_code); |
| 4114 | | @memcpy(out_code, in_code); |
| 4115 | | |
| 4116 | | const res = if (shdr.sh_flags & elf.SHF_ALLOC == 0) |
| 4117 | | atom_ptr.resolveRelocsNonAlloc(self, out_code, &undefs) |
| 4118 | | else |
| 4119 | | atom_ptr.resolveRelocsAlloc(self, out_code); |
| 4120 | | _ = res catch |err| switch (err) { |
| 4121 | | error.UnsupportedCpuArch => { |
| 4122 | | try self.reportUnsupportedCpuArch(); |
| 4123 | | return error.FlushFailure; |
| 4124 | | }, |
| 4125 | | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, |
| 4126 | | else => |e| return e, |
| 4127 | | }; |
| 4128 | | } |
| 4129 | | |
| 4130 | | try self.base.file.?.pwriteAll(buffer, sh_offset); |
| 4040 | for (self.objects.items) |index| { |
| 4041 | try self.file(index).?.object.writeAtoms(self); |
| 4131 | 4042 | } |
| 4132 | 4043 | |
| 4133 | 4044 | if (self.requiresThunks()) { |
| 4045 | const gpa = self.base.comp.gpa; |
| 4134 | 4046 | var buffer = std.ArrayList(u8).init(gpa); |
| 4135 | 4047 | defer buffer.deinit(); |
| 4136 | 4048 | |
| 4137 | 4049 | for (self.thunks.items) |th| { |
| 4138 | 4050 | const thunk_size = th.size(self); |
| 4139 | 4051 | try buffer.ensureUnusedCapacity(thunk_size); |
| 4140 | | const shdr = slice.items(.shdr)[th.output_section_index]; |
| 4052 | const shdr = self.sections.items(.shdr)[th.output_section_index]; |
| 4141 | 4053 | const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset; |
| 4142 | 4054 | try th.write(self, buffer.writer()); |
| 4143 | 4055 | assert(buffer.items.len == thunk_size); |
| ... | ... | @@ -4145,10 +4057,6 @@ fn writeAtoms(self: *Elf) !void { |
| 4145 | 4057 | buffer.clearRetainingCapacity(); |
| 4146 | 4058 | } |
| 4147 | 4059 | } |
| 4148 | | |
| 4149 | | try self.reportUndefinedSymbols(&undefs); |
| 4150 | | |
| 4151 | | if (has_reloc_errors) return error.FlushFailure; |
| 4152 | 4060 | } |
| 4153 | 4061 | |
| 4154 | 4062 | pub fn updateSymtabSize(self: *Elf) !void { |
| ... | ... | @@ -5089,7 +4997,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { |
| 5089 | 4997 | return off; |
| 5090 | 4998 | } |
| 5091 | 4999 | |
| 5092 | | fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 5000 | pub fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 5093 | 5001 | const gpa = self.base.comp.gpa; |
| 5094 | 5002 | const max_notes = 4; |
| 5095 | 5003 | |