I discovered why the icons aren’t showing up. It appears that previous versions of WP ignored the _wp_attached_file meta key, where the newest version requires it for looking up the attachment data. The attachments that weren’t displaying were missing this key.
Below is PHP code for descending through the post database, verifying the presence of this key (and file) and updating accordingly. I’ll leave it to you to add it to your theme (I added it to a submenu for database tools). After processing, it will display the number of updates, skipped posts and errors.
// descend through the database
$updated = 0;
$skipped = 0;
$error = 0;
$upload_dir = wp_upload_dir();
$sql = sprintf("select * from %s where post_type = 'attachment'", $wpdb->posts);
$all_attachments = $wpdb->get_results($sql);
foreach ($all_attachments as $attachment) {
// get the meta value
$meta = get_post_meta($attachment->ID, "_wp_attachment_metadata", true);
$file = $meta['file'];
// verify that the file exists
$file_path = $upload_dir['basedir'] . '/' . $file;
if (!file_exists($file_path)) {
$error++;
}
else {
// add the meta value, which returns false if it already exists
$adding_meta = add_post_meta($attachment->ID, '_wp_attached_file', $file, true);
if ($adding_meta)
$updated++;
else
$skipped++;
}
}
echo '<div id="message" class="updated"><p>' . sprintf("%d attachments were updated, %d were skipped and %d had errors.", $updated, $skipped, $error) . '</p></div>';