| ... | @@ -924,7 +924,7 @@ const ElfContents = struct { | ... | @@ -924,7 +924,7 @@ const ElfContents = struct { |
| 924 | // - unused sections are removed | 924 | // - unused sections are removed |
| 925 | // when emitting the debug file: | 925 | // when emitting the debug file: |
| 926 | // - all sections are kept, but some are emptied and their types is changed to SHT_NOBITS | 926 | // - all sections are kept, but some are emptied and their types is changed to SHT_NOBITS |
| 927 | // the program header is kept unchanged. (`strip` does update it, but `eu-strip` does not, and it still works) TODO: maybe it can be omitted altogether from debug? | 927 | // the program header is kept unchanged. (`strip` does update it, but `eu-strip` does not, and it still works) |
| 928 | | 928 | |
| 929 | const Update = struct { | 929 | const Update = struct { |
| 930 | action: enum { keep, strip, empty }, | 930 | action: enum { keep, strip, empty }, |
| ... | @@ -1021,6 +1021,7 @@ const ElfContents = struct { | ... | @@ -1021,6 +1021,7 @@ const ElfContents = struct { |
| 1021 | eof_offset = @sizeOf(elf.Elf64_Ehdr); | 1021 | eof_offset = @sizeOf(elf.Elf64_Ehdr); |
| 1022 | | 1022 | |
| 1023 | // program header as-is. | 1023 | // program header as-is. |
| | 1024 | // nb: for only-debug files, removing it appears to work, but is invalid by ELF specifcation. |
| 1024 | { | 1025 | { |
| 1025 | std.debug.assert(updated_elf_header.e_phoff == @sizeOf(elf.Elf64_Ehdr)); | 1026 | std.debug.assert(updated_elf_header.e_phoff == @sizeOf(elf.Elf64_Ehdr)); |
| 1026 | const data = std.mem.sliceAsBytes(self.program_segments); | 1027 | const data = std.mem.sliceAsBytes(self.program_segments); |
| ... | @@ -1164,10 +1165,60 @@ const ElfContents = struct { | ... | @@ -1164,10 +1165,60 @@ const ElfContents = struct { |
| 1164 | cmdbuf.appendAssumeCapacity(.{ .write_data = .{ .data = data, .out_offset = updated_elf_header.e_shoff } }); | 1165 | cmdbuf.appendAssumeCapacity(.{ .write_data = .{ .data = data, .out_offset = updated_elf_header.e_shoff } }); |
| 1165 | } | 1166 | } |
| 1166 | | 1167 | |
| 1167 | // write the target files | 1168 | // consolidate holes between writes: |
| 1168 | // TODO: pack together contiguous copies (cmdbuf is ordered, by construction) | 1169 | // by coping original padding data from in_file (by fusing contiguous ranges) |
| 1169 | // TODO: fill the paddings with zero or copy from source file | 1170 | // by writing zeroes otherwise |
| 1170 | for (cmdbuf.items) |cmd| { | 1171 | const zeroes = [1]u8{0} ** 4096; |
| | 1172 | const consolidated_cmdbuf = blk: { |
| | 1173 | var newbuf = std.ArrayList(WriteCmd).init(allocator); |
| | 1174 | try newbuf.ensureUnusedCapacity(cmdbuf.items.len * 2); |
| | 1175 | var offset: u64 = 0; |
| | 1176 | var fused_cmd: ?WriteCmd = null; |
| | 1177 | for (cmdbuf.items) |cmd| { |
| | 1178 | switch (cmd) { |
| | 1179 | .write_data => |data| { |
| | 1180 | std.debug.assert(data.out_offset >= offset); |
| | 1181 | if (fused_cmd) |prev| { |
| | 1182 | newbuf.appendAssumeCapacity(prev); |
| | 1183 | fused_cmd = null; |
| | 1184 | } |
| | 1185 | if (data.out_offset > offset) { |
| | 1186 | newbuf.appendAssumeCapacity(.{ .write_data = .{ .data = zeroes[0 .. @intCast(usize, data.out_offset - offset)], .out_offset = offset } }); |
| | 1187 | } |
| | 1188 | newbuf.appendAssumeCapacity(cmd); |
| | 1189 | offset = data.out_offset + data.data.len; |
| | 1190 | }, |
| | 1191 | .copy_range => |range| { |
| | 1192 | std.debug.assert(range.out_offset >= offset); |
| | 1193 | if (fused_cmd) |prev| { |
| | 1194 | if (range.in_offset >= prev.copy_range.in_offset + prev.copy_range.len and (range.out_offset - prev.copy_range.out_offset == range.in_offset - prev.copy_range.in_offset)) { |
| | 1195 | fused_cmd = .{ .copy_range = .{ |
| | 1196 | .in_offset = prev.copy_range.in_offset, |
| | 1197 | .out_offset = prev.copy_range.out_offset, |
| | 1198 | .len = (range.out_offset + range.len) - prev.copy_range.out_offset, |
| | 1199 | } }; |
| | 1200 | } else { |
| | 1201 | newbuf.appendAssumeCapacity(prev); |
| | 1202 | if (range.out_offset > offset) { |
| | 1203 | newbuf.appendAssumeCapacity(.{ .write_data = .{ .data = zeroes[0 .. @intCast(usize, range.out_offset - offset)], .out_offset = offset } }); |
| | 1204 | } |
| | 1205 | fused_cmd = cmd; |
| | 1206 | } |
| | 1207 | } else { |
| | 1208 | fused_cmd = cmd; |
| | 1209 | } |
| | 1210 | offset = range.out_offset + range.len; |
| | 1211 | }, |
| | 1212 | } |
| | 1213 | } |
| | 1214 | if (fused_cmd) |cmd| { |
| | 1215 | newbuf.appendAssumeCapacity(cmd); |
| | 1216 | } |
| | 1217 | break :blk newbuf.items; |
| | 1218 | }; |
| | 1219 | |
| | 1220 | // write the output file |
| | 1221 | for (consolidated_cmdbuf) |cmd| { |
| 1171 | switch (cmd) { | 1222 | switch (cmd) { |
| 1172 | .write_data => |data| { | 1223 | .write_data => |data| { |
| 1173 | var iovec = [_]std.os.iovec_const{.{ .iov_base = data.data.ptr, .iov_len = data.data.len }}; | 1224 | var iovec = [_]std.os.iovec_const{.{ .iov_base = data.data.ptr, .iov_len = data.data.len }}; |