diff --git a/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php b/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php
index 3b490f0f19..1649700f4c 100644
--- a/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php
+++ b/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php
@@ -11,7 +11,9 @@
  *   core = {6,7},
  *   type_map = {
  *     "email" = "email"
- *   }
+ *   },
+ *   source_module = "email",
+ *   destination_module = "core"
  * )
  */
 class Email extends FieldPluginBase {
diff --git a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php
index 2e61589fb5..f45e95d2cc 100644
--- a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php
+++ b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php
@@ -10,7 +10,9 @@
  *   type_map = {
  *     "entityreference" = "entity_reference",
  *   },
- *   core = {7}
+ *   core = {7},
+ *   source_module = "entityreference",
+ *   destination_module = "core"
  * )
  */
 class EntityReference extends FieldPluginBase {}
diff --git a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php
index 90803288e4..cf2f4567a8 100644
--- a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php
+++ b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php
@@ -12,7 +12,9 @@
  *     "number_decimal" = "decimal",
  *     "number_float" = "float",
  *   },
- *   core = {7}
+ *   core = {7},
+ *   source_module = "number",
+ *   destination_module = "core"
  * )
  */
 class NumberField extends FieldPluginBase {}
diff --git a/core/modules/datetime/src/Plugin/migrate/field/DateField.php b/core/modules/datetime/src/Plugin/migrate/field/DateField.php
index 0dd56c9acf..c3e611a4d4 100644
--- a/core/modules/datetime/src/Plugin/migrate/field/DateField.php
+++ b/core/modules/datetime/src/Plugin/migrate/field/DateField.php
@@ -14,7 +14,9 @@
  *     "datestamp" =  "timestamp",
  *     "datetime" =  "datetime",
  *   },
- *   core = {6,7}
+ *   core = {6,7},
+ *   source_module = "date",
+ *   destination_module = "datetime"
  * )
  */
 class DateField extends FieldPluginBase {
diff --git a/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php b/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php
index c4e7b4981d..732fd3feea 100644
--- a/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php
+++ b/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php
@@ -16,7 +16,9 @@
  *     "datestamp" =  "timestamp",
  *     "datetime" =  "datetime",
  *   },
- *   core = {6}
+ *   core = {6},
+ *   source_module = "date",
+ *   destination_module = "datetime"
  * )
  *
  * @deprecated in Drupal 8.4.x, to be removed before Drupal 9.0.x. Use
diff --git a/core/modules/field/src/Plugin/migrate/source/d7/Field.php b/core/modules/field/src/Plugin/migrate/source/d7/Field.php
index 9e92619f8e..da9e037328 100644
--- a/core/modules/field/src/Plugin/migrate/source/d7/Field.php
+++ b/core/modules/field/src/Plugin/migrate/source/d7/Field.php
@@ -15,7 +15,7 @@
  *
  * @MigrateSource(
  *   id = "d7_field",
- *   source_module = "field"
+ *   source_module = "field_sql_storage"
  * )
  */
 class Field extends DrupalSqlBase {
diff --git a/core/modules/file/src/Plugin/migrate/cckfield/d6/FileField.php b/core/modules/file/src/Plugin/migrate/cckfield/d6/FileField.php
index 373d1e90b7..8dba3b022a 100644
--- a/core/modules/file/src/Plugin/migrate/cckfield/d6/FileField.php
+++ b/core/modules/file/src/Plugin/migrate/cckfield/d6/FileField.php
@@ -11,7 +11,9 @@
 /**
  * @MigrateCckField(
  *   id = "filefield",
- *   core = {6}
+ *   core = {6},
+ *   source_module = "filefield",
+ *   destination_module = "file"
  * )
  *
  *  @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
diff --git a/core/modules/file/src/Plugin/migrate/cckfield/d7/FileField.php b/core/modules/file/src/Plugin/migrate/cckfield/d7/FileField.php
index 9d184ff86a..002c61f18b 100644
--- a/core/modules/file/src/Plugin/migrate/cckfield/d7/FileField.php
+++ b/core/modules/file/src/Plugin/migrate/cckfield/d7/FileField.php
@@ -11,7 +11,11 @@
 /**
  * @MigrateCckField(
  *   id = "file",
- *   core = {7}
+ *   core = {7},
+ *   source_module = "file",
+ *   destination_module = "file",
+ *   source_module = "text",
+ *   destination_module = "text",
  * )
  *
  * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
diff --git a/core/modules/file/src/Plugin/migrate/cckfield/d7/ImageField.php b/core/modules/file/src/Plugin/migrate/cckfield/d7/ImageField.php
index 45f5b9d239..7a51444109 100644
--- a/core/modules/file/src/Plugin/migrate/cckfield/d7/ImageField.php
+++ b/core/modules/file/src/Plugin/migrate/cckfield/d7/ImageField.php
@@ -10,7 +10,9 @@
 /**
  * @MigrateCckField(
  *   id = "image",
- *   core = {7}
+ *   core = {7},
+ *   source_module = "image",
+ *   destination_module = "file"
  * )
  *
  * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
diff --git a/core/modules/file/src/Plugin/migrate/field/d6/FileField.php b/core/modules/file/src/Plugin/migrate/field/d6/FileField.php
index 930c13b030..87c3bfe7ac 100644
--- a/core/modules/file/src/Plugin/migrate/field/d6/FileField.php
+++ b/core/modules/file/src/Plugin/migrate/field/d6/FileField.php
@@ -9,7 +9,9 @@
 /**
  * @MigrateField(
  *   id = "filefield",
- *   core = {6}
+ *   core = {6},
+ *   source_module = "filefield",
+ *   destination_module = "file"
  * )
  */
 class FileField extends FieldPluginBase {
diff --git a/core/modules/file/src/Plugin/migrate/field/d6/FileField.php b/core/modules/file/src/Plugin/migrate/field/d6/ImageField.php
similarity index 88%
copy from core/modules/file/src/Plugin/migrate/field/d6/FileField.php
copy to core/modules/file/src/Plugin/migrate/field/d6/ImageField.php
index 930c13b030..0a7541fbff 100644
--- a/core/modules/file/src/Plugin/migrate/field/d6/FileField.php
+++ b/core/modules/file/src/Plugin/migrate/field/d6/ImageField.php
@@ -8,11 +8,13 @@
 
 /**
  * @MigrateField(
- *   id = "filefield",
- *   core = {6}
+ *   id = "imagefield",
+ *   core = {6},
+ *   source_module = "imagefield",
+ *   destination_module = "file"
  * )
  */
-class FileField extends FieldPluginBase {
+class ImageField extends FieldPluginBase {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/file/src/Plugin/migrate/field/d7/FileField.php b/core/modules/file/src/Plugin/migrate/field/d7/FileField.php
index 4243d43c42..2d7e7ba387 100644
--- a/core/modules/file/src/Plugin/migrate/field/d7/FileField.php
+++ b/core/modules/file/src/Plugin/migrate/field/d7/FileField.php
@@ -8,7 +8,9 @@
 /**
  * @MigrateField(
  *   id = "file",
- *   core = {7}
+ *   core = {7},
+ *   source_module = "file",
+ *   destination_module = "file"
  * )
  */
 class FileField extends D6FileField {
diff --git a/core/modules/file/src/Plugin/migrate/field/d7/ImageField.php b/core/modules/file/src/Plugin/migrate/field/d7/ImageField.php
index 7783ae2886..fea19c667b 100644
--- a/core/modules/file/src/Plugin/migrate/field/d7/ImageField.php
+++ b/core/modules/file/src/Plugin/migrate/field/d7/ImageField.php
@@ -8,7 +8,9 @@
 /**
  * @MigrateField(
  *   id = "image",
- *   core = {7}
+ *   core = {7},
+ *   source_module = "image",
+ *   destination_module = "file"
  * )
  */
 class ImageField extends FieldPluginBase {
diff --git a/core/modules/link/src/Plugin/migrate/cckfield/LinkField.php b/core/modules/link/src/Plugin/migrate/cckfield/LinkField.php
index 8acf70a998..f902987c67 100644
--- a/core/modules/link/src/Plugin/migrate/cckfield/LinkField.php
+++ b/core/modules/link/src/Plugin/migrate/cckfield/LinkField.php
@@ -13,7 +13,9 @@
  *   core = {6},
  *   type_map = {
  *     "link_field" = "link"
- *   }
+ *   },
+ *   source_module = "link",
+ *   destination_module = "link"
  * )
  *
  * @deprecated in Drupal 8.3.x and will be removed in Drupal 9.0.x. Use
diff --git a/core/modules/link/src/Plugin/migrate/cckfield/d7/LinkField.php b/core/modules/link/src/Plugin/migrate/cckfield/d7/LinkField.php
index 6a7ff8898b..c4f09f25e5 100644
--- a/core/modules/link/src/Plugin/migrate/cckfield/d7/LinkField.php
+++ b/core/modules/link/src/Plugin/migrate/cckfield/d7/LinkField.php
@@ -13,7 +13,9 @@
  *   core = {7},
  *   type_map = {
  *     "link_field" = "link"
- *   }
+ *   },
+ *   source_module = "link",
+ *   destination_module = "link"
  * )
  *
  * This plugin provides the exact same functionality as the Drupal 6 "link"
diff --git a/core/modules/link/src/Plugin/migrate/field/d6/LinkField.php b/core/modules/link/src/Plugin/migrate/field/d6/LinkField.php
index 0d03656ad8..cb69994bc3 100644
--- a/core/modules/link/src/Plugin/migrate/field/d6/LinkField.php
+++ b/core/modules/link/src/Plugin/migrate/field/d6/LinkField.php
@@ -10,8 +10,10 @@
  *   id = "link",
  *   core = {6},
  *   type_map = {
- *     "link_field" = "link"
- *   }
+ *     "link_field" = "link",
+ *   },
+ *   source_module = "link",
+ *   destination_module = "link"
  * )
  */
 class LinkField extends FieldPluginBase {
diff --git a/core/modules/link/src/Plugin/migrate/field/d7/LinkField.php b/core/modules/link/src/Plugin/migrate/field/d7/LinkField.php
index bb71418aba..0dcf4c64c5 100644
--- a/core/modules/link/src/Plugin/migrate/field/d7/LinkField.php
+++ b/core/modules/link/src/Plugin/migrate/field/d7/LinkField.php
@@ -11,7 +11,9 @@
  *   core = {7},
  *   type_map = {
  *     "link_field" = "link"
- *   }
+ *   },
+ *   source_module = "link",
+ *   destination_module = "link"
  * )
  *
  * This plugin provides the exact same functionality as the Drupal 6 "link"
diff --git a/core/modules/migrate/tests/src/Kernel/Plugin/MigrationProvidersExistTest.php b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationProvidersExistTest.php
index 8e166998c4..5133f714f4 100644
--- a/core/modules/migrate/tests/src/Kernel/Plugin/MigrationProvidersExistTest.php
+++ b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationProvidersExistTest.php
@@ -2,8 +2,10 @@
 
 namespace Drupal\Tests\migrate\Kernel\Plugin;
 
+use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
 use Drupal\Component\Render\FormattableMarkup;
 use Drupal\KernelTests\FileSystemModuleDiscoveryDataProviderTrait;
+use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManager;
 use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
 
 /**
@@ -61,4 +63,183 @@ public function testProvidersExist() {
     }
   }
 
+  /**
+   * Tests that modules exist for all field plugins.
+   */
+  public function testFieldProvidersExist() {
+    $expected_mappings = [
+      'userreference' => [
+        'source_module' => 'user_reference',
+        'destination_module' => 'entity_reference',
+      ],
+      'nodereference' => [
+        'source_module' => 'node_reference',
+        'destination_module' => 'entity_reference',
+      ],
+      'optionwidgets' => [
+        'source_module' => 'optionwidgets',
+        'destination_module' => 'options',
+      ],
+      'list' => [
+        'source_module' => 'list',
+        'destination_module' => 'options',
+      ],
+      'options' => [
+        'source_module' => 'options',
+        'destination_module' => 'options',
+      ],
+      'filefield' => [
+        'source_module' => 'filefield',
+        'destination_module' => 'file',
+      ],
+      'imagefield' => [
+        'source_module' => 'imagefield',
+        'destination_module' => 'file',
+      ],
+      'file' => [
+        'source_module' => 'file',
+        'destination_module' => 'file',
+      ],
+      'image' => [
+        'source_module' => 'image',
+        'destination_module' => 'file',
+      ],
+      'phone' => [
+        'source_module' => 'phone',
+        'destination_module' => 'telephone',
+      ],
+      'link' => [
+        'source_module' => 'link',
+        'destination_module' => 'link',
+      ],
+      'link_field' => [
+        'source_module' => 'link',
+        'destination_module' => 'link',
+      ],
+      'd6_text' => [
+        'source_module' => 'text',
+        'destination_module' => 'text',
+      ],
+      'd7_text' => [
+        'source_module' => 'text',
+        'destination_module' => 'text',
+      ],
+      'taxonomy_term_reference' => [
+        'source_module' => 'taxonomy',
+        'destination_module' => 'entity_reference',
+      ],
+      'date' => [
+        'source_module' => 'date',
+        'destination_module' => 'datetime',
+      ],
+      'datetime' => [
+        'source_module' => 'date',
+        'destination_module' => 'datetime',
+      ],
+      'email' => [
+        'source_module' => 'email',
+        'destination_module' => 'core',
+      ],
+      'number_default' => [
+        'source_module' => 'number',
+        'destination_module' => 'core',
+      ],
+      'entityreference' => [
+        'source_module' => 'entityreference',
+        'destination_module' => 'core',
+      ],
+    ];
+    // Install all available modules.
+    $module_handler = $this->container->get('module_handler');
+    $modules = $this->coreModuleListDataProvider();
+    $modules_enabled = $module_handler->getModuleList();
+    $modules_to_enable = array_keys(array_diff_key($modules, $modules_enabled));
+    $this->enableModules($modules_to_enable);
+
+    /** @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManager $plugin_manager */
+    $plugin_manager = $this->container->get('plugin.manager.migrate.field');
+    $definitions = $plugin_manager->getDefinitions();
+    foreach ($definitions as $key => $definition) {
+      $this->assertEquals($expected_mappings[$key]['source_module'], $plugin_manager->getSourceModule($definition));
+      $this->assertEquals($expected_mappings[$key]['destination_module'], $plugin_manager->getDestinationModule($definition));
+      unset($definitions[$key]);
+    }
+    // Make sure we test all the fields.
+    $this->assertEmpty($definitions);
+  }
+
+  /**
+   * Test a missing required definition.
+   *
+   * @dataProvider fieldPluginDefinitionsProvider
+   */
+  public function testFieldProviderMissingRequiredProperty($definitions, $missing_property) {
+    $mock_discovery = $this->getMockBuilder(MigrateFieldPluginManager::class)
+      ->disableOriginalConstructor()
+      ->setMethods(['getDefinitions'])
+      ->getMock();
+    $mock_discovery->method('getDefinitions')
+      ->willReturn($definitions);
+    $mock_plugin_manager = $this->getMockBuilder(MigrateFieldPluginManager::class)
+      ->disableOriginalConstructor()
+      ->setMethods(['getDiscovery'])
+      ->getMock();
+    $mock_plugin_manager->method('getDiscovery')
+      ->willReturn($mock_discovery);
+    $this->setExpectedException(InvalidPluginDefinitionException::class, "The missing_{$missing_property} plugin should define the $missing_property property.");
+    $mock_plugin_manager->getDefinitions();
+  }
+
+  /**
+   * Data provider for field plugin definitions.
+   *
+   * @return array
+   */
+  public function fieldPluginDefinitionsProvider() {
+    return [
+      'missing_core_scenario' => [
+        'definitions' => [
+          'missing_core' => [
+            'source_module' => 'migrate',
+            'destination_module' => 'migrate',
+            'id' => 'missing_core',
+            'class' => 'foo',
+            'provider' => 'foo',
+          ],
+        ],
+        'missing_property' => 'core',
+      ],
+      'missing_source_scenario' => [
+        'definitions' => [
+          'missing_source_module' => [
+            'core' => [
+              0 => 6,
+              1 => 7,
+            ],
+            'destination_module' => 'migrate',
+            'id' => 'missing_source_module',
+            'class' => 'foo',
+            'provider' => 'foo',
+          ],
+        ],
+        'missing_property' => 'source_module',
+      ],
+      'missing_destination_scenario' => [
+        'definitions' => [
+          'missing_destination_module' => [
+            'core' => [
+              0 => 6,
+              1 => 7,
+            ],
+            'source_module' => 'migrate',
+            'id' => 'missing_destination_module',
+            'class' => 'foo',
+            'provider' => 'foo',
+          ],
+        ],
+        'missing_property' => 'destination_module',
+      ],
+    ];
+  }
+
 }
diff --git a/core/modules/migrate_drupal/src/Annotation/MigrateField.php b/core/modules/migrate_drupal/src/Annotation/MigrateField.php
index ad78bc924d..7192749837 100644
--- a/core/modules/migrate_drupal/src/Annotation/MigrateField.php
+++ b/core/modules/migrate_drupal/src/Annotation/MigrateField.php
@@ -51,4 +51,26 @@ public function __construct($values) {
    */
   public $core = [];
 
+  /**
+   * Identifies the system providing the data the field plugin will read.
+   *
+   * The field plugin itself determines how the value is used. For example,
+   * Migrate Drupal's field plugins expect source_module to be the name of a
+   * module that must be installed and enabled in the source database.
+   *
+   * @var string
+   */
+  public $source_module;
+
+  /**
+   * Identifies the system handling the data the destination plugin will write.
+   *
+   * The destination plugin itself determines how the value is used. For
+   * example, Migrate Drupal's destination plugins expect destination_module to
+   * be the name of a module that must be installed on the destination.
+   *
+   * @var string
+   */
+  public $destination_module;
+
 }
diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManager.php b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManager.php
index 515e71e054..13f8871544 100644
--- a/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManager.php
+++ b/core/modules/migrate_drupal/src/Plugin/MigrateCckFieldPluginManager.php
@@ -2,6 +2,10 @@
 
 namespace Drupal\migrate_drupal\Plugin;
 
+use Drupal\Component\Plugin\Exception\PluginNotFoundException;
+use Drupal\migrate\Plugin\MigratePluginManager;
+use Drupal\migrate\Plugin\MigrationInterface;
+
 @trigger_error('MigrateCckFieldPluginManager is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateFieldPluginManager instead.', E_USER_DEPRECATED);
 
 /**
@@ -14,4 +18,42 @@
  *
  * @ingroup migration
  */
-class MigrateCckFieldPluginManager extends MigrateFieldPluginManager implements MigrateCckFieldPluginManagerInterface {}
+class MigrateCckFieldPluginManager extends MigrateFieldPluginManager implements MigrateCckFieldPluginManagerInterface {
+
+  /**
+   * The default version of core to use for cck field plugins.
+   *
+   * These plugins were initially only built and used for Drupal 6 cck fields.
+   * Having been extended for Drupal 7 with a "core" annotation, we fall back to
+   * Drupal 6 where none exists.
+   */
+  const DEFAULT_CORE_VERSION = 6;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPluginIdFromFieldType($field_type, array $configuration = [], MigrationInterface $migration = NULL) {
+    $core = static::DEFAULT_CORE_VERSION;
+    if (!empty($configuration['core'])) {
+      $core = $configuration['core'];
+    }
+    elseif (!empty($migration->getPluginDefinition()['migration_tags'])) {
+      foreach ($migration->getPluginDefinition()['migration_tags'] as $tag) {
+        if ($tag == 'Drupal 7') {
+          $core = 7;
+        }
+      }
+    }
+
+    $definitions = $this->getDefinitions();
+    foreach ($definitions as $plugin_id => $definition) {
+      if (in_array($core, $definition['core'])) {
+        if (array_key_exists($field_type, $definition['type_map']) || $field_type === $plugin_id) {
+          return $plugin_id;
+        }
+      }
+    }
+    throw new PluginNotFoundException($field_type);
+  }
+
+}
\ No newline at end of file
diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php
index 2b33c858b9..8901d0d289 100644
--- a/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php
+++ b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManager.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\migrate_drupal\Plugin;
 
+use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
 use Drupal\Component\Plugin\Exception\PluginNotFoundException;
 use Drupal\migrate\Plugin\MigratePluginManager;
 use Drupal\migrate\Plugin\MigrationInterface;
@@ -53,4 +54,31 @@ public function getPluginIdFromFieldType($field_type, array $configuration = [],
     throw new PluginNotFoundException($field_type);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function processDefinition(&$definition, $plugin_id) {
+    parent::processDefinition($definition, $plugin_id);
+
+    foreach (['core', 'source_module', 'destination_module'] as $required_property) {
+      if (empty($definition[$required_property])) {
+        throw new InvalidPluginDefinitionException($plugin_id, sprintf('The %s plugin should define the %s property.', $definition['id'], $required_property));
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSourceModule($definition) {
+    return isset($definition['source_module']) ? $definition['source_module'] : '';
+  }
+
+ /**
+   * {@inheritdoc}
+   */
+  public function getDestinationModule($definition) {
+    return isset($definition['destination_module']) ? $definition['destination_module'] : '';
+  }
+
 }
diff --git a/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManagerInterface.php b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManagerInterface.php
index 7219c2b301..2783903c4a 100644
--- a/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManagerInterface.php
+++ b/core/modules/migrate_drupal/src/Plugin/MigrateFieldPluginManagerInterface.php
@@ -25,4 +25,25 @@
    */
   public function getPluginIdFromFieldType($field_type, array $configuration = [], MigrationInterface $migration = NULL);
 
+  /**
+   * Gets the source module providing the source data.
+   *
+   * @param array $definition
+   *   The field plugin definition.
+   *
+   * @return string|null
+   *   The source module or NULL if not found.
+   */
+  public function getSourceModule($definition);
+
+  /**
+   * Gets the destination module handling the destination data.
+   *
+   * @param array $definition
+   *   The field plugin definition.
+   *
+   * @return string|null
+   *   The destination module or NULL if not found.
+   */
+  public function getDestinationModule($definition);
 }
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php b/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php
index 1579afadc5..4f5f08086f 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php
@@ -11,6 +11,8 @@
  *   type_map = {
  *     "nodereference" = "entity_reference",
  *   },
+*    source_module = "node_reference",
+ *   destination_module = "entity_reference",
  * )
  */
 class NodeReference extends FieldPluginBase {
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php b/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php
index 11df8ec243..9702cd69df 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/field/UserReference.php
@@ -11,6 +11,8 @@
  *   type_map = {
  *     "userreference" = "entity_reference",
  *   },
+ *   source_module = "user_reference",
+ *   destination_module = "entity_reference",
  * )
  */
 class UserReference extends FieldPluginBase {
diff --git a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php
index acb9d9cd7e..bb5e5fd501 100644
--- a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php
+++ b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6FileField.php
@@ -10,7 +10,9 @@
  *   core = {6},
  *   type_map = {
  *     "file" = "file"
- *   }
+ *   },
+ *   source_module = "foo",
+ *   destination_module = "bar",
  * )
  */
 class D6FileField extends FieldPluginBase {}
diff --git a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6NoCoreVersionSpecified.php b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6NoCoreVersionSpecified.php
index 39f109b697..00e2fbfc62 100644
--- a/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6NoCoreVersionSpecified.php
+++ b/core/modules/migrate_drupal/tests/modules/migrate_field_plugin_manager_test/src/Plugin/migrate/field/D6NoCoreVersionSpecified.php
@@ -6,10 +6,9 @@
 
 /**
  * @MigrateField(
- *   id = "d6_no_core_version_specified"
+ *   id = "d6_no_core_version_specified",
+ *   source_module = "foo",
+ *   destination_module = "bar",
  * )
  */
-class D6NoCoreVersionSpecified extends FieldPluginBase {
-
-
-}
+class D6NoCoreVersionSpecified extends FieldPluginBase { }
diff --git a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
index 0d9b53e531..c9c8a117db 100644
--- a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
+++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
@@ -2,13 +2,16 @@
 
 namespace Drupal\migrate_drupal_ui\Form;
 
+use Drupal\Component\Plugin\Exception\PluginNotFoundException;
 use Drupal\Core\Datetime\DateFormatterInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\RendererInterface;
 use Drupal\Core\State\StateInterface;
 use Drupal\Core\Url;
 use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
+use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
 use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeImportBatch;
 use Drupal\migrate_drupal\MigrationConfigurationTrait;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -49,6 +52,20 @@ class MigrateUpgradeForm extends ConfirmFormBase {
   protected $pluginManager;
 
   /**
+   * The field migrate plugin manager.
+   *
+   * @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
+   */
+  protected $fieldPluginManager;
+
+  /**
+   * The modue handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
    * Constructs the MigrateUpgradeForm.
    *
    * @param \Drupal\Core\State\StateInterface $state
@@ -59,12 +76,18 @@ class MigrateUpgradeForm extends ConfirmFormBase {
    *   The renderer service.
    * @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $plugin_manager
    *   The migration plugin manager.
+   * @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager
+   *   The field plugin manager.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The ID map migration plugin manager.
    */
-  public function __construct(StateInterface $state, DateFormatterInterface $date_formatter, RendererInterface $renderer, MigrationPluginManagerInterface $plugin_manager) {
+  public function __construct(StateInterface $state, DateFormatterInterface $date_formatter, RendererInterface $renderer, MigrationPluginManagerInterface $plugin_manager, MigrateFieldPluginManagerInterface $field_plugin_manager, ModuleHandlerInterface $module_handler) {
     $this->state = $state;
     $this->dateFormatter = $date_formatter;
     $this->renderer = $renderer;
     $this->pluginManager = $plugin_manager;
+    $this->fieldPluginManager = $field_plugin_manager;
+    $this->moduleHandler = $module_handler;
   }
 
   /**
@@ -75,7 +98,9 @@ public static function create(ContainerInterface $container) {
       $container->get('state'),
       $container->get('date.formatter'),
       $container->get('renderer'),
-      $container->get('plugin.manager.migration')
+      $container->get('plugin.manager.migration'),
+      $container->get('plugin.manager.migrate.field'),
+      $container->get('module_handler')
     );
   }
 
@@ -474,6 +499,54 @@ public function buildConfirmForm(array $form, FormStateInterface $form_state) {
         $table_data[$source_module][$destination_module][$migration_id] = $migration->label();
       }
     }
+
+    // Get all the field types from the source database using the source
+    // plugin in the field migration.
+    $field_types = [];
+    $definition = [
+      'source' => [
+        'ignore_map' => TRUE,
+        'plugin' => 'd' . "$version" . '_field',
+      ],
+      'destination' => [
+        'plugin' => 'null',
+      ],
+    ];
+    try {
+      $source_plugin = \Drupal::service('plugin.manager.migration')
+        ->createStubMigration($definition)
+        ->getSourcePlugin();
+      $source_plugin->checkRequirements();
+
+      foreach ($source_plugin as $row) {
+        $field_types[] = $row->getSourceProperty('type');
+      }
+      $field_types = array_unique($field_types);
+    }
+    catch (RequirementsException $e) {
+      // If checkRequirements() failed then the field module did not exist and
+      // we do not have any fields. Therefore, $field_types will be empty below.
+    }
+
+    // For each field type in the source get the source_module and the
+    // destination_module from the relevant field plugin.
+    foreach ($field_types as $field_type) {
+      try {
+        $plugin_id = $this->fieldPluginManager->getPluginIdFromFieldType($field_type, ['core' => $version]);
+        $definition = $this->fieldPluginManager->getDefinition($plugin_id);
+        $source_module = $this->fieldPluginManager->getSourceModule($definition);
+        $destination_module = $this->fieldPluginManager->getDestinationModule($definition);
+        if (($destination_module == 'core') || $this->moduleHandler->moduleExists($destination_module)) {
+          $field_plugin_id = $definition['id'];
+          $table_data[$source_module][$destination_module][$definition['id']] = $field_plugin_id;
+        }
+      }
+      catch (PluginNotFoundException $ex) {
+        // If checkRequirements() failed then there is no field migration for
+        // this field type.
+      }
+    }
+
     // Sort the table by source module names and within that destination
     // module names.
     ksort($table_data);
@@ -485,6 +558,11 @@ public function buildConfirmForm(array $form, FormStateInterface $form_state) {
     $system_data = $form_state->get('system_data');
     $unmigrated_source_modules = array_diff_key($system_data['module'], $table_data);
 
+    // Remove core profiles from the list.
+    foreach (['standard', 'minimal'] as $profile) {
+      unset($unmigrated_source_modules[$profile]);
+    }
+
     // Missing migrations.
     $form['missing_module_list_title'] = [
       '#type' => 'item',
diff --git a/core/modules/options/src/Plugin/migrate/field/d6/OptionWidgetsField.php b/core/modules/options/src/Plugin/migrate/field/d6/OptionWidgetsField.php
new file mode 100644
index 0000000000..b6b5516aa0
--- /dev/null
+++ b/core/modules/options/src/Plugin/migrate/field/d6/OptionWidgetsField.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Drupal\options\Plugin\migrate\field\d7;
+
+use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
+
+/**
+ * @MigrateField(
+ *   id = "optionwidgets",
+ *   core = {6},
+ *   source_module = "optionwidgets",
+ *   destination_module = "options"
+ * )
+ */
+class OptionWidgetsField extends FieldPluginBase {}
diff --git a/core/modules/options/src/Plugin/migrate/field/d7/ListField.php b/core/modules/options/src/Plugin/migrate/field/d7/ListField.php
index fff29ee177..714c364b8f 100644
--- a/core/modules/options/src/Plugin/migrate/field/d7/ListField.php
+++ b/core/modules/options/src/Plugin/migrate/field/d7/ListField.php
@@ -12,7 +12,9 @@
  *     "list_integer" = "list_integer",
  *     "list_text" = "list_string",
  *   },
- *   core = {7}
+ *   core = {7},
+ *   source_module = "list",
+ *   destination_module = "options"
  * )
  */
 class ListField extends FieldPluginBase {}
diff --git a/core/modules/options/src/Plugin/migrate/field/d7/OptionsField.php b/core/modules/options/src/Plugin/migrate/field/d7/OptionsField.php
new file mode 100644
index 0000000000..e54ccb3e37
--- /dev/null
+++ b/core/modules/options/src/Plugin/migrate/field/d7/OptionsField.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Drupal\options\Plugin\migrate\field\d7;
+
+use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
+
+/**
+ * @MigrateField(
+ *   id = "options",
+ *   core = {7},
+ *   source_module = "options",
+ *   destination_module = "options"
+ * )
+ */
+class OptionsField extends FieldPluginBase {}
diff --git a/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php b/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php
index 27cb8d355f..0c72879598 100644
--- a/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php
+++ b/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php
@@ -13,7 +13,9 @@
  *   type_map = {
  *     "taxonomy_term_reference" = "entity_reference"
  *   },
- *   core = {6,7}
+ *   core = {6,7},
+ *   source_module = "taxonomy",
+ *   destination_module = "entity_reference",
  * )
  *
  * @deprecated in Drupal 8.4.x, to be removed before Drupal 9.0.x. Use
diff --git a/core/modules/taxonomy/src/Plugin/migrate/field/TaxonomyTermReference.php b/core/modules/taxonomy/src/Plugin/migrate/field/TaxonomyTermReference.php
index 56ec20ac27..afb5458de0 100644
--- a/core/modules/taxonomy/src/Plugin/migrate/field/TaxonomyTermReference.php
+++ b/core/modules/taxonomy/src/Plugin/migrate/field/TaxonomyTermReference.php
@@ -11,7 +11,9 @@
  *   type_map = {
  *     "taxonomy_term_reference" = "entity_reference"
  *   },
- *   core = {6,7}
+ *   core = {6,7},
+ *   source_module = "taxonomy",
+ *   destination_module = "entity_reference",
  * )
  */
 class TaxonomyTermReference extends FieldPluginBase {
diff --git a/core/modules/telephone/src/Plugin/migrate/field/d7/PhoneField.php b/core/modules/telephone/src/Plugin/migrate/field/d7/PhoneField.php
index 3164cecdca..d98f344344 100644
--- a/core/modules/telephone/src/Plugin/migrate/field/d7/PhoneField.php
+++ b/core/modules/telephone/src/Plugin/migrate/field/d7/PhoneField.php
@@ -10,7 +10,9 @@
  *   type_map = {
  *     "phone" = "telephone",
  *   },
- *   core = {7}
+ *   core = {7},
+ *   source_module = "phone",
+ *   destination_module = "telephone"
  * )
  */
 class PhoneField extends FieldPluginBase {}
diff --git a/core/modules/text/src/Plugin/migrate/cckfield/TextField.php b/core/modules/text/src/Plugin/migrate/cckfield/TextField.php
index e2511de836..394f104173 100644
--- a/core/modules/text/src/Plugin/migrate/cckfield/TextField.php
+++ b/core/modules/text/src/Plugin/migrate/cckfield/TextField.php
@@ -16,7 +16,9 @@
  *     "text_long" = "text_long",
  *     "text_with_summary" = "text_with_summary"
  *   },
- *   core = {6,7}
+ *   core = {6,7},
+ *   source_module = "text",
+ *   destination_module = "text",
  * )
  *
  * @deprecated in Drupal 8.3.x, to be removed before Drupal 9.0.x. Use
diff --git a/core/modules/text/src/Plugin/migrate/field/d6/TextField.php b/core/modules/text/src/Plugin/migrate/field/d6/TextField.php
index 62deeee10c..cd1e2f7b29 100644
--- a/core/modules/text/src/Plugin/migrate/field/d6/TextField.php
+++ b/core/modules/text/src/Plugin/migrate/field/d6/TextField.php
@@ -14,7 +14,9 @@
  *     "text_long" = "text_long",
  *     "text_with_summary" = "text_with_summary"
  *   },
- *   core = {6}
+ *   core = {6},
+ *   source_module = "text",
+ *   destination_module = "text",
  * )
  */
 class TextField extends FieldPluginBase {
diff --git a/core/modules/text/src/Plugin/migrate/field/d7/TextField.php b/core/modules/text/src/Plugin/migrate/field/d7/TextField.php
index ccdedd427a..6433ed33d7 100644
--- a/core/modules/text/src/Plugin/migrate/field/d7/TextField.php
+++ b/core/modules/text/src/Plugin/migrate/field/d7/TextField.php
@@ -14,7 +14,9 @@
  *     "text_long" = "text_long",
  *     "text_with_summary" = "text_with_summary"
  *   },
- *   core = {7}
+ *   core = {7},
+ *   source_module = "text",
+ *   destination_module = "text",
  * )
  */
 class TextField extends FieldPluginBase {
