authorgravatar for michael.larouche@gmail.comMichaël Larouche <michael.larouche@gmail.com> 2020-01-21 17:32:00-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-03 15:07:34-05:00
log9b11e5e1f1e0debd1e5484883b2daad8b2b33cb7
tree568397a81b76f343bfee781937926bd231e574ad
parent958f00f1c71f205ce738433d00e9da7dde060f14

Add InstallRawStep to Zig build system that does a similar job to llvm-objcopy. To use it, do 'exe.installRaw("kernel.bin");' where exe is a LibExeObjStep

Part of #2826

8 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;
21pub const WriteFileStep = @import("build/write_file.zig").WriteFileStep;21pub const WriteFileStep = @import("build/write_file.zig").WriteFileStep;
22pub const RunStep = @import("build/run.zig").RunStep;22pub const RunStep = @import("build/run.zig").RunStep;
23pub const CheckFileStep = @import("build/check_file.zig").CheckFileStep;23pub const CheckFileStep = @import("build/check_file.zig").CheckFileStep;
24pub const InstallRawStep = @import("build/emit_raw.zig").InstallRawStep;
2425
25pub const Builder = struct {26pub 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 }
826827
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 path832 ///`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 }
841846
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 }
14091418
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 @@
1const std = @import("std");
2
3const Allocator = std.mem.Allocator;
4const ArenaAllocator = std.heap.ArenaAllocator;
5const ArrayList = std.ArrayList;
6const Builder = std.build.Builder;
7const File = std.fs.File;
8const InstallDir = std.build.InstallDir;
9const LibExeObjStep = std.build.LibExeObjStep;
10const Step = std.build.Step;
11const elf = std.elf;
12const fs = std.fs;
13const io = std.io;
14const sort = std.sort;
15const warn = std.debug.warn;
16
17const BinOutStream = io.OutStream(anyerror);
18const BinSeekStream = io.SeekableStream(anyerror, anyerror);
19const ElfSeekStream = io.SeekableStream(anyerror, anyerror);
20const ElfInStream = io.InStream(anyerror);
21
22const BinaryElfSection = struct {
23 elfOffset: u64,
24 binaryOffset: u64,
25 fileSize: usize,
26 segment: ?*BinaryElfSegment,
27};
28
29const BinaryElfSegment = struct {
30 physicalAddress: u64,
31 virtualAddress: u64,
32 elfOffset: u64,
33 binaryOffset: u64,
34 fileSize: usize,
35 firstSection: ?*BinaryElfSection,
36};
37
38const 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
154const WriteContext = struct {
155 inStream: *ElfInStream,
156 inSeekStream: *ElfSeekStream,
157 outStream: *BinOutStream,
158 outSeekStream: *BinSeekStream,
159};
160
161fn 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
172fn 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
211pub 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 {
946fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section {946fn 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}
953953
...@@ -987,12 +987,12 @@ pub fn openElfDebugInfo(...@@ -987,12 +987,12 @@ pub fn openElfDebugInfo(
987987
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 else996 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};
332332
333/// TODO delete this in favor of Elf64_Shdr333pub const SectionHeader = Elf64_Shdr;
334pub const SectionHeader = struct {334pub 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};
346335
347pub const Elf = struct {336pub 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,
361351
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);
422412
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 }
427417
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));
433433
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 }
445445
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);
447476
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);
450479
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 }
483508
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 {
499524
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 }
503529
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;
507533
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);
510536
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 }
524550
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};
529555
...@@ -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};
607pub 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};
617pub 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};
581pub const Elf32_Shdr = extern struct {627pub 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};
658pub 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};
668pub 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};
678pub const Elf32_Dyn = extern struct {704pub 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};
835861
862comptime {
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
836pub const Auxv = switch (@sizeOf(usize)) {873pub 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 }
974974
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);
3333
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 }
7878
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();
8181
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}
129129
130fn constructLinkerArgs(ctx: *Context) !void {130fn 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}
3434
35pub 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
52pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {35pub 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();