| ... | @@ -158,6 +158,10 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) | ... | @@ -158,6 +158,10 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) |
| 158 | } | 158 | } |
| 159 | | 159 | |
| 160 | // TODO handle globals N_GSYM, and statics N_STSYM | 160 | // TODO handle globals N_GSYM, and statics N_STSYM |
| | 161 | // |
| | 162 | // NOTE: ld64.lld and Apple's ld differ in STABS layout. |
| | 163 | // Apple's ld emit N_BNSYM and N_ENSYM to mark the start and end of |
| | 164 | // functions, while ld64.lld doesn't. |
| 161 | switch (sym.n_type.stab) { | 165 | switch (sym.n_type.stab) { |
| 162 | .oso => switch (state) { | 166 | .oso => switch (state) { |
| 163 | .init, .oso_close => { | 167 | .init, .oso_close => { |
| ... | @@ -178,6 +182,14 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) | ... | @@ -178,6 +182,14 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) |
| 178 | else => return error.InvalidMachO, | 182 | else => return error.InvalidMachO, |
| 179 | }, | 183 | }, |
| 180 | .fun => switch (state) { | 184 | .fun => switch (state) { |
| | 185 | .oso_open => { |
| | 186 | state = .fun_strx; |
| | 187 | last_sym = .{ |
| | 188 | .strx = sym.n_strx, |
| | 189 | .addr = sym.n_value, |
| | 190 | .ofile = ofile, |
| | 191 | }; |
| | 192 | }, |
| 181 | .bnsym => { | 193 | .bnsym => { |
| 182 | state = .fun_strx; | 194 | state = .fun_strx; |
| 183 | last_sym.strx = sym.n_strx; | 195 | last_sym.strx = sym.n_strx; |
| ... | @@ -185,20 +197,24 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) | ... | @@ -185,20 +197,24 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) |
| 185 | .fun_strx => { | 197 | .fun_strx => { |
| 186 | state = .fun_size; | 198 | state = .fun_size; |
| 187 | }, | 199 | }, |
| | 200 | .fun_size => { |
| | 201 | if (last_sym.strx != 0) { |
| | 202 | appendStabSymbol(&symbols, &symbol_names, strings, last_sym); |
| | 203 | } |
| | 204 | last_sym = .{ |
| | 205 | .strx = sym.n_strx, |
| | 206 | .addr = sym.n_value, |
| | 207 | .ofile = ofile, |
| | 208 | }; |
| | 209 | state = .fun_strx; |
| | 210 | }, |
| 188 | else => return error.InvalidMachO, | 211 | else => return error.InvalidMachO, |
| 189 | }, | 212 | }, |
| 190 | .ensym => switch (state) { | 213 | .ensym => switch (state) { |
| 191 | .fun_size => { | 214 | .fun_size => { |
| 192 | state = .ensym; | 215 | state = .ensym; |
| 193 | if (last_sym.strx != 0) { | 216 | if (last_sym.strx != 0) { |
| 194 | const name = std.mem.sliceTo(strings[last_sym.strx..], 0); | 217 | appendStabSymbol(&symbols, &symbol_names, strings, last_sym); |
| 195 | const gop = symbol_names.getOrPutAssumeCapacity(name); | | |
| 196 | if (!gop.found_existing) { | | |
| 197 | assert(gop.index == symbols.items.len); | | |
| 198 | symbols.appendAssumeCapacity(last_sym); | | |
| 199 | } else { | | |
| 200 | symbols.items[gop.index] = last_sym; | | |
| 201 | } | | |
| 202 | } | 218 | } |
| 203 | }, | 219 | }, |
| 204 | else => return error.InvalidMachO, | 220 | else => return error.InvalidMachO, |
| ... | @@ -208,6 +224,12 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) | ... | @@ -208,6 +224,12 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) |
| 208 | .oso_open, .ensym => { | 224 | .oso_open, .ensym => { |
| 209 | state = .oso_close; | 225 | state = .oso_close; |
| 210 | }, | 226 | }, |
| | 227 | .fun_size => { |
| | 228 | state = .oso_close; |
| | 229 | if (last_sym.strx != 0) { |
| | 230 | appendStabSymbol(&symbols, &symbol_names, strings, last_sym); |
| | 231 | } |
| | 232 | }, |
| 211 | else => return error.InvalidMachO, | 233 | else => return error.InvalidMachO, |
| 212 | }, | 234 | }, |
| 213 | else => {}, | 235 | else => {}, |
| ... | @@ -356,6 +378,22 @@ test { | ... | @@ -356,6 +378,22 @@ test { |
| 356 | _ = Symbol; | 378 | _ = Symbol; |
| 357 | } | 379 | } |
| 358 | | 380 | |
| | 381 | fn appendStabSymbol( |
| | 382 | symbols: *std.ArrayList(Symbol), |
| | 383 | symbol_names: *std.StringArrayHashMapUnmanaged(void), |
| | 384 | strings: []const u8, |
| | 385 | last_sym: Symbol, |
| | 386 | ) void { |
| | 387 | const name = std.mem.sliceTo(strings[last_sym.strx..], 0); |
| | 388 | const gop = symbol_names.getOrPutAssumeCapacity(name); |
| | 389 | if (!gop.found_existing) { |
| | 390 | assert(gop.index == symbols.items.len); |
| | 391 | symbols.appendAssumeCapacity(last_sym); |
| | 392 | } else { |
| | 393 | symbols.items[gop.index] = last_sym; |
| | 394 | } |
| | 395 | } |
| | 396 | |
| 359 | fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile { | 397 | fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile { |
| 360 | const all_mapped_memory, const mapped_ofile = map: { | 398 | const all_mapped_memory, const mapped_ofile = map: { |
| 361 | const open_paren = paren: { | 399 | const open_paren = paren: { |