| ... | ... | @@ -76,12 +76,14 @@ pub fn main(init: std.process.Init) !void { |
| 76 | 76 | return Io.File.stdout().writeStreamingAll(io, usage); |
| 77 | 77 | } else if (mem.eql(u8, arg, "--all-headers")) { |
| 78 | 78 | opt_file_headers = true; |
| 79 | opt_linker_member = .second_linker; |
| 79 | 80 | opt_member_headers = true; |
| 80 | 81 | opt_section_headers = true; |
| 81 | 82 | opt_symbols = true; |
| 82 | 83 | opt_relocs = true; |
| 83 | 84 | } else if (mem.eql(u8, arg, "--exports")) { |
| 84 | 85 | opt_exports = true; |
| 86 | opt_linker_member = .second_linker; |
| 85 | 87 | } else if (mem.eql(u8, arg, "--file-headers")) { |
| 86 | 88 | opt_file_headers = true; |
| 87 | 89 | } else if (mem.eql(u8, arg, "--imports")) { |
| ... | ... | @@ -551,12 +553,21 @@ const coff = struct { |
| 551 | 553 | const sig = std.mem.readInt(u16, member_sig[2..4], .little); |
| 552 | 554 | |
| 553 | 555 | const is_imp_lib = machine == std.coff.IMAGE.FILE.MACHINE.UNKNOWN and sig == 0xffff; |
| 554 | | if (d.opts.member_headers or (d.opts.exports and is_imp_lib)) { |
| 556 | if (d.opts.member_headers) |
| 555 | 557 | try dumpArchiveHeader(d, &header, member.offset); |
| 556 | | if (is_imp_lib) { |
| 557 | | try w.writeAll("\nImport header:\n"); |
| 558 | 558 | |
| 559 | if (d.opts.member_headers or (d.opts.exports and is_imp_lib)) { |
| 560 | if (is_imp_lib) { |
| 559 | 561 | const imp_header = try r.takeStruct(std.coff.ImportHeader, .little); |
| 562 | const sym_name = (try r.takeDelimiter(0)).?; |
| 563 | const imp_dll = (try r.takeDelimiter(0)).?; |
| 564 | |
| 565 | if (!filterMatches(d.opts.symbol_filters, sym_name)) |
| 566 | continue; |
| 567 | |
| 568 | if (d.element(.@"header-name")) |
| 569 | try w.writeAll("\nImport header:\n"); |
| 570 | |
| 560 | 571 | try dumpHeader(d, std.coff.ImportHeader, &imp_header, struct { |
| 561 | 572 | pub fn sig1(_: *const DumpContext, _: *const std.coff.ImportHeader) !void {} |
| 562 | 573 | pub fn sig2(_: *const DumpContext, _: *const std.coff.ImportHeader) !void {} |
| ... | ... | @@ -569,8 +580,6 @@ const coff = struct { |
| 569 | 580 | } |
| 570 | 581 | }); |
| 571 | 582 | |
| 572 | | const sym_name = (try r.takeDelimiter(0)).?; |
| 573 | | const imp_dll = (try r.takeDelimiter(0)).?; |
| 574 | 583 | const imp_name = imp_name: switch (imp_header.types.name_type) { |
| 575 | 584 | .NAME_NOPREFIX, |
| 576 | 585 | .NAME_UNDECORATE, |
| ... | ... | @@ -847,7 +856,7 @@ const coff = struct { |
| 847 | 856 | |
| 848 | 857 | try dumpFlags(w, "{s}", std.coff.SectionHeader.Flags, &section.header.flags, 1); |
| 849 | 858 | if (section.name.len > 8) |
| 850 | | try w.print("| {s}", .{section.name}); |
| 859 | try w.print("\n | {s}", .{section.name}); |
| 851 | 860 | |
| 852 | 861 | try w.writeByte('\n'); |
| 853 | 862 | } |
| ... | ... | @@ -861,6 +870,10 @@ const coff = struct { |
| 861 | 870 | section_number: std.coff.SectionNumber, |
| 862 | 871 | }) = .empty; |
| 863 | 872 | defer symbols.deinit(gpa); |
| 873 | |
| 874 | var name_arena: std.heap.ArenaAllocator = .init(gpa); |
| 875 | defer name_arena.deinit(); |
| 876 | |
| 864 | 877 | if (d.opts.relocs) |
| 865 | 878 | try symbols.ensureUnusedCapacity(gpa, header.number_of_symbols); |
| 866 | 879 | |
| ... | ... | @@ -893,7 +906,7 @@ const coff = struct { |
| 893 | 906 | &.{}; |
| 894 | 907 | defer symbol_i += symbol.number_of_aux_symbols + 1; |
| 895 | 908 | |
| 896 | | const name = std.mem.sliceTo(if (std.mem.eql(u8, symbol.name[0..4], "\x00\x00\x00\x00")) name: { |
| 909 | const name = if (std.mem.eql(u8, symbol.name[0..4], "\x00\x00\x00\x00")) name: { |
| 897 | 910 | const index = std.mem.readInt(u32, symbol.name[4..], .little); |
| 898 | 911 | if (index >= string_table.len) |
| 899 | 912 | return d.failParse("invalid name offset for symbol {x} ({x} >= {x})", .{ |
| ... | ... | @@ -901,8 +914,8 @@ const coff = struct { |
| 901 | 914 | index, |
| 902 | 915 | string_table.len, |
| 903 | 916 | }); |
| 904 | | break :name string_table[index..]; |
| 905 | | } else &symbol.name, 0); |
| 917 | break :name std.mem.sliceTo(string_table[index..], 0); |
| 918 | } else try name_arena.allocator().dupe(u8, std.mem.sliceTo(&symbol.name, 0)); |
| 906 | 919 | |
| 907 | 920 | if (d.opts.relocs) |
| 908 | 921 | symbols.appendNTimesAssumeCapacity(.{ |
| ... | ... | @@ -1152,8 +1165,17 @@ const coff = struct { |
| 1152 | 1165 | } else &.{}; |
| 1153 | 1166 | defer gpa.free(rva_index); |
| 1154 | 1167 | |
| 1155 | | if (d.opts.exports) { |
| 1156 | | if (try seekToDataDirectory(d, rva_index, sections.items, image_info.?.data_dirs, .EXPORT)) |section_index| { |
| 1168 | if (d.opts.exports) exports: { |
| 1169 | if (try seekToDataDirectory( |
| 1170 | d, |
| 1171 | rva_index, |
| 1172 | sections.items, |
| 1173 | (image_info orelse { |
| 1174 | try w.writeAll("COFF objects do not contain an export data directory"); |
| 1175 | break :exports; |
| 1176 | }).data_dirs, |
| 1177 | .EXPORT, |
| 1178 | )) |section_index| { |
| 1157 | 1179 | const export_dir = r.takeStruct(std.coff.ExportDirectoryTable, .little) catch |err| |
| 1158 | 1180 | return d.failParse("unable to read export directory: {t}", .{err}); |
| 1159 | 1181 | |
| ... | ... | @@ -1239,12 +1261,15 @@ const coff = struct { |
| 1239 | 1261 | } |
| 1240 | 1262 | } |
| 1241 | 1263 | |
| 1242 | | if (d.opts.imports) { |
| 1264 | if (d.opts.imports) imports: { |
| 1243 | 1265 | if (try seekToDataDirectory( |
| 1244 | 1266 | d, |
| 1245 | 1267 | rva_index, |
| 1246 | 1268 | sections.items, |
| 1247 | | image_info.?.data_dirs, |
| 1269 | (image_info orelse { |
| 1270 | try w.writeAll("COFF objects do not contain an import data directory"); |
| 1271 | break :imports; |
| 1272 | }).data_dirs, |
| 1248 | 1273 | .IMPORT, |
| 1249 | 1274 | )) |_| { |
| 1250 | 1275 | const Entry = std.coff.ImportDirectoryEntry; |
| ... | ... | @@ -1374,12 +1399,15 @@ const coff = struct { |
| 1374 | 1399 | } |
| 1375 | 1400 | } |
| 1376 | 1401 | |
| 1377 | | if (d.opts.tls) { |
| 1402 | if (d.opts.tls) tls: { |
| 1378 | 1403 | if (try seekToDataDirectory( |
| 1379 | 1404 | d, |
| 1380 | 1405 | rva_index, |
| 1381 | 1406 | sections.items, |
| 1382 | | image_info.?.data_dirs, |
| 1407 | (image_info orelse { |
| 1408 | try w.writeAll("COFF objects do not contain a TLS data directory"); |
| 1409 | break :tls; |
| 1410 | }).data_dirs, |
| 1383 | 1411 | .TLS, |
| 1384 | 1412 | )) |_| { |
| 1385 | 1413 | switch (image_info.?.magic) { |
| ... | ... | @@ -1579,7 +1607,8 @@ const coff = struct { |
| 1579 | 1607 | } |
| 1580 | 1608 | |
| 1581 | 1609 | fn dumpArchiveHeader(d: *const DumpContext, header: *const ArchiveHeader, pos: u32) !void { |
| 1582 | | try d.w.print("Archive member at offset 0x{x}: '{s}'\n", .{ pos, header.name }); |
| 1610 | if (d.element(.@"header-name")) |
| 1611 | try d.w.print("Archive member at offset 0x{x}: '{s}'\n", .{ pos, header.name }); |
| 1583 | 1612 | try dumpHeader(d, ArchiveHeader, header, struct { |
| 1584 | 1613 | pub fn name(_: *const DumpContext, _: *const ArchiveHeader) !void {} |
| 1585 | 1614 | pub fn file_mode(id: *const DumpContext, h: *const ArchiveHeader) !void { |
| ... | ... | @@ -1595,7 +1624,8 @@ const coff = struct { |
| 1595 | 1624 | std.mem.endsWith(u8, name, "_address") or |
| 1596 | 1625 | std.mem.startsWith(u8, name, "pointer_")) |
| 1597 | 1626 | return .va; |
| 1598 | | if (std.mem.startsWith(u8, name, "number_")) |
| 1627 | if (std.mem.startsWith(u8, name, "number_") or |
| 1628 | std.mem.startsWith(u8, name, "size")) |
| 1599 | 1629 | return .size; |
| 1600 | 1630 | return null; |
| 1601 | 1631 | } |
| ... | ... | @@ -1658,8 +1688,8 @@ const usage = |
| 1658 | 1688 | \\ |
| 1659 | 1689 | \\Options: |
| 1660 | 1690 | \\ -h, --help Print this help and exit |
| 1661 | | \\ --all-headers Alias for --file-headers --member-headers --section-headers --relocs --symbols |
| 1662 | | \\ --exports Display exported symbols |
| 1691 | \\ --all-headers Alias for --file-headers --linker-member=2 --member-headers --section-headers --relocs --symbols |
| 1692 | \\ --exports Display exported symbols. In the case of COFF import libraries, display import headers. |
| 1663 | 1693 | \\ --file-headers Display file-format specific headers |
| 1664 | 1694 | \\ --imports Display imported symbols |
| 1665 | 1695 | \\ --linker-member[=1|2|longnames] (Coff) Display contents of the specified archive linker member (default 2) |