authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-07 15:32:02-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:35-07:00
log8a8bf5ad023451a22fd7abf438e6c7ee105ac6bf
tree9053ae0292046c50120f690c28774c8a715d7a5f
parentaffe5ed867009c889f2df7b624387c2bceefcc0e

maker: update ObjCopy to new system


6 files changed, 215 insertions(+), 114 deletions(-)

BRANCH_TODO+1
...@@ -20,6 +20,7 @@...@@ -20,6 +20,7 @@
20 - and adjust dependencyInner to not openDir()20 - and adjust dependencyInner to not openDir()
2121
22## Followup Issues22## Followup Issues
23* stop leaking into global process arena
23* reduce the size of Maker.Step.Extended (make Run smaller) probably by using an arena per make24* reduce the size of Maker.Step.Extended (make Run smaller) probably by using an arena per make
24* link_eh_frame_hdr should be DefaultingBool25* link_eh_frame_hdr should be DefaultingBool
25* make --foo, --no-foo CLI args uniform (make them -f args instead)26* make --foo, --no-foo CLI args uniform (make them -f args instead)
lib/compiler/Maker.zig+2-3
...@@ -612,7 +612,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -612,7 +612,7 @@ pub fn main(init: process.Init.Minimal) !void {
612 step.state = .precheck_done;612 step.state = .precheck_done;
613 const deps = step_index.ptr(c).deps.slice(c);613 const deps = step_index.ptr(c).deps.slice(c);
614 step.pending_deps = @intCast(deps.len);614 step.pending_deps = @intCast(deps.len);
615 step.reset(gpa);615 step.reset(&maker);
616 }616 }
617 continue :rebuild;617 continue :rebuild;
618 },618 },
...@@ -1506,10 +1506,9 @@ fn constructGraphAndCheckForDependencyLoop(...@@ -1506,10 +1506,9 @@ fn constructGraphAndCheckForDependencyLoop(
1506/// invalidated.1506/// invalidated.
1507pub fn invalidateResult(maker: *Maker, step: *Step) bool {1507pub fn invalidateResult(maker: *Maker, step: *Step) bool {
1508 if (step.state == .precheck_done) return false;1508 if (step.state == .precheck_done) return false;
1509 const gpa = maker.gpa;
1510 assert(step.pending_deps == 0);1509 assert(step.pending_deps == 0);
1511 step.state = .precheck_done;1510 step.state = .precheck_done;
1512 step.reset(gpa);1511 step.reset(maker);
1513 for (step.dependants.items) |dependant_index| {1512 for (step.dependants.items) |dependant_index| {
1514 const dependant = maker.stepByIndex(dependant_index);1513 const dependant = maker.stepByIndex(dependant_index);
1515 _ = invalidateResult(maker, dependant);1514 _ = invalidateResult(maker, dependant);
lib/compiler/Maker/Step.zig+6-4
...@@ -23,6 +23,7 @@ pub const Run = @import("Step/Run.zig");...@@ -23,6 +23,7 @@ pub const Run = @import("Step/Run.zig");
23pub const InstallArtifact = @import("Step/InstallArtifact.zig");23pub const InstallArtifact = @import("Step/InstallArtifact.zig");
24pub const InstallFile = @import("Step/InstallFile.zig");24pub const InstallFile = @import("Step/InstallFile.zig");
25pub const UpdateSourceFiles = @import("Step/UpdateSourceFiles.zig");25pub const UpdateSourceFiles = @import("Step/UpdateSourceFiles.zig");
26pub const ObjCopy = @import("Step/ObjCopy.zig");
2627
27/// Avoid false sharing.28/// Avoid false sharing.
28_: void align(std.atomic.cache_line) = {},29_: void align(std.atomic.cache_line) = {},
...@@ -76,7 +77,7 @@ pub const Extended = union(enum) {...@@ -76,7 +77,7 @@ pub const Extended = union(enum) {
76 install_artifact: InstallArtifact,77 install_artifact: InstallArtifact,
77 install_dir: Todo,78 install_dir: Todo,
78 install_file: InstallFile,79 install_file: InstallFile,
79 obj_copy: Todo,80 obj_copy: ObjCopy,
80 options: Todo,81 options: Todo,
81 remove_dir: Todo,82 remove_dir: Todo,
82 run: Run,83 run: Run,
...@@ -306,8 +307,9 @@ pub fn make(...@@ -306,8 +307,9 @@ pub fn make(
306}307}
307308
308/// Prepares the step for being re-evaluated.309/// Prepares the step for being re-evaluated.
309pub fn reset(step: *Step, gpa: Allocator) void {310pub fn reset(step: *Step, maker: *Maker) void {
310 assert(step.state == .precheck_done);311 assert(step.state == .precheck_done);
312 const gpa = maker.gpa;
311313
312 if (step.result_failed_command) |cmd| gpa.free(cmd);314 if (step.result_failed_command) |cmd| gpa.free(cmd);
313315
...@@ -318,7 +320,7 @@ pub fn reset(step: *Step, gpa: Allocator) void {...@@ -318,7 +320,7 @@ pub fn reset(step: *Step, gpa: Allocator) void {
318 step.result_peak_rss = 0;320 step.result_peak_rss = 0;
319 step.result_failed_command = null;321 step.result_failed_command = null;
320 step.test_results = .{};322 step.test_results = .{};
321 step.clearWatchInputs();323 step.clearWatchInputs(maker);
322324
323 step.result_error_bundle.deinit(gpa);325 step.result_error_bundle.deinit(gpa);
324 step.result_error_bundle = std.zig.ErrorBundle.empty;326 step.result_error_bundle = std.zig.ErrorBundle.empty;
...@@ -732,7 +734,7 @@ fn failWithCacheError(...@@ -732,7 +734,7 @@ fn failWithCacheError(
732pub fn writeManifest(s: *Step, maker: *Maker, man: *Cache.Manifest) !void {734pub fn writeManifest(s: *Step, maker: *Maker, man: *Cache.Manifest) !void {
733 if (s.test_results.isSuccess()) {735 if (s.test_results.isSuccess()) {
734 man.writeManifest() catch |err| {736 man.writeManifest() catch |err| {
735 try s.addError(maker, "unable to write cache manifest: {t}", .{err});737 try s.addError(maker, "failed writing cache manifest: {t}", .{err});
736 };738 };
737 }739 }
738}740}
lib/compiler/Maker/Step/ObjCopy.zig+101-68
...@@ -2,6 +2,7 @@ const ObjCopy = @This();...@@ -2,6 +2,7 @@ const ObjCopy = @This();
22
3const std = @import("std");3const std = @import("std");
4const Io = std.Io;4const Io = std.Io;
5const Path = std.Build.Cache.Path;
5const allocPrint = std.fmt.allocPrint;6const allocPrint = std.fmt.allocPrint;
6const Configuration = std.Build.Configuration;7const Configuration = std.Build.Configuration;
78
...@@ -23,120 +24,152 @@ pub fn make(...@@ -23,120 +24,152 @@ pub fn make(
23 const conf_step = step_index.ptr(conf);24 const conf_step = step_index.ptr(conf);
24 const conf_oc = conf_step.extended.get(conf.extra).obj_copy;25 const conf_oc = conf_step.extended.get(conf.extra).obj_copy;
25 const cache_root = graph.local_cache_root;26 const cache_root = graph.local_cache_root;
27 const input_lazy_path = conf_oc.input_file.get(conf);
28 const only_section: ?[]const u8 = if (conf_oc.only_section.value) |s| s.slice(conf) else null;
29 const opt_basename: ?[]const u8 = if (conf_oc.basename.value) |s| s.slice(conf) else null;
30 const opt_debug_basename: ?[]const u8 = if (conf_oc.debug_basename.value) |s| s.slice(conf) else null;
2631
27 try step.singleUnchangingWatchInput(maker, arena, conf_oc.input_file);32 try step.singleUnchangingWatchInput(maker, arena, input_lazy_path);
2833
29 var man = graph.cache.obtain();34 var man = graph.cache.obtain();
30 defer man.deinit();35 defer man.deinit();
3136
32 const src_path = try maker.resolveLazyPathIndex(arena, conf_oc.input_file, step_index);37 const input_path = try maker.resolveLazyPath(arena, input_lazy_path, step_index);
33 _ = try man.addFilePath(src_path, null);38 _ = try man.addFilePath(input_path, null);
34 man.hash.addOptionalBytes(conf_oc.only_section);39 man.hash.addOptionalBytes(only_section);
35 man.hash.addOptional(conf_oc.pad_to);40 man.hash.addOptionalBytes(opt_basename);
36 man.hash.addOptional(conf_oc.format);41 man.hash.addOptionalBytes(opt_debug_basename);
37 man.hash.add(conf_oc.compress_debug);42 man.hash.addOptional(conf_oc.pad_to.value);
38 man.hash.add(conf_oc.strip);43 man.hash.add(conf_oc.flags.format);
39 man.hash.add(conf_oc.output_file_debug != null);44 man.hash.add(conf_oc.flags.compress_debug);
45 man.hash.add(conf_oc.flags.strip);
46 man.hash.add(conf_oc.debug_file.value != null);
4047
41 if (try step.cacheHit(&man)) {48 const basename = opt_basename orelse Io.Dir.path.basename(input_path.sub_path);
49
50 if (try step.cacheHit(maker, &man)) {
42 // Cache hit, skip subprocess execution.51 // Cache hit, skip subprocess execution.
43 const digest = man.final();52 const digest = man.final();
44 conf_oc.output_file.path = try cache_root.join(arena, &.{53 maker.generatedPath(conf_oc.output_file).* = .{
45 "o", &digest, conf_oc.basename,54 .root_dir = cache_root,
46 });55 .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, basename }),
47 if (conf_oc.output_file_debug) |*file| {56 };
48 file.path = try cache_root.join(arena, &.{57 if (conf_oc.debug_file.value) |debug_file| {
49 "o", &digest, try allocPrint(arena, "{s}.debug", .{conf_oc.basename}),58 const debug_basename = opt_debug_basename orelse try allocPrint(arena, "{s}.debug", .{
59 Io.Dir.path.basename(input_path.sub_path),
50 });60 });
61 maker.generatedPath(debug_file).* = .{
62 .root_dir = cache_root,
63 .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, debug_basename }),
64 };
51 }65 }
52 return;66 return;
53 }67 }
5468
69 // We don't find out more input files while executing objcopy so we can
70 // already obtain the digest and use it directly as the output path.
55 const digest = man.final();71 const digest = man.final();
56 const cache_path = "o" ++ Io.Dir.path.sep_str ++ digest;72 const dest_path: Path = .{
57 const full_dest_path = try cache_root.join(arena, &.{ cache_path, conf_oc.basename });73 .root_dir = cache_root,
58 const full_dest_path_debug = try cache_root.join(arena, &.{74 .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, basename }),
59 cache_path, try allocPrint(arena, "{s}.debug", .{conf_oc.basename}),75 };
60 });76 const dest_dirname = dest_path.dirname().?;
61 cache_root.handle.createDirPath(io, cache_path) catch |err|77 dest_dirname.root_dir.handle.createDirPath(io, dest_dirname.sub_path) catch |err|
62 return step.fail("unable to make path {s}: {t}", .{ cache_path, err });78 return step.fail(maker, "failed to create path {f}: {t}", .{ dest_dirname, err });
6379
64 var argv: std.ArrayList([]const u8) = .empty;80 var argv: std.ArrayList([]const u8) = .empty;
65 try argv.ensureUnusedCapacity(arena, 11);81 try argv.ensureUnusedCapacity(arena, 11);
6682
67 argv.addManyAsArrayAssumeCapacity(2).* = .{ graph.zig_exe, "objcopy" };83 argv.addManyAsArrayAssumeCapacity(2).* = .{ graph.zig_exe, "objcopy" };
6884
69 if (conf_oc.only_section) |only_section|85 if (only_section) |s| argv.addManyAsArrayAssumeCapacity(2).* = .{ "-j", s };
70 argv.addManyAsArrayAssumeCapacity(2).* = .{ "-j", only_section };
7186
72 switch (conf_oc.strip) {87 switch (conf_oc.flags.strip) {
73 .none => {},88 .none => {},
74 .debug => argv.appendAssumeCapacity("--strip-debug"),89 .debug => argv.appendAssumeCapacity("--strip-debug"),
75 .debug_and_symbols => argv.appendAssumeCapacity("--strip-all"),90 .debug_and_symbols => argv.appendAssumeCapacity("--strip-all"),
76 }91 }
7792
78 if (conf_oc.pad_to) |pad_to| {93 if (conf_oc.pad_to.value) |pad_to| {
79 argv.addManyAsArrayAssumeCapacity(2).* = .{94 argv.addManyAsArrayAssumeCapacity(2).* = .{
80 "--pad-to", try allocPrint(arena, "{d}", .{pad_to}),95 "--pad-to", try allocPrint(arena, "{d}", .{pad_to}),
81 };96 };
82 }97 }
8398
84 if (conf_oc.format) |format| {99 switch (conf_oc.flags.format) {
85 argv.addManyAsArrayAssumeCapacity(2).* = .{100 .default => {},
86 "-O",101 else => |t| argv.addManyAsArrayAssumeCapacity(2).* = .{ "-O", @tagName(t) },
87 switch (format) {
88 .bin => "binary",
89 .hex => "hex",
90 .elf => "elf",
91 },
92 };
93 }102 }
94103
95 if (conf_oc.compress_debug)104 if (conf_oc.flags.compress_debug)
96 argv.appendAssumeCapacity("--compress-debug-sections");105 argv.appendAssumeCapacity("--compress-debug-sections");
97106
98 if (conf_oc.output_file_debug != null)107 if (conf_oc.debug_file.value) |debug_file| {
99 argv.appendAssumeCapacity(try allocPrint(arena, "--extract-to={s}", .{full_dest_path_debug}));108 const debug_basename = opt_debug_basename orelse try allocPrint(arena, "{s}.debug", .{
109 Io.Dir.path.basename(input_path.sub_path),
110 });
111 const debug_dest_path: Path = .{
112 .root_dir = cache_root,
113 .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, debug_basename }),
114 };
115 argv.appendAssumeCapacity(try allocPrint(arena, "--extract-to={f}", .{debug_dest_path}));
116 maker.generatedPath(debug_file).* = debug_dest_path;
117 }
100118
101 try argv.ensureUnusedCapacity(arena, 9);119 try argv.ensureUnusedCapacity(arena, conf_oc.add_section.slice.len * 2);
102120
103 if (conf_oc.add_section) |section| {121 for (conf_oc.add_section.slice) |section| {
104 argv.appendAssumeCapacity("--add-section");122 argv.appendAssumeCapacity("--add-section");
105 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={f}", .{123 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={f}", .{
106 section.section_name, try maker.resolveLazyPathIndex(arena, section.file_path, step_index),124 section.section_name.slice(conf),
125 try maker.resolveLazyPathIndex(arena, section.file_path, step_index),
107 }));126 }));
108 }127 }
109128
110 if (conf_oc.set_section_alignment) |set_align| {129 for (conf_oc.update_section.slice) |update| {
111 argv.appendAssumeCapacity("--set-section-alignment");130 const name = update.section_name.slice(conf);
112 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={d}", .{ set_align.section_name, set_align.alignment }));
113 }
114131
115 if (conf_oc.set_section_flags) |set_flags| {132 try argv.ensureUnusedCapacity(arena, 4);
116 const f = set_flags.flags;133
117 // trailing comma is allowed134 if (update.flags.alignment.toBytes()) |a| {
118 argv.appendAssumeCapacity("--set-section-flags");135 argv.appendAssumeCapacity("--set-section-alignment");
119 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{136 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={d}", .{ name, a }));
120 set_flags.section_name,137 }
121 if (f.alloc) "alloc," else "",138
122 if (f.contents) "contents," else "",139 const f = update.flags.section_flags;
123 if (f.load) "load," else "",140 const default_flags: Configuration.Step.ObjCopy.SectionFlags = .{};
124 if (f.readonly) "readonly," else "",141
125 if (f.code) "code," else "",142 if (f != default_flags) {
126 if (f.exclude) "exclude," else "",143 // trailing comma is allowed
127 if (f.large) "large," else "",144 argv.appendAssumeCapacity("--set-section-flags");
128 if (f.merge) "merge," else "",145 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{
129 if (f.strings) "strings," else "",146 name,
130 }));147 if (f.alloc) "alloc," else "",
148 if (f.contents) "contents," else "",
149 if (f.load) "load," else "",
150 if (f.readonly) "readonly," else "",
151 if (f.code) "code," else "",
152 if (f.exclude) "exclude," else "",
153 if (f.large) "large," else "",
154 if (f.merge) "merge," else "",
155 if (f.strings) "strings," else "",
156 }));
157 }
131 }158 }
132159
133 argv.appendAssumeCapacity(src_path);160 argv.appendAssumeCapacity(try allocPrint(arena, "{f}", .{input_path}));
134 argv.appendAssumeCapacity(full_dest_path);161 argv.appendAssumeCapacity(try allocPrint(arena, "{f}", .{dest_path}));
135162
136 argv.appendAssumeCapacity("--listen=-");163 argv.appendAssumeCapacity("--listen=-");
137 _ = try Step.evalZigProcess(step_index, maker, argv.items, progress_node, false);164 _ = Step.evalZigProcess(step_index, maker, argv.items, progress_node, false) catch |err| switch (err) {
165 error.NeedCompileErrorCheck => unreachable,
166 else => |e| return e,
167 };
168
169 maker.generatedPath(conf_oc.output_file).* = dest_path;
138170
139 conf_oc.output_file.path = full_dest_path;171 man.writeManifest() catch |err| switch (err) {
140 if (conf_oc.output_file_debug) |*file| file.path = full_dest_path_debug;172 error.Canceled => |e| return e,
141 try man.writeManifest();173 else => |e| try step.addError(maker, "failed writing cache manifest: {t}", .{e}),
174 };
142}175}
lib/std/Build/Configuration.zig+98-1
...@@ -1102,10 +1102,87 @@ pub const Step = extern struct {...@@ -1102,10 +1102,87 @@ pub const Step = extern struct {
11021102
1103 pub const ObjCopy = struct {1103 pub const ObjCopy = struct {
1104 flags: @This().Flags,1104 flags: @This().Flags,
1105 input_file: LazyPath.Index,
1106 output_file: GeneratedFileIndex,
1107 basename: Storage.FlagOptional(.flags, .basename, String),
1108 debug_file: Storage.FlagOptional(.flags, .debug_file, GeneratedFileIndex),
1109 debug_basename: Storage.FlagOptional(.flags, .debug_basename, String),
1110 only_section: Storage.FlagOptional(.flags, .only_section, String),
1111 pad_to: Storage.FlagOptional(.flags, .pad_to, u64),
1112 add_section: Storage.FlagLengthPrefixedList(.flags, .add_section, AddSection),
1113 update_section: Storage.FlagLengthPrefixedList(.flags, .update_section, UpdateSection),
1114
1115 pub const Format = enum(u2) {
1116 binary,
1117 hex,
1118 elf,
1119 default,
1120
1121 pub fn init(f: ?std.Build.Step.ObjCopy.Format) @This() {
1122 return switch (f orelse return .default) {
1123 .binary => .binary,
1124 .hex => .hex,
1125 .elf => .elf,
1126 };
1127 }
1128 };
1129
1130 pub const Strip = enum(u2) {
1131 none,
1132 debug,
1133 debug_and_symbols,
1134 };
1135
1136 pub const AddSection = extern struct {
1137 section_name: String,
1138 file_path: LazyPath.Index,
1139 };
1140
1141 pub const UpdateSection = extern struct {
1142 section_name: String,
1143 flags: @This().Flags,
1144
1145 pub const Flags = packed struct(u32) {
1146 section_flags: SectionFlags,
1147 alignment: Alignment,
1148 _: u17 = 0,
1149 };
1150 };
1151
1152 pub const SectionFlags = packed struct(u9) {
1153 /// add SHF_ALLOC
1154 alloc: bool = false,
1155 /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing
1156 contents: bool = false,
1157 /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents)
1158 load: bool = false,
1159 /// readonly: clear default SHF_WRITE flag
1160 readonly: bool = false,
1161 /// add SHF_EXECINSTR
1162 code: bool = false,
1163 /// add SHF_EXCLUDE
1164 exclude: bool = false,
1165 /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64
1166 large: bool = false,
1167 /// add SHF_MERGE
1168 merge: bool = false,
1169 /// add SHF_STRINGS
1170 strings: bool = false,
1171 };
11051172
1106 pub const Flags = packed struct(u32) {1173 pub const Flags = packed struct(u32) {
1107 tag: Tag = .obj_copy,1174 tag: Tag = .obj_copy,
1108 _: u27 = 0,1175 basename: bool,
1176 debug_file: bool,
1177 debug_basename: bool,
1178 format: Format,
1179 strip: Strip,
1180 compress_debug: bool,
1181 only_section: bool,
1182 pad_to: bool,
1183 add_section: bool,
1184 update_section: bool,
1185 _: u15 = 0,
1109 };1186 };
1110 };1187 };
11111188
...@@ -1658,6 +1735,26 @@ pub const Bytes = extern struct {...@@ -1658,6 +1735,26 @@ pub const Bytes = extern struct {
1658 }1735 }
1659};1736};
16601737
1738/// Stored as a power-of-two, with one special value to indicate none.
1739pub const Alignment = enum(u6) {
1740 @"1" = 0,
1741 @"2" = 1,
1742 @"4" = 2,
1743 @"8" = 3,
1744 @"16" = 4,
1745 @"32" = 5,
1746 @"64" = 6,
1747 none = std.math.maxInt(u6),
1748 _,
1749
1750 pub fn toBytes(a: @This()) ?u64 {
1751 return switch (a) {
1752 .none => null,
1753 else => @as(u64, 1) << @intFromEnum(a),
1754 };
1755 }
1756};
1757
1661pub const DefaultingBool = enum(u2) {1758pub const DefaultingBool = enum(u2) {
1662 false,1759 false,
1663 true,1760 true,
lib/std/Build/Step/ObjCopy.zig+7-38
...@@ -6,11 +6,11 @@ const Configuration = std.Build.Configuration;...@@ -6,11 +6,11 @@ const Configuration = std.Build.Configuration;
66
7step: Step,7step: Step,
8input_file: std.Build.LazyPath,8input_file: std.Build.LazyPath,
9basename: []const u8,9basename: ?[]const u8,
10output_file: Configuration.GeneratedFileIndex,10output_file: Configuration.GeneratedFileIndex,
11output_file_debug: Configuration.OptionalGeneratedFileIndex,11output_file_debug: Configuration.OptionalGeneratedFileIndex,
1212
13format: ?RawFormat,13format: ?Format,
14only_section: ?[]const u8,14only_section: ?[]const u8,
15pad_to: ?u64,15pad_to: ?u64,
16strip: Strip,16strip: Strip,
...@@ -22,38 +22,9 @@ set_section_flags: ?SetSectionFlags,...@@ -22,38 +22,9 @@ set_section_flags: ?SetSectionFlags,
2222
23pub const base_tag: Step.Tag = .obj_copy;23pub const base_tag: Step.Tag = .obj_copy;
2424
25pub const RawFormat = enum {25pub const Format = enum { binary, hex, elf };
26 bin,26pub const Strip = Configuration.Step.ObjCopy.Strip;
27 hex,27pub const SectionFlags = Configuration.Step.ObjCopy.SectionFlags;
28 elf,
29};
30
31pub const Strip = enum {
32 none,
33 debug,
34 debug_and_symbols,
35};
36
37pub const SectionFlags = packed struct {
38 /// add SHF_ALLOC
39 alloc: bool = false,
40 /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing
41 contents: bool = false,
42 /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents)
43 load: bool = false,
44 /// readonly: clear default SHF_WRITE flag
45 readonly: bool = false,
46 /// add SHF_EXECINSTR
47 code: bool = false,
48 /// add SHF_EXCLUDE
49 exclude: bool = false,
50 /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64
51 large: bool = false,
52 /// add SHF_MERGE
53 merge: bool = false,
54 /// add SHF_STRINGS
55 strings: bool = false,
56};
5728
58pub const AddSection = struct {29pub const AddSection = struct {
59 section_name: []const u8,30 section_name: []const u8,
...@@ -72,7 +43,7 @@ pub const SetSectionFlags = struct {...@@ -72,7 +43,7 @@ pub const SetSectionFlags = struct {
7243
73pub const Options = struct {44pub const Options = struct {
74 basename: ?[]const u8 = null,45 basename: ?[]const u8 = null,
75 format: ?RawFormat = null,46 format: ?Format = null,
76 only_section: ?[]const u8 = null,47 only_section: ?[]const u8 = null,
77 pad_to: ?u64 = null,48 pad_to: ?u64 = null,
7849
...@@ -95,7 +66,6 @@ pub fn create(...@@ -95,7 +66,6 @@ pub fn create(
95 options: Options,66 options: Options,
96) *ObjCopy {67) *ObjCopy {
97 const graph = owner.graph;68 const graph = owner.graph;
98 const arena = graph.arena;
99 const obj_copy = graph.create(ObjCopy);69 const obj_copy = graph.create(ObjCopy);
100 obj_copy.* = .{70 obj_copy.* = .{
101 .step = .init(.{71 .step = .init(.{
...@@ -104,8 +74,7 @@ pub fn create(...@@ -104,8 +74,7 @@ pub fn create(
104 .owner = owner,74 .owner = owner,
105 }),75 }),
106 .input_file = input_file,76 .input_file = input_file,
107 .basename = options.basename orelse77 .basename = options.basename,
108 std.fmt.allocPrint(arena, "{f}", .{input_file.fmt(graph)}) catch @panic("OOM"),
109 .output_file = graph.addGeneratedFile(&obj_copy.step),78 .output_file = graph.addGeneratedFile(&obj_copy.step),
110 .output_file_debug = if (options.strip != .none and options.extract_to_separate_file)79 .output_file_debug = if (options.strip != .none and options.extract_to_separate_file)
111 .init(graph.addGeneratedFile(&obj_copy.step))80 .init(graph.addGeneratedFile(&obj_copy.step))