| ... | @@ -76,12 +76,14 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -76,12 +76,14 @@ pub fn main(init: std.process.Init) !void { |
| 76 | return Io.File.stdout().writeStreamingAll(io, usage); | 76 | return Io.File.stdout().writeStreamingAll(io, usage); |
| 77 | } else if (mem.eql(u8, arg, "--all-headers")) { | 77 | } else if (mem.eql(u8, arg, "--all-headers")) { |
| 78 | opt_file_headers = true; | 78 | opt_file_headers = true; |
| | 79 | opt_linker_member = .second_linker; |
| 79 | opt_member_headers = true; | 80 | opt_member_headers = true; |
| 80 | opt_section_headers = true; | 81 | opt_section_headers = true; |
| 81 | opt_symbols = true; | 82 | opt_symbols = true; |
| 82 | opt_relocs = true; | 83 | opt_relocs = true; |
| 83 | } else if (mem.eql(u8, arg, "--exports")) { | 84 | } else if (mem.eql(u8, arg, "--exports")) { |
| 84 | opt_exports = true; | 85 | opt_exports = true; |
| | 86 | opt_linker_member = .second_linker; |
| 85 | } else if (mem.eql(u8, arg, "--file-headers")) { | 87 | } else if (mem.eql(u8, arg, "--file-headers")) { |
| 86 | opt_file_headers = true; | 88 | opt_file_headers = true; |
| 87 | } else if (mem.eql(u8, arg, "--imports")) { | 89 | } else if (mem.eql(u8, arg, "--imports")) { |
| ... | @@ -551,12 +553,21 @@ const coff = struct { | ... | @@ -551,12 +553,21 @@ const coff = struct { |
| 551 | const sig = std.mem.readInt(u16, member_sig[2..4], .little); | 553 | const sig = std.mem.readInt(u16, member_sig[2..4], .little); |
| 552 | | 554 | |
| 553 | const is_imp_lib = machine == std.coff.IMAGE.FILE.MACHINE.UNKNOWN and sig == 0xffff; | 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 | try dumpArchiveHeader(d, &header, member.offset); | 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 | const imp_header = try r.takeStruct(std.coff.ImportHeader, .little); | 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 | try dumpHeader(d, std.coff.ImportHeader, &imp_header, struct { | 571 | try dumpHeader(d, std.coff.ImportHeader, &imp_header, struct { |
| 561 | pub fn sig1(_: *const DumpContext, _: *const std.coff.ImportHeader) !void {} | 572 | pub fn sig1(_: *const DumpContext, _: *const std.coff.ImportHeader) !void {} |
| 562 | pub fn sig2(_: *const DumpContext, _: *const std.coff.ImportHeader) !void {} | 573 | pub fn sig2(_: *const DumpContext, _: *const std.coff.ImportHeader) !void {} |
| ... | @@ -569,8 +580,6 @@ const coff = struct { | ... | @@ -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 | const imp_name = imp_name: switch (imp_header.types.name_type) { | 583 | const imp_name = imp_name: switch (imp_header.types.name_type) { |
| 575 | .NAME_NOPREFIX, | 584 | .NAME_NOPREFIX, |
| 576 | .NAME_UNDECORATE, | 585 | .NAME_UNDECORATE, |
| ... | @@ -847,7 +856,7 @@ const coff = struct { | ... | @@ -847,7 +856,7 @@ const coff = struct { |
| 847 | | 856 | |
| 848 | try dumpFlags(w, "{s}", std.coff.SectionHeader.Flags, &section.header.flags, 1); | 857 | try dumpFlags(w, "{s}", std.coff.SectionHeader.Flags, &section.header.flags, 1); |
| 849 | if (section.name.len > 8) | 858 | if (section.name.len > 8) |
| 850 | try w.print("| {s}", .{section.name}); | 859 | try w.print("\n | {s}", .{section.name}); |
| 851 | | 860 | |
| 852 | try w.writeByte('\n'); | 861 | try w.writeByte('\n'); |
| 853 | } | 862 | } |
| ... | @@ -861,6 +870,10 @@ const coff = struct { | ... | @@ -861,6 +870,10 @@ const coff = struct { |
| 861 | section_number: std.coff.SectionNumber, | 870 | section_number: std.coff.SectionNumber, |
| 862 | }) = .empty; | 871 | }) = .empty; |
| 863 | defer symbols.deinit(gpa); | 872 | defer symbols.deinit(gpa); |
| | 873 | |
| | 874 | var name_arena: std.heap.ArenaAllocator = .init(gpa); |
| | 875 | defer name_arena.deinit(); |
| | 876 | |
| 864 | if (d.opts.relocs) | 877 | if (d.opts.relocs) |
| 865 | try symbols.ensureUnusedCapacity(gpa, header.number_of_symbols); | 878 | try symbols.ensureUnusedCapacity(gpa, header.number_of_symbols); |
| 866 | | 879 | |
| ... | @@ -893,7 +906,7 @@ const coff = struct { | ... | @@ -893,7 +906,7 @@ const coff = struct { |
| 893 | &.{}; | 906 | &.{}; |
| 894 | defer symbol_i += symbol.number_of_aux_symbols + 1; | 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 | const index = std.mem.readInt(u32, symbol.name[4..], .little); | 910 | const index = std.mem.readInt(u32, symbol.name[4..], .little); |
| 898 | if (index >= string_table.len) | 911 | if (index >= string_table.len) |
| 899 | return d.failParse("invalid name offset for symbol {x} ({x} >= {x})", .{ | 912 | return d.failParse("invalid name offset for symbol {x} ({x} >= {x})", .{ |
| ... | @@ -901,8 +914,8 @@ const coff = struct { | ... | @@ -901,8 +914,8 @@ const coff = struct { |
| 901 | index, | 914 | index, |
| 902 | string_table.len, | 915 | string_table.len, |
| 903 | }); | 916 | }); |
| 904 | break :name string_table[index..]; | 917 | break :name std.mem.sliceTo(string_table[index..], 0); |
| 905 | } else &symbol.name, 0); | 918 | } else try name_arena.allocator().dupe(u8, std.mem.sliceTo(&symbol.name, 0)); |
| 906 | | 919 | |
| 907 | if (d.opts.relocs) | 920 | if (d.opts.relocs) |
| 908 | symbols.appendNTimesAssumeCapacity(.{ | 921 | symbols.appendNTimesAssumeCapacity(.{ |
| ... | @@ -1152,8 +1165,17 @@ const coff = struct { | ... | @@ -1152,8 +1165,17 @@ const coff = struct { |
| 1152 | } else &.{}; | 1165 | } else &.{}; |
| 1153 | defer gpa.free(rva_index); | 1166 | defer gpa.free(rva_index); |
| 1154 | | 1167 | |
| 1155 | if (d.opts.exports) { | 1168 | if (d.opts.exports) exports: { |
| 1156 | if (try seekToDataDirectory(d, rva_index, sections.items, image_info.?.data_dirs, .EXPORT)) |section_index| { | 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 | const export_dir = r.takeStruct(std.coff.ExportDirectoryTable, .little) catch |err| | 1179 | const export_dir = r.takeStruct(std.coff.ExportDirectoryTable, .little) catch |err| |
| 1158 | return d.failParse("unable to read export directory: {t}", .{err}); | 1180 | return d.failParse("unable to read export directory: {t}", .{err}); |
| 1159 | | 1181 | |
| ... | @@ -1239,12 +1261,15 @@ const coff = struct { | ... | @@ -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 | if (try seekToDataDirectory( | 1265 | if (try seekToDataDirectory( |
| 1244 | d, | 1266 | d, |
| 1245 | rva_index, | 1267 | rva_index, |
| 1246 | sections.items, | 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 | .IMPORT, | 1273 | .IMPORT, |
| 1249 | )) |_| { | 1274 | )) |_| { |
| 1250 | const Entry = std.coff.ImportDirectoryEntry; | 1275 | const Entry = std.coff.ImportDirectoryEntry; |
| ... | @@ -1374,12 +1399,15 @@ const coff = struct { | ... | @@ -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 | if (try seekToDataDirectory( | 1403 | if (try seekToDataDirectory( |
| 1379 | d, | 1404 | d, |
| 1380 | rva_index, | 1405 | rva_index, |
| 1381 | sections.items, | 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 | .TLS, | 1411 | .TLS, |
| 1384 | )) |_| { | 1412 | )) |_| { |
| 1385 | switch (image_info.?.magic) { | 1413 | switch (image_info.?.magic) { |
| ... | @@ -1579,7 +1607,8 @@ const coff = struct { | ... | @@ -1579,7 +1607,8 @@ const coff = struct { |
| 1579 | } | 1607 | } |
| 1580 | | 1608 | |
| 1581 | fn dumpArchiveHeader(d: *const DumpContext, header: *const ArchiveHeader, pos: u32) !void { | 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 | try dumpHeader(d, ArchiveHeader, header, struct { | 1612 | try dumpHeader(d, ArchiveHeader, header, struct { |
| 1584 | pub fn name(_: *const DumpContext, _: *const ArchiveHeader) !void {} | 1613 | pub fn name(_: *const DumpContext, _: *const ArchiveHeader) !void {} |
| 1585 | pub fn file_mode(id: *const DumpContext, h: *const ArchiveHeader) !void { | 1614 | pub fn file_mode(id: *const DumpContext, h: *const ArchiveHeader) !void { |
| ... | @@ -1595,7 +1624,8 @@ const coff = struct { | ... | @@ -1595,7 +1624,8 @@ const coff = struct { |
| 1595 | std.mem.endsWith(u8, name, "_address") or | 1624 | std.mem.endsWith(u8, name, "_address") or |
| 1596 | std.mem.startsWith(u8, name, "pointer_")) | 1625 | std.mem.startsWith(u8, name, "pointer_")) |
| 1597 | return .va; | 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 | return .size; | 1629 | return .size; |
| 1600 | return null; | 1630 | return null; |
| 1601 | } | 1631 | } |
| ... | @@ -1658,8 +1688,8 @@ const usage = | ... | @@ -1658,8 +1688,8 @@ const usage = |
| 1658 | \\ | 1688 | \\ |
| 1659 | \\Options: | 1689 | \\Options: |
| 1660 | \\ -h, --help Print this help and exit | 1690 | \\ -h, --help Print this help and exit |
| 1661 | \\ --all-headers Alias for --file-headers --member-headers --section-headers --relocs --symbols | 1691 | \\ --all-headers Alias for --file-headers --linker-member=2 --member-headers --section-headers --relocs --symbols |
| 1662 | \\ --exports Display exported symbols | 1692 | \\ --exports Display exported symbols. In the case of COFF import libraries, display import headers. |
| 1663 | \\ --file-headers Display file-format specific headers | 1693 | \\ --file-headers Display file-format specific headers |
| 1664 | \\ --imports Display imported symbols | 1694 | \\ --imports Display imported symbols |
| 1665 | \\ --linker-member[=1|2|longnames] (Coff) Display contents of the specified archive linker member (default 2) | 1695 | \\ --linker-member[=1|2|longnames] (Coff) Display contents of the specified archive linker member (default 2) |