| ... | @@ -535,10 +535,10 @@ const coff = struct { | ... | @@ -535,10 +535,10 @@ const coff = struct { |
| 535 | opts.imports or | 535 | opts.imports or |
| 536 | opts.tls; | 536 | opts.tls; |
| 537 | | 537 | |
| 538 | const data_dirs = if (header.size_of_optional_header > 0) data_dirs: { | 538 | const data_dirs, const magic = if (header.size_of_optional_header > 0) optional_header: { |
| 539 | if (!opts.file_headers and !needs_data_dirs) { | 539 | if (!opts.file_headers and !needs_data_dirs) { |
| 540 | try fr.seekBy(header.size_of_optional_header); | 540 | try fr.seekBy(header.size_of_optional_header); |
| 541 | break :data_dirs &.{}; | 541 | break :optional_header .{ &.{}, null }; |
| 542 | } | 542 | } |
| 543 | | 543 | |
| 544 | if (opts.file_headers) try w.writeAll("COFF Optional Header:\n"); | 544 | if (opts.file_headers) try w.writeAll("COFF Optional Header:\n"); |
| ... | @@ -614,10 +614,10 @@ const coff = struct { | ... | @@ -614,10 +614,10 @@ const coff = struct { |
| 614 | } | 614 | } |
| 615 | if (opts.file_headers) try w.writeByte('\n'); | 615 | if (opts.file_headers) try w.writeByte('\n'); |
| 616 | | 616 | |
| 617 | break :data_dirs known_dirs[0..@min(known_dirs.len, num_directory_entries)]; | 617 | break :optional_header .{ known_dirs[0..@min(known_dirs.len, num_directory_entries)], magic }; |
| 618 | } else if (is_image) { | 618 | } else if (is_image) { |
| 619 | return failParse(opts, "image did not contain an optional header", .{}); | 619 | return failParse(opts, "image did not contain an optional header", .{}); |
| 620 | } else &.{}; | 620 | } else .{ &.{}, null }; |
| 621 | | 621 | |
| 622 | // Section names in images don't use the string table, as they must fit inline in the header | 622 | // Section names in images don't use the string table, as they must fit inline in the header |
| 623 | const load_string_table = (opts.strings or !is_image) and header.pointer_to_symbol_table > 0; | 623 | const load_string_table = (opts.strings or !is_image) and header.pointer_to_symbol_table > 0; |
| ... | @@ -1098,7 +1098,134 @@ const coff = struct { | ... | @@ -1098,7 +1098,134 @@ const coff = struct { |
| 1098 | | 1098 | |
| 1099 | if (opts.imports) { | 1099 | if (opts.imports) { |
| 1100 | if (try seekToDataDirectory(opts, fr, w, rva_index, sections.items, data_dirs, .IMPORT)) |_| { | 1100 | if (try seekToDataDirectory(opts, fr, w, rva_index, sections.items, data_dirs, .IMPORT)) |_| { |
| 1101 | // TODO | 1101 | const Entry = std.coff.ImportDirectoryEntry; |
| | 1102 | var directory_entries: std.ArrayList(Entry) = .empty; |
| | 1103 | defer directory_entries.deinit(gpa); |
| | 1104 | while (true) { |
| | 1105 | const entry = r.takeStruct(Entry, .little) catch |err| |
| | 1106 | return failParse( |
| | 1107 | opts, |
| | 1108 | "unable to read import directory entry {x}: {t}", |
| | 1109 | .{ directory_entries.items.len, err }, |
| | 1110 | ); |
| | 1111 | |
| | 1112 | if (std.mem.allEqual(u8, std.mem.asBytes(&entry), 0)) break; |
| | 1113 | (try directory_entries.addOne(gpa)).* = entry; |
| | 1114 | } |
| | 1115 | |
| | 1116 | for (directory_entries.items) |entry| { |
| | 1117 | const name_section = sectionContainingRva(rva_index, sections.items, entry.name_rva) orelse |
| | 1118 | return failParse( |
| | 1119 | opts, |
| | 1120 | "import directory entry name rva 0x{x} was not found in any section", |
| | 1121 | .{entry.name_rva}, |
| | 1122 | ); |
| | 1123 | |
| | 1124 | const name_loc = sections.items[name_section].rvaFileOffset(entry.name_rva) catch unreachable; |
| | 1125 | fr.seekTo(name_loc) catch |err| |
| | 1126 | return failParse( |
| | 1127 | opts, |
| | 1128 | "unable to seek to import directory entry name at 0x{x}: {t}", |
| | 1129 | .{ name_loc, err }, |
| | 1130 | ); |
| | 1131 | |
| | 1132 | const dll_name = (try r.takeDelimiter(0)).?; |
| | 1133 | |
| | 1134 | try w.print("Import table entry for {s}:\n", .{dll_name}); |
| | 1135 | try dumpHeader(w, Entry, &entry, struct {}); |
| | 1136 | |
| | 1137 | try w.print( |
| | 1138 | \\ |
| | 1139 | \\ Ord Hint Name |
| | 1140 | \\ |
| | 1141 | , .{}); |
| | 1142 | |
| | 1143 | const ilt_section = sectionContainingRva( |
| | 1144 | rva_index, |
| | 1145 | sections.items, |
| | 1146 | entry.import_lookup_table_rva, |
| | 1147 | ) orelse |
| | 1148 | return failParse( |
| | 1149 | opts, |
| | 1150 | "import directory entry ilt rva 0x{x} was not found in any section", |
| | 1151 | .{entry.import_lookup_table_rva}, |
| | 1152 | ); |
| | 1153 | |
| | 1154 | const ilt_loc = sections.items[ilt_section].rvaFileOffset( |
| | 1155 | entry.import_lookup_table_rva, |
| | 1156 | ) catch unreachable; |
| | 1157 | fr.seekTo(ilt_loc) catch |err| |
| | 1158 | return failParse( |
| | 1159 | opts, |
| | 1160 | "unable to seek to import directory ilt at 0x{x}: {t}", |
| | 1161 | .{ ilt_loc, err }, |
| | 1162 | ); |
| | 1163 | |
| | 1164 | switch (magic.?) { |
| | 1165 | _ => try w.writeAll("(unknown magic)"), |
| | 1166 | inline else => |m| { |
| | 1167 | const TableEntry = std.coff.ImportLookupTableEntry(m); |
| | 1168 | const null_entry: TableEntry = @bitCast(@as(@typeInfo(TableEntry).@"struct".backing_integer.?, 0)); |
| | 1169 | |
| | 1170 | var ilt_entries: std.ArrayList(TableEntry) = .empty; |
| | 1171 | defer ilt_entries.deinit(gpa); |
| | 1172 | while (true) { |
| | 1173 | const table_entry = r.takeStruct(TableEntry, .little) catch |err| |
| | 1174 | return failParse( |
| | 1175 | opts, |
| | 1176 | "unable to read ilt entry {s}:{x}: {t}", |
| | 1177 | .{ dll_name, ilt_entries.items.len, err }, |
| | 1178 | ); |
| | 1179 | if (table_entry == null_entry) break; |
| | 1180 | (try ilt_entries.addOne(gpa)).* = table_entry; |
| | 1181 | } |
| | 1182 | |
| | 1183 | for (ilt_entries.items, 0..) |ilt_entry, ilt_entry_i| { |
| | 1184 | if (ilt_entry.is_ordinal) { |
| | 1185 | try w.print("{x: >4}", .{ilt_entry.payload.ordinal.ordinal}); |
| | 1186 | } else { |
| | 1187 | const hint_section = sectionContainingRva( |
| | 1188 | rva_index, |
| | 1189 | sections.items, |
| | 1190 | ilt_entry.payload.hint_name_rva, |
| | 1191 | ) orelse |
| | 1192 | return failParse( |
| | 1193 | opts, |
| | 1194 | "import directory ilt entry 0x{x}'s hint rva 0x{x} was not found in any section", |
| | 1195 | .{ ilt_entry_i, ilt_entry.payload.hint_name_rva }, |
| | 1196 | ); |
| | 1197 | |
| | 1198 | const hint_loc = sections.items[hint_section].rvaFileOffset( |
| | 1199 | ilt_entry.payload.hint_name_rva, |
| | 1200 | ) catch unreachable; |
| | 1201 | fr.seekTo(hint_loc) catch |err| |
| | 1202 | return failParse( |
| | 1203 | opts, |
| | 1204 | "unable to seek to ilt entry 0x{x}'s hint at 0x{x}: {t}", |
| | 1205 | .{ ilt_entry_i, hint_loc, err }, |
| | 1206 | ); |
| | 1207 | |
| | 1208 | const hint = r.takeInt(u16, .little) catch |err| |
| | 1209 | return failParse( |
| | 1210 | opts, |
| | 1211 | "unable to read import directory ilt entry 0x{x}'s hint: {t}", |
| | 1212 | .{ ilt_entry_i, err }, |
| | 1213 | ); |
| | 1214 | |
| | 1215 | const name = r.takeDelimiter(0) catch |err| |
| | 1216 | return failParse( |
| | 1217 | opts, |
| | 1218 | "unable to read import directory ilt entry 0x{x}'s name: {t}", |
| | 1219 | .{ ilt_entry_i, err }, |
| | 1220 | ); |
| | 1221 | |
| | 1222 | try w.print(" {x: >4} | {s}\n", .{ hint, name.? }); |
| | 1223 | } |
| | 1224 | } |
| | 1225 | try w.writeByte('\n'); |
| | 1226 | }, |
| | 1227 | } |
| | 1228 | } |
| 1102 | } | 1229 | } |
| 1103 | } | 1230 | } |
| 1104 | | 1231 | |