| ... | @@ -26,6 +26,50 @@ pub const Strip = enum { | ... | @@ -26,6 +26,50 @@ pub const Strip = enum { |
| 26 | debug_and_symbols, | 26 | debug_and_symbols, |
| 27 | }; | 27 | }; |
| 28 | | 28 | |
| | 29 | pub const SectionFlags = packed struct { |
| | 30 | /// add SHF_ALLOC |
| | 31 | alloc: bool = false, |
| | 32 | |
| | 33 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing |
| | 34 | contents: bool = false, |
| | 35 | |
| | 36 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents) |
| | 37 | load: bool = false, |
| | 38 | |
| | 39 | /// readonly: clear default SHF_WRITE flag |
| | 40 | readonly: bool = false, |
| | 41 | |
| | 42 | /// add SHF_EXECINSTR |
| | 43 | code: bool = false, |
| | 44 | |
| | 45 | /// add SHF_EXCLUDE |
| | 46 | exclude: bool = false, |
| | 47 | |
| | 48 | /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64 |
| | 49 | large: bool = false, |
| | 50 | |
| | 51 | /// add SHF_MERGE |
| | 52 | merge: bool = false, |
| | 53 | |
| | 54 | /// add SHF_STRINGS |
| | 55 | strings: bool = false, |
| | 56 | }; |
| | 57 | |
| | 58 | pub const AddSection = struct { |
| | 59 | section_name: []const u8, |
| | 60 | file_path: std.Build.LazyPath, |
| | 61 | }; |
| | 62 | |
| | 63 | pub const SetSectionAlignment = struct { |
| | 64 | section_name: []const u8, |
| | 65 | alignment: u32, |
| | 66 | }; |
| | 67 | |
| | 68 | pub const SetSectionFlags = struct { |
| | 69 | section_name: []const u8, |
| | 70 | flags: SectionFlags, |
| | 71 | }; |
| | 72 | |
| 29 | step: Step, | 73 | step: Step, |
| 30 | input_file: std.Build.LazyPath, | 74 | input_file: std.Build.LazyPath, |
| 31 | basename: []const u8, | 75 | basename: []const u8, |
| ... | @@ -38,6 +82,10 @@ pad_to: ?u64, | ... | @@ -38,6 +82,10 @@ pad_to: ?u64, |
| 38 | strip: Strip, | 82 | strip: Strip, |
| 39 | compress_debug: bool, | 83 | compress_debug: bool, |
| 40 | | 84 | |
| | 85 | add_section: ?AddSection, |
| | 86 | set_section_alignment: ?SetSectionAlignment, |
| | 87 | set_section_flags: ?SetSectionFlags, |
| | 88 | |
| 41 | pub const Options = struct { | 89 | pub const Options = struct { |
| 42 | basename: ?[]const u8 = null, | 90 | basename: ?[]const u8 = null, |
| 43 | format: ?RawFormat = null, | 91 | format: ?RawFormat = null, |
| ... | @@ -51,6 +99,10 @@ pub const Options = struct { | ... | @@ -51,6 +99,10 @@ pub const Options = struct { |
| 51 | /// note: the `basename` is baked into the elf file to specify the link to the separate debug file. | 99 | /// note: the `basename` is baked into the elf file to specify the link to the separate debug file. |
| 52 | /// see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html | 100 | /// see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html |
| 53 | extract_to_separate_file: bool = false, | 101 | extract_to_separate_file: bool = false, |
| | 102 | |
| | 103 | add_section: ?AddSection = null, |
| | 104 | set_section_alignment: ?SetSectionAlignment = null, |
| | 105 | set_section_flags: ?SetSectionFlags = null, |
| 54 | }; | 106 | }; |
| 55 | | 107 | |
| 56 | pub fn create( | 108 | pub fn create( |
| ... | @@ -75,6 +127,9 @@ pub fn create( | ... | @@ -75,6 +127,9 @@ pub fn create( |
| 75 | .pad_to = options.pad_to, | 127 | .pad_to = options.pad_to, |
| 76 | .strip = options.strip, | 128 | .strip = options.strip, |
| 77 | .compress_debug = options.compress_debug, | 129 | .compress_debug = options.compress_debug, |
| | 130 | .add_section = options.add_section, |
| | 131 | .set_section_alignment = options.set_section_alignment, |
| | 132 | .set_section_flags = options.set_section_flags, |
| 78 | }; | 133 | }; |
| 79 | input_file.addStepDependencies(&objcopy.step); | 134 | input_file.addStepDependencies(&objcopy.step); |
| 80 | return objcopy; | 135 | return objcopy; |
| ... | @@ -155,6 +210,31 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -155,6 +210,31 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 155 | if (objcopy.output_file_debug != null) { | 210 | if (objcopy.output_file_debug != null) { |
| 156 | try argv.appendSlice(&.{b.fmt("--extract-to={s}", .{full_dest_path_debug})}); | 211 | try argv.appendSlice(&.{b.fmt("--extract-to={s}", .{full_dest_path_debug})}); |
| 157 | } | 212 | } |
| | 213 | if (objcopy.add_section) |section| { |
| | 214 | try argv.append("--add-section"); |
| | 215 | try argv.appendSlice(&.{b.fmt("{s}={s}", .{ section.section_name, section.file_path.getPath(b) })}); |
| | 216 | } |
| | 217 | if (objcopy.set_section_alignment) |set_align| { |
| | 218 | try argv.append("--set-section-alignment"); |
| | 219 | try argv.appendSlice(&.{b.fmt("{s}={d}", .{ set_align.section_name, set_align.alignment })}); |
| | 220 | } |
| | 221 | if (objcopy.set_section_flags) |set_flags| { |
| | 222 | const f = set_flags.flags; |
| | 223 | // trailing comma is allowed |
| | 224 | try argv.append("--set-section-flags"); |
| | 225 | try argv.appendSlice(&.{b.fmt("{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{ |
| | 226 | set_flags.section_name, |
| | 227 | if (f.alloc) "alloc," else "", |
| | 228 | if (f.contents) "contents," else "", |
| | 229 | if (f.load) "load," else "", |
| | 230 | if (f.readonly) "readonly," else "", |
| | 231 | if (f.code) "code," else "", |
| | 232 | if (f.exclude) "exclude," else "", |
| | 233 | if (f.large) "large," else "", |
| | 234 | if (f.merge) "merge," else "", |
| | 235 | if (f.strings) "strings," else "", |
| | 236 | })}); |
| | 237 | } |
| 158 | | 238 | |
| 159 | try argv.appendSlice(&.{ full_src_path, full_dest_path }); | 239 | try argv.appendSlice(&.{ full_src_path, full_dest_path }); |
| 160 | | 240 | |