@@ -5715,43 +5715,62 @@ fn writeDyldInfoData(self: *MachO) !void {
5715
5715
5716
5716
const seg = & self .load_commands .items [self .linkedit_segment_cmd_index .? ].segment ;
5717
5717
const dyld_info = & self .load_commands .items [self .dyld_info_cmd_index .? ].dyld_info_only ;
5718
+
5719
+ const rebase_off = mem .alignForwardGeneric (u64 , seg .inner .fileoff , @alignOf (u64 ));
5718
5720
const rebase_size = try bind .rebaseInfoSize (rebase_pointers .items );
5719
- const bind_size = try bind .bindInfoSize (bind_pointers .items );
5720
- const lazy_bind_size = try bind .lazyBindInfoSize (lazy_bind_pointers .items );
5721
- const export_size = trie .size ;
5721
+ dyld_info .rebase_off = @intCast (u32 , rebase_off );
5722
+ dyld_info .rebase_size = @intCast (u32 , rebase_size );
5723
+ log .debug ("writing rebase info from 0x{x} to 0x{x}" , .{
5724
+ dyld_info .rebase_off ,
5725
+ dyld_info .rebase_off + dyld_info .rebase_size ,
5726
+ });
5722
5727
5723
- dyld_info .rebase_off = @intCast (u32 , seg .inner .fileoff );
5724
- dyld_info .rebase_size = @intCast (u32 , mem .alignForwardGeneric (u64 , rebase_size , @alignOf (u64 )));
5725
- seg .inner .filesize += dyld_info .rebase_size ;
5728
+ const bind_off = mem .alignForwardGeneric (u64 , dyld_info .rebase_off + dyld_info .rebase_size , @alignOf (u64 ));
5729
+ const bind_size = try bind .bindInfoSize (bind_pointers .items );
5730
+ dyld_info .bind_off = @intCast (u32 , bind_off );
5731
+ dyld_info .bind_size = @intCast (u32 , bind_size );
5732
+ log .debug ("writing bind info from 0x{x} to 0x{x}" , .{
5733
+ dyld_info .bind_off ,
5734
+ dyld_info .bind_off + dyld_info .bind_size ,
5735
+ });
5726
5736
5727
- dyld_info .bind_off = dyld_info .rebase_off + dyld_info .rebase_size ;
5728
- dyld_info .bind_size = @intCast (u32 , mem .alignForwardGeneric (u64 , bind_size , @alignOf (u64 )));
5729
- seg .inner .filesize += dyld_info .bind_size ;
5737
+ const lazy_bind_off = mem .alignForwardGeneric (u64 , dyld_info .bind_off + dyld_info .bind_size , @alignOf (u64 ));
5738
+ const lazy_bind_size = try bind .lazyBindInfoSize (lazy_bind_pointers .items );
5739
+ dyld_info .lazy_bind_off = @intCast (u32 , lazy_bind_off );
5740
+ dyld_info .lazy_bind_size = @intCast (u32 , lazy_bind_size );
5741
+ log .debug ("writing lazy bind info from 0x{x} to 0x{x}" , .{
5742
+ dyld_info .lazy_bind_off ,
5743
+ dyld_info .lazy_bind_off + dyld_info .lazy_bind_size ,
5744
+ });
5730
5745
5731
- dyld_info .lazy_bind_off = dyld_info .bind_off + dyld_info .bind_size ;
5732
- dyld_info .lazy_bind_size = @intCast (u32 , mem .alignForwardGeneric (u64 , lazy_bind_size , @alignOf (u64 )));
5733
- seg .inner .filesize += dyld_info .lazy_bind_size ;
5746
+ const export_off = mem .alignForwardGeneric (u64 , dyld_info .lazy_bind_off + dyld_info .lazy_bind_size , @alignOf (u64 ));
5747
+ const export_size = trie .size ;
5748
+ dyld_info .export_off = @intCast (u32 , export_off );
5749
+ dyld_info .export_size = @intCast (u32 , export_size );
5750
+ log .debug ("writing export trie from 0x{x} to 0x{x}" , .{
5751
+ dyld_info .export_off ,
5752
+ dyld_info .export_off + dyld_info .export_size ,
5753
+ });
5734
5754
5735
- dyld_info .export_off = dyld_info .lazy_bind_off + dyld_info .lazy_bind_size ;
5736
- dyld_info .export_size = @intCast (u32 , mem .alignForwardGeneric (u64 , export_size , @alignOf (u64 )));
5737
- seg .inner .filesize += dyld_info .export_size ;
5755
+ seg .inner .filesize = dyld_info .export_off + dyld_info .export_size - seg .inner .fileoff ;
5738
5756
5739
- const needed_size = dyld_info .rebase_size + dyld_info .bind_size + dyld_info .lazy_bind_size + dyld_info . export_size ;
5757
+ const needed_size = dyld_info .export_off + dyld_info .export_size - dyld_info .rebase_off ;
5740
5758
var buffer = try self .base .allocator .alloc (u8 , needed_size );
5741
5759
defer self .base .allocator .free (buffer );
5742
5760
mem .set (u8 , buffer , 0 );
5743
5761
5744
5762
var stream = std .io .fixedBufferStream (buffer );
5745
5763
const writer = stream .writer ();
5746
5764
5765
+ const base_off = dyld_info .rebase_off ;
5747
5766
try bind .writeRebaseInfo (rebase_pointers .items , writer );
5748
- try stream .seekBy ( @intCast ( i64 , dyld_info .rebase_size ) - @intCast ( i64 , rebase_size ) );
5767
+ try stream .seekTo ( dyld_info .bind_off - base_off );
5749
5768
5750
5769
try bind .writeBindInfo (bind_pointers .items , writer );
5751
- try stream .seekBy ( @intCast ( i64 , dyld_info .bind_size ) - @intCast ( i64 , bind_size ) );
5770
+ try stream .seekTo ( dyld_info .lazy_bind_off - base_off );
5752
5771
5753
5772
try bind .writeLazyBindInfo (lazy_bind_pointers .items , writer );
5754
- try stream .seekBy ( @intCast ( i64 , dyld_info .lazy_bind_size ) - @intCast ( i64 , lazy_bind_size ) );
5773
+ try stream .seekTo ( dyld_info .export_off - base_off );
5755
5774
5756
5775
_ = try trie .write (writer );
5757
5776
@@ -5762,7 +5781,7 @@ fn writeDyldInfoData(self: *MachO) !void {
5762
5781
5763
5782
try self .base .file .? .pwriteAll (buffer , dyld_info .rebase_off );
5764
5783
try self .populateLazyBindOffsetsInStubHelper (
5765
- buffer [dyld_info .rebase_size + dyld_info . bind_size .. ][0.. dyld_info .lazy_bind_size ],
5784
+ buffer [dyld_info .lazy_bind_off - base_off .. ][0.. dyld_info .lazy_bind_size ],
5766
5785
);
5767
5786
self .load_commands_dirty = true ;
5768
5787
}
@@ -5932,32 +5951,31 @@ fn writeFunctionStarts(self: *MachO) !void {
5932
5951
} else break ;
5933
5952
}
5934
5953
5935
- const max_size = @intCast (usize , offsets .items .len * @sizeOf (u64 ));
5936
- var buffer = try self .base .allocator .alloc (u8 , max_size );
5937
- defer self .base .allocator .free (buffer );
5938
- mem .set (u8 , buffer , 0 );
5954
+ var buffer = std .ArrayList (u8 ).init (self .base .allocator );
5955
+ defer buffer .deinit ();
5939
5956
5940
- var stream = std . io . fixedBufferStream ( buffer );
5941
- const writer = stream . writer ( );
5957
+ const max_size = @intCast ( usize , offsets . items . len * @sizeOf ( u64 ) );
5958
+ try buffer . ensureTotalCapacity ( max_size );
5942
5959
5943
5960
for (offsets .items ) | offset | {
5944
- try std .leb .writeULEB128 (writer , offset );
5961
+ try std .leb .writeULEB128 (buffer . writer () , offset );
5945
5962
}
5946
5963
5947
- const needed_size = @intCast (u32 , mem .alignForwardGeneric (u64 , stream .pos , @sizeOf (u64 )));
5948
5964
const seg = & self .load_commands .items [self .linkedit_segment_cmd_index .? ].segment ;
5949
5965
const fn_cmd = & self .load_commands .items [self .function_starts_cmd_index .? ].linkedit_data ;
5950
5966
5951
- fn_cmd .dataoff = @intCast (u32 , seg .inner .fileoff + seg .inner .filesize );
5952
- fn_cmd .datasize = needed_size ;
5953
- seg .inner .filesize += needed_size ;
5967
+ const dataoff = mem .alignForwardGeneric (u64 , seg .inner .fileoff + seg .inner .filesize , @alignOf (u64 ));
5968
+ const datasize = buffer .items .len ;
5969
+ fn_cmd .dataoff = @intCast (u32 , dataoff );
5970
+ fn_cmd .datasize = @intCast (u32 , datasize );
5971
+ seg .inner .filesize = fn_cmd .dataoff + fn_cmd .datasize - seg .inner .fileoff ;
5954
5972
5955
5973
log .debug ("writing function starts info from 0x{x} to 0x{x}" , .{
5956
5974
fn_cmd .dataoff ,
5957
5975
fn_cmd .dataoff + fn_cmd .datasize ,
5958
5976
});
5959
5977
5960
- try self .base .file .? .pwriteAll (buffer [0 .. needed_size ] , fn_cmd .dataoff );
5978
+ try self .base .file .? .pwriteAll (buffer . items , fn_cmd .dataoff );
5961
5979
self .load_commands_dirty = true ;
5962
5980
}
5963
5981
@@ -6005,11 +6023,12 @@ fn writeDices(self: *MachO) !void {
6005
6023
6006
6024
const seg = & self .load_commands .items [self .linkedit_segment_cmd_index .? ].segment ;
6007
6025
const dice_cmd = & self .load_commands .items [self .data_in_code_cmd_index .? ].linkedit_data ;
6008
- const needed_size = @intCast (u32 , buf .items .len );
6009
6026
6010
- dice_cmd .dataoff = @intCast (u32 , seg .inner .fileoff + seg .inner .filesize );
6011
- dice_cmd .datasize = needed_size ;
6012
- seg .inner .filesize += needed_size ;
6027
+ const dataoff = mem .alignForwardGeneric (u64 , seg .inner .fileoff + seg .inner .filesize , @alignOf (u64 ));
6028
+ const datasize = buf .items .len ;
6029
+ dice_cmd .dataoff = @intCast (u32 , dataoff );
6030
+ dice_cmd .datasize = @intCast (u32 , datasize );
6031
+ seg .inner .filesize = dice_cmd .dataoff + dice_cmd .datasize - seg .inner .fileoff ;
6013
6032
6014
6033
log .debug ("writing data-in-code from 0x{x} to 0x{x}" , .{
6015
6034
dice_cmd .dataoff ,
@@ -6026,7 +6045,8 @@ fn writeSymbolTable(self: *MachO) !void {
6026
6045
6027
6046
const seg = & self .load_commands .items [self .linkedit_segment_cmd_index .? ].segment ;
6028
6047
const symtab = & self .load_commands .items [self .symtab_cmd_index .? ].symtab ;
6029
- symtab .symoff = @intCast (u32 , seg .inner .fileoff + seg .inner .filesize );
6048
+ const symoff = mem .alignForwardGeneric (u64 , seg .inner .fileoff + seg .inner .filesize , @alignOf (macho .nlist_64 ));
6049
+ symtab .symoff = @intCast (u32 , symoff );
6030
6050
6031
6051
var locals = std .ArrayList (macho .nlist_64 ).init (self .base .allocator );
6032
6052
defer locals .deinit ();
@@ -6126,7 +6146,7 @@ fn writeSymbolTable(self: *MachO) !void {
6126
6146
try self .base .file .? .pwriteAll (mem .sliceAsBytes (undefs .items ), undefs_off );
6127
6147
6128
6148
symtab .nsyms = @intCast (u32 , nlocals + nexports + nundefs );
6129
- seg .inner .filesize += locals_size + exports_size + undefs_size ;
6149
+ seg .inner .filesize = symtab . symoff + symtab . nsyms * @sizeOf ( macho . nlist_64 ) - seg . inner . fileoff ;
6130
6150
6131
6151
// Update dynamic symbol table.
6132
6152
const dysymtab = & self .load_commands .items [self .dysymtab_cmd_index .? ].dysymtab ;
@@ -6146,22 +6166,21 @@ fn writeSymbolTable(self: *MachO) !void {
6146
6166
const nstubs = @intCast (u32 , self .stubs_table .keys ().len );
6147
6167
const ngot_entries = @intCast (u32 , self .got_entries_table .keys ().len );
6148
6168
6149
- dysymtab .indirectsymoff = @intCast (u32 , seg .inner .fileoff + seg .inner .filesize );
6169
+ const indirectsymoff = mem .alignForwardGeneric (u64 , seg .inner .fileoff + seg .inner .filesize , @alignOf (u64 ));
6170
+ dysymtab .indirectsymoff = @intCast (u32 , indirectsymoff );
6150
6171
dysymtab .nindirectsyms = nstubs * 2 + ngot_entries ;
6151
6172
6152
- const needed_size = dysymtab .nindirectsyms * @sizeOf (u32 );
6153
- seg .inner .filesize += needed_size ;
6173
+ seg .inner .filesize = dysymtab .indirectsymoff + dysymtab .nindirectsyms * @sizeOf (u32 ) - seg .inner .fileoff ;
6154
6174
6155
6175
log .debug ("writing indirect symbol table from 0x{x} to 0x{x}" , .{
6156
6176
dysymtab .indirectsymoff ,
6157
- dysymtab .indirectsymoff + needed_size ,
6177
+ dysymtab .indirectsymoff + dysymtab . nindirectsyms * @sizeOf ( u32 ) ,
6158
6178
});
6159
6179
6160
- var buf = try self .base .allocator .alloc (u8 , needed_size );
6161
- defer self .base .allocator .free (buf );
6162
-
6163
- var stream = std .io .fixedBufferStream (buf );
6164
- var writer = stream .writer ();
6180
+ var buf = std .ArrayList (u8 ).init (self .base .allocator );
6181
+ defer buf .deinit ();
6182
+ try buf .ensureTotalCapacity (dysymtab .nindirectsyms * @sizeOf (u32 ));
6183
+ const writer = buf .writer ();
6165
6184
6166
6185
stubs .reserved1 = 0 ;
6167
6186
for (self .stubs_table .keys ()) | key | {
@@ -6195,7 +6214,9 @@ fn writeSymbolTable(self: *MachO) !void {
6195
6214
}
6196
6215
}
6197
6216
6198
- try self .base .file .? .pwriteAll (buf , dysymtab .indirectsymoff );
6217
+ assert (buf .items .len == dysymtab .nindirectsyms * @sizeOf (u32 ));
6218
+
6219
+ try self .base .file .? .pwriteAll (buf .items , dysymtab .indirectsymoff );
6199
6220
self .load_commands_dirty = true ;
6200
6221
}
6201
6222
@@ -6205,18 +6226,16 @@ fn writeStringTable(self: *MachO) !void {
6205
6226
6206
6227
const seg = & self .load_commands .items [self .linkedit_segment_cmd_index .? ].segment ;
6207
6228
const symtab = & self .load_commands .items [self .symtab_cmd_index .? ].symtab ;
6208
- symtab .stroff = @intCast (u32 , seg .inner .fileoff + seg .inner .filesize );
6209
- symtab .strsize = @intCast (u32 , mem .alignForwardGeneric (u64 , self .strtab .items .len , @alignOf (u64 )));
6210
- seg .inner .filesize += symtab .strsize ;
6229
+ const stroff = mem .alignForwardGeneric (u64 , seg .inner .fileoff + seg .inner .filesize , @alignOf (u64 ));
6230
+ const strsize = self .strtab .items .len ;
6231
+ symtab .stroff = @intCast (u32 , stroff );
6232
+ symtab .strsize = @intCast (u32 , strsize );
6233
+ seg .inner .filesize = symtab .stroff + symtab .strsize - seg .inner .fileoff ;
6211
6234
6212
6235
log .debug ("writing string table from 0x{x} to 0x{x}" , .{ symtab .stroff , symtab .stroff + symtab .strsize });
6213
6236
6214
6237
try self .base .file .? .pwriteAll (self .strtab .items , symtab .stroff );
6215
6238
6216
- if (symtab .strsize > self .strtab .items .len ) {
6217
- // This is potentially the last section, so we need to pad it out.
6218
- try self .base .file .? .pwriteAll (&[_ ]u8 {0 }, seg .inner .fileoff + seg .inner .filesize - 1 );
6219
- }
6220
6239
self .load_commands_dirty = true ;
6221
6240
}
6222
6241
@@ -6240,25 +6259,22 @@ fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void {
6240
6259
const tracy = trace (@src ());
6241
6260
defer tracy .end ();
6242
6261
6243
- const linkedit_segment = & self .load_commands .items [self .linkedit_segment_cmd_index .? ].segment ;
6244
- const code_sig_cmd = & self .load_commands .items [self .code_signature_cmd_index .? ].linkedit_data ;
6262
+ const seg = & self .load_commands .items [self .linkedit_segment_cmd_index .? ].segment ;
6263
+ const cs_cmd = & self .load_commands .items [self .code_signature_cmd_index .? ].linkedit_data ;
6245
6264
// Code signature data has to be 16-bytes aligned for Apple tools to recognize the file
6246
6265
// https://github.com/opensource-apple/cctools/blob/fdb4825f303fd5c0751be524babd32958181b3ed/libstuff/checkout.c#L271
6247
- const fileoff = mem .alignForwardGeneric (u64 , linkedit_segment .inner .fileoff + linkedit_segment .inner .filesize , 16 );
6248
- const padding = fileoff - (linkedit_segment .inner .fileoff + linkedit_segment .inner .filesize );
6249
- const needed_size = code_sig .estimateSize (fileoff );
6250
- code_sig_cmd .dataoff = @intCast (u32 , fileoff );
6251
- code_sig_cmd .datasize = needed_size ;
6266
+ const dataoff = mem .alignForwardGeneric (u64 , seg .inner .fileoff + seg .inner .filesize , 16 );
6267
+ const datasize = code_sig .estimateSize (dataoff );
6268
+ cs_cmd .dataoff = @intCast (u32 , dataoff );
6269
+ cs_cmd .datasize = @intCast (u32 , code_sig .estimateSize (dataoff ));
6252
6270
6253
6271
// Advance size of __LINKEDIT segment
6254
- linkedit_segment .inner .filesize += needed_size + padding ;
6255
- if (linkedit_segment .inner .vmsize < linkedit_segment .inner .filesize ) {
6256
- linkedit_segment .inner .vmsize = mem .alignForwardGeneric (u64 , linkedit_segment .inner .filesize , self .page_size );
6257
- }
6258
- log .debug ("writing code signature padding from 0x{x} to 0x{x}" , .{ fileoff , fileoff + needed_size });
6272
+ seg .inner .filesize = cs_cmd .dataoff + cs_cmd .datasize - seg .inner .fileoff ;
6273
+ seg .inner .vmsize = mem .alignForwardGeneric (u64 , seg .inner .filesize , self .page_size );
6274
+ log .debug ("writing code signature padding from 0x{x} to 0x{x}" , .{ dataoff , dataoff + datasize });
6259
6275
// Pad out the space. We need to do this to calculate valid hashes for everything in the file
6260
6276
// except for code signature data.
6261
- try self .base .file .? .pwriteAll (&[_ ]u8 {0 }, fileoff + needed_size - 1 );
6277
+ try self .base .file .? .pwriteAll (&[_ ]u8 {0 }, dataoff + datasize - 1 );
6262
6278
self .load_commands_dirty = true ;
6263
6279
}
6264
6280
0 commit comments