Commit e1d54b6d1a

Patrick Wickenhaeuser <35903594+patrickwick@users.noreply.github.com>
2024-10-04 12:38:35
19009: zig objcopy: integrate --add-section, --set-section-alignment and --set-section-flags into std.Build.Step.ObjCopy
1 parent 8f55efc
Changed files (2)
lib
compiler
std
Build
lib/compiler/objcopy.zig
@@ -40,9 +40,9 @@ fn cmdObjCopy(
     var only_keep_debug: bool = false;
     var compress_debug_sections: bool = false;
     var listen = false;
-    var add_section: ?AddSectionOptions = null;
-    var set_section_alignment: ?SetSectionAlignmentOptions = null;
-    var set_section_flags: ?SetSectionFlagsOptions = null;
+    var add_section: ?AddSection = null;
+    var set_section_alignment: ?SetSectionAlignment = null;
+    var set_section_flags: ?SetSectionFlags = null;
     while (i < args.len) : (i += 1) {
         const arg = args[i];
         if (!mem.startsWith(u8, arg, "-")) {
@@ -279,23 +279,22 @@ pub const EmitRawElfOptions = struct {
     ofmt: std.Target.ObjectFormat,
     only_section: ?[]const u8 = null,
     pad_to: ?u64 = null,
-    add_section: ?AddSectionOptions,
-    set_section_alignment: ?SetSectionAlignmentOptions,
-    set_section_flags: ?SetSectionFlagsOptions,
+    add_section: ?AddSection,
+    set_section_alignment: ?SetSectionAlignment,
+    set_section_flags: ?SetSectionFlags,
 };
 
-const AddSectionOptions = struct {
+const AddSection = struct {
     section_name: []const u8,
-    // file to store in new section
     file_path: []const u8,
 };
 
-const SetSectionAlignmentOptions = struct {
+const SetSectionAlignment = struct {
     section_name: []const u8,
     alignment: u32,
 };
 
-const SetSectionFlagsOptions = struct {
+const SetSectionFlags = struct {
     section_name: []const u8,
     flags: SectionFlags,
 };
@@ -740,9 +739,9 @@ const StripElfOptions = struct {
     strip_debug: bool = false,
     only_keep_debug: bool = false,
     compress_debug: bool = false,
-    add_section: ?AddSectionOptions,
-    set_section_alignment: ?SetSectionAlignmentOptions,
-    set_section_flags: ?SetSectionFlagsOptions,
+    add_section: ?AddSection,
+    set_section_alignment: ?SetSectionAlignment,
+    set_section_flags: ?SetSectionFlags,
 };
 
 fn stripElf(
@@ -976,9 +975,9 @@ fn ElfFile(comptime is_64: bool) type {
             section_filter: Filter = .all,
             debuglink: ?DebugLink = null,
             compress_debug: bool = false,
-            add_section: ?AddSectionOptions = null,
-            set_section_alignment: ?SetSectionAlignmentOptions = null,
-            set_section_flags: ?SetSectionFlagsOptions = null,
+            add_section: ?AddSection = null,
+            set_section_alignment: ?SetSectionAlignment = null,
+            set_section_flags: ?SetSectionFlags = null,
         };
         fn emit(self: *const Self, gpa: Allocator, out_file: File, in_file: File, options: EmitElfOptions) !void {
             var arena = std.heap.ArenaAllocator.init(gpa);
lib/std/Build/Step/ObjCopy.zig
@@ -26,6 +26,50 @@ pub const Strip = enum {
     debug_and_symbols,
 };
 
+pub const SectionFlags = packed struct {
+    /// add SHF_ALLOC
+    alloc: bool = false,
+
+    /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing
+    contents: bool = false,
+
+    /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents)
+    load: bool = false,
+
+    /// readonly: clear default SHF_WRITE flag
+    readonly: bool = false,
+
+    /// add SHF_EXECINSTR
+    code: bool = false,
+
+    /// add SHF_EXCLUDE
+    exclude: bool = false,
+
+    /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64
+    large: bool = false,
+
+    /// add SHF_MERGE
+    merge: bool = false,
+
+    /// add SHF_STRINGS
+    strings: bool = false,
+};
+
+pub const AddSection = struct {
+    section_name: []const u8,
+    file_path: std.Build.LazyPath,
+};
+
+pub const SetSectionAlignment = struct {
+    section_name: []const u8,
+    alignment: u32,
+};
+
+pub const SetSectionFlags = struct {
+    section_name: []const u8,
+    flags: SectionFlags,
+};
+
 step: Step,
 input_file: std.Build.LazyPath,
 basename: []const u8,
@@ -38,6 +82,10 @@ pad_to: ?u64,
 strip: Strip,
 compress_debug: bool,
 
+add_section: ?AddSection,
+set_section_alignment: ?SetSectionAlignment,
+set_section_flags: ?SetSectionFlags,
+
 pub const Options = struct {
     basename: ?[]const u8 = null,
     format: ?RawFormat = null,
@@ -51,6 +99,10 @@ pub const Options = struct {
     /// note: the `basename` is baked into the elf file to specify the link to the separate debug file.
     /// see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
     extract_to_separate_file: bool = false,
+
+    add_section: ?AddSection = null,
+    set_section_alignment: ?SetSectionAlignment = null,
+    set_section_flags: ?SetSectionFlags = null,
 };
 
 pub fn create(
@@ -75,6 +127,9 @@ pub fn create(
         .pad_to = options.pad_to,
         .strip = options.strip,
         .compress_debug = options.compress_debug,
+        .add_section = options.add_section,
+        .set_section_alignment = options.set_section_alignment,
+        .set_section_flags = options.set_section_flags,
     };
     input_file.addStepDependencies(&objcopy.step);
     return objcopy;
@@ -155,6 +210,31 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
     if (objcopy.output_file_debug != null) {
         try argv.appendSlice(&.{b.fmt("--extract-to={s}", .{full_dest_path_debug})});
     }
+    if (objcopy.add_section) |section| {
+        try argv.append("--add-section");
+        try argv.appendSlice(&.{b.fmt("{s}={s}", .{ section.section_name, section.file_path.getPath(b) })});
+    }
+    if (objcopy.set_section_alignment) |set_align| {
+        try argv.append("--set-section-alignment");
+        try argv.appendSlice(&.{b.fmt("{s}={d}", .{ set_align.section_name, set_align.alignment })});
+    }
+    if (objcopy.set_section_flags) |set_flags| {
+        const f = set_flags.flags;
+        // trailing comma is allowed
+        try argv.append("--set-section-flags");
+        try argv.appendSlice(&.{b.fmt("{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{
+            set_flags.section_name,
+            if (f.alloc) "alloc," else "",
+            if (f.contents) "contents," else "",
+            if (f.load) "load," else "",
+            if (f.readonly) "readonly," else "",
+            if (f.code) "code," else "",
+            if (f.exclude) "exclude," else "",
+            if (f.large) "large," else "",
+            if (f.merge) "merge," else "",
+            if (f.strings) "strings," else "",
+        })});
+    }
 
     try argv.appendSlice(&.{ full_src_path, full_dest_path });