diff --git a/gcc/ctfc.cc b/gcc/ctfc.cc
index 6fe44d2e8d49..f24e7bff9487 100644
--- a/gcc/ctfc.cc
+++ b/gcc/ctfc.cc
@@ -179,6 +179,40 @@ ctf_dvd_lookup (const ctf_container_ref ctfc, dw_die_ref die)
   return NULL;
 }
 
+/* Insert a dummy CTF variable into the list of variables to be ignored.  */
+
+static void
+ctf_dvd_ignore_insert (ctf_container_ref ctfc, ctf_dvdef_ref dvd)
+{
+  bool existed = false;
+  ctf_dvdef_ref entry = dvd;
+
+  ctf_dvdef_ref * item = ctfc->ctfc_ignore_vars->find_slot (entry, INSERT);
+  if (*item == NULL)
+     *item = dvd;
+  else
+    existed = true;
+  /* Duplicate variable records not expected to be inserted.  */
+  gcc_assert (!existed);
+}
+
+/* Lookup the dummy CTF variable given the DWARF die for the non-defining
+   decl to be ignored.  */
+
+bool
+ctf_dvd_ignore_lookup (const ctf_container_ref ctfc, dw_die_ref die)
+{
+  ctf_dvdef_t entry;
+  entry.dvd_key = die;
+
+  ctf_dvdef_ref * slot = ctfc->ctfc_ignore_vars->find_slot (&entry, NO_INSERT);
+
+  if (slot)
+    return true;
+
+  return false;
+}
+
 /* Append member definition to the list.  Member list is a singly-linked list
    with list start pointing to the head.  */
 
@@ -666,9 +700,10 @@ ctf_add_member_offset (ctf_container_ref ctfc, dw_die_ref sou,
 
 int
 ctf_add_variable (ctf_container_ref ctfc, const char * name, ctf_id_t ref,
-		  dw_die_ref die, unsigned int external_vis)
+		  dw_die_ref die, unsigned int external_vis,
+		  dw_die_ref die_var_decl)
 {
-  ctf_dvdef_ref dvd;
+  ctf_dvdef_ref dvd, dvd_ignore;
 
   gcc_assert (name);
 
@@ -680,6 +715,24 @@ ctf_add_variable (ctf_container_ref ctfc, const char * name, ctf_id_t ref,
       dvd->dvd_name = ctf_add_string (ctfc, name, &(dvd->dvd_name_offset));
       dvd->dvd_visibility = external_vis;
       dvd->dvd_type = ref;
+
+      /* If DW_AT_specification attribute exists, keep track of it as this is
+	 the non-defining declaration corresponding to the variable.  We will
+	 skip emitting CTF variable for such incomplete, non-defining
+	 declarations.
+	 There could be some non-defining declarations, however, for which a
+	 defining declaration does not show up in the same CU.  For such
+	 cases, the compiler continues to emit CTF variable record as
+	 usual.  */
+      if (die_var_decl)
+	{
+	  dvd_ignore = ggc_cleared_alloc<ctf_dvdef_t> ();
+	  dvd_ignore->dvd_key = die_var_decl;
+	  /* It's alright to leave other fields as zero.  No valid CTF
+	     variable will be added for these DW_TAG_variable DIEs.  */
+	  ctf_dvd_ignore_insert (ctfc, dvd_ignore);
+	}
+
       ctf_dvd_insert (ctfc, dvd);
 
       if (strcmp (name, ""))
@@ -900,6 +953,8 @@ new_ctf_container (void)
     = hash_table<ctfc_dtd_hasher>::create_ggc (100);
   tu_ctfc->ctfc_vars
     = hash_table<ctfc_dvd_hasher>::create_ggc (100);
+  tu_ctfc->ctfc_ignore_vars
+    = hash_table<ctfc_dvd_hasher>::create_ggc (10);
 
   return tu_ctfc;
 }
@@ -952,6 +1007,9 @@ ctfc_delete_container (ctf_container_ref ctfc)
       ctfc->ctfc_vars->empty ();
       ctfc->ctfc_types = NULL;
 
+      ctfc->ctfc_ignore_vars->empty ();
+      ctfc->ctfc_ignore_vars = NULL;
+
       ctfc_delete_strtab (&ctfc->ctfc_strtable);
       ctfc_delete_strtab (&ctfc->ctfc_aux_strtable);
       if (ctfc->ctfc_vars_list)
diff --git a/gcc/ctfc.h b/gcc/ctfc.h
index 4ce756c728a7..001e544ef083 100644
--- a/gcc/ctfc.h
+++ b/gcc/ctfc.h
@@ -274,6 +274,8 @@ typedef struct GTY (()) ctf_container
   hash_table <ctfc_dtd_hasher> * GTY (()) ctfc_types;
   /* CTF variables.  */
   hash_table <ctfc_dvd_hasher> * GTY (()) ctfc_vars;
+  /* CTF variables to be ignored.  */
+  hash_table <ctfc_dvd_hasher> * GTY (()) ctfc_ignore_vars;
 
   /* CTF string table.  */
   ctf_strtable_t ctfc_strtable;
@@ -394,6 +396,8 @@ extern ctf_dtdef_ref ctf_dtd_lookup (const ctf_container_ref ctfc,
 				     dw_die_ref die);
 extern ctf_dvdef_ref ctf_dvd_lookup (const ctf_container_ref ctfc,
 				     dw_die_ref die);
+extern bool ctf_dvd_ignore_lookup (const ctf_container_ref ctfc,
+				   dw_die_ref die);
 
 extern const char * ctf_add_string (ctf_container_ref, const char *,
 				    uint32_t *, int);
@@ -430,7 +434,7 @@ extern int ctf_add_member_offset (ctf_container_ref, dw_die_ref, const char *,
 extern int ctf_add_function_arg (ctf_container_ref, dw_die_ref,
 				 const char *, ctf_id_t);
 extern int ctf_add_variable (ctf_container_ref, const char *, ctf_id_t,
-			     dw_die_ref, unsigned int);
+			     dw_die_ref, unsigned int, dw_die_ref);
 
 extern ctf_id_t ctf_lookup_tree_type (ctf_container_ref, const tree);
 extern ctf_id_t get_btf_id (ctf_id_t);
diff --git a/gcc/ctfout.cc b/gcc/ctfout.cc
index 28a873b2027d..3cf89b94f993 100644
--- a/gcc/ctfout.cc
+++ b/gcc/ctfout.cc
@@ -212,6 +212,13 @@ ctf_dvd_preprocess_cb (ctf_dvdef_ref * slot, void * arg)
   ctf_dvdef_ref var = (ctf_dvdef_ref) *slot;
   ctf_container_ref arg_ctfc = dvd_arg->dvd_arg_ctfc;
 
+  /* If the CTF variable corresponds to an extern variable declaration with
+     a defining declaration later on, skip it.  Only CTF variable
+     corresponding to the defining declaration for the extern variable is
+     desirable.  */
+  if (ctf_dvd_ignore_lookup (arg_ctfc, var->dvd_key))
+    return 1;
+
   ctf_preprocess_var (arg_ctfc, var);
 
   /* Keep track of global objts.  */
@@ -276,16 +283,16 @@ static void
 ctf_preprocess (ctf_container_ref ctfc)
 {
   size_t num_ctf_types = ctfc->ctfc_types->elements ();
+  size_t num_ctf_vars = ctfc_get_num_ctf_vars (ctfc);
 
   /* Initialize an array to keep track of the CTF variables at global
-     scope.  */
-  size_t num_global_objts = ctfc->ctfc_num_global_objts;
+     scope.  At this time, size it conservatively.  */
+  size_t num_global_objts = num_ctf_vars;
   if (num_global_objts)
     {
       ctfc->ctfc_gobjts_list = ggc_vec_alloc<ctf_dvdef_t*>(num_global_objts);
     }
 
-  size_t num_ctf_vars = ctfc_get_num_ctf_vars (ctfc);
   if (num_ctf_vars)
     {
       ctf_dvd_preprocess_arg_t dvd_arg;
@@ -299,8 +306,11 @@ ctf_preprocess (ctf_container_ref ctfc)
 	 list for sorting.  */
       ctfc->ctfc_vars->traverse<void *, ctf_dvd_preprocess_cb> (&dvd_arg);
       /* Sort the list.  */
-      qsort (ctfc->ctfc_vars_list, num_ctf_vars, sizeof (ctf_dvdef_ref),
-	     ctf_varent_compare);
+      qsort (ctfc->ctfc_vars_list, ctfc->ctfc_vars_list_count,
+	     sizeof (ctf_dvdef_ref), ctf_varent_compare);
+      /* Update the actual number of the generated CTF variables at global
+	 scope.  */
+      ctfc->ctfc_num_global_objts = dvd_arg.dvd_global_obj_idx;
     }
 
   /* Initialize an array to keep track of the CTF functions types for global
@@ -476,7 +486,7 @@ output_ctf_header (ctf_container_ref ctfc)
       /* Vars appear after function index.  */
       varoff = funcidxoff + ctfc->ctfc_num_global_funcs * sizeof (uint32_t);
       /* CTF types appear after vars.  */
-      typeoff = varoff + ctfc_get_num_ctf_vars (ctfc) * sizeof (ctf_varent_t);
+      typeoff = varoff + (ctfc->ctfc_vars_list_count) * sizeof (ctf_varent_t);
       /* The total number of bytes for CTF types is the sum of the number of
 	 times struct ctf_type_t, struct ctf_stype_t are written, plus the
 	 amount of variable length data after each one of these.  */
@@ -595,7 +605,7 @@ static void
 output_ctf_vars (ctf_container_ref ctfc)
 {
   size_t i;
-  size_t num_ctf_vars = ctfc_get_num_ctf_vars (ctfc);
+  unsigned int num_ctf_vars = ctfc->ctfc_vars_list_count;
   if (num_ctf_vars)
     {
       /* Iterate over the list of sorted vars and output the asm.  */
diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc
index 747b2f661072..a6329ab6ee48 100644
--- a/gcc/dwarf2ctf.cc
+++ b/gcc/dwarf2ctf.cc
@@ -808,12 +808,26 @@ gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
   if (ctf_dvd_lookup (ctfc, die))
     return;
 
+  /* Do not generate CTF variable records for non-defining incomplete
+     declarations.  Such declarations can be known via the DWARF
+     DW_AT_specification attribute.  */
+  if (ctf_dvd_ignore_lookup (ctfc, die))
+    return;
+
+  /* The value of the DW_AT_specification attribute, if present, is a
+     reference to the debugging information entry representing the
+     non-defining declaration.  */
+  dw_die_ref decl = get_AT_ref (die, DW_AT_specification);
+
   /* Add the type of the variable.  */
   var_type_id = gen_ctf_type (ctfc, var_type);
 
   /* Generate the new CTF variable and update global counter.  */
-  (void) ctf_add_variable (ctfc, var_name, var_type_id, die, external_vis);
-  ctfc->ctfc_num_global_objts += 1;
+  (void) ctf_add_variable (ctfc, var_name, var_type_id, die, external_vis,
+			   decl);
+  /* Skip updating the number of global objects at this time.  This is updated
+     later after pre-processing as some CTF variable records although
+     generated now, will not be emitted later.  [PR105089].  */
 }
 
 /* Add a CTF function record for the given input DWARF DIE.  */
