| 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 | 21 | pub const WriteFileStep = @import("build/write_file.zig").WriteFileStep; |
| 22 | 22 | pub const RunStep = @import("build/run.zig").RunStep; |
| 23 | 23 | pub const CheckFileStep = @import("build/check_file.zig").CheckFileStep; |
| 24 | pub const InstallRawStep = @import("build/emit_raw.zig").InstallRawStep; | |
| 24 | 25 | |
| 25 | 26 | pub const Builder = struct { |
| 26 | 27 | install_tls: TopLevelStep, |
| ... | ... | @@ -824,6 +825,10 @@ pub const Builder = struct { |
| 824 | 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 | 832 | ///`dest_rel_path` is relative to install prefix path |
| 828 | 833 | pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { |
| 829 | 834 | return self.addInstallFileWithDir(src_path, .Prefix, dest_rel_path); |
| ... | ... | @@ -839,6 +844,10 @@ pub const Builder = struct { |
| 839 | 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 | 851 | pub fn addInstallFileWithDir( |
| 843 | 852 | self: *Builder, |
| 844 | 853 | src_path: []const u8, |
| ... | ... | @@ -1407,6 +1416,10 @@ pub const LibExeObjStep = struct { |
| 1407 | 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 | 1423 | /// Creates a `RunStep` with an executable built with `addExecutable`. |
| 1411 | 1424 | /// Add command line arguments with `addArg`. |
| 1412 | 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 | 946 | fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section { |
| 947 | 947 | const elf_header = (try elf_file.findSection(name)) orelse return null; |
| 948 | 948 | return DwarfInfo.Section{ |
| 949 | .offset = elf_header.offset, | |
| 950 | .size = elf_header.size, | |
| 949 | .offset = elf_header.sh_offset, | |
| 950 | .size = elf_header.sh_size, | |
| 951 | 951 | }; |
| 952 | 952 | } |
| 953 | 953 | |
| ... | ... | @@ -987,12 +987,12 @@ pub fn openElfDebugInfo( |
| 987 | 987 | |
| 988 | 988 | var di = DwarfInfo{ |
| 989 | 989 | .endian = efile.endian, |
| 990 | .debug_info = (data[@intCast(usize, debug_info.offset)..@intCast(usize, debug_info.offset + debug_info.size)]), | |
| 991 | .debug_abbrev = (data[@intCast(usize, debug_abbrev.offset)..@intCast(usize, debug_abbrev.offset + debug_abbrev.size)]), | |
| 992 | .debug_str = (data[@intCast(usize, debug_str.offset)..@intCast(usize, debug_str.offset + debug_str.size)]), | |
| 993 | .debug_line = (data[@intCast(usize, debug_line.offset)..@intCast(usize, debug_line.offset + debug_line.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.sh_offset)..@intCast(usize, debug_abbrev.sh_offset + debug_abbrev.sh_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.sh_offset)..@intCast(usize, debug_line.sh_offset + debug_line.sh_size)]), | |
| 994 | 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 | 996 | else |
| 997 | 997 | null, |
| 998 | 998 | }; |
lib/std/elf.zig+96-59| ... | ... | @@ -330,19 +330,8 @@ pub const ET = extern enum(u16) { |
| 330 | 330 | pub const HIPROC = 0xffff; |
| 331 | 331 | }; |
| 332 | 332 | |
| 333 | /// TODO delete this in favor of Elf64_Shdr | |
| 334 | pub const SectionHeader = struct { | |
| 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 | }; | |
| 333 | pub const SectionHeader = Elf64_Shdr; | |
| 334 | pub const ProgramHeader = Elf64_Phdr; | |
| 346 | 335 | |
| 347 | 336 | pub const Elf = struct { |
| 348 | 337 | seekable_stream: *io.SeekableStream(anyerror, anyerror), |
| ... | ... | @@ -357,6 +346,7 @@ pub const Elf = struct { |
| 357 | 346 | string_section_index: usize, |
| 358 | 347 | string_section: *SectionHeader, |
| 359 | 348 | section_headers: []SectionHeader, |
| 349 | program_headers: []ProgramHeader, | |
| 360 | 350 | allocator: *mem.Allocator, |
| 361 | 351 | |
| 362 | 352 | /// Call close when done. |
| ... | ... | @@ -421,14 +411,24 @@ pub const Elf = struct { |
| 421 | 411 | try seekable_stream.seekBy(4); |
| 422 | 412 | |
| 423 | 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 | 415 | return error.InvalidFormat; |
| 426 | 416 | } |
| 427 | 417 | |
| 428 | 418 | const ph_entry_size = try in.readInt(u16, elf.endian); |
| 429 | 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 | 425 | const sh_entry_size = try in.readInt(u16, elf.endian); |
| 431 | 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 | 432 | elf.string_section_index = @as(usize, try in.readInt(u16, elf.endian)); |
| 433 | 433 | |
| 434 | 434 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; |
| ... | ... | @@ -443,47 +443,72 @@ pub const Elf = struct { |
| 443 | 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 | 475 | try seekable_stream.seekTo(elf.section_header_offset); |
| 447 | 476 | |
| 448 | 477 | elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); |
| 449 | 478 | errdefer elf.allocator.free(elf.section_headers); |
| 450 | 479 | |
| 451 | 480 | if (elf.is_64) { |
| 452 | if (sh_entry_size != 64) return error.InvalidFormat; | |
| 453 | ||
| 454 | 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 | 483 | elf_section.sh_type = try in.readInt(u32, elf.endian); |
| 457 | elf_section.flags = try in.readInt(u64, elf.endian); | |
| 458 | elf_section.addr = try in.readInt(u64, elf.endian); | |
| 459 | elf_section.offset = try in.readInt(u64, elf.endian); | |
| 460 | elf_section.size = try in.readInt(u64, elf.endian); | |
| 461 | elf_section.link = try in.readInt(u32, elf.endian); | |
| 462 | elf_section.info = try in.readInt(u32, elf.endian); | |
| 463 | elf_section.addr_align = try in.readInt(u64, elf.endian); | |
| 464 | elf_section.ent_size = try in.readInt(u64, elf.endian); | |
| 484 | elf_section.sh_flags = try in.readInt(u64, elf.endian); | |
| 485 | elf_section.sh_addr = try in.readInt(u64, elf.endian); | |
| 486 | elf_section.sh_offset = try in.readInt(u64, elf.endian); | |
| 487 | elf_section.sh_size = try in.readInt(u64, elf.endian); | |
| 488 | elf_section.sh_link = try in.readInt(u32, elf.endian); | |
| 489 | elf_section.sh_info = try in.readInt(u32, elf.endian); | |
| 490 | elf_section.sh_addralign = try in.readInt(u64, elf.endian); | |
| 491 | elf_section.sh_entsize = try in.readInt(u64, elf.endian); | |
| 465 | 492 | } |
| 466 | 493 | } else { |
| 467 | if (sh_entry_size != 40) return error.InvalidFormat; | |
| 468 | ||
| 469 | 494 | for (elf.section_headers) |*elf_section| { |
| 470 | 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 | 497 | elf_section.sh_type = try in.readInt(u32, elf.endian); |
| 473 | elf_section.flags = @as(u64, try in.readInt(u32, elf.endian)); | |
| 474 | elf_section.addr = @as(u64, try in.readInt(u32, elf.endian)); | |
| 475 | elf_section.offset = @as(u64, try in.readInt(u32, elf.endian)); | |
| 476 | elf_section.size = @as(u64, try in.readInt(u32, elf.endian)); | |
| 477 | elf_section.link = try in.readInt(u32, elf.endian); | |
| 478 | elf_section.info = try in.readInt(u32, elf.endian); | |
| 479 | elf_section.addr_align = @as(u64, try in.readInt(u32, elf.endian)); | |
| 480 | elf_section.ent_size = @as(u64, try in.readInt(u32, elf.endian)); | |
| 498 | elf_section.sh_flags = @as(u64, try in.readInt(u32, elf.endian)); | |
| 499 | elf_section.sh_addr = @as(u64, try in.readInt(u32, elf.endian)); | |
| 500 | elf_section.sh_offset = @as(u64, try in.readInt(u32, elf.endian)); | |
| 501 | elf_section.sh_size = @as(u64, try in.readInt(u32, elf.endian)); | |
| 502 | elf_section.sh_link = try in.readInt(u32, elf.endian); | |
| 503 | elf_section.sh_info = try in.readInt(u32, elf.endian); | |
| 504 | elf_section.sh_addralign = @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 | 509 | for (elf.section_headers) |*elf_section| { |
| 485 | 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 | 512 | if (stream_end < file_end_offset) return error.InvalidFormat; |
| 488 | 513 | } |
| 489 | 514 | } |
| ... | ... | @@ -499,13 +524,14 @@ pub const Elf = struct { |
| 499 | 524 | |
| 500 | 525 | pub fn close(elf: *Elf) void { |
| 501 | 526 | elf.allocator.free(elf.section_headers); |
| 527 | elf.allocator.free(elf.program_headers); | |
| 502 | 528 | } |
| 503 | 529 | |
| 504 | 530 | pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader { |
| 505 | 531 | section_loop: for (elf.section_headers) |*elf_section| { |
| 506 | 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 | 535 | try elf.seekable_stream.seekTo(name_offset); |
| 510 | 536 | |
| 511 | 537 | for (name) |expected_c| { |
| ... | ... | @@ -523,7 +549,7 @@ pub const Elf = struct { |
| 523 | 549 | } |
| 524 | 550 | |
| 525 | 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 | 604 | e_shnum: Elf64_Half, |
| 579 | 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 | 627 | pub const Elf32_Shdr = extern struct { |
| 582 | 628 | sh_name: Elf32_Word, |
| 583 | 629 | sh_type: Elf32_Word, |
| ... | ... | @@ -655,26 +701,6 @@ pub const Elf64_Rela = extern struct { |
| 655 | 701 | r_info: Elf64_Xword, |
| 656 | 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 | 704 | pub const Elf32_Dyn = extern struct { |
| 679 | 705 | d_tag: Elf32_Sword, |
| 680 | 706 | d_un: extern union { |
| ... | ... | @@ -833,6 +859,17 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct { |
| 833 | 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 | 873 | pub const Auxv = switch (@sizeOf(usize)) { |
| 837 | 874 | 4 => Elf32_auxv_t, |
| 838 | 875 | 8 => Elf64_auxv_t, |
lib/std/target.zig+17| ... | ... | @@ -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 | 992 | pub fn isMinGW(self: Target) bool { |
| 976 | 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 | 31 | llvm.SetTarget(module, comp.llvm_triple.toSliceConst()); |
| 32 | 32 | llvm.SetDataLayout(module, comp.target_layout_str); |
| 33 | 33 | |
| 34 | if (util.getObjectFormat(comp.target) == .coff) { | |
| 34 | if (comp.target.getObjectFormat() == .coff) { | |
| 35 | 35 | llvm.AddModuleCodeViewFlag(module); |
| 36 | 36 | } else { |
| 37 | 37 | llvm.AddModuleDebugInfoFlag(module); |
src-self-hosted/link.zig+2-2| ... | ... | @@ -76,7 +76,7 @@ pub fn link(comp: *Compilation) !void { |
| 76 | 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 | 80 | const args_slice = ctx.args.toSlice(); |
| 81 | 81 | |
| 82 | 82 | { |
| ... | ... | @@ -128,7 +128,7 @@ fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType { |
| 128 | 128 | } |
| 129 | 129 | |
| 130 | 130 | fn constructLinkerArgs(ctx: *Context) !void { |
| 131 | switch (util.getObjectFormat(ctx.comp.target)) { | |
| 131 | switch (ctx.comp.target.getObjectFormat()) { | |
| 132 | 132 | .unknown => unreachable, |
| 133 | 133 | .coff => return constructLinkerArgsCoff(ctx), |
| 134 | 134 | .elf => return constructLinkerArgsElf(ctx), |
src-self-hosted/util.zig-17| ... | ... | @@ -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 | 35 | pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { |
| 53 | 36 | const env = self.getAbi(); |
| 54 | 37 | const arch = self.getArch(); |