| ... | ... | @@ -158,6 +158,10 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | 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 | 165 | switch (sym.n_type.stab) { |
| 162 | 166 | .oso => switch (state) { |
| 163 | 167 | .init, .oso_close => { |
| ... | ... | @@ -178,6 +182,14 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) |
| 178 | 182 | else => return error.InvalidMachO, |
| 179 | 183 | }, |
| 180 | 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 | 193 | .bnsym => { |
| 182 | 194 | state = .fun_strx; |
| 183 | 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 | 197 | .fun_strx => { |
| 186 | 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 | 211 | else => return error.InvalidMachO, |
| 189 | 212 | }, |
| 190 | 213 | .ensym => switch (state) { |
| 191 | 214 | .fun_size => { |
| 192 | 215 | state = .ensym; |
| 193 | 216 | if (last_sym.strx != 0) { |
| 194 | | const name = std.mem.sliceTo(strings[last_sym.strx..], 0); |
| 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 | | } |
| 217 | appendStabSymbol(&symbols, &symbol_names, strings, last_sym); |
| 202 | 218 | } |
| 203 | 219 | }, |
| 204 | 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 | 224 | .oso_open, .ensym => { |
| 209 | 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 | 233 | else => return error.InvalidMachO, |
| 212 | 234 | }, |
| 213 | 235 | else => {}, |
| ... | ... | @@ -356,6 +378,22 @@ test { |
| 356 | 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 | 397 | fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile { |
| 360 | 398 | const all_mapped_memory, const mapped_ofile = map: { |
| 361 | 399 | const open_paren = paren: { |