| author | |
| committer | |
| log | 9b11e5e1f1e0debd1e5484883b2daad8b2b33cb7 |
| tree | 568397a81b76f343bfee781937926bd231e574ad |
| parent | 958f00f1c71f205ce738433d00e9da7dde060f14 |
Part of #28268 files changed, 391 insertions(+), 86 deletions(-)
lib/std/build.zig+13| ... | @@ -21,6 +21,7 @@ pub const TranslateCStep = @import("build/translate_c.zig").TranslateCStep; | ... | @@ -21,6 +21,7 @@ pub const TranslateCStep = @import("build/translate_c.zig").TranslateCStep; |
| 21 | pub const WriteFileStep = @import("build/write_file.zig").WriteFileStep; | 21 | pub const WriteFileStep = @import("build/write_file.zig").WriteFileStep; |
| 22 | pub const RunStep = @import("build/run.zig").RunStep; | 22 | pub const RunStep = @import("build/run.zig").RunStep; |
| 23 | pub const CheckFileStep = @import("build/check_file.zig").CheckFileStep; | 23 | pub const CheckFileStep = @import("build/check_file.zig").CheckFileStep; |
| 24 | pub const InstallRawStep = @import("build/emit_raw.zig").InstallRawStep; | ||
| 24 | 25 | ||
| 25 | pub const Builder = struct { | 26 | pub const Builder = struct { |
| 26 | install_tls: TopLevelStep, | 27 | install_tls: TopLevelStep, |
| ... | @@ -824,6 +825,10 @@ pub const Builder = struct { | ... | @@ -824,6 +825,10 @@ pub const Builder = struct { |
| 824 | self.getInstallStep().dependOn(&self.addInstallFileWithDir(src_path, .Lib, dest_rel_path).step); | 825 | self.getInstallStep().dependOn(&self.addInstallFileWithDir(src_path, .Lib, dest_rel_path).step); |
| 825 | } | 826 | } |
| 826 | 827 | ||
| 828 | pub fn installRaw(self: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8) void { | ||
| 829 | self.getInstallStep().dependOn(&self.addInstallRaw(artifact, dest_filename).step); | ||
| 830 | } | ||
| 831 | |||
| 827 | ///`dest_rel_path` is relative to install prefix path | 832 | ///`dest_rel_path` is relative to install prefix path |
| 828 | pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { | 833 | pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { |
| 829 | return self.addInstallFileWithDir(src_path, .Prefix, dest_rel_path); | 834 | return self.addInstallFileWithDir(src_path, .Prefix, dest_rel_path); |
| ... | @@ -839,6 +844,10 @@ pub const Builder = struct { | ... | @@ -839,6 +844,10 @@ pub const Builder = struct { |
| 839 | return self.addInstallFileWithDir(src_path, .Lib, dest_rel_path); | 844 | return self.addInstallFileWithDir(src_path, .Lib, dest_rel_path); |
| 840 | } | 845 | } |
| 841 | 846 | ||
| 847 | pub fn addInstallRaw(self: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8) *InstallRawStep { | ||
| 848 | return InstallRawStep.create(self, artifact, dest_filename); | ||
| 849 | } | ||
| 850 | |||
| 842 | pub fn addInstallFileWithDir( | 851 | pub fn addInstallFileWithDir( |
| 843 | self: *Builder, | 852 | self: *Builder, |
| 844 | src_path: []const u8, | 853 | src_path: []const u8, |
| ... | @@ -1407,6 +1416,10 @@ pub const LibExeObjStep = struct { | ... | @@ -1407,6 +1416,10 @@ pub const LibExeObjStep = struct { |
| 1407 | self.builder.installArtifact(self); | 1416 | self.builder.installArtifact(self); |
| 1408 | } | 1417 | } |
| 1409 | 1418 | ||
| 1419 | pub fn installRaw(self: *LibExeObjStep, dest_filename: [] const u8) void { | ||
| 1420 | self.builder.installRaw(self, dest_filename); | ||
| 1421 | } | ||
| 1422 | |||
| 1410 | /// Creates a `RunStep` with an executable built with `addExecutable`. | 1423 | /// Creates a `RunStep` with an executable built with `addExecutable`. |
| 1411 | /// Add command line arguments with `addArg`. | 1424 | /// Add command line arguments with `addArg`. |
| 1412 | pub fn run(exe: *LibExeObjStep) *RunStep { | 1425 | pub fn run(exe: *LibExeObjStep) *RunStep { |
lib/std/build/emit_raw.zig created+255| ... | @@ -0,0 +1,255 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const Allocator = std.mem.Allocator; | ||
| 4 | const ArenaAllocator = std.heap.ArenaAllocator; | ||
| 5 | const ArrayList = std.ArrayList; | ||
| 6 | const Builder = std.build.Builder; | ||
| 7 | const File = std.fs.File; | ||
| 8 | const InstallDir = std.build.InstallDir; | ||
| 9 | const LibExeObjStep = std.build.LibExeObjStep; | ||
| 10 | const Step = std.build.Step; | ||
| 11 | const elf = std.elf; | ||
| 12 | const fs = std.fs; | ||
| 13 | const io = std.io; | ||
| 14 | const sort = std.sort; | ||
| 15 | const warn = std.debug.warn; | ||
| 16 | |||
| 17 | const BinOutStream = io.OutStream(anyerror); | ||
| 18 | const BinSeekStream = io.SeekableStream(anyerror, anyerror); | ||
| 19 | const ElfSeekStream = io.SeekableStream(anyerror, anyerror); | ||
| 20 | const ElfInStream = io.InStream(anyerror); | ||
| 21 | |||
| 22 | const BinaryElfSection = struct { | ||
| 23 | elfOffset: u64, | ||
| 24 | binaryOffset: u64, | ||
| 25 | fileSize: usize, | ||
| 26 | segment: ?*BinaryElfSegment, | ||
| 27 | }; | ||
| 28 | |||
| 29 | const BinaryElfSegment = struct { | ||
| 30 | physicalAddress: u64, | ||
| 31 | virtualAddress: u64, | ||
| 32 | elfOffset: u64, | ||
| 33 | binaryOffset: u64, | ||
| 34 | fileSize: usize, | ||
| 35 | firstSection: ?*BinaryElfSection, | ||
| 36 | }; | ||
| 37 | |||
| 38 | const BinaryElfOutput = struct { | ||
| 39 | segments: ArrayList(*BinaryElfSegment), | ||
| 40 | sections: ArrayList(*BinaryElfSection), | ||
| 41 | |||
| 42 | const Self = @This(); | ||
| 43 | |||
| 44 | pub fn init(allocator: *Allocator) Self { | ||
| 45 | return Self{ | ||
| 46 | .segments = ArrayList(*BinaryElfSegment).init(allocator), | ||
| 47 | .sections = ArrayList(*BinaryElfSection).init(allocator), | ||
| 48 | }; | ||
| 49 | } | ||
| 50 | |||
| 51 | pub fn deinit(self: *Self) void { | ||
| 52 | self.sections.deinit(); | ||
| 53 | self.segments.deinit(); | ||
| 54 | } | ||
| 55 | |||
| 56 | pub fn parseElf(self: *Self, elfFile: elf.Elf) !void { | ||
| 57 | const allocator = self.segments.allocator; | ||
| 58 | |||
| 59 | for (elfFile.section_headers) |section, i| { | ||
| 60 | if (sectionValidForOutput(section)) { | ||
| 61 | const newSection = try allocator.create(BinaryElfSection); | ||
| 62 | |||
| 63 | newSection.binaryOffset = 0; | ||
| 64 | newSection.elfOffset = section.sh_offset; | ||
| 65 | newSection.fileSize = @intCast(usize, section.sh_size); | ||
| 66 | newSection.segment = null; | ||
| 67 | |||
| 68 | try self.sections.append(newSection); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | for (elfFile.program_headers) |programHeader, i| { | ||
| 73 | if (programHeader.p_type == elf.PT_LOAD) { | ||
| 74 | const newSegment = try allocator.create(BinaryElfSegment); | ||
| 75 | |||
| 76 | newSegment.physicalAddress = if (programHeader.p_paddr != 0) programHeader.p_paddr else programHeader.p_vaddr; | ||
| 77 | newSegment.virtualAddress = programHeader.p_vaddr; | ||
| 78 | newSegment.fileSize = @intCast(usize, programHeader.p_filesz); | ||
| 79 | newSegment.elfOffset = programHeader.p_offset; | ||
| 80 | newSegment.binaryOffset = 0; | ||
| 81 | newSegment.firstSection = null; | ||
| 82 | |||
| 83 | for (self.sections.toSlice()) |section| { | ||
| 84 | if (sectionWithinSegment(section, programHeader)) { | ||
| 85 | if (section.segment) |sectionSegment| { | ||
| 86 | if (sectionSegment.elfOffset > newSegment.elfOffset) { | ||
| 87 | section.segment = newSegment; | ||
| 88 | } | ||
| 89 | } else { | ||
| 90 | section.segment = newSegment; | ||
| 91 | } | ||
| 92 | |||
| 93 | if (newSegment.firstSection == null) { | ||
| 94 | newSegment.firstSection = section; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | try self.segments.append(newSegment); | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | sort.sort(*BinaryElfSegment, self.segments.toSlice(), segmentSortCompare); | ||
| 104 | |||
| 105 | if (self.segments.len > 0) { | ||
| 106 | const firstSegment = self.segments.at(0); | ||
| 107 | if (firstSegment.firstSection) |firstSection| { | ||
| 108 | const diff = firstSection.elfOffset - firstSegment.elfOffset; | ||
| 109 | |||
| 110 | firstSegment.elfOffset += diff; | ||
| 111 | firstSegment.fileSize += diff; | ||
| 112 | firstSegment.physicalAddress += diff; | ||
| 113 | |||
| 114 | const basePhysicalAddress = firstSegment.physicalAddress; | ||
| 115 | |||
| 116 | for (self.segments.toSlice()) |segment| { | ||
| 117 | segment.binaryOffset = segment.physicalAddress - basePhysicalAddress; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | for (self.sections.toSlice()) |section| { | ||
| 123 | if (section.segment) |segment| { | ||
| 124 | section.binaryOffset = segment.binaryOffset + (section.elfOffset - segment.elfOffset); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | sort.sort(*BinaryElfSection, self.sections.toSlice(), sectionSortCompare); | ||
| 129 | } | ||
| 130 | |||
| 131 | fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.ProgramHeader) bool { | ||
| 132 | return segment.p_offset <= section.elfOffset and (segment.p_offset + segment.p_filesz) >= (section.elfOffset + section.fileSize); | ||
| 133 | } | ||
| 134 | |||
| 135 | fn sectionValidForOutput(section: elf.SectionHeader) bool { | ||
| 136 | return section.sh_size > 0 and section.sh_type != elf.SHT_NOBITS and ((section.sh_flags & elf.SHF_ALLOC) == elf.SHF_ALLOC); | ||
| 137 | } | ||
| 138 | |||
| 139 | fn segmentSortCompare(left: *BinaryElfSegment, right: *BinaryElfSegment) bool { | ||
| 140 | if (left.physicalAddress < right.physicalAddress) { | ||
| 141 | return true; | ||
| 142 | } | ||
| 143 | if (left.physicalAddress > right.physicalAddress) { | ||
| 144 | return false; | ||
| 145 | } | ||
| 146 | return false; | ||
| 147 | } | ||
| 148 | |||
| 149 | fn sectionSortCompare(left: *BinaryElfSection, right: *BinaryElfSection) bool { | ||
| 150 | return left.binaryOffset < right.binaryOffset; | ||
| 151 | } | ||
| 152 | }; | ||
| 153 | |||
| 154 | const WriteContext = struct { | ||
| 155 | inStream: *ElfInStream, | ||
| 156 | inSeekStream: *ElfSeekStream, | ||
| 157 | outStream: *BinOutStream, | ||
| 158 | outSeekStream: *BinSeekStream, | ||
| 159 | }; | ||
| 160 | |||
| 161 | fn writeBinaryElfSection(allocator: *Allocator, context: WriteContext, section: *BinaryElfSection) !void { | ||
| 162 | var readBuffer = try allocator.alloc(u8, section.fileSize); | ||
| 163 | defer allocator.free(readBuffer); | ||
| 164 | |||
| 165 | try context.inSeekStream.seekTo(section.elfOffset); | ||
| 166 | _ = try context.inStream.read(readBuffer); | ||
| 167 | |||
| 168 | try context.outSeekStream.seekTo(section.binaryOffset); | ||
| 169 | try context.outStream.write(readBuffer); | ||
| 170 | } | ||
| 171 | |||
| 172 | fn emit_raw(allocator: *Allocator, elf_path: []const u8, raw_path: []const u8) !void { | ||
| 173 | var arenaAlloc = ArenaAllocator.init(allocator); | ||
| 174 | errdefer arenaAlloc.deinit(); | ||
| 175 | var arena_allocator = &arenaAlloc.allocator; | ||
| 176 | |||
| 177 | const currentDir = fs.cwd(); | ||
| 178 | |||
| 179 | var file = try currentDir.openFile(elf_path, File.OpenFlags{}); | ||
| 180 | defer file.close(); | ||
| 181 | |||
| 182 | var fileInStream = file.inStream(); | ||
| 183 | var fileSeekStream = file.seekableStream(); | ||
| 184 | |||
| 185 | var elfFile = try elf.Elf.openStream(allocator, @ptrCast(*ElfSeekStream, &fileSeekStream.stream), @ptrCast(*ElfInStream, &fileInStream.stream)); | ||
| 186 | defer elfFile.close(); | ||
| 187 | |||
| 188 | var outFile = try currentDir.createFile(raw_path, File.CreateFlags{}); | ||
| 189 | defer outFile.close(); | ||
| 190 | |||
| 191 | var outFileOutStream = outFile.outStream(); | ||
| 192 | var outFileSeekStream = outFile.seekableStream(); | ||
| 193 | |||
| 194 | const writeContext = WriteContext{ | ||
| 195 | .inStream = @ptrCast(*ElfInStream, &fileInStream.stream), | ||
| 196 | .inSeekStream = @ptrCast(*ElfSeekStream, &fileSeekStream.stream), | ||
| 197 | .outStream = @ptrCast(*BinOutStream, &outFileOutStream.stream), | ||
| 198 | .outSeekStream = @ptrCast(*BinSeekStream, &outFileSeekStream.stream), | ||
| 199 | }; | ||
| 200 | |||
| 201 | var binaryElfOutput = BinaryElfOutput.init(arena_allocator); | ||
| 202 | defer binaryElfOutput.deinit(); | ||
| 203 | |||
| 204 | try binaryElfOutput.parseElf(elfFile); | ||
| 205 | |||
| 206 | for (binaryElfOutput.sections.toSlice()) |section| { | ||
| 207 | try writeBinaryElfSection(allocator, writeContext, section); | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | pub const InstallRawStep = struct { | ||
| 212 | step: Step, | ||
| 213 | builder: *Builder, | ||
| 214 | artifact: *LibExeObjStep, | ||
| 215 | dest_dir: InstallDir, | ||
| 216 | dest_filename: [] const u8, | ||
| 217 | |||
| 218 | const Self = @This(); | ||
| 219 | |||
| 220 | pub fn create(builder: *Builder, artifact: *LibExeObjStep, dest_filename: [] const u8) *Self { | ||
| 221 | const self = builder.allocator.create(Self) catch unreachable; | ||
| 222 | self.* = Self{ | ||
| 223 | .step = Step.init(builder.fmt("install raw binary {}", .{artifact.step.name}), builder.allocator, make), | ||
| 224 | .builder = builder, | ||
| 225 | .artifact = artifact, | ||
| 226 | .dest_dir = switch (artifact.kind) { | ||
| 227 | .Obj => unreachable, | ||
| 228 | .Test => unreachable, | ||
| 229 | .Exe => .Bin, | ||
| 230 | .Lib => unreachable, | ||
| 231 | }, | ||
| 232 | .dest_filename = dest_filename, | ||
| 233 | }; | ||
| 234 | self.step.dependOn(&artifact.step); | ||
| 235 | |||
| 236 | builder.pushInstalledFile(self.dest_dir, dest_filename); | ||
| 237 | return self; | ||
| 238 | } | ||
| 239 | |||
| 240 | fn make(step: *Step) !void { | ||
| 241 | const self = @fieldParentPtr(Self, "step", step); | ||
| 242 | const builder = self.builder; | ||
| 243 | |||
| 244 | if (self.artifact.target.getObjectFormat() != .elf) { | ||
| 245 | warn("InstallRawStep only works with ELF format.\n", .{}); | ||
| 246 | return error.InvalidObjectFormat; | ||
| 247 | } | ||
| 248 | |||
| 249 | const full_src_path = self.artifact.getOutputPath(); | ||
| 250 | const full_dest_path = builder.getInstallPath(self.dest_dir, self.dest_filename); | ||
| 251 | |||
| 252 | fs.makePath(builder.allocator, builder.getInstallPath(self.dest_dir, "")) catch unreachable; | ||
| 253 | try emit_raw(builder.allocator, full_src_path, full_dest_path); | ||
| 254 | } | ||
| 255 | }; | ||
| \ No newline at end of file | |||
lib/std/debug.zig+7-7| ... | @@ -946,8 +946,8 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { | ... | @@ -946,8 +946,8 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { |
| 946 | fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section { | 946 | fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section { |
| 947 | const elf_header = (try elf_file.findSection(name)) orelse return null; | 947 | const elf_header = (try elf_file.findSection(name)) orelse return null; |
| 948 | return DwarfInfo.Section{ | 948 | return DwarfInfo.Section{ |
| 949 | .offset = elf_header.offset, | 949 | .offset = elf_header.sh_offset, |
| 950 | .size = elf_header.size, | 950 | .size = elf_header.sh_size, |
| 951 | }; | 951 | }; |
| 952 | } | 952 | } |
| 953 | 953 | ||
| ... | @@ -987,12 +987,12 @@ pub fn openElfDebugInfo( | ... | @@ -987,12 +987,12 @@ pub fn openElfDebugInfo( |
| 987 | 987 | ||
| 988 | var di = DwarfInfo{ | 988 | var di = DwarfInfo{ |
| 989 | .endian = efile.endian, | 989 | .endian = efile.endian, |
| 990 | .debug_info = (data[@intCast(usize, debug_info.offset)..@intCast(usize, debug_info.offset + debug_info.size)]), | 990 | .debug_info = (data[@intCast(usize, debug_info.sh_offset)..@intCast(usize, debug_info.sh_offset + debug_info.sh_size)]), |
| 991 | .debug_abbrev = (data[@intCast(usize, debug_abbrev.offset)..@intCast(usize, debug_abbrev.offset + debug_abbrev.size)]), | 991 | .debug_abbrev = (data[@intCast(usize, debug_abbrev.sh_offset)..@intCast(usize, debug_abbrev.sh_offset + debug_abbrev.sh_size)]), |
| 992 | .debug_str = (data[@intCast(usize, debug_str.offset)..@intCast(usize, debug_str.offset + debug_str.size)]), | 992 | .debug_str = (data[@intCast(usize, debug_str.sh_offset)..@intCast(usize, debug_str.sh_offset + debug_str.sh_size)]), |
| 993 | .debug_line = (data[@intCast(usize, debug_line.offset)..@intCast(usize, debug_line.offset + debug_line.size)]), | 993 | .debug_line = (data[@intCast(usize, debug_line.sh_offset)..@intCast(usize, debug_line.sh_offset + debug_line.sh_size)]), |
| 994 | .debug_ranges = if (opt_debug_ranges) |debug_ranges| | 994 | .debug_ranges = if (opt_debug_ranges) |debug_ranges| |
| 995 | data[@intCast(usize, debug_ranges.offset)..@intCast(usize, debug_ranges.offset + debug_ranges.size)] | 995 | data[@intCast(usize, debug_ranges.sh_offset)..@intCast(usize, debug_ranges.sh_offset + debug_ranges.sh_size)] |
| 996 | else | 996 | else |
| 997 | null, | 997 | null, |
| 998 | }; | 998 | }; |
lib/std/elf.zig+96-59| ... | @@ -330,19 +330,8 @@ pub const ET = extern enum(u16) { | ... | @@ -330,19 +330,8 @@ pub const ET = extern enum(u16) { |
| 330 | pub const HIPROC = 0xffff; | 330 | pub const HIPROC = 0xffff; |
| 331 | }; | 331 | }; |
| 332 | 332 | ||
| 333 | /// TODO delete this in favor of Elf64_Shdr | 333 | pub const SectionHeader = Elf64_Shdr; |
| 334 | pub const SectionHeader = struct { | 334 | pub const ProgramHeader = Elf64_Phdr; |
| 335 | name: u32, | ||
| 336 | sh_type: u32, | ||
| 337 | flags: u64, | ||
| 338 | addr: u64, | ||
| 339 | offset: u64, | ||
| 340 | size: u64, | ||
| 341 | link: u32, | ||
| 342 | info: u32, | ||
| 343 | addr_align: u64, | ||
| 344 | ent_size: u64, | ||
| 345 | }; | ||
| 346 | 335 | ||
| 347 | pub const Elf = struct { | 336 | pub const Elf = struct { |
| 348 | seekable_stream: *io.SeekableStream(anyerror, anyerror), | 337 | seekable_stream: *io.SeekableStream(anyerror, anyerror), |
| ... | @@ -357,6 +346,7 @@ pub const Elf = struct { | ... | @@ -357,6 +346,7 @@ pub const Elf = struct { |
| 357 | string_section_index: usize, | 346 | string_section_index: usize, |
| 358 | string_section: *SectionHeader, | 347 | string_section: *SectionHeader, |
| 359 | section_headers: []SectionHeader, | 348 | section_headers: []SectionHeader, |
| 349 | program_headers: []ProgramHeader, | ||
| 360 | allocator: *mem.Allocator, | 350 | allocator: *mem.Allocator, |
| 361 | 351 | ||
| 362 | /// Call close when done. | 352 | /// Call close when done. |
| ... | @@ -421,14 +411,24 @@ pub const Elf = struct { | ... | @@ -421,14 +411,24 @@ pub const Elf = struct { |
| 421 | try seekable_stream.seekBy(4); | 411 | try seekable_stream.seekBy(4); |
| 422 | 412 | ||
| 423 | const header_size = try in.readInt(u16, elf.endian); | 413 | const header_size = try in.readInt(u16, elf.endian); |
| 424 | if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) { | 414 | if ((elf.is_64 and header_size != @sizeOf(Elf64_Ehdr)) or (!elf.is_64 and header_size != @sizeOf(Elf32_Ehdr))) { |
| 425 | return error.InvalidFormat; | 415 | return error.InvalidFormat; |
| 426 | } | 416 | } |
| 427 | 417 | ||
| 428 | const ph_entry_size = try in.readInt(u16, elf.endian); | 418 | const ph_entry_size = try in.readInt(u16, elf.endian); |
| 429 | const ph_entry_count = try in.readInt(u16, elf.endian); | 419 | const ph_entry_count = try in.readInt(u16, elf.endian); |
| 420 | |||
| 421 | if ((elf.is_64 and ph_entry_size != @sizeOf(Elf64_Phdr)) or (!elf.is_64 and ph_entry_size != @sizeOf(Elf32_Phdr))) { | ||
| 422 | return error.InvalidFormat; | ||
| 423 | } | ||
| 424 | |||
| 430 | const sh_entry_size = try in.readInt(u16, elf.endian); | 425 | const sh_entry_size = try in.readInt(u16, elf.endian); |
| 431 | const sh_entry_count = try in.readInt(u16, elf.endian); | 426 | const sh_entry_count = try in.readInt(u16, elf.endian); |
| 427 | |||
| 428 | if ((elf.is_64 and sh_entry_size != @sizeOf(Elf64_Shdr)) or (!elf.is_64 and sh_entry_size != @sizeOf(Elf32_Shdr))) { | ||
| 429 | return error.InvalidFormat; | ||
| 430 | } | ||
| 431 | |||
| 432 | elf.string_section_index = @as(usize, try in.readInt(u16, elf.endian)); | 432 | elf.string_section_index = @as(usize, try in.readInt(u16, elf.endian)); |
| 433 | 433 | ||
| 434 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; | 434 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; |
| ... | @@ -443,47 +443,72 @@ pub const Elf = struct { | ... | @@ -443,47 +443,72 @@ pub const Elf = struct { |
| 443 | return error.InvalidFormat; | 443 | return error.InvalidFormat; |
| 444 | } | 444 | } |
| 445 | 445 | ||
| 446 | try seekable_stream.seekTo(elf.program_header_offset); | ||
| 447 | |||
| 448 | elf.program_headers = try elf.allocator.alloc(ProgramHeader, ph_entry_count); | ||
| 449 | errdefer elf.allocator.free(elf.program_headers); | ||
| 450 | |||
| 451 | if (elf.is_64) { | ||
| 452 | for (elf.program_headers) |*elf_program| { | ||
| 453 | elf_program.p_type = try in.readInt(Elf64_Word, elf.endian); | ||
| 454 | elf_program.p_flags = try in.readInt(Elf64_Word, elf.endian); | ||
| 455 | elf_program.p_offset = try in.readInt(Elf64_Off, elf.endian); | ||
| 456 | elf_program.p_vaddr = try in.readInt(Elf64_Addr, elf.endian); | ||
| 457 | elf_program.p_paddr = try in.readInt(Elf64_Addr, elf.endian); | ||
| 458 | elf_program.p_filesz = try in.readInt(Elf64_Xword, elf.endian); | ||
| 459 | elf_program.p_memsz = try in.readInt(Elf64_Xword, elf.endian); | ||
| 460 | elf_program.p_align = try in.readInt(Elf64_Xword, elf.endian); | ||
| 461 | } | ||
| 462 | } else { | ||
| 463 | for (elf.program_headers) |*elf_program| { | ||
| 464 | elf_program.p_type = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); | ||
| 465 | elf_program.p_offset = @as(Elf64_Off, try in.readInt(Elf32_Off, elf.endian)); | ||
| 466 | elf_program.p_vaddr = @as(Elf64_Addr, try in.readInt(Elf32_Addr, elf.endian)); | ||
| 467 | elf_program.p_paddr = @as(Elf64_Addr, try in.readInt(Elf32_Addr, elf.endian)); | ||
| 468 | elf_program.p_filesz = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); | ||
| 469 | elf_program.p_memsz = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); | ||
| 470 | elf_program.p_flags = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); | ||
| 471 | elf_program.p_align = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 446 | try seekable_stream.seekTo(elf.section_header_offset); | 475 | try seekable_stream.seekTo(elf.section_header_offset); |
| 447 | 476 | ||
| 448 | elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); | 477 | elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); |
| 449 | errdefer elf.allocator.free(elf.section_headers); | 478 | errdefer elf.allocator.free(elf.section_headers); |
| 450 | 479 | ||
| 451 | if (elf.is_64) { | 480 | if (elf.is_64) { |
| 452 | if (sh_entry_size != 64) return error.InvalidFormat; | ||
| 453 | |||
| 454 | for (elf.section_headers) |*elf_section| { | 481 | for (elf.section_headers) |*elf_section| { |
| 455 | elf_section.name = try in.readInt(u32, elf.endian); | 482 | elf_section.sh_name = try in.readInt(u32, elf.endian); |
| 456 | elf_section.sh_type = try in.readInt(u32, elf.endian); | 483 | elf_section.sh_type = try in.readInt(u32, elf.endian); |
| 457 | elf_section.flags = try in.readInt(u64, elf.endian); | 484 | elf_section.sh_flags = try in.readInt(u64, elf.endian); |
| 458 | elf_section.addr = try in.readInt(u64, elf.endian); | 485 | elf_section.sh_addr = try in.readInt(u64, elf.endian); |
| 459 | elf_section.offset = try in.readInt(u64, elf.endian); | 486 | elf_section.sh_offset = try in.readInt(u64, elf.endian); |
| 460 | elf_section.size = try in.readInt(u64, elf.endian); | 487 | elf_section.sh_size = try in.readInt(u64, elf.endian); |
| 461 | elf_section.link = try in.readInt(u32, elf.endian); | 488 | elf_section.sh_link = try in.readInt(u32, elf.endian); |
| 462 | elf_section.info = try in.readInt(u32, elf.endian); | 489 | elf_section.sh_info = try in.readInt(u32, elf.endian); |
| 463 | elf_section.addr_align = try in.readInt(u64, elf.endian); | 490 | elf_section.sh_addralign = try in.readInt(u64, elf.endian); |
| 464 | elf_section.ent_size = try in.readInt(u64, elf.endian); | 491 | elf_section.sh_entsize = try in.readInt(u64, elf.endian); |
| 465 | } | 492 | } |
| 466 | } else { | 493 | } else { |
| 467 | if (sh_entry_size != 40) return error.InvalidFormat; | ||
| 468 | |||
| 469 | for (elf.section_headers) |*elf_section| { | 494 | for (elf.section_headers) |*elf_section| { |
| 470 | // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? | 495 | // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? |
| 471 | elf_section.name = try in.readInt(u32, elf.endian); | 496 | elf_section.sh_name = try in.readInt(u32, elf.endian); |
| 472 | elf_section.sh_type = try in.readInt(u32, elf.endian); | 497 | elf_section.sh_type = try in.readInt(u32, elf.endian); |
| 473 | elf_section.flags = @as(u64, try in.readInt(u32, elf.endian)); | 498 | elf_section.sh_flags = @as(u64, try in.readInt(u32, elf.endian)); |
| 474 | elf_section.addr = @as(u64, try in.readInt(u32, elf.endian)); | 499 | elf_section.sh_addr = @as(u64, try in.readInt(u32, elf.endian)); |
| 475 | elf_section.offset = @as(u64, try in.readInt(u32, elf.endian)); | 500 | elf_section.sh_offset = @as(u64, try in.readInt(u32, elf.endian)); |
| 476 | elf_section.size = @as(u64, try in.readInt(u32, elf.endian)); | 501 | elf_section.sh_size = @as(u64, try in.readInt(u32, elf.endian)); |
| 477 | elf_section.link = try in.readInt(u32, elf.endian); | 502 | elf_section.sh_link = try in.readInt(u32, elf.endian); |
| 478 | elf_section.info = try in.readInt(u32, elf.endian); | 503 | elf_section.sh_info = try in.readInt(u32, elf.endian); |
| 479 | elf_section.addr_align = @as(u64, try in.readInt(u32, elf.endian)); | 504 | elf_section.sh_addralign = @as(u64, try in.readInt(u32, elf.endian)); |
| 480 | elf_section.ent_size = @as(u64, try in.readInt(u32, elf.endian)); | 505 | elf_section.sh_entsize = @as(u64, try in.readInt(u32, elf.endian)); |
| 481 | } | 506 | } |
| 482 | } | 507 | } |
| 483 | 508 | ||
| 484 | for (elf.section_headers) |*elf_section| { | 509 | for (elf.section_headers) |*elf_section| { |
| 485 | if (elf_section.sh_type != SHT_NOBITS) { | 510 | if (elf_section.sh_type != SHT_NOBITS) { |
| 486 | const file_end_offset = try math.add(u64, elf_section.offset, elf_section.size); | 511 | const file_end_offset = try math.add(u64, elf_section.sh_offset, elf_section.sh_size); |
| 487 | if (stream_end < file_end_offset) return error.InvalidFormat; | 512 | if (stream_end < file_end_offset) return error.InvalidFormat; |
| 488 | } | 513 | } |
| 489 | } | 514 | } |
| ... | @@ -499,13 +524,14 @@ pub const Elf = struct { | ... | @@ -499,13 +524,14 @@ pub const Elf = struct { |
| 499 | 524 | ||
| 500 | pub fn close(elf: *Elf) void { | 525 | pub fn close(elf: *Elf) void { |
| 501 | elf.allocator.free(elf.section_headers); | 526 | elf.allocator.free(elf.section_headers); |
| 527 | elf.allocator.free(elf.program_headers); | ||
| 502 | } | 528 | } |
| 503 | 529 | ||
| 504 | pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader { | 530 | pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader { |
| 505 | section_loop: for (elf.section_headers) |*elf_section| { | 531 | section_loop: for (elf.section_headers) |*elf_section| { |
| 506 | if (elf_section.sh_type == SHT_NULL) continue; | 532 | if (elf_section.sh_type == SHT_NULL) continue; |
| 507 | 533 | ||
| 508 | const name_offset = elf.string_section.offset + elf_section.name; | 534 | const name_offset = elf.string_section.sh_offset + elf_section.sh_name; |
| 509 | try elf.seekable_stream.seekTo(name_offset); | 535 | try elf.seekable_stream.seekTo(name_offset); |
| 510 | 536 | ||
| 511 | for (name) |expected_c| { | 537 | for (name) |expected_c| { |
| ... | @@ -523,7 +549,7 @@ pub const Elf = struct { | ... | @@ -523,7 +549,7 @@ pub const Elf = struct { |
| 523 | } | 549 | } |
| 524 | 550 | ||
| 525 | pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void { | 551 | pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void { |
| 526 | try elf.seekable_stream.seekTo(elf_section.offset); | 552 | try elf.seekable_stream.seekTo(elf_section.sh_offset); |
| 527 | } | 553 | } |
| 528 | }; | 554 | }; |
| 529 | 555 | ||
| ... | @@ -578,6 +604,26 @@ pub const Elf64_Ehdr = extern struct { | ... | @@ -578,6 +604,26 @@ pub const Elf64_Ehdr = extern struct { |
| 578 | e_shnum: Elf64_Half, | 604 | e_shnum: Elf64_Half, |
| 579 | e_shstrndx: Elf64_Half, | 605 | e_shstrndx: Elf64_Half, |
| 580 | }; | 606 | }; |
| 607 | pub const Elf32_Phdr = extern struct { | ||
| 608 | p_type: Elf32_Word, | ||
| 609 | p_offset: Elf32_Off, | ||
| 610 | p_vaddr: Elf32_Addr, | ||
| 611 | p_paddr: Elf32_Addr, | ||
| 612 | p_filesz: Elf32_Word, | ||
| 613 | p_memsz: Elf32_Word, | ||
| 614 | p_flags: Elf32_Word, | ||
| 615 | p_align: Elf32_Word, | ||
| 616 | }; | ||
| 617 | pub const Elf64_Phdr = extern struct { | ||
| 618 | p_type: Elf64_Word, | ||
| 619 | p_flags: Elf64_Word, | ||
| 620 | p_offset: Elf64_Off, | ||
| 621 | p_vaddr: Elf64_Addr, | ||
| 622 | p_paddr: Elf64_Addr, | ||
| 623 | p_filesz: Elf64_Xword, | ||
| 624 | p_memsz: Elf64_Xword, | ||
| 625 | p_align: Elf64_Xword, | ||
| 626 | }; | ||
| 581 | pub const Elf32_Shdr = extern struct { | 627 | pub const Elf32_Shdr = extern struct { |
| 582 | sh_name: Elf32_Word, | 628 | sh_name: Elf32_Word, |
| 583 | sh_type: Elf32_Word, | 629 | sh_type: Elf32_Word, |
| ... | @@ -655,26 +701,6 @@ pub const Elf64_Rela = extern struct { | ... | @@ -655,26 +701,6 @@ pub const Elf64_Rela = extern struct { |
| 655 | r_info: Elf64_Xword, | 701 | r_info: Elf64_Xword, |
| 656 | r_addend: Elf64_Sxword, | 702 | r_addend: Elf64_Sxword, |
| 657 | }; | 703 | }; |
| 658 | pub const Elf32_Phdr = extern struct { | ||
| 659 | p_type: Elf32_Word, | ||
| 660 | p_offset: Elf32_Off, | ||
| 661 | p_vaddr: Elf32_Addr, | ||
| 662 | p_paddr: Elf32_Addr, | ||
| 663 | p_filesz: Elf32_Word, | ||
| 664 | p_memsz: Elf32_Word, | ||
| 665 | p_flags: Elf32_Word, | ||
| 666 | p_align: Elf32_Word, | ||
| 667 | }; | ||
| 668 | pub const Elf64_Phdr = extern struct { | ||
| 669 | p_type: Elf64_Word, | ||
| 670 | p_flags: Elf64_Word, | ||
| 671 | p_offset: Elf64_Off, | ||
| 672 | p_vaddr: Elf64_Addr, | ||
| 673 | p_paddr: Elf64_Addr, | ||
| 674 | p_filesz: Elf64_Xword, | ||
| 675 | p_memsz: Elf64_Xword, | ||
| 676 | p_align: Elf64_Xword, | ||
| 677 | }; | ||
| 678 | pub const Elf32_Dyn = extern struct { | 704 | pub const Elf32_Dyn = extern struct { |
| 679 | d_tag: Elf32_Sword, | 705 | d_tag: Elf32_Sword, |
| 680 | d_un: extern union { | 706 | d_un: extern union { |
| ... | @@ -833,6 +859,17 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct { | ... | @@ -833,6 +859,17 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct { |
| 833 | flags2: Elf32_Word, | 859 | flags2: Elf32_Word, |
| 834 | }; | 860 | }; |
| 835 | 861 | ||
| 862 | comptime { | ||
| 863 | debug.assert(@sizeOf(Elf32_Ehdr) == 52); | ||
| 864 | debug.assert(@sizeOf(Elf64_Ehdr) == 64); | ||
| 865 | |||
| 866 | debug.assert(@sizeOf(Elf32_Phdr) == 32); | ||
| 867 | debug.assert(@sizeOf(Elf64_Phdr) == 56); | ||
| 868 | |||
| 869 | debug.assert(@sizeOf(Elf32_Shdr) == 40); | ||
| 870 | debug.assert(@sizeOf(Elf64_Shdr) == 64); | ||
| 871 | } | ||
| 872 | |||
| 836 | pub const Auxv = switch (@sizeOf(usize)) { | 873 | pub const Auxv = switch (@sizeOf(usize)) { |
| 837 | 4 => Elf32_auxv_t, | 874 | 4 => Elf32_auxv_t, |
| 838 | 8 => Elf64_auxv_t, | 875 | 8 => Elf64_auxv_t, |
lib/std/target.zig+17| ... | @@ -972,6 +972,23 @@ pub const Target = union(enum) { | ... | @@ -972,6 +972,23 @@ pub const Target = union(enum) { |
| 972 | } | 972 | } |
| 973 | } | 973 | } |
| 974 | 974 | ||
| 975 | pub fn getObjectFormat(self: Target) ObjectFormat { | ||
| 976 | switch (self) { | ||
| 977 | .Native => return @import("builtin").object_format, | ||
| 978 | .Cross => blk: { | ||
| 979 | if (self.isWindows() or self.isUefi()) { | ||
| 980 | return .coff; | ||
| 981 | } else if (self.isDarwin()) { | ||
| 982 | return .macho; | ||
| 983 | } | ||
| 984 | if (self.isWasm()) { | ||
| 985 | return .wasm; | ||
| 986 | } | ||
| 987 | return .elf; | ||
| 988 | }, | ||
| 989 | } | ||
| 990 | } | ||
| 991 | |||
| 975 | pub fn isMinGW(self: Target) bool { | 992 | pub fn isMinGW(self: Target) bool { |
| 976 | return self.isWindows() and self.isGnu(); | 993 | return self.isWindows() and self.isGnu(); |
| 977 | } | 994 | } |
src-self-hosted/codegen.zig+1-1| ... | @@ -31,7 +31,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) | ... | @@ -31,7 +31,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) |
| 31 | llvm.SetTarget(module, comp.llvm_triple.toSliceConst()); | 31 | llvm.SetTarget(module, comp.llvm_triple.toSliceConst()); |
| 32 | llvm.SetDataLayout(module, comp.target_layout_str); | 32 | llvm.SetDataLayout(module, comp.target_layout_str); |
| 33 | 33 | ||
| 34 | if (util.getObjectFormat(comp.target) == .coff) { | 34 | if (comp.target.getObjectFormat() == .coff) { |
| 35 | llvm.AddModuleCodeViewFlag(module); | 35 | llvm.AddModuleCodeViewFlag(module); |
| 36 | } else { | 36 | } else { |
| 37 | llvm.AddModuleDebugInfoFlag(module); | 37 | llvm.AddModuleDebugInfoFlag(module); |
src-self-hosted/link.zig+2-2| ... | @@ -76,7 +76,7 @@ pub fn link(comp: *Compilation) !void { | ... | @@ -76,7 +76,7 @@ pub fn link(comp: *Compilation) !void { |
| 76 | std.debug.warn("\n", .{}); | 76 | std.debug.warn("\n", .{}); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | const extern_ofmt = toExternObjectFormatType(util.getObjectFormat(comp.target)); | 79 | const extern_ofmt = toExternObjectFormatType(comp.target.getObjectFormat()); |
| 80 | const args_slice = ctx.args.toSlice(); | 80 | const args_slice = ctx.args.toSlice(); |
| 81 | 81 | ||
| 82 | { | 82 | { |
| ... | @@ -128,7 +128,7 @@ fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType { | ... | @@ -128,7 +128,7 @@ fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType { |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | fn constructLinkerArgs(ctx: *Context) !void { | 130 | fn constructLinkerArgs(ctx: *Context) !void { |
| 131 | switch (util.getObjectFormat(ctx.comp.target)) { | 131 | switch (ctx.comp.target.getObjectFormat()) { |
| 132 | .unknown => unreachable, | 132 | .unknown => unreachable, |
| 133 | .coff => return constructLinkerArgsCoff(ctx), | 133 | .coff => return constructLinkerArgsCoff(ctx), |
| 134 | .elf => return constructLinkerArgsElf(ctx), | 134 | .elf => return constructLinkerArgsElf(ctx), |
src-self-hosted/util.zig-17| ... | @@ -32,23 +32,6 @@ pub fn getFloatAbi(self: Target) FloatAbi { | ... | @@ -32,23 +32,6 @@ pub fn getFloatAbi(self: Target) FloatAbi { |
| 32 | }; | 32 | }; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | pub fn getObjectFormat(target: Target) Target.ObjectFormat { | ||
| 36 | switch (target) { | ||
| 37 | .Native => return @import("builtin").object_format, | ||
| 38 | .Cross => blk: { | ||
| 39 | if (target.isWindows() or target.isUefi()) { | ||
| 40 | return .coff; | ||
| 41 | } else if (target.isDarwin()) { | ||
| 42 | return .macho; | ||
| 43 | } | ||
| 44 | if (target.isWasm()) { | ||
| 45 | return .wasm; | ||
| 46 | } | ||
| 47 | return .elf; | ||
| 48 | }, | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { | 35 | pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { |
| 53 | const env = self.getAbi(); | 36 | const env = self.getAbi(); |
| 54 | const arch = self.getArch(); | 37 | const arch = self.getArch(); |