| ... | ... | @@ -535,10 +535,10 @@ const coff = struct { |
| 535 | 535 | opts.imports or |
| 536 | 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 | 539 | if (!opts.file_headers and !needs_data_dirs) { |
| 540 | 540 | try fr.seekBy(header.size_of_optional_header); |
| 541 | | break :data_dirs &.{}; |
| 541 | break :optional_header .{ &.{}, null }; |
| 542 | 542 | } |
| 543 | 543 | |
| 544 | 544 | if (opts.file_headers) try w.writeAll("COFF Optional Header:\n"); |
| ... | ... | @@ -614,10 +614,10 @@ const coff = struct { |
| 614 | 614 | } |
| 615 | 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 | 618 | } else if (is_image) { |
| 619 | 619 | return failParse(opts, "image did not contain an optional header", .{}); |
| 620 | | } else &.{}; |
| 620 | } else .{ &.{}, null }; |
| 621 | 621 | |
| 622 | 622 | // Section names in images don't use the string table, as they must fit inline in the header |
| 623 | 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 | 1098 | |
| 1099 | 1099 | if (opts.imports) { |
| 1100 | 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 | |