@@ -24,8 +24,11 @@ mtime: u64,
24
24
contents : []align (@alignOf (u64 )) const u8 ,
25
25
26
26
header : macho.mach_header_64 = undefined ,
27
- in_symtab : []align (1 ) const macho.nlist_64 = undefined ,
28
- in_strtab : []const u8 = undefined ,
27
+
28
+ /// Symtab and strtab might not exist for empty object files so we use an optional
29
+ /// to signal this.
30
+ in_symtab : ? []align (1 ) const macho.nlist_64 = null ,
31
+ in_strtab : ? []const u8 = null ,
29
32
30
33
symtab : std .ArrayListUnmanaged (macho .nlist_64 ) = .{},
31
34
sections : std .ArrayListUnmanaged (macho .section_64 ) = .{},
@@ -105,7 +108,7 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)
105
108
self .contents .ptr + symtab .symoff ,
106
109
)[0.. symtab .nsyms ];
107
110
self .in_strtab = self .contents [symtab .stroff .. ][0.. symtab .strsize ];
108
- try self .symtab .appendUnalignedSlice (allocator , self .in_symtab );
111
+ try self .symtab .appendUnalignedSlice (allocator , self .in_symtab .? );
109
112
},
110
113
else = > {},
111
114
}
@@ -243,17 +246,61 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
243
246
244
247
log .debug ("splitting object({d}, {s}) into atoms: one-shot mode" , .{ object_id , self .name });
245
248
249
+ const in_symtab = self .in_symtab orelse {
250
+ for (self .sections .items ) | sect , id | {
251
+ if (sect .isDebug ()) continue ;
252
+ const match = (try macho_file .getOutputSection (sect )) orelse {
253
+ log .debug (" unhandled section" , .{});
254
+ continue ;
255
+ };
256
+ if (sect .size == 0 ) continue ;
257
+
258
+ const sect_id = @intCast (u8 , id );
259
+ const sym_index = self .sections_as_symbols .get (sect_id ) orelse blk : {
260
+ const sym_index = @intCast (u32 , self .symtab .items .len );
261
+ try self .symtab .append (gpa , .{
262
+ .n_strx = 0 ,
263
+ .n_type = macho .N_SECT ,
264
+ .n_sect = match + 1 ,
265
+ .n_desc = 0 ,
266
+ .n_value = sect .addr ,
267
+ });
268
+ try self .sections_as_symbols .putNoClobber (gpa , sect_id , sym_index );
269
+ break :blk sym_index ;
270
+ };
271
+ const code : ? []const u8 = if (! sect .isZerofill ()) try self .getSectionContents (sect ) else null ;
272
+ const relocs = @ptrCast (
273
+ [* ]align (1 ) const macho .relocation_info ,
274
+ self .contents .ptr + sect .reloff ,
275
+ )[0.. sect .nreloc ];
276
+ const atom = try self .createAtomFromSubsection (
277
+ macho_file ,
278
+ object_id ,
279
+ sym_index ,
280
+ sect .size ,
281
+ sect .@"align" ,
282
+ code ,
283
+ relocs ,
284
+ &.{},
285
+ match ,
286
+ sect ,
287
+ );
288
+ try macho_file .addAtomToSection (atom , match );
289
+ }
290
+ return ;
291
+ };
292
+
246
293
// You would expect that the symbol table is at least pre-sorted based on symbol's type:
247
294
// local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance,
248
295
// the GO compiler does not necessarily respect that therefore we sort immediately by type
249
296
// and address within.
250
297
const context = Context {
251
298
.object = self ,
252
299
};
253
- var sorted_all_syms = try std .ArrayList (SymbolAtIndex ).initCapacity (gpa , self . in_symtab .len );
300
+ var sorted_all_syms = try std .ArrayList (SymbolAtIndex ).initCapacity (gpa , in_symtab .len );
254
301
defer sorted_all_syms .deinit ();
255
302
256
- for (self . in_symtab ) | _ , index | {
303
+ for (in_symtab ) | _ , index | {
257
304
sorted_all_syms .appendAssumeCapacity (.{ .index = @intCast (u32 , index ) });
258
305
}
259
306
@@ -282,6 +329,8 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
282
329
const subsections_via_symbols = self .header .flags & macho .MH_SUBSECTIONS_VIA_SYMBOLS != 0 ;
283
330
284
331
for (self .sections .items ) | sect , id | {
332
+ if (sect .isDebug ()) continue ;
333
+
285
334
const sect_id = @intCast (u8 , id );
286
335
log .debug ("splitting section '{s},{s}' into atoms" , .{ sect .segName (), sect .sectName () });
287
336
@@ -530,8 +579,9 @@ fn createAtomFromSubsection(
530
579
}
531
580
532
581
pub fn getSourceSymbol (self : Object , index : u32 ) ? macho.nlist_64 {
533
- if (index >= self .in_symtab .len ) return null ;
534
- return self .in_symtab [index ];
582
+ const symtab = self .in_symtab .? ;
583
+ if (index >= symtab .len ) return null ;
584
+ return symtab [index ];
535
585
}
536
586
537
587
pub fn getSourceSection (self : Object , index : u16 ) macho.section_64 {
@@ -636,8 +686,9 @@ pub fn getSectionContents(self: Object, sect: macho.section_64) error{Overflow}!
636
686
}
637
687
638
688
pub fn getString (self : Object , off : u32 ) []const u8 {
639
- assert (off < self .in_strtab .len );
640
- return mem .sliceTo (@ptrCast ([* :0 ]const u8 , self .in_strtab .ptr + off ), 0 );
689
+ const strtab = self .in_strtab .? ;
690
+ assert (off < strtab .len );
691
+ return mem .sliceTo (@ptrCast ([* :0 ]const u8 , strtab .ptr + off ), 0 );
641
692
}
642
693
643
694
pub fn getAtomForSymbol (self : Object , sym_index : u32 ) ? * Atom {
0 commit comments