[16/19] libctf: add linking of the variable section

Message ID 20190716180420.236506-17-nick.alcock@oracle.com
State New
Headers show
Series
  • CTF linking support
Related show

Commit Message

Nick Alcock July 16, 2019, 6:04 p.m.
The compiler describes the name and type of all file-scope variables in
this section.  Merging it at link time requires using the type mapping
added in the previous commit to determine the appropriate type for the
variable in the output, given its type in the input: we check the shared
container first, and if the type doesn't exist there, it must be a
conflicted type in the per-CU child, and the variable should go there
too (no other option is possible: no variable can have a type that is
defined in some *other* CU).

libctf/
	* ctf-link.c (ctf_link_one_variable): New.
	(ctf_link_one_input_archive_member): Call it.
---
 libctf/ctf-link.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

-- 
2.22.0.238.g049a27acdc

Patch

diff --git a/libctf/ctf-link.c b/libctf/ctf-link.c
index 1b1a718786..fe88dd44e9 100644
--- a/libctf/ctf-link.c
+++ b/libctf/ctf-link.c
@@ -262,6 +262,74 @@  ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_)
 
 /* Link one variable in.  */
 
+static int
+ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
+{
+  ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
+  ctf_dvdef_t *dvd;
+  ctf_id_t dst_type = 0;
+  ctf_file_t *check_fp;
+
+  /* In unconflicted link mode, when called on a child, we want to try to merge
+     into the parent first, then the child (if there is one): it must be
+     possible to merge into one of those given valid input.  Look for the type
+     of this variable in the parent.  */
+
+  if (arg->out_fp->ctf_parent)
+    {
+      check_fp = arg->out_fp->ctf_parent;
+
+      dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
+      if (dst_type != 0)
+	{
+	  /* Got it in the parent.  Is there already a variable of this name in
+	     the parent? Does it already refer to the right type?  */
+
+	  dvd = ctf_dynhash_lookup (check_fp->ctf_dvhash, name);
+	  if (dvd && dvd->dvd_type == dst_type)
+	    return 0;
+
+	  /* No variable here: we can add it.  */
+	  if (!dvd)
+	    {
+	      ctf_add_variable (check_fp, name, dst_type);
+	      return 0;
+	    }
+	}
+    }
+
+  /* Not in the parent, or conflicted, or no parent at all.  Find the type in
+     the child if necessary, then add it there.  */
+
+  /* This type is from the parent's perspective: childify it.  */
+  if (dst_type != 0 && arg->out_fp->ctf_parent)
+    {
+      dst_type = LCTF_TYPE_TO_INDEX (arg->out_fp->ctf_parent, dst_type);
+      dst_type = LCTF_INDEX_TO_TYPE (arg->out_fp, dst_type, 1);
+    }
+  else
+    {
+      /* Look up the type in the child.  */
+      check_fp = arg->out_fp;
+
+      dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
+    }
+
+  /* Type still unknown. Impossible: warn and fail.  */
+  if (dst_type == 0)
+    {
+      ctf_dprintf ("Type %lx from CTF archive member %s, input file %s not "
+		   "known in parent while adding variable %s: this should "
+		   "never happen.\n", type, arg->arcname, arg->file_name,
+		   name);
+      return EINVAL;
+    }
+
+  ctf_add_variable (check_fp, name, dst_type);
+
+  return 0;
+}
+
 /* Merge every type and variable in this archive member into the link, so we can
    relink things that have already had ld run on them.  We use the archive
    member name, sans any leading '.ctf.', as the CU name for ambiguous types if
@@ -306,6 +374,7 @@  ctf_link_one_input_archive_member (ctf_file_t *in_fp, const char *name, void *ar
   err = ctf_type_iter_all (in_fp, ctf_link_one_type, arg);
 
   if (err == 0)
+    err = ctf_variable_iter (in_fp, ctf_link_one_variable, arg);
   arg->in_input_cu_file = 0;
   free (arg->arcname);