authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-08 12:15:46+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-08 12:15:46+01:00
logce207caa24dc3a283288beb7ee5fd4a07c2c8691
tree2bb9c32250c547a4a8ca33c9e99a5b310e80f90b
parent37033a96ac2e33a56eb2e153462d1a730b426029

macho: in relocatable mode, macho emit __DWARF directly


3 files changed, 312 insertions(+), 106 deletions(-)

src/link/Dwarf.zig+194-82
...@@ -1282,10 +1282,17 @@ pub fn commitDeclState(...@@ -1282,10 +1282,17 @@ pub fn commitDeclState(
1282 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);1282 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);
1283 },1283 },
1284 .macho => {1284 .macho => {
1285 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;1285 const macho_file = self.bin_file.cast(File.MachO).?;
1286 const debug_line_sect = d_sym.getSectionPtr(d_sym.debug_line_section_index.?);1286 if (macho_file.base.isRelocatable()) {
1287 const file_pos = debug_line_sect.offset + src_fn.off;1287 const debug_line_sect = &macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?];
1288 try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len);1288 const file_pos = debug_line_sect.offset + src_fn.off;
1289 try pwriteDbgLineNops(macho_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);
1290 } else {
1291 const d_sym = macho_file.getDebugSymbols().?;
1292 const debug_line_sect = d_sym.getSectionPtr(d_sym.debug_line_section_index.?);
1293 const file_pos = debug_line_sect.offset + src_fn.off;
1294 try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len);
1295 }
1289 },1296 },
1290 .wasm => {1297 .wasm => {
1291 const wasm_file = self.bin_file.cast(File.Wasm).?;1298 const wasm_file = self.bin_file.cast(File.Wasm).?;
...@@ -1352,18 +1359,32 @@ pub fn commitDeclState(...@@ -1352,18 +1359,32 @@ pub fn commitDeclState(
13521359
1353 .macho => {1360 .macho => {
1354 const macho_file = self.bin_file.cast(File.MachO).?;1361 const macho_file = self.bin_file.cast(File.MachO).?;
1355 const d_sym = macho_file.getDebugSymbols().?;1362 if (macho_file.base.isRelocatable()) {
1356 const sect_index = d_sym.debug_line_section_index.?;1363 const sect_index = macho_file.debug_line_sect_index.?;
1357 try d_sym.growSection(sect_index, needed_size, true, macho_file);1364 try macho_file.growSection(sect_index, needed_size);
1358 const sect = d_sym.getSection(sect_index);1365 const sect = macho_file.sections.items(.header)[sect_index];
1359 const file_pos = sect.offset + src_fn.off;1366 const file_pos = sect.offset + src_fn.off;
1360 try pwriteDbgLineNops(1367 try pwriteDbgLineNops(
1361 d_sym.file,1368 macho_file.base.file.?,
1362 file_pos,1369 file_pos,
1363 prev_padding_size,1370 prev_padding_size,
1364 dbg_line_buffer.items,1371 dbg_line_buffer.items,
1365 next_padding_size,1372 next_padding_size,
1366 );1373 );
1374 } else {
1375 const d_sym = macho_file.getDebugSymbols().?;
1376 const sect_index = d_sym.debug_line_section_index.?;
1377 try d_sym.growSection(sect_index, needed_size, true, macho_file);
1378 const sect = d_sym.getSection(sect_index);
1379 const file_pos = sect.offset + src_fn.off;
1380 try pwriteDbgLineNops(
1381 d_sym.file,
1382 file_pos,
1383 prev_padding_size,
1384 dbg_line_buffer.items,
1385 next_padding_size,
1386 );
1387 }
1367 },1388 },
13681389
1369 .wasm => {1390 .wasm => {
...@@ -1460,16 +1481,21 @@ pub fn commitDeclState(...@@ -1460,16 +1481,21 @@ pub fn commitDeclState(
1460 while (decl_state.exprloc_relocs.popOrNull()) |reloc| {1481 while (decl_state.exprloc_relocs.popOrNull()) |reloc| {
1461 switch (self.bin_file.tag) {1482 switch (self.bin_file.tag) {
1462 .macho => {1483 .macho => {
1463 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;1484 const macho_file = self.bin_file.cast(File.MachO).?;
1464 try d_sym.relocs.append(d_sym.allocator, .{1485 if (macho_file.base.isRelocatable()) {
1465 .type = switch (reloc.type) {1486 // TODO
1466 .direct_load => .direct_load,1487 } else {
1467 .got_load => .got_load,1488 const d_sym = macho_file.getDebugSymbols().?;
1468 },1489 try d_sym.relocs.append(d_sym.allocator, .{
1469 .target = reloc.target,1490 .type = switch (reloc.type) {
1470 .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off,1491 .direct_load => .direct_load,
1471 .addend = 0,1492 .got_load => .got_load,
1472 });1493 },
1494 .target = reloc.target,
1495 .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off,
1496 .addend = 0,
1497 });
1498 }
1473 },1499 },
1474 .elf => {}, // TODO1500 .elf => {}, // TODO
1475 else => unreachable,1501 else => unreachable,
...@@ -1512,10 +1538,17 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)...@@ -1512,10 +1538,17 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)
1512 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);1538 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);
1513 },1539 },
1514 .macho => {1540 .macho => {
1515 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;1541 const macho_file = self.bin_file.cast(File.MachO).?;
1516 const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);1542 if (macho_file.base.isRelocatable()) {
1517 const file_pos = debug_info_sect.offset + atom.off;1543 const debug_info_sect = macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?];
1518 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);1544 const file_pos = debug_info_sect.offset + atom.off;
1545 try pwriteDbgInfoNops(macho_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);
1546 } else {
1547 const d_sym = macho_file.getDebugSymbols().?;
1548 const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);
1549 const file_pos = debug_info_sect.offset + atom.off;
1550 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);
1551 }
1519 },1552 },
1520 .wasm => {1553 .wasm => {
1521 const wasm_file = self.bin_file.cast(File.Wasm).?;1554 const wasm_file = self.bin_file.cast(File.Wasm).?;
...@@ -1599,19 +1632,34 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons...@@ -1599,19 +1632,34 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
15991632
1600 .macho => {1633 .macho => {
1601 const macho_file = self.bin_file.cast(File.MachO).?;1634 const macho_file = self.bin_file.cast(File.MachO).?;
1602 const d_sym = macho_file.getDebugSymbols().?;1635 if (macho_file.base.isRelocatable()) {
1603 const sect_index = d_sym.debug_info_section_index.?;1636 const sect_index = macho_file.debug_info_sect_index.?;
1604 try d_sym.growSection(sect_index, needed_size, true, macho_file);1637 try macho_file.growSection(sect_index, needed_size);
1605 const sect = d_sym.getSection(sect_index);1638 const sect = macho_file.sections.items(.header)[sect_index];
1606 const file_pos = sect.offset + atom.off;1639 const file_pos = sect.offset + atom.off;
1607 try pwriteDbgInfoNops(1640 try pwriteDbgInfoNops(
1608 d_sym.file,1641 macho_file.base.file.?,
1609 file_pos,1642 file_pos,
1610 prev_padding_size,1643 prev_padding_size,
1611 dbg_info_buf,1644 dbg_info_buf,
1612 next_padding_size,1645 next_padding_size,
1613 trailing_zero,1646 trailing_zero,
1614 );1647 );
1648 } else {
1649 const d_sym = macho_file.getDebugSymbols().?;
1650 const sect_index = d_sym.debug_info_section_index.?;
1651 try d_sym.growSection(sect_index, needed_size, true, macho_file);
1652 const sect = d_sym.getSection(sect_index);
1653 const file_pos = sect.offset + atom.off;
1654 try pwriteDbgInfoNops(
1655 d_sym.file,
1656 file_pos,
1657 prev_padding_size,
1658 dbg_info_buf,
1659 next_padding_size,
1660 trailing_zero,
1661 );
1662 }
1615 },1663 },
16161664
1617 .wasm => {1665 .wasm => {
...@@ -1672,10 +1720,17 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: InternPool.D...@@ -1672,10 +1720,17 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: InternPool.D
1672 try elf_file.base.file.?.pwriteAll(&data, file_pos);1720 try elf_file.base.file.?.pwriteAll(&data, file_pos);
1673 },1721 },
1674 .macho => {1722 .macho => {
1675 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;1723 const macho_file = self.bin_file.cast(File.MachO).?;
1676 const sect = d_sym.getSection(d_sym.debug_line_section_index.?);1724 if (macho_file.base.isRelocatable()) {
1677 const file_pos = sect.offset + atom.off + self.getRelocDbgLineOff();1725 const sect = macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?];
1678 try d_sym.file.pwriteAll(&data, file_pos);1726 const file_pos = sect.offset + atom.off + self.getRelocDbgLineOff();
1727 try macho_file.base.file.?.pwriteAll(&data, file_pos);
1728 } else {
1729 const d_sym = macho_file.getDebugSymbols().?;
1730 const sect = d_sym.getSection(d_sym.debug_line_section_index.?);
1731 const file_pos = sect.offset + atom.off + self.getRelocDbgLineOff();
1732 try d_sym.file.pwriteAll(&data, file_pos);
1733 }
1679 },1734 },
1680 .wasm => {1735 .wasm => {
1681 const wasm_file = self.bin_file.cast(File.Wasm).?;1736 const wasm_file = self.bin_file.cast(File.Wasm).?;
...@@ -1880,12 +1935,20 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1880,12 +1935,20 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1880 },1935 },
1881 .macho => {1936 .macho => {
1882 const macho_file = self.bin_file.cast(File.MachO).?;1937 const macho_file = self.bin_file.cast(File.MachO).?;
1883 const d_sym = macho_file.getDebugSymbols().?;1938 if (macho_file.base.isRelocatable()) {
1884 const sect_index = d_sym.debug_abbrev_section_index.?;1939 const sect_index = macho_file.debug_abbrev_sect_index.?;
1885 try d_sym.growSection(sect_index, needed_size, false, macho_file);1940 try macho_file.growSection(sect_index, needed_size);
1886 const sect = d_sym.getSection(sect_index);1941 const sect = macho_file.sections.items(.header)[sect_index];
1887 const file_pos = sect.offset + abbrev_offset;1942 const file_pos = sect.offset + abbrev_offset;
1888 try d_sym.file.pwriteAll(&abbrev_buf, file_pos);1943 try macho_file.base.file.?.pwriteAll(&abbrev_buf, file_pos);
1944 } else {
1945 const d_sym = macho_file.getDebugSymbols().?;
1946 const sect_index = d_sym.debug_abbrev_section_index.?;
1947 try d_sym.growSection(sect_index, needed_size, false, macho_file);
1948 const sect = d_sym.getSection(sect_index);
1949 const file_pos = sect.offset + abbrev_offset;
1950 try d_sym.file.pwriteAll(&abbrev_buf, file_pos);
1951 }
1889 },1952 },
1890 .wasm => {1953 .wasm => {
1891 const wasm_file = self.bin_file.cast(File.Wasm).?;1954 const wasm_file = self.bin_file.cast(File.Wasm).?;
...@@ -1970,10 +2033,17 @@ pub fn writeDbgInfoHeader(self: *Dwarf, zcu: *Module, low_pc: u64, high_pc: u64)...@@ -1970,10 +2033,17 @@ pub fn writeDbgInfoHeader(self: *Dwarf, zcu: *Module, low_pc: u64, high_pc: u64)
1970 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);2033 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);
1971 },2034 },
1972 .macho => {2035 .macho => {
1973 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;2036 const macho_file = self.bin_file.cast(File.MachO).?;
1974 const debug_info_sect = d_sym.getSection(d_sym.debug_info_section_index.?);2037 if (macho_file.base.isRelocatable()) {
1975 const file_pos = debug_info_sect.offset;2038 const debug_info_sect = macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?];
1976 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt, false);2039 const file_pos = debug_info_sect.offset;
2040 try pwriteDbgInfoNops(macho_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);
2041 } else {
2042 const d_sym = macho_file.getDebugSymbols().?;
2043 const debug_info_sect = d_sym.getSection(d_sym.debug_info_section_index.?);
2044 const file_pos = debug_info_sect.offset;
2045 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt, false);
2046 }
1977 },2047 },
1978 .wasm => {2048 .wasm => {
1979 const wasm_file = self.bin_file.cast(File.Wasm).?;2049 const wasm_file = self.bin_file.cast(File.Wasm).?;
...@@ -2296,12 +2366,20 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {...@@ -2296,12 +2366,20 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
2296 },2366 },
2297 .macho => {2367 .macho => {
2298 const macho_file = self.bin_file.cast(File.MachO).?;2368 const macho_file = self.bin_file.cast(File.MachO).?;
2299 const d_sym = macho_file.getDebugSymbols().?;2369 if (macho_file.base.isRelocatable()) {
2300 const sect_index = d_sym.debug_aranges_section_index.?;2370 const sect_index = macho_file.debug_aranges_sect_index.?;
2301 try d_sym.growSection(sect_index, needed_size, false, macho_file);2371 try macho_file.growSection(sect_index, needed_size);
2302 const sect = d_sym.getSection(sect_index);2372 const sect = macho_file.sections.items(.header)[sect_index];
2303 const file_pos = sect.offset;2373 const file_pos = sect.offset;
2304 try d_sym.file.pwriteAll(di_buf.items, file_pos);2374 try macho_file.base.file.?.pwriteAll(di_buf.items, file_pos);
2375 } else {
2376 const d_sym = macho_file.getDebugSymbols().?;
2377 const sect_index = d_sym.debug_aranges_section_index.?;
2378 try d_sym.growSection(sect_index, needed_size, false, macho_file);
2379 const sect = d_sym.getSection(sect_index);
2380 const file_pos = sect.offset;
2381 try d_sym.file.pwriteAll(di_buf.items, file_pos);
2382 }
2305 },2383 },
2306 .wasm => {2384 .wasm => {
2307 const wasm_file = self.bin_file.cast(File.Wasm).?;2385 const wasm_file = self.bin_file.cast(File.Wasm).?;
...@@ -2437,16 +2515,28 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2437,16 +2515,28 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2437 },2515 },
2438 .macho => {2516 .macho => {
2439 const macho_file = self.bin_file.cast(File.MachO).?;2517 const macho_file = self.bin_file.cast(File.MachO).?;
2440 const d_sym = macho_file.getDebugSymbols().?;2518 if (macho_file.base.isRelocatable()) {
2441 const sect_index = d_sym.debug_line_section_index.?;2519 const sect_index = macho_file.debug_line_sect_index.?;
2442 const needed_size: u32 = @intCast(d_sym.getSection(sect_index).size + delta);2520 const needed_size: u32 = @intCast(macho_file.sections.items(.header)[sect_index].size + delta);
2443 try d_sym.growSection(sect_index, needed_size, true, macho_file);2521 try macho_file.growSection(sect_index, needed_size);
2444 const file_pos = d_sym.getSection(sect_index).offset + first_fn.off;2522 const file_pos = macho_file.sections.items(.header)[sect_index].offset + first_fn.off;
24452523
2446 const amt = try d_sym.file.preadAll(buffer, file_pos);2524 const amt = try macho_file.base.file.?.preadAll(buffer, file_pos);
2447 if (amt != buffer.len) return error.InputOutput;2525 if (amt != buffer.len) return error.InputOutput;
2526
2527 try macho_file.base.file.?.pwriteAll(buffer, file_pos + delta);
2528 } else {
2529 const d_sym = macho_file.getDebugSymbols().?;
2530 const sect_index = d_sym.debug_line_section_index.?;
2531 const needed_size: u32 = @intCast(d_sym.getSection(sect_index).size + delta);
2532 try d_sym.growSection(sect_index, needed_size, true, macho_file);
2533 const file_pos = d_sym.getSection(sect_index).offset + first_fn.off;
2534
2535 const amt = try d_sym.file.preadAll(buffer, file_pos);
2536 if (amt != buffer.len) return error.InputOutput;
24482537
2449 try d_sym.file.pwriteAll(buffer, file_pos + delta);2538 try d_sym.file.pwriteAll(buffer, file_pos + delta);
2539 }
2450 },2540 },
2451 .wasm => {2541 .wasm => {
2452 const wasm_file = self.bin_file.cast(File.Wasm).?;2542 const wasm_file = self.bin_file.cast(File.Wasm).?;
...@@ -2492,10 +2582,17 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2492,10 +2582,17 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2492 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);2582 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);
2493 },2583 },
2494 .macho => {2584 .macho => {
2495 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;2585 const macho_file = self.bin_file.cast(File.MachO).?;
2496 const debug_line_sect = d_sym.getSection(d_sym.debug_line_section_index.?);2586 if (macho_file.base.isRelocatable()) {
2497 const file_pos = debug_line_sect.offset;2587 const debug_line_sect = macho_file.sections.items(.header)[macho_file.debug_line_sect_index.?];
2498 try pwriteDbgLineNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt);2588 const file_pos = debug_line_sect.offset;
2589 try pwriteDbgLineNops(macho_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);
2590 } else {
2591 const d_sym = macho_file.getDebugSymbols().?;
2592 const debug_line_sect = d_sym.getSection(d_sym.debug_line_section_index.?);
2593 const file_pos = debug_line_sect.offset;
2594 try pwriteDbgLineNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt);
2595 }
2499 },2596 },
2500 .wasm => {2597 .wasm => {
2501 const wasm_file = self.bin_file.cast(File.Wasm).?;2598 const wasm_file = self.bin_file.cast(File.Wasm).?;
...@@ -2613,9 +2710,15 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2613,9 +2710,15 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
2613 break :pos debug_info_sect.sh_offset;2710 break :pos debug_info_sect.sh_offset;
2614 },2711 },
2615 .macho => pos: {2712 .macho => pos: {
2616 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;2713 const macho_file = self.bin_file.cast(File.MachO).?;
2617 const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);2714 if (macho_file.base.isRelocatable()) {
2618 break :pos debug_info_sect.offset;2715 const debug_info_sect = &macho_file.sections.items(.header)[macho_file.debug_info_sect_index.?];
2716 break :pos debug_info_sect.offset;
2717 } else {
2718 const d_sym = macho_file.getDebugSymbols().?;
2719 const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);
2720 break :pos debug_info_sect.offset;
2721 }
2619 },2722 },
2620 // for wasm, the offset is always 0 as we write to memory first2723 // for wasm, the offset is always 0 as we write to memory first
2621 .wasm => 0,2724 .wasm => 0,
...@@ -2633,8 +2736,13 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2633,8 +2736,13 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
2633 try elf_file.base.file.?.pwriteAll(&buf, file_pos + atom.off + reloc.offset);2736 try elf_file.base.file.?.pwriteAll(&buf, file_pos + atom.off + reloc.offset);
2634 },2737 },
2635 .macho => {2738 .macho => {
2636 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;2739 const macho_file = self.bin_file.cast(File.MachO).?;
2637 try d_sym.file.pwriteAll(&buf, file_pos + atom.off + reloc.offset);2740 if (macho_file.base.isRelocatable()) {
2741 try macho_file.base.file.?.pwriteAll(&buf, file_pos + atom.off + reloc.offset);
2742 } else {
2743 const d_sym = macho_file.getDebugSymbols().?;
2744 try d_sym.file.pwriteAll(&buf, file_pos + atom.off + reloc.offset);
2745 }
2638 },2746 },
2639 .wasm => {2747 .wasm => {
2640 const wasm_file = self.bin_file.cast(File.Wasm).?;2748 const wasm_file = self.bin_file.cast(File.Wasm).?;
...@@ -2659,8 +2767,12 @@ fn addDIFile(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclIndex) !u28...@@ -2659,8 +2767,12 @@ fn addDIFile(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclIndex) !u28
2659 },2767 },
2660 .macho => {2768 .macho => {
2661 const macho_file = self.bin_file.cast(File.MachO).?;2769 const macho_file = self.bin_file.cast(File.MachO).?;
2662 const d_sym = macho_file.getDebugSymbols().?;2770 if (macho_file.base.isRelocatable()) {
2663 d_sym.markDirty(d_sym.debug_line_section_index.?, macho_file);2771 macho_file.markDirty(macho_file.debug_line_sect_index.?);
2772 } else {
2773 const d_sym = macho_file.getDebugSymbols().?;
2774 d_sym.markDirty(d_sym.debug_line_section_index.?, macho_file);
2775 }
2664 },2776 },
2665 .wasm => {},2777 .wasm => {},
2666 else => unreachable,2778 else => unreachable,
src/link/MachO.zig+111-23
...@@ -103,6 +103,14 @@ zig_const_sect_index: ?u8 = null,...@@ -103,6 +103,14 @@ zig_const_sect_index: ?u8 = null,
103zig_data_sect_index: ?u8 = null,103zig_data_sect_index: ?u8 = null,
104zig_bss_sect_index: ?u8 = null,104zig_bss_sect_index: ?u8 = null,
105105
106/// Tracked DWARF section headers that apply only when we emit relocatable.
107/// For executable and loadable images, DWARF is tracked directly by dSYM bundle object.
108debug_info_sect_index: ?u8 = null,
109debug_abbrev_sect_index: ?u8 = null,
110debug_str_sect_index: ?u8 = null,
111debug_aranges_sect_index: ?u8 = null,
112debug_line_sect_index: ?u8 = null,
113
106has_tlv: bool = false,114has_tlv: bool = false,
107binds_to_weak: bool = false,115binds_to_weak: bool = false,
108weak_defines: bool = false,116weak_defines: bool = false,
...@@ -259,32 +267,11 @@ pub fn createEmpty(...@@ -259,32 +267,11 @@ pub fn createEmpty(
259 try zo.init(self);267 try zo.init(self);
260268
261 try self.initMetadata(.{269 try self.initMetadata(.{
270 .emit = emit,
271 .zo = zo,
262 .symbol_count_hint = options.symbol_count_hint,272 .symbol_count_hint = options.symbol_count_hint,
263 .program_code_size_hint = options.program_code_size_hint,273 .program_code_size_hint = options.program_code_size_hint,
264 });274 });
265
266 if (zo.dwarf != null and !self.base.isRelocatable()) {
267 // Create dSYM bundle.
268 log.debug("creating {s}.dSYM bundle", .{emit.sub_path});
269
270 const sep = fs.path.sep_str;
271 const d_sym_path = try std.fmt.allocPrint(
272 arena,
273 "{s}.dSYM" ++ sep ++ "Contents" ++ sep ++ "Resources" ++ sep ++ "DWARF",
274 .{emit.sub_path},
275 );
276
277 var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{});
278 defer d_sym_bundle.close();
279
280 const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{
281 .truncate = false,
282 .read = true,
283 });
284
285 self.d_sym = .{ .allocator = gpa, .file = d_sym_file };
286 try self.d_sym.?.initMetadata(self);
287 }
288 }275 }
289 }276 }
290277
...@@ -2007,6 +1994,11 @@ pub fn sortSections(self: *MachO) !void {...@@ -2007,6 +1994,11 @@ pub fn sortSections(self: *MachO) !void {
2007 &self.eh_frame_sect_index,1994 &self.eh_frame_sect_index,
2008 &self.unwind_info_sect_index,1995 &self.unwind_info_sect_index,
2009 &self.objc_stubs_sect_index,1996 &self.objc_stubs_sect_index,
1997 &self.debug_info_sect_index,
1998 &self.debug_str_sect_index,
1999 &self.debug_line_sect_index,
2000 &self.debug_abbrev_sect_index,
2001 &self.debug_info_sect_index,
2010 }) |maybe_index| {2002 }) |maybe_index| {
2011 if (maybe_index.*) |*index| {2003 if (maybe_index.*) |*index| {
2012 index.* = backlinks[index.*];2004 index.* = backlinks[index.*];
...@@ -3317,6 +3309,8 @@ fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64...@@ -3317,6 +3309,8 @@ fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64
3317}3309}
33183310
3319const InitMetadataOptions = struct {3311const InitMetadataOptions = struct {
3312 emit: Compilation.Emit,
3313 zo: *ZigObject,
3320 symbol_count_hint: u64,3314 symbol_count_hint: u64,
3321 program_code_size_hint: u64,3315 program_code_size_hint: u64,
3322};3316};
...@@ -3385,6 +3379,31 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {...@@ -3385,6 +3379,31 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
3385 .prot = macho.PROT.READ | macho.PROT.WRITE,3379 .prot = macho.PROT.READ | macho.PROT.WRITE,
3386 });3380 });
3387 }3381 }
3382
3383 if (options.zo.dwarf) |_| {
3384 // Create dSYM bundle.
3385 log.debug("creating {s}.dSYM bundle", .{options.emit.sub_path});
3386
3387 const gpa = self.base.comp.gpa;
3388 const sep = fs.path.sep_str;
3389 const d_sym_path = try std.fmt.allocPrint(
3390 gpa,
3391 "{s}.dSYM" ++ sep ++ "Contents" ++ sep ++ "Resources" ++ sep ++ "DWARF",
3392 .{options.emit.sub_path},
3393 );
3394 defer gpa.free(d_sym_path);
3395
3396 var d_sym_bundle = try options.emit.directory.handle.makeOpenPath(d_sym_path, .{});
3397 defer d_sym_bundle.close();
3398
3399 const d_sym_file = try d_sym_bundle.createFile(options.emit.sub_path, .{
3400 .truncate = false,
3401 .read = true,
3402 });
3403
3404 self.d_sym = .{ .allocator = gpa, .file = d_sym_file };
3405 try self.d_sym.?.initMetadata(self);
3406 }
3388 }3407 }
33893408
3390 const appendSect = struct {3409 const appendSect = struct {
...@@ -3462,6 +3481,44 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {...@@ -3462,6 +3481,44 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
3462 appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?);3481 appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?);
3463 }3482 }
3464 }3483 }
3484
3485 if (self.base.isRelocatable()) {
3486 {
3487 self.debug_str_sect_index = try self.addSection("__DWARF", "__debug_str", .{
3488 .flags = macho.S_ATTR_DEBUG,
3489 });
3490 try allocSect(self, self.debug_str_sect_index.?, 200);
3491 }
3492
3493 {
3494 self.debug_info_sect_index = try self.addSection("__DWARF", "__debug_info", .{
3495 .flags = macho.S_ATTR_DEBUG,
3496 });
3497 try allocSect(self, self.debug_info_sect_index.?, 200);
3498 }
3499
3500 {
3501 self.debug_abbrev_sect_index = try self.addSection("__DWARF", "__debug_abbrev", .{
3502 .flags = macho.S_ATTR_DEBUG,
3503 });
3504 try allocSect(self, self.debug_abbrev_sect_index.?, 128);
3505 }
3506
3507 {
3508 self.debug_aranges_sect_index = try self.addSection("__DWARF", "__debug_aranges", .{
3509 .alignment = 4,
3510 .flags = macho.S_ATTR_DEBUG,
3511 });
3512 try allocSect(self, self.debug_aranges_sect_index.?, 160);
3513 }
3514
3515 {
3516 self.debug_line_sect_index = try self.addSection("__DWARF", "__debug_line", .{
3517 .flags = macho.S_ATTR_DEBUG,
3518 });
3519 try allocSect(self, self.debug_line_sect_index.?, 250);
3520 }
3521 }
3465}3522}
34663523
3467pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {3524pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
...@@ -3549,6 +3606,22 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void...@@ -3549,6 +3606,22 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void
3549 sect.size = needed_size;3606 sect.size = needed_size;
3550}3607}
35513608
3609pub fn markDirty(self: *MachO, sect_index: u8) void {
3610 if (self.getZigObject()) |zo| {
3611 if (self.debug_info_sect_index.? == sect_index) {
3612 zo.debug_info_header_dirty = true;
3613 } else if (self.debug_line_sect_index.? == sect_index) {
3614 zo.debug_line_header_dirty = true;
3615 } else if (self.debug_abbrev_sect_index.? == sect_index) {
3616 zo.debug_abbrev_dirty = true;
3617 } else if (self.debug_str_sect_index.? == sect_index) {
3618 zo.debug_strtab_dirty = true;
3619 } else if (self.debug_aranges_sect_index.? == sect_index) {
3620 zo.debug_aranges_dirty = true;
3621 }
3622 }
3623}
3624
3552pub fn getTarget(self: MachO) std.Target {3625pub fn getTarget(self: MachO) std.Target {
3553 return self.base.comp.root_mod.resolved_target.result;3626 return self.base.comp.root_mod.resolved_target.result;
3554}3627}
...@@ -3624,6 +3697,21 @@ pub fn isZigSection(self: MachO, sect_id: u8) bool {...@@ -3624,6 +3697,21 @@ pub fn isZigSection(self: MachO, sect_id: u8) bool {
3624 return false;3697 return false;
3625}3698}
36263699
3700pub fn isDebugSection(self: MachO, sect_id: u8) bool {
3701 inline for (&[_]?u8{
3702 self.debug_info_sect_index,
3703 self.debug_abbrev_sect_index,
3704 self.debug_str_sect_index,
3705 self.debug_aranges_sect_index,
3706 self.debug_line_sect_index,
3707 }) |maybe_index| {
3708 if (maybe_index) |index| {
3709 if (index == sect_id) return true;
3710 }
3711 }
3712 return false;
3713}
3714
3627pub fn addSegment(self: *MachO, name: []const u8, opts: struct {3715pub fn addSegment(self: *MachO, name: []const u8, opts: struct {
3628 vmaddr: u64 = 0,3716 vmaddr: u64 = 0,
3629 vmsize: u64 = 0,3717 vmsize: u64 = 0,
src/link/MachO/ZigObject.zig+7-1
...@@ -471,7 +471,13 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO) !void {...@@ -471,7 +471,13 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO) !void {
471 self.debug_strtab_dirty = false;471 self.debug_strtab_dirty = false;
472 }472 }
473 } else {473 } else {
474 // TODO: relocatable474 const sect_index = macho_file.debug_str_sect_index.?;
475 if (self.debug_strtab_dirty or dw.strtab.buffer.items.len != macho_file.sections.items(.header)[sect_index].size) {
476 const needed_size = @as(u32, @intCast(dw.strtab.buffer.items.len));
477 try macho_file.growSection(sect_index, needed_size);
478 try macho_file.base.file.?.pwriteAll(dw.strtab.buffer.items, macho_file.sections.items(.header)[sect_index].offset);
479 self.debug_strtab_dirty = false;
480 }
475 }481 }
476 }482 }
477483