xref: /netbsd-src/external/gpl3/gdb.old/dist/libctf/ctf-link.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* CTF linking.
2*6881a400Schristos    Copyright (C) 2019-2022 Free Software Foundation, Inc.
37d62b00eSchristos 
47d62b00eSchristos    This file is part of libctf.
57d62b00eSchristos 
67d62b00eSchristos    libctf is free software; you can redistribute it and/or modify it under
77d62b00eSchristos    the terms of the GNU General Public License as published by the Free
87d62b00eSchristos    Software Foundation; either version 3, or (at your option) any later
97d62b00eSchristos    version.
107d62b00eSchristos 
117d62b00eSchristos    This program is distributed in the hope that it will be useful, but
127d62b00eSchristos    WITHOUT ANY WARRANTY; without even the implied warranty of
137d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
147d62b00eSchristos    See the GNU General Public License for more details.
157d62b00eSchristos 
167d62b00eSchristos    You should have received a copy of the GNU General Public License
177d62b00eSchristos    along with this program; see the file COPYING.  If not see
187d62b00eSchristos    <http://www.gnu.org/licenses/>.  */
197d62b00eSchristos 
207d62b00eSchristos #include <ctf-impl.h>
217d62b00eSchristos #include <string.h>
227d62b00eSchristos 
237d62b00eSchristos #if defined (PIC)
247d62b00eSchristos #pragma weak ctf_open
257d62b00eSchristos #endif
267d62b00eSchristos 
27*6881a400Schristos /* CTF linking consists of adding CTF archives full of content to be merged into
287d62b00eSchristos    this one to the current file (which must be writable) by calling
29*6881a400Schristos    ctf_link_add_ctf.  Once this is done, a call to ctf_link will merge the type
30*6881a400Schristos    tables together, generating new CTF files as needed, with this one as a
31*6881a400Schristos    parent, to contain types from the inputs which conflict.  ctf_link_add_strtab
32*6881a400Schristos    takes a callback which provides string/offset pairs to be added to the
33*6881a400Schristos    external symbol table and deduplicated from all CTF string tables in the
34*6881a400Schristos    output link; ctf_link_shuffle_syms takes a callback which provides symtab
35*6881a400Schristos    entries in ascending order, and shuffles the function and data sections to
36*6881a400Schristos    match; and ctf_link_write emits a CTF file (if there are no conflicts
37*6881a400Schristos    requiring per-compilation-unit sub-CTF files) or CTF archives (otherwise) and
38*6881a400Schristos    returns it, suitable for addition in the .ctf section of the output.  */
397d62b00eSchristos 
407d62b00eSchristos /* Return the name of the compilation unit this CTF dict or its parent applies
417d62b00eSchristos    to, or a non-null string otherwise: prefer the parent.  Used in debugging
427d62b00eSchristos    output.  Sometimes used for outputs too.  */
437d62b00eSchristos const char *
44*6881a400Schristos ctf_link_input_name (ctf_dict_t *fp)
457d62b00eSchristos {
467d62b00eSchristos   if (fp->ctf_parent && fp->ctf_parent->ctf_cuname)
477d62b00eSchristos     return fp->ctf_parent->ctf_cuname;
487d62b00eSchristos   else if (fp->ctf_cuname)
497d62b00eSchristos     return fp->ctf_cuname;
507d62b00eSchristos   else
517d62b00eSchristos     return "(unnamed)";
527d62b00eSchristos }
537d62b00eSchristos 
54*6881a400Schristos /* Return the cuname of a dict, or the string "unnamed-CU" if none.  */
55*6881a400Schristos 
56*6881a400Schristos static const char *
57*6881a400Schristos ctf_unnamed_cuname (ctf_dict_t *fp)
58*6881a400Schristos {
59*6881a400Schristos   const char *cuname = ctf_cuname (fp);
60*6881a400Schristos 
61*6881a400Schristos   if (!cuname)
62*6881a400Schristos     cuname = "unnamed-CU";
63*6881a400Schristos 
64*6881a400Schristos   return cuname;
65*6881a400Schristos }
66*6881a400Schristos 
677d62b00eSchristos /* The linker inputs look like this.  clin_fp is used for short-circuited
687d62b00eSchristos    CU-mapped links that can entirely avoid the first link phase in some
69*6881a400Schristos    situations in favour of just passing on the contained ctf_dict_t: it is
70*6881a400Schristos    always the sole ctf_dict_t inside the corresponding clin_arc.  If set, it
717d62b00eSchristos    gets assigned directly to the final link inputs and freed from there, so it
727d62b00eSchristos    never gets explicitly freed in the ctf_link_input.  */
737d62b00eSchristos typedef struct ctf_link_input
747d62b00eSchristos {
75*6881a400Schristos   char *clin_filename;
767d62b00eSchristos   ctf_archive_t *clin_arc;
77*6881a400Schristos   ctf_dict_t *clin_fp;
787d62b00eSchristos   int n;
797d62b00eSchristos } ctf_link_input_t;
807d62b00eSchristos 
817d62b00eSchristos static void
827d62b00eSchristos ctf_link_input_close (void *input)
837d62b00eSchristos {
847d62b00eSchristos   ctf_link_input_t *i = (ctf_link_input_t *) input;
857d62b00eSchristos   if (i->clin_arc)
867d62b00eSchristos     ctf_arc_close (i->clin_arc);
87*6881a400Schristos   free (i->clin_filename);
887d62b00eSchristos   free (i);
897d62b00eSchristos }
907d62b00eSchristos 
917d62b00eSchristos /* Like ctf_link_add_ctf, below, but with no error-checking, so it can be called
927d62b00eSchristos    in the middle of an ongoing link.  */
937d62b00eSchristos static int
94*6881a400Schristos ctf_link_add_ctf_internal (ctf_dict_t *fp, ctf_archive_t *ctf,
95*6881a400Schristos 			   ctf_dict_t *fp_input, const char *name)
967d62b00eSchristos {
97*6881a400Schristos   int existing = 0;
98*6881a400Schristos   ctf_link_input_t *input;
99*6881a400Schristos   char *filename, *keyname;
100*6881a400Schristos 
101*6881a400Schristos   /* Existing: return it, or (if a different dict with the same name
102*6881a400Schristos      is already there) make up a new unique name.  Always use the actual name
103*6881a400Schristos      for the filename, because that needs to be ctf_open()ed.  */
104*6881a400Schristos 
105*6881a400Schristos   if ((input = ctf_dynhash_lookup (fp->ctf_link_inputs, name)) != NULL)
106*6881a400Schristos     {
107*6881a400Schristos       if ((fp_input != NULL && (input->clin_fp == fp_input))
108*6881a400Schristos 	  || (ctf != NULL && (input->clin_arc == ctf)))
109*6881a400Schristos 	return 0;
110*6881a400Schristos       existing = 1;
111*6881a400Schristos     }
112*6881a400Schristos 
113*6881a400Schristos   if ((filename = strdup (name)) == NULL)
114*6881a400Schristos     goto oom;
1157d62b00eSchristos 
1167d62b00eSchristos   if ((input = calloc (1, sizeof (ctf_link_input_t))) == NULL)
117*6881a400Schristos     goto oom1;
1187d62b00eSchristos 
1197d62b00eSchristos   input->clin_arc = ctf;
1207d62b00eSchristos   input->clin_fp = fp_input;
121*6881a400Schristos   input->clin_filename = filename;
1227d62b00eSchristos   input->n = ctf_dynhash_elements (fp->ctf_link_inputs);
1237d62b00eSchristos 
124*6881a400Schristos   if (existing)
125*6881a400Schristos     {
126*6881a400Schristos       if (asprintf (&keyname, "%s#%li", name, (long int)
127*6881a400Schristos 		    ctf_dynhash_elements (fp->ctf_link_inputs)) < 0)
128*6881a400Schristos 	goto oom2;
129*6881a400Schristos     }
130*6881a400Schristos   else if ((keyname = strdup (name)) == NULL)
131*6881a400Schristos     goto oom2;
132*6881a400Schristos 
133*6881a400Schristos   if (ctf_dynhash_insert (fp->ctf_link_inputs, keyname, input) < 0)
134*6881a400Schristos     goto oom3;
1357d62b00eSchristos 
1367d62b00eSchristos   return 0;
137*6881a400Schristos 
138*6881a400Schristos  oom3:
139*6881a400Schristos   free (keyname);
140*6881a400Schristos  oom2:
1417d62b00eSchristos   free (input);
142*6881a400Schristos  oom1:
143*6881a400Schristos   free (filename);
144*6881a400Schristos  oom:
1457d62b00eSchristos   return ctf_set_errno (fp, ENOMEM);
1467d62b00eSchristos }
1477d62b00eSchristos 
1487d62b00eSchristos /* Add a file, memory buffer, or unopened file (by name) to a link.
1497d62b00eSchristos 
1507d62b00eSchristos    You can call this with:
1517d62b00eSchristos 
1527d62b00eSchristos     CTF and NAME: link the passed ctf_archive_t, with the given NAME.
1537d62b00eSchristos     NAME alone: open NAME as a CTF file when needed.
1547d62b00eSchristos     BUF and NAME: open the BUF (of length N) as CTF, with the given NAME.  (Not
1557d62b00eSchristos     yet implemented.)
1567d62b00eSchristos 
1577d62b00eSchristos     Passed in CTF args are owned by the dictionary and will be freed by it.
1587d62b00eSchristos     The BUF arg is *not* owned by the dictionary, and the user should not free
1597d62b00eSchristos     its referent until the link is done.
1607d62b00eSchristos 
1617d62b00eSchristos     The order of calls to this function influences the order of types in the
1627d62b00eSchristos     final link output, but otherwise is not important.
1637d62b00eSchristos 
164*6881a400Schristos     Repeated additions of the same NAME have no effect; repeated additions of
165*6881a400Schristos     different dicts with the same NAME add all the dicts with unique NAMEs
166*6881a400Schristos     derived from NAME.
167*6881a400Schristos 
1687d62b00eSchristos     Private for now, but may in time become public once support for BUF is
1697d62b00eSchristos     implemented.  */
1707d62b00eSchristos 
1717d62b00eSchristos static int
172*6881a400Schristos ctf_link_add (ctf_dict_t *fp, ctf_archive_t *ctf, const char *name,
1737d62b00eSchristos 	      void *buf _libctf_unused_, size_t n _libctf_unused_)
1747d62b00eSchristos {
1757d62b00eSchristos   if (buf)
1767d62b00eSchristos     return (ctf_set_errno (fp, ECTF_NOTYET));
1777d62b00eSchristos 
1787d62b00eSchristos   if (!((ctf && name && !buf)
1797d62b00eSchristos 	|| (name && !buf && !ctf)
1807d62b00eSchristos 	|| (buf && name && !ctf)))
1817d62b00eSchristos     return (ctf_set_errno (fp, EINVAL));
1827d62b00eSchristos 
1837d62b00eSchristos   /* We can only lazily open files if libctf.so is in use rather than
1847d62b00eSchristos      libctf-nobfd.so.  This is a little tricky: in shared libraries, we can use
1857d62b00eSchristos      a weak symbol so that -lctf -lctf-nobfd works, but in static libraries we
1867d62b00eSchristos      must distinguish between the two libraries explicitly.  */
1877d62b00eSchristos 
1887d62b00eSchristos #if defined (PIC)
1897d62b00eSchristos   if (!buf && !ctf && name && !ctf_open)
1907d62b00eSchristos     return (ctf_set_errno (fp, ECTF_NEEDSBFD));
1917d62b00eSchristos #elif NOBFD
1927d62b00eSchristos   if (!buf && !ctf && name)
1937d62b00eSchristos     return (ctf_set_errno (fp, ECTF_NEEDSBFD));
1947d62b00eSchristos #endif
1957d62b00eSchristos 
1967d62b00eSchristos   if (fp->ctf_link_outputs)
1977d62b00eSchristos     return (ctf_set_errno (fp, ECTF_LINKADDEDLATE));
1987d62b00eSchristos   if (fp->ctf_link_inputs == NULL)
1997d62b00eSchristos     fp->ctf_link_inputs = ctf_dynhash_create (ctf_hash_string,
2007d62b00eSchristos 					      ctf_hash_eq_string, free,
2017d62b00eSchristos 					      ctf_link_input_close);
2027d62b00eSchristos 
2037d62b00eSchristos   if (fp->ctf_link_inputs == NULL)
2047d62b00eSchristos     return (ctf_set_errno (fp, ENOMEM));
2057d62b00eSchristos 
2067d62b00eSchristos   return ctf_link_add_ctf_internal (fp, ctf, NULL, name);
2077d62b00eSchristos }
2087d62b00eSchristos 
2097d62b00eSchristos /* Add an opened CTF archive or unopened file (by name) to a link.
2107d62b00eSchristos    If CTF is NULL and NAME is non-null, an unopened file is meant:
2117d62b00eSchristos    otherwise, the specified archive is assumed to have the given NAME.
2127d62b00eSchristos 
2137d62b00eSchristos     Passed in CTF args are owned by the dictionary and will be freed by it.
2147d62b00eSchristos 
2157d62b00eSchristos     The order of calls to this function influences the order of types in the
2167d62b00eSchristos     final link output, but otherwise is not important.  */
2177d62b00eSchristos 
2187d62b00eSchristos int
219*6881a400Schristos ctf_link_add_ctf (ctf_dict_t *fp, ctf_archive_t *ctf, const char *name)
2207d62b00eSchristos {
2217d62b00eSchristos   return ctf_link_add (fp, ctf, name, NULL, 0);
2227d62b00eSchristos }
2237d62b00eSchristos 
224*6881a400Schristos /* Lazily open a CTF archive for linking, if not already open.
2257d62b00eSchristos 
226*6881a400Schristos    Returns the number of files contained within the opened archive (0 for none),
227*6881a400Schristos    or -1 on error, as usual.  */
228*6881a400Schristos static ssize_t
229*6881a400Schristos ctf_link_lazy_open (ctf_dict_t *fp, ctf_link_input_t *input)
2307d62b00eSchristos {
231*6881a400Schristos   size_t count;
232*6881a400Schristos   int err;
233*6881a400Schristos 
234*6881a400Schristos   if (input->clin_arc)
235*6881a400Schristos     return ctf_archive_count (input->clin_arc);
236*6881a400Schristos 
237*6881a400Schristos   if (input->clin_fp)
238*6881a400Schristos     return 1;
239*6881a400Schristos 
240*6881a400Schristos   /* See ctf_link_add_ctf.  */
241*6881a400Schristos #if defined (PIC) || !NOBFD
242*6881a400Schristos   input->clin_arc = ctf_open (input->clin_filename, NULL, &err);
243*6881a400Schristos #else
244*6881a400Schristos   ctf_err_warn (fp, 0, ECTF_NEEDSBFD, _("cannot open %s lazily"),
245*6881a400Schristos 		input->clin_filename);
246*6881a400Schristos   ctf_set_errno (fp, ECTF_NEEDSBFD);
247*6881a400Schristos   return -1;
248*6881a400Schristos #endif
249*6881a400Schristos 
250*6881a400Schristos   /* Having no CTF sections is not an error.  We just don't need to do
251*6881a400Schristos      anything.  */
252*6881a400Schristos 
253*6881a400Schristos   if (!input->clin_arc)
254*6881a400Schristos     {
255*6881a400Schristos       if (err == ECTF_NOCTFDATA)
256*6881a400Schristos 	return 0;
257*6881a400Schristos 
258*6881a400Schristos       ctf_err_warn (fp, 0, err, _("opening CTF %s failed"),
259*6881a400Schristos 		    input->clin_filename);
260*6881a400Schristos       ctf_set_errno (fp, err);
261*6881a400Schristos       return -1;
262*6881a400Schristos     }
263*6881a400Schristos 
264*6881a400Schristos   if ((count = ctf_archive_count (input->clin_arc)) == 0)
265*6881a400Schristos     ctf_arc_close (input->clin_arc);
266*6881a400Schristos 
267*6881a400Schristos   return (ssize_t) count;
268*6881a400Schristos }
269*6881a400Schristos 
270*6881a400Schristos /* Find a non-clashing unique name for a per-CU output dict, to prevent distinct
271*6881a400Schristos    members corresponding to inputs with identical cunames from overwriting each
272*6881a400Schristos    other.  The name should be something like NAME.  */
273*6881a400Schristos 
274*6881a400Schristos static char *
275*6881a400Schristos ctf_new_per_cu_name (ctf_dict_t *fp, const char *name)
276*6881a400Schristos {
277*6881a400Schristos   char *dynname;
278*6881a400Schristos   long int i = 0;
279*6881a400Schristos 
280*6881a400Schristos   if ((dynname = strdup (name)) == NULL)
281*6881a400Schristos     return NULL;
282*6881a400Schristos 
283*6881a400Schristos   while ((ctf_dynhash_lookup (fp->ctf_link_outputs, dynname)) != NULL)
284*6881a400Schristos     {
285*6881a400Schristos       free (dynname);
286*6881a400Schristos       if (asprintf (&dynname, "%s#%li", name, i++) < 0)
287*6881a400Schristos 	return NULL;
288*6881a400Schristos     }
289*6881a400Schristos 
290*6881a400Schristos   return dynname;
291*6881a400Schristos }
292*6881a400Schristos 
293*6881a400Schristos /* Return a per-CU output CTF dictionary suitable for the given INPUT or CU,
294*6881a400Schristos    creating and interning it if need be.  */
295*6881a400Schristos 
296*6881a400Schristos static ctf_dict_t *
297*6881a400Schristos ctf_create_per_cu (ctf_dict_t *fp, ctf_dict_t *input, const char *cu_name)
298*6881a400Schristos {
299*6881a400Schristos   ctf_dict_t *cu_fp;
3007d62b00eSchristos   const char *ctf_name = NULL;
3017d62b00eSchristos   char *dynname = NULL;
3027d62b00eSchristos 
303*6881a400Schristos   /* Already has a per-CU mapping?  Just return it.  */
304*6881a400Schristos 
305*6881a400Schristos   if (input && input->ctf_link_in_out)
306*6881a400Schristos     return input->ctf_link_in_out;
307*6881a400Schristos 
308*6881a400Schristos   /* Check the mapping table and translate the per-CU name we use
309*6881a400Schristos      accordingly.  */
310*6881a400Schristos 
311*6881a400Schristos   if (cu_name == NULL)
312*6881a400Schristos     cu_name = ctf_unnamed_cuname (input);
3137d62b00eSchristos 
3147d62b00eSchristos   if (fp->ctf_link_in_cu_mapping)
3157d62b00eSchristos     {
316*6881a400Schristos       if ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_in_cu_mapping,
317*6881a400Schristos 					  cu_name)) == NULL)
318*6881a400Schristos 	ctf_name = cu_name;
3197d62b00eSchristos     }
3207d62b00eSchristos 
3217d62b00eSchristos   if (ctf_name == NULL)
322*6881a400Schristos     ctf_name = cu_name;
3237d62b00eSchristos 
324*6881a400Schristos   /* Look up the per-CU dict.  If we don't know of one, or it is for
325*6881a400Schristos      a different input CU which just happens to have the same name,
326*6881a400Schristos      create a new one.  */
327*6881a400Schristos 
328*6881a400Schristos   if ((cu_fp = ctf_dynhash_lookup (fp->ctf_link_outputs, ctf_name)) == NULL
329*6881a400Schristos       || cu_fp->ctf_link_in_out != fp)
3307d62b00eSchristos     {
3317d62b00eSchristos       int err;
3327d62b00eSchristos 
3337d62b00eSchristos       if ((cu_fp = ctf_create (&err)) == NULL)
3347d62b00eSchristos 	{
3357d62b00eSchristos 	  ctf_err_warn (fp, 0, err, _("cannot create per-CU CTF archive for "
336*6881a400Schristos 				      "input CU %s"), cu_name);
3377d62b00eSchristos 	  ctf_set_errno (fp, err);
3387d62b00eSchristos 	  return NULL;
3397d62b00eSchristos 	}
3407d62b00eSchristos 
341*6881a400Schristos       ctf_import_unref (cu_fp, fp);
342*6881a400Schristos 
343*6881a400Schristos       if ((dynname = ctf_new_per_cu_name (fp, ctf_name)) == NULL)
3447d62b00eSchristos 	goto oom;
3457d62b00eSchristos 
346*6881a400Schristos       ctf_cuname_set (cu_fp, cu_name);
347*6881a400Schristos 
3487d62b00eSchristos       ctf_parent_name_set (cu_fp, _CTF_SECTION);
349*6881a400Schristos       cu_fp->ctf_link_in_out = fp;
350*6881a400Schristos       fp->ctf_link_in_out = cu_fp;
351*6881a400Schristos 
352*6881a400Schristos       if (ctf_dynhash_insert (fp->ctf_link_outputs, dynname, cu_fp) < 0)
353*6881a400Schristos 	goto oom;
3547d62b00eSchristos     }
3557d62b00eSchristos   return cu_fp;
3567d62b00eSchristos 
3577d62b00eSchristos  oom:
3587d62b00eSchristos   free (dynname);
359*6881a400Schristos   ctf_dict_close (cu_fp);
3607d62b00eSchristos   ctf_set_errno (fp, ENOMEM);
3617d62b00eSchristos   return NULL;
3627d62b00eSchristos }
3637d62b00eSchristos 
3647d62b00eSchristos /* Add a mapping directing that the CU named FROM should have its
365*6881a400Schristos    conflicting/non-duplicate types (depending on link mode) go into a dict
3667d62b00eSchristos    named TO.  Many FROMs can share a TO.
3677d62b00eSchristos 
368*6881a400Schristos    We forcibly add a dict named TO in every case, even though it may well
3697d62b00eSchristos    wind up empty, because clients that use this facility usually expect to find
370*6881a400Schristos    every TO dict present, even if empty, and malfunction otherwise.  */
3717d62b00eSchristos 
3727d62b00eSchristos int
373*6881a400Schristos ctf_link_add_cu_mapping (ctf_dict_t *fp, const char *from, const char *to)
3747d62b00eSchristos {
3757d62b00eSchristos   int err;
3767d62b00eSchristos   char *f = NULL, *t = NULL;
3777d62b00eSchristos   ctf_dynhash_t *one_out;
3787d62b00eSchristos 
379*6881a400Schristos   /* Mappings cannot be set up if per-CU output dicts already exist.  */
380*6881a400Schristos   if (fp->ctf_link_outputs && ctf_dynhash_elements (fp->ctf_link_outputs) != 0)
381*6881a400Schristos       return (ctf_set_errno (fp, ECTF_LINKADDEDLATE));
382*6881a400Schristos 
3837d62b00eSchristos   if (fp->ctf_link_in_cu_mapping == NULL)
3847d62b00eSchristos     fp->ctf_link_in_cu_mapping = ctf_dynhash_create (ctf_hash_string,
3857d62b00eSchristos 						     ctf_hash_eq_string, free,
3867d62b00eSchristos 						     free);
3877d62b00eSchristos   if (fp->ctf_link_in_cu_mapping == NULL)
3887d62b00eSchristos     goto oom;
3897d62b00eSchristos 
3907d62b00eSchristos   if (fp->ctf_link_out_cu_mapping == NULL)
3917d62b00eSchristos     fp->ctf_link_out_cu_mapping = ctf_dynhash_create (ctf_hash_string,
3927d62b00eSchristos 						      ctf_hash_eq_string, free,
3937d62b00eSchristos 						      (ctf_hash_free_fun)
3947d62b00eSchristos 						      ctf_dynhash_destroy);
3957d62b00eSchristos   if (fp->ctf_link_out_cu_mapping == NULL)
3967d62b00eSchristos     goto oom;
3977d62b00eSchristos 
3987d62b00eSchristos   f = strdup (from);
3997d62b00eSchristos   t = strdup (to);
4007d62b00eSchristos   if (!f || !t)
4017d62b00eSchristos     goto oom;
4027d62b00eSchristos 
4037d62b00eSchristos   /* Track both in a list from FROM to TO and in a list from TO to a list of
4047d62b00eSchristos      FROM.  The former is used to create TUs with the mapped-to name at need:
4057d62b00eSchristos      the latter is used in deduplicating links to pull in all input CUs
4067d62b00eSchristos      corresponding to a single output CU.  */
4077d62b00eSchristos 
4087d62b00eSchristos   if ((err = ctf_dynhash_insert (fp->ctf_link_in_cu_mapping, f, t)) < 0)
4097d62b00eSchristos     {
4107d62b00eSchristos       ctf_set_errno (fp, err);
4117d62b00eSchristos       goto oom_noerrno;
4127d62b00eSchristos     }
4137d62b00eSchristos 
4147d62b00eSchristos   /* f and t are now owned by the in_cu_mapping: reallocate them.  */
4157d62b00eSchristos   f = strdup (from);
4167d62b00eSchristos   t = strdup (to);
4177d62b00eSchristos   if (!f || !t)
4187d62b00eSchristos     goto oom;
4197d62b00eSchristos 
4207d62b00eSchristos   if ((one_out = ctf_dynhash_lookup (fp->ctf_link_out_cu_mapping, t)) == NULL)
4217d62b00eSchristos     {
4227d62b00eSchristos       if ((one_out = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
4237d62b00eSchristos 					 free, NULL)) == NULL)
4247d62b00eSchristos 	goto oom;
4257d62b00eSchristos       if ((err = ctf_dynhash_insert (fp->ctf_link_out_cu_mapping,
4267d62b00eSchristos 				     t, one_out)) < 0)
4277d62b00eSchristos 	{
4287d62b00eSchristos 	  ctf_dynhash_destroy (one_out);
4297d62b00eSchristos 	  ctf_set_errno (fp, err);
4307d62b00eSchristos 	  goto oom_noerrno;
4317d62b00eSchristos 	}
4327d62b00eSchristos     }
4337d62b00eSchristos   else
434*6881a400Schristos     {
4357d62b00eSchristos       free (t);
436*6881a400Schristos       t = NULL;
437*6881a400Schristos     }
4387d62b00eSchristos 
4397d62b00eSchristos   if (ctf_dynhash_insert (one_out, f, NULL) < 0)
4407d62b00eSchristos     {
4417d62b00eSchristos       ctf_set_errno (fp, err);
4427d62b00eSchristos       goto oom_noerrno;
4437d62b00eSchristos     }
4447d62b00eSchristos 
4457d62b00eSchristos   return 0;
4467d62b00eSchristos 
4477d62b00eSchristos  oom:
4487d62b00eSchristos   ctf_set_errno (fp, errno);
4497d62b00eSchristos  oom_noerrno:
4507d62b00eSchristos   free (f);
4517d62b00eSchristos   free (t);
4527d62b00eSchristos   return -1;
4537d62b00eSchristos }
4547d62b00eSchristos 
4557d62b00eSchristos /* Set a function which is called to transform the names of archive members.
4567d62b00eSchristos    This is useful for applying regular transformations to many names, where
4577d62b00eSchristos    ctf_link_add_cu_mapping applies arbitrarily irregular changes to single
4587d62b00eSchristos    names.  The member name changer is applied at ctf_link_write time, so it
4597d62b00eSchristos    cannot conflate multiple CUs into one the way ctf_link_add_cu_mapping can.
4607d62b00eSchristos    The changer function accepts a name and should return a new
4617d62b00eSchristos    dynamically-allocated name, or NULL if the name should be left unchanged.  */
4627d62b00eSchristos void
463*6881a400Schristos ctf_link_set_memb_name_changer (ctf_dict_t *fp,
4647d62b00eSchristos 				ctf_link_memb_name_changer_f *changer,
4657d62b00eSchristos 				void *arg)
4667d62b00eSchristos {
4677d62b00eSchristos   fp->ctf_link_memb_name_changer = changer;
4687d62b00eSchristos   fp->ctf_link_memb_name_changer_arg = arg;
4697d62b00eSchristos }
4707d62b00eSchristos 
4717d62b00eSchristos /* Set a function which is used to filter out unwanted variables from the link.  */
4727d62b00eSchristos int
473*6881a400Schristos ctf_link_set_variable_filter (ctf_dict_t *fp, ctf_link_variable_filter_f *filter,
4747d62b00eSchristos 			      void *arg)
4757d62b00eSchristos {
4767d62b00eSchristos   fp->ctf_link_variable_filter = filter;
4777d62b00eSchristos   fp->ctf_link_variable_filter_arg = arg;
4787d62b00eSchristos   return 0;
4797d62b00eSchristos }
4807d62b00eSchristos 
481*6881a400Schristos /* Check if we can safely add a variable with the given type to this dict.  */
4827d62b00eSchristos 
4837d62b00eSchristos static int
484*6881a400Schristos check_variable (const char *name, ctf_dict_t *fp, ctf_id_t type,
4857d62b00eSchristos 		ctf_dvdef_t **out_dvd)
4867d62b00eSchristos {
4877d62b00eSchristos   ctf_dvdef_t *dvd;
4887d62b00eSchristos 
4897d62b00eSchristos   dvd = ctf_dynhash_lookup (fp->ctf_dvhash, name);
4907d62b00eSchristos   *out_dvd = dvd;
4917d62b00eSchristos   if (!dvd)
4927d62b00eSchristos     return 1;
4937d62b00eSchristos 
4947d62b00eSchristos   if (dvd->dvd_type != type)
4957d62b00eSchristos     {
4967d62b00eSchristos       /* Variable here.  Wrong type: cannot add.  Just skip it, because there is
4977d62b00eSchristos 	 no way to express this in CTF.  Don't even warn: this case is too
4987d62b00eSchristos 	 common.  (This might be the parent, in which case we'll try adding in
4997d62b00eSchristos 	 the child first, and only then give up.)  */
5007d62b00eSchristos       ctf_dprintf ("Inexpressible duplicate variable %s skipped.\n", name);
5017d62b00eSchristos     }
5027d62b00eSchristos 
5037d62b00eSchristos   return 0;				      /* Already exists.  */
5047d62b00eSchristos }
5057d62b00eSchristos 
506*6881a400Schristos /* Link one variable named NAME of type TYPE found in IN_FP into FP.  */
5077d62b00eSchristos 
5087d62b00eSchristos static int
509*6881a400Schristos ctf_link_one_variable (ctf_dict_t *fp, ctf_dict_t *in_fp, const char *name,
510*6881a400Schristos 		       ctf_id_t type, int cu_mapped)
5117d62b00eSchristos {
512*6881a400Schristos   ctf_dict_t *per_cu_out_fp;
5137d62b00eSchristos   ctf_id_t dst_type = 0;
5147d62b00eSchristos   ctf_dvdef_t *dvd;
5157d62b00eSchristos 
5167d62b00eSchristos   /* See if this variable is filtered out.  */
5177d62b00eSchristos 
518*6881a400Schristos   if (fp->ctf_link_variable_filter)
5197d62b00eSchristos     {
520*6881a400Schristos       void *farg = fp->ctf_link_variable_filter_arg;
521*6881a400Schristos       if (fp->ctf_link_variable_filter (in_fp, name, type, farg))
5227d62b00eSchristos 	return 0;
5237d62b00eSchristos     }
5247d62b00eSchristos 
525*6881a400Schristos   /* If this type is mapped to a type in the parent dict, we want to try to add
526*6881a400Schristos      to that first: if it reports a duplicate, or if the type is in a child
527*6881a400Schristos      already, add straight to the child.  */
5287d62b00eSchristos 
529*6881a400Schristos   if ((dst_type = ctf_dedup_type_mapping (fp, in_fp, type)) == CTF_ERR)
530*6881a400Schristos     return -1;					/* errno is set for us.  */
5317d62b00eSchristos 
5327d62b00eSchristos   if (dst_type != 0)
5337d62b00eSchristos     {
534*6881a400Schristos       if (!ctf_assert (fp, ctf_type_isparent (fp, dst_type)))
535*6881a400Schristos 	return -1;				/* errno is set for us.  */
536*6881a400Schristos 
537*6881a400Schristos       if (check_variable (name, fp, dst_type, &dvd))
5387d62b00eSchristos 	{
5397d62b00eSchristos 	  /* No variable here: we can add it.  */
540*6881a400Schristos 	  if (ctf_add_variable (fp, name, dst_type) < 0)
541*6881a400Schristos 	    return -1; 				/* errno is set for us.  */
5427d62b00eSchristos 	  return 0;
5437d62b00eSchristos 	}
5447d62b00eSchristos 
5457d62b00eSchristos       /* Already present?  Nothing to do.  */
5467d62b00eSchristos       if (dvd && dvd->dvd_type == dst_type)
5477d62b00eSchristos 	return 0;
5487d62b00eSchristos     }
5497d62b00eSchristos 
5507d62b00eSchristos   /* Can't add to the parent due to a name clash, or because it references a
5517d62b00eSchristos      type only present in the child.  Try adding to the child, creating if need
5527d62b00eSchristos      be.  If we can't do that, skip it.  Don't add to a child if we're doing a
5537d62b00eSchristos      CU-mapped link, since that has only one output.  */
5547d62b00eSchristos 
555*6881a400Schristos   if (cu_mapped)
5567d62b00eSchristos     {
5577d62b00eSchristos       ctf_dprintf ("Variable %s in input file %s depends on a type %lx hidden "
558*6881a400Schristos 		   "due to conflicts: skipped.\n", name,
559*6881a400Schristos 		   ctf_unnamed_cuname (in_fp), type);
5607d62b00eSchristos       return 0;
5617d62b00eSchristos     }
5627d62b00eSchristos 
563*6881a400Schristos   if ((per_cu_out_fp = ctf_create_per_cu (fp, in_fp, NULL)) == NULL)
564*6881a400Schristos     return -1;					/* errno is set for us.  */
5657d62b00eSchristos 
5667d62b00eSchristos   /* If the type was not found, check for it in the child too.  */
5677d62b00eSchristos   if (dst_type == 0)
5687d62b00eSchristos     {
569*6881a400Schristos       if ((dst_type = ctf_dedup_type_mapping (per_cu_out_fp,
570*6881a400Schristos 					      in_fp, type)) == CTF_ERR)
571*6881a400Schristos 	return -1;				/* errno is set for us.   */
5727d62b00eSchristos 
5737d62b00eSchristos       if (dst_type == 0)
5747d62b00eSchristos 	{
575*6881a400Schristos 	  ctf_err_warn (fp, 1, 0, _("type %lx for variable %s in input file %s "
5767d62b00eSchristos 				    "not found: skipped"), type, name,
577*6881a400Schristos 			ctf_unnamed_cuname (in_fp));
5787d62b00eSchristos 	  /* Do not terminate the link: just skip the variable.  */
5797d62b00eSchristos 	  return 0;
5807d62b00eSchristos 	}
5817d62b00eSchristos     }
5827d62b00eSchristos 
5837d62b00eSchristos   if (check_variable (name, per_cu_out_fp, dst_type, &dvd))
5847d62b00eSchristos     if (ctf_add_variable (per_cu_out_fp, name, dst_type) < 0)
585*6881a400Schristos       return (ctf_set_errno (fp, ctf_errno (per_cu_out_fp)));
5867d62b00eSchristos   return 0;
5877d62b00eSchristos }
5887d62b00eSchristos 
5897d62b00eSchristos typedef struct link_sort_inputs_cb_arg
5907d62b00eSchristos {
5917d62b00eSchristos   int is_cu_mapped;
592*6881a400Schristos   ctf_dict_t *fp;
5937d62b00eSchristos } link_sort_inputs_cb_arg_t;
5947d62b00eSchristos 
5957d62b00eSchristos /* Sort the inputs by N (the link order).  For CU-mapped links, this is a
5967d62b00eSchristos    mapping of input to output name, not a mapping of input name to input
5977d62b00eSchristos    ctf_link_input_t: compensate accordingly.  */
5987d62b00eSchristos static int
5997d62b00eSchristos ctf_link_sort_inputs (const ctf_next_hkv_t *one, const ctf_next_hkv_t *two,
6007d62b00eSchristos 		      void *arg)
6017d62b00eSchristos {
6027d62b00eSchristos   ctf_link_input_t *input_1;
6037d62b00eSchristos   ctf_link_input_t *input_2;
6047d62b00eSchristos   link_sort_inputs_cb_arg_t *cu_mapped = (link_sort_inputs_cb_arg_t *) arg;
6057d62b00eSchristos 
6067d62b00eSchristos   if (!cu_mapped || !cu_mapped->is_cu_mapped)
6077d62b00eSchristos     {
6087d62b00eSchristos       input_1 = (ctf_link_input_t *) one->hkv_value;
6097d62b00eSchristos       input_2 = (ctf_link_input_t *) two->hkv_value;
6107d62b00eSchristos     }
6117d62b00eSchristos   else
6127d62b00eSchristos     {
6137d62b00eSchristos       const char *name_1 = (const char *) one->hkv_key;
6147d62b00eSchristos       const char *name_2 = (const char *) two->hkv_key;
6157d62b00eSchristos 
6167d62b00eSchristos       input_1 = ctf_dynhash_lookup (cu_mapped->fp->ctf_link_inputs, name_1);
6177d62b00eSchristos       input_2 = ctf_dynhash_lookup (cu_mapped->fp->ctf_link_inputs, name_2);
6187d62b00eSchristos 
6197d62b00eSchristos       /* There is no guarantee that CU-mappings actually have corresponding
6207d62b00eSchristos 	 inputs: the relative ordering in that case is unimportant.  */
6217d62b00eSchristos       if (!input_1)
6227d62b00eSchristos 	return -1;
6237d62b00eSchristos       if (!input_2)
6247d62b00eSchristos 	return 1;
6257d62b00eSchristos     }
6267d62b00eSchristos 
6277d62b00eSchristos   if (input_1->n < input_2->n)
6287d62b00eSchristos     return -1;
6297d62b00eSchristos   else if (input_1->n > input_2->n)
6307d62b00eSchristos     return 1;
6317d62b00eSchristos   else
6327d62b00eSchristos     return 0;
6337d62b00eSchristos }
6347d62b00eSchristos 
6357d62b00eSchristos /* Count the number of input dicts in the ctf_link_inputs, or that subset of the
6367d62b00eSchristos    ctf_link_inputs given by CU_NAMES if set.  Return the number of input dicts,
6377d62b00eSchristos    and optionally the name and ctf_link_input_t of the single input archive if
6387d62b00eSchristos    only one exists (no matter how many dicts it contains).  */
6397d62b00eSchristos static ssize_t
640*6881a400Schristos ctf_link_deduplicating_count_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
6417d62b00eSchristos 				     ctf_link_input_t **only_one_input)
6427d62b00eSchristos {
6437d62b00eSchristos   ctf_dynhash_t *inputs = fp->ctf_link_inputs;
6447d62b00eSchristos   ctf_next_t *i = NULL;
6457d62b00eSchristos   void *name, *input;
6467d62b00eSchristos   ctf_link_input_t *one_input = NULL;
6477d62b00eSchristos   const char *one_name = NULL;
6487d62b00eSchristos   ssize_t count = 0, narcs = 0;
6497d62b00eSchristos   int err;
6507d62b00eSchristos 
6517d62b00eSchristos   if (cu_names)
6527d62b00eSchristos     inputs = cu_names;
6537d62b00eSchristos 
6547d62b00eSchristos   while ((err = ctf_dynhash_next (inputs, &i, &name, &input)) == 0)
6557d62b00eSchristos     {
6567d62b00eSchristos       ssize_t one_count;
6577d62b00eSchristos 
6587d62b00eSchristos       one_name = (const char *) name;
6597d62b00eSchristos       /* If we are processing CU names, get the real input.  */
6607d62b00eSchristos       if (cu_names)
6617d62b00eSchristos 	one_input = ctf_dynhash_lookup (fp->ctf_link_inputs, one_name);
6627d62b00eSchristos       else
6637d62b00eSchristos 	one_input = (ctf_link_input_t *) input;
6647d62b00eSchristos 
6657d62b00eSchristos       if (!one_input)
6667d62b00eSchristos 	continue;
6677d62b00eSchristos 
6687d62b00eSchristos       one_count = ctf_link_lazy_open (fp, one_input);
6697d62b00eSchristos 
6707d62b00eSchristos       if (one_count < 0)
6717d62b00eSchristos 	{
6727d62b00eSchristos 	  ctf_next_destroy (i);
6737d62b00eSchristos 	  return -1;				/* errno is set for us.  */
6747d62b00eSchristos 	}
6757d62b00eSchristos 
6767d62b00eSchristos       count += one_count;
6777d62b00eSchristos       narcs++;
6787d62b00eSchristos     }
6797d62b00eSchristos   if (err != ECTF_NEXT_END)
6807d62b00eSchristos     {
6817d62b00eSchristos       ctf_err_warn (fp, 0, err, _("iteration error counting deduplicating "
6827d62b00eSchristos 				  "CTF link inputs"));
6837d62b00eSchristos       ctf_set_errno (fp, err);
6847d62b00eSchristos       return -1;
6857d62b00eSchristos     }
6867d62b00eSchristos 
6877d62b00eSchristos   if (!count)
6887d62b00eSchristos     return 0;
6897d62b00eSchristos 
6907d62b00eSchristos   if (narcs == 1)
6917d62b00eSchristos     {
6927d62b00eSchristos       if (only_one_input)
6937d62b00eSchristos 	*only_one_input = one_input;
6947d62b00eSchristos     }
6957d62b00eSchristos   else if (only_one_input)
6967d62b00eSchristos     *only_one_input = NULL;
6977d62b00eSchristos 
6987d62b00eSchristos   return count;
6997d62b00eSchristos }
7007d62b00eSchristos 
7017d62b00eSchristos /* Allocate and populate an inputs array big enough for a given set of inputs:
7027d62b00eSchristos    either a specific set of CU names (those from that set found in the
7037d62b00eSchristos    ctf_link_inputs), or the entire ctf_link_inputs (if cu_names is not set).
7047d62b00eSchristos    The number of inputs (from ctf_link_deduplicating_count_inputs, above) is
7057d62b00eSchristos    passed in NINPUTS: an array of uint32_t containing parent pointers
7067d62b00eSchristos    (corresponding to those members of the inputs that have parents) is allocated
7077d62b00eSchristos    and returned in PARENTS.
7087d62b00eSchristos 
7097d62b00eSchristos    The inputs are *archives*, not files: the archive can have multiple members
7107d62b00eSchristos    if it is the result of a previous incremental link.  We want to add every one
7117d62b00eSchristos    in turn, including the shared parent.  (The dedup machinery knows that a type
7127d62b00eSchristos    used by a single dictionary and its parent should not be shared in
7137d62b00eSchristos    CTF_LINK_SHARE_DUPLICATED mode.)
7147d62b00eSchristos 
7157d62b00eSchristos    If no inputs exist that correspond to these CUs, return NULL with the errno
7167d62b00eSchristos    set to ECTF_NOCTFDATA.  */
717*6881a400Schristos static ctf_dict_t **
718*6881a400Schristos ctf_link_deduplicating_open_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
7197d62b00eSchristos 				    ssize_t ninputs, uint32_t **parents)
7207d62b00eSchristos {
7217d62b00eSchristos   ctf_dynhash_t *inputs = fp->ctf_link_inputs;
7227d62b00eSchristos   ctf_next_t *i = NULL;
7237d62b00eSchristos   void *name, *input;
7247d62b00eSchristos   link_sort_inputs_cb_arg_t sort_arg;
725*6881a400Schristos   ctf_dict_t **dedup_inputs = NULL;
726*6881a400Schristos   ctf_dict_t **walk;
7277d62b00eSchristos   uint32_t *parents_ = NULL;
7287d62b00eSchristos   int err;
7297d62b00eSchristos 
7307d62b00eSchristos   if (cu_names)
7317d62b00eSchristos     inputs = cu_names;
7327d62b00eSchristos 
733*6881a400Schristos   if ((dedup_inputs = calloc (ninputs, sizeof (ctf_dict_t *))) == NULL)
7347d62b00eSchristos     goto oom;
7357d62b00eSchristos 
7367d62b00eSchristos   if ((parents_ = calloc (ninputs, sizeof (uint32_t))) == NULL)
7377d62b00eSchristos     goto oom;
7387d62b00eSchristos 
7397d62b00eSchristos   walk = dedup_inputs;
7407d62b00eSchristos 
7417d62b00eSchristos   /* Counting done: push every input into the array, in the order they were
7427d62b00eSchristos      passed to ctf_link_add_ctf (and ultimately ld).  */
7437d62b00eSchristos 
7447d62b00eSchristos   sort_arg.is_cu_mapped = (cu_names != NULL);
7457d62b00eSchristos   sort_arg.fp = fp;
7467d62b00eSchristos 
7477d62b00eSchristos   while ((err = ctf_dynhash_next_sorted (inputs, &i, &name, &input,
7487d62b00eSchristos 					 ctf_link_sort_inputs, &sort_arg)) == 0)
7497d62b00eSchristos     {
7507d62b00eSchristos       const char *one_name = (const char *) name;
7517d62b00eSchristos       ctf_link_input_t *one_input;
752*6881a400Schristos       ctf_dict_t *one_fp;
753*6881a400Schristos       ctf_dict_t *parent_fp = NULL;
7547d62b00eSchristos       uint32_t parent_i;
7557d62b00eSchristos       ctf_next_t *j = NULL;
7567d62b00eSchristos 
7577d62b00eSchristos       /* If we are processing CU names, get the real input.  All the inputs
7587d62b00eSchristos 	 will have been opened, if they contained any CTF at all.  */
7597d62b00eSchristos       if (cu_names)
7607d62b00eSchristos 	one_input = ctf_dynhash_lookup (fp->ctf_link_inputs, one_name);
7617d62b00eSchristos       else
7627d62b00eSchristos 	one_input = (ctf_link_input_t *) input;
7637d62b00eSchristos 
7647d62b00eSchristos       if (!one_input || (!one_input->clin_arc && !one_input->clin_fp))
7657d62b00eSchristos 	continue;
7667d62b00eSchristos 
7677d62b00eSchristos       /* Short-circuit: if clin_fp is set, just use it.   */
7687d62b00eSchristos       if (one_input->clin_fp)
7697d62b00eSchristos 	{
7707d62b00eSchristos 	  parents_[walk - dedup_inputs] = walk - dedup_inputs;
7717d62b00eSchristos 	  *walk = one_input->clin_fp;
7727d62b00eSchristos 	  walk++;
7737d62b00eSchristos 	  continue;
7747d62b00eSchristos 	}
7757d62b00eSchristos 
7767d62b00eSchristos       /* Get and insert the parent archive (if any), if this archive has
7777d62b00eSchristos 	 multiple members.  We assume, as elsewhere, that the parent is named
7787d62b00eSchristos 	 _CTF_SECTION.  */
7797d62b00eSchristos 
780*6881a400Schristos       if ((parent_fp = ctf_dict_open (one_input->clin_arc, _CTF_SECTION,
781*6881a400Schristos 				      &err)) == NULL)
7827d62b00eSchristos 	{
7837d62b00eSchristos 	  if (err != ECTF_NOMEMBNAM)
7847d62b00eSchristos 	    {
7857d62b00eSchristos 	      ctf_next_destroy (i);
7867d62b00eSchristos 	      ctf_set_errno (fp, err);
7877d62b00eSchristos 	      goto err;
7887d62b00eSchristos 	    }
7897d62b00eSchristos 	}
7907d62b00eSchristos       else
7917d62b00eSchristos 	{
7927d62b00eSchristos 	  *walk = parent_fp;
7937d62b00eSchristos 	  parent_i = walk - dedup_inputs;
7947d62b00eSchristos 	  walk++;
7957d62b00eSchristos 	}
7967d62b00eSchristos 
7977d62b00eSchristos       /* We disregard the input archive name: either it is the parent (which we
7987d62b00eSchristos 	 already have), or we want to put everything into one TU sharing the
7997d62b00eSchristos 	 cuname anyway (if this is a CU-mapped link), or this is the final phase
8007d62b00eSchristos 	 of a relink with CU-mapping off (i.e. ld -r) in which case the cuname
8017d62b00eSchristos 	 is correctly set regardless.  */
8027d62b00eSchristos       while ((one_fp = ctf_archive_next (one_input->clin_arc, &j, NULL,
8037d62b00eSchristos 					 1, &err)) != NULL)
8047d62b00eSchristos 	{
8057d62b00eSchristos 	  if (one_fp->ctf_flags & LCTF_CHILD)
8067d62b00eSchristos 	    {
8077d62b00eSchristos 	      /* The contents of the parents array for elements not
8087d62b00eSchristos 		 corresponding to children is undefined.  If there is no parent
8097d62b00eSchristos 		 (itself a sign of a likely linker bug or corrupt input), we set
8107d62b00eSchristos 		 it to itself.  */
8117d62b00eSchristos 
8127d62b00eSchristos 	      ctf_import (one_fp, parent_fp);
8137d62b00eSchristos 	      if (parent_fp)
8147d62b00eSchristos 		parents_[walk - dedup_inputs] = parent_i;
8157d62b00eSchristos 	      else
8167d62b00eSchristos 		parents_[walk - dedup_inputs] = walk - dedup_inputs;
8177d62b00eSchristos 	    }
8187d62b00eSchristos 	  *walk = one_fp;
8197d62b00eSchristos 	  walk++;
8207d62b00eSchristos 	}
8217d62b00eSchristos       if (err != ECTF_NEXT_END)
8227d62b00eSchristos 	{
8237d62b00eSchristos 	  ctf_next_destroy (i);
8247d62b00eSchristos 	  goto iterr;
8257d62b00eSchristos 	}
8267d62b00eSchristos     }
8277d62b00eSchristos   if (err != ECTF_NEXT_END)
8287d62b00eSchristos     goto iterr;
8297d62b00eSchristos 
8307d62b00eSchristos   *parents = parents_;
8317d62b00eSchristos 
8327d62b00eSchristos   return dedup_inputs;
8337d62b00eSchristos 
8347d62b00eSchristos  oom:
8357d62b00eSchristos   err = ENOMEM;
8367d62b00eSchristos 
8377d62b00eSchristos  iterr:
8387d62b00eSchristos   ctf_set_errno (fp, err);
8397d62b00eSchristos 
8407d62b00eSchristos  err:
8417d62b00eSchristos   free (dedup_inputs);
8427d62b00eSchristos   free (parents_);
8437d62b00eSchristos   ctf_err_warn (fp, 0, 0, _("error in deduplicating CTF link "
8447d62b00eSchristos 			    "input allocation"));
8457d62b00eSchristos   return NULL;
8467d62b00eSchristos }
8477d62b00eSchristos 
8487d62b00eSchristos /* Close INPUTS that have already been linked, first the passed array, and then
8497d62b00eSchristos    that subset of the ctf_link_inputs archives they came from cited by the
8507d62b00eSchristos    CU_NAMES.  If CU_NAMES is not specified, close all the ctf_link_inputs in one
8517d62b00eSchristos    go, leaving it empty.  */
8527d62b00eSchristos static int
853*6881a400Schristos ctf_link_deduplicating_close_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
854*6881a400Schristos 				     ctf_dict_t **inputs, ssize_t ninputs)
8557d62b00eSchristos {
8567d62b00eSchristos   ctf_next_t *it = NULL;
8577d62b00eSchristos   void *name;
8587d62b00eSchristos   int err;
8597d62b00eSchristos   ssize_t i;
8607d62b00eSchristos 
8617d62b00eSchristos   /* This is the inverse of ctf_link_deduplicating_open_inputs: so first, close
8627d62b00eSchristos      all the individual input dicts, opened by the archive iterator.  */
8637d62b00eSchristos   for (i = 0; i < ninputs; i++)
864*6881a400Schristos     ctf_dict_close (inputs[i]);
8657d62b00eSchristos 
8667d62b00eSchristos   /* Now close the archives they are part of.  */
8677d62b00eSchristos   if (cu_names)
8687d62b00eSchristos     {
8697d62b00eSchristos       while ((err = ctf_dynhash_next (cu_names, &it, &name, NULL)) == 0)
8707d62b00eSchristos 	{
8717d62b00eSchristos 	  /* Remove the input from the linker inputs, if it exists, which also
8727d62b00eSchristos 	     closes it.  */
8737d62b00eSchristos 
8747d62b00eSchristos 	  ctf_dynhash_remove (fp->ctf_link_inputs, (const char *) name);
8757d62b00eSchristos 	}
8767d62b00eSchristos       if (err != ECTF_NEXT_END)
8777d62b00eSchristos 	{
8787d62b00eSchristos 	  ctf_err_warn (fp, 0, err, _("iteration error in deduplicating link "
8797d62b00eSchristos 				      "input freeing"));
8807d62b00eSchristos 	  ctf_set_errno (fp, err);
8817d62b00eSchristos 	}
8827d62b00eSchristos     }
8837d62b00eSchristos   else
8847d62b00eSchristos     ctf_dynhash_empty (fp->ctf_link_inputs);
8857d62b00eSchristos 
8867d62b00eSchristos   return 0;
8877d62b00eSchristos }
8887d62b00eSchristos 
889*6881a400Schristos /* Do a deduplicating link of all variables in the inputs.
890*6881a400Schristos 
891*6881a400Schristos    Also, if we are not omitting the variable section, integrate all symbols from
892*6881a400Schristos    the symtypetabs into the variable section too.  (Duplication with the
893*6881a400Schristos    symtypetab section in the output will be eliminated at serialization time.)  */
894*6881a400Schristos 
8957d62b00eSchristos static int
896*6881a400Schristos ctf_link_deduplicating_variables (ctf_dict_t *fp, ctf_dict_t **inputs,
8977d62b00eSchristos 				  size_t ninputs, int cu_mapped)
8987d62b00eSchristos {
8997d62b00eSchristos   size_t i;
9007d62b00eSchristos 
9017d62b00eSchristos   for (i = 0; i < ninputs; i++)
9027d62b00eSchristos     {
903*6881a400Schristos       ctf_next_t *it = NULL;
904*6881a400Schristos       ctf_id_t type;
905*6881a400Schristos       const char *name;
9067d62b00eSchristos 
907*6881a400Schristos       /* First the variables on the inputs.  */
908*6881a400Schristos 
909*6881a400Schristos       while ((type = ctf_variable_next (inputs[i], &it, &name)) != CTF_ERR)
910*6881a400Schristos 	{
911*6881a400Schristos 	  if (ctf_link_one_variable (fp, inputs[i], name, type, cu_mapped) < 0)
912*6881a400Schristos 	    {
913*6881a400Schristos 	      ctf_next_destroy (it);
914*6881a400Schristos 	      return -1;			/* errno is set for us.  */
9157d62b00eSchristos 	    }
916*6881a400Schristos 	}
917*6881a400Schristos       if (ctf_errno (inputs[i]) != ECTF_NEXT_END)
918*6881a400Schristos 	return ctf_set_errno (fp, ctf_errno (inputs[i]));
919*6881a400Schristos 
920*6881a400Schristos       /* Next the symbols.  We integrate data symbols even though the compiler
921*6881a400Schristos 	 is currently doing the same, to allow the compiler to stop in
922*6881a400Schristos 	 future.  */
923*6881a400Schristos 
924*6881a400Schristos       while ((type = ctf_symbol_next (inputs[i], &it, &name, 0)) != CTF_ERR)
925*6881a400Schristos 	{
926*6881a400Schristos 	  if (ctf_link_one_variable (fp, inputs[i], name, type, 1) < 0)
927*6881a400Schristos 	    {
928*6881a400Schristos 	      ctf_next_destroy (it);
929*6881a400Schristos 	      return -1;			/* errno is set for us.  */
930*6881a400Schristos 	    }
931*6881a400Schristos 	}
932*6881a400Schristos       if (ctf_errno (inputs[i]) != ECTF_NEXT_END)
933*6881a400Schristos 	return ctf_set_errno (fp, ctf_errno (inputs[i]));
934*6881a400Schristos 
935*6881a400Schristos       /* Finally the function symbols.  */
936*6881a400Schristos 
937*6881a400Schristos       while ((type = ctf_symbol_next (inputs[i], &it, &name, 1)) != CTF_ERR)
938*6881a400Schristos 	{
939*6881a400Schristos 	  if (ctf_link_one_variable (fp, inputs[i], name, type, 1) < 0)
940*6881a400Schristos 	    {
941*6881a400Schristos 	      ctf_next_destroy (it);
942*6881a400Schristos 	      return -1;			/* errno is set for us.  */
943*6881a400Schristos 	    }
944*6881a400Schristos 	}
945*6881a400Schristos       if (ctf_errno (inputs[i]) != ECTF_NEXT_END)
946*6881a400Schristos 	return ctf_set_errno (fp, ctf_errno (inputs[i]));
947*6881a400Schristos     }
948*6881a400Schristos   return 0;
949*6881a400Schristos }
950*6881a400Schristos 
951*6881a400Schristos /* Check for symbol conflicts during linking.  Three possibilities: already
952*6881a400Schristos    exists, conflicting, or nonexistent.  We don't have a dvd structure we can
953*6881a400Schristos    use as a flag like check_variable does, so we use a tristate return
954*6881a400Schristos    value instead: -1: conflicting; 1: nonexistent: 0: already exists.  */
955*6881a400Schristos 
956*6881a400Schristos static int
957*6881a400Schristos check_sym (ctf_dict_t *fp, const char *name, ctf_id_t type, int functions)
958*6881a400Schristos {
959*6881a400Schristos   ctf_dynhash_t *thishash = functions ? fp->ctf_funchash : fp->ctf_objthash;
960*6881a400Schristos   ctf_dynhash_t *thathash = functions ? fp->ctf_objthash : fp->ctf_funchash;
961*6881a400Schristos   void *value;
962*6881a400Schristos 
963*6881a400Schristos   /* Wrong type (function when object is wanted, etc).  */
964*6881a400Schristos   if (ctf_dynhash_lookup_kv (thathash, name, NULL, NULL))
965*6881a400Schristos     return -1;
966*6881a400Schristos 
967*6881a400Schristos   /* Not present at all yet.  */
968*6881a400Schristos   if (!ctf_dynhash_lookup_kv (thishash, name, NULL, &value))
969*6881a400Schristos     return 1;
970*6881a400Schristos 
971*6881a400Schristos   /* Already present.  */
972*6881a400Schristos   if ((ctf_id_t) (uintptr_t) value == type)
973*6881a400Schristos     return 0;
974*6881a400Schristos 
975*6881a400Schristos   /* Wrong type.  */
976*6881a400Schristos   return -1;
977*6881a400Schristos }
978*6881a400Schristos 
979*6881a400Schristos /* Do a deduplicating link of one symtypetab (function info or data object) in
980*6881a400Schristos    one input dict.  */
981*6881a400Schristos 
982*6881a400Schristos static int
983*6881a400Schristos ctf_link_deduplicating_one_symtypetab (ctf_dict_t *fp, ctf_dict_t *input,
984*6881a400Schristos 				       int cu_mapped, int functions)
985*6881a400Schristos {
986*6881a400Schristos   ctf_next_t *it = NULL;
987*6881a400Schristos   const char *name;
988*6881a400Schristos   ctf_id_t type;
989*6881a400Schristos 
990*6881a400Schristos   while ((type = ctf_symbol_next (input, &it, &name, functions)) != CTF_ERR)
991*6881a400Schristos     {
992*6881a400Schristos       ctf_id_t dst_type;
993*6881a400Schristos       ctf_dict_t *per_cu_out_fp;
994*6881a400Schristos       int sym;
995*6881a400Schristos 
996*6881a400Schristos       /* Look in the parent first.  */
997*6881a400Schristos 
998*6881a400Schristos       if ((dst_type = ctf_dedup_type_mapping (fp, input, type)) == CTF_ERR)
999*6881a400Schristos 	return -1;				/* errno is set for us.  */
1000*6881a400Schristos 
1001*6881a400Schristos       if (dst_type != 0)
1002*6881a400Schristos 	{
1003*6881a400Schristos 	  if (!ctf_assert (fp, ctf_type_isparent (fp, dst_type)))
1004*6881a400Schristos 	    return -1;				/* errno is set for us.  */
1005*6881a400Schristos 
1006*6881a400Schristos 	  sym = check_sym (fp, name, dst_type, functions);
1007*6881a400Schristos 
1008*6881a400Schristos 	  /* Already present: next symbol.  */
1009*6881a400Schristos 	  if (sym == 0)
1010*6881a400Schristos 	    continue;
1011*6881a400Schristos 	  /* Not present: add it.  */
1012*6881a400Schristos 	  else if (sym > 0)
1013*6881a400Schristos 	    {
1014*6881a400Schristos 	      if (ctf_add_funcobjt_sym (fp, functions,
1015*6881a400Schristos 					name, dst_type) < 0)
1016*6881a400Schristos 		return -1; 			/* errno is set for us.  */
1017*6881a400Schristos 	      continue;
1018*6881a400Schristos 	    }
1019*6881a400Schristos 	}
1020*6881a400Schristos 
1021*6881a400Schristos       /* Can't add to the parent due to a name clash (most unlikely), or because
1022*6881a400Schristos 	 it references a type only present in the child.  Try adding to the
1023*6881a400Schristos 	 child, creating if need be.  If we can't do that, skip it.  Don't add
1024*6881a400Schristos 	 to a child if we're doing a CU-mapped link, since that has only one
1025*6881a400Schristos 	 output.  */
1026*6881a400Schristos       if (cu_mapped)
1027*6881a400Schristos 	{
1028*6881a400Schristos 	  ctf_dprintf ("Symbol %s in input file %s depends on a type %lx "
1029*6881a400Schristos 		       "hidden due to conflicts: skipped.\n", name,
1030*6881a400Schristos 		       ctf_unnamed_cuname (input), type);
1031*6881a400Schristos 	  continue;
1032*6881a400Schristos 	}
1033*6881a400Schristos 
1034*6881a400Schristos       if ((per_cu_out_fp = ctf_create_per_cu (fp, input, NULL)) == NULL)
1035*6881a400Schristos 	return -1;				/* errno is set for us.  */
1036*6881a400Schristos 
1037*6881a400Schristos       /* If the type was not found, check for it in the child too.  */
1038*6881a400Schristos       if (dst_type == 0)
1039*6881a400Schristos 	{
1040*6881a400Schristos 	  if ((dst_type = ctf_dedup_type_mapping (per_cu_out_fp,
1041*6881a400Schristos 						  input, type)) == CTF_ERR)
1042*6881a400Schristos 	    return -1;				/* errno is set for us.  */
1043*6881a400Schristos 
1044*6881a400Schristos 	  if (dst_type == 0)
1045*6881a400Schristos 	    {
1046*6881a400Schristos 	      ctf_err_warn (fp, 1, 0,
1047*6881a400Schristos 			    _("type %lx for symbol %s in input file %s "
1048*6881a400Schristos 			      "not found: skipped"), type, name,
1049*6881a400Schristos 			    ctf_unnamed_cuname (input));
1050*6881a400Schristos 	      continue;
1051*6881a400Schristos 	    }
1052*6881a400Schristos 	}
1053*6881a400Schristos 
1054*6881a400Schristos       sym = check_sym (per_cu_out_fp, name, dst_type, functions);
1055*6881a400Schristos 
1056*6881a400Schristos       /* Already present: next symbol.  */
1057*6881a400Schristos       if (sym == 0)
1058*6881a400Schristos 	continue;
1059*6881a400Schristos       /* Not present: add it.  */
1060*6881a400Schristos       else if (sym > 0)
1061*6881a400Schristos 	{
1062*6881a400Schristos 	  if (ctf_add_funcobjt_sym (per_cu_out_fp, functions,
1063*6881a400Schristos 				    name, dst_type) < 0)
1064*6881a400Schristos 	    return -1;				/* errno is set for us.  */
1065*6881a400Schristos 	}
1066*6881a400Schristos       else
1067*6881a400Schristos 	{
1068*6881a400Schristos 	  /* Perhaps this should be an assertion failure.  */
1069*6881a400Schristos 	  ctf_err_warn (fp, 0, ECTF_DUPLICATE,
1070*6881a400Schristos 			_("symbol %s in input file %s found conflicting "
1071*6881a400Schristos 			  "even when trying in per-CU dict."), name,
1072*6881a400Schristos 			ctf_unnamed_cuname (input));
1073*6881a400Schristos 	  return (ctf_set_errno (fp, ECTF_DUPLICATE));
1074*6881a400Schristos 	}
1075*6881a400Schristos     }
1076*6881a400Schristos   if (ctf_errno (input) != ECTF_NEXT_END)
1077*6881a400Schristos     {
1078*6881a400Schristos       ctf_set_errno (fp, ctf_errno (input));
1079*6881a400Schristos       ctf_err_warn (fp, 0, ctf_errno (input),
1080*6881a400Schristos 		    functions ? _("iterating over function symbols") :
1081*6881a400Schristos 		    _("iterating over data symbols"));
1082*6881a400Schristos       return -1;
1083*6881a400Schristos     }
1084*6881a400Schristos 
1085*6881a400Schristos   return 0;
1086*6881a400Schristos }
1087*6881a400Schristos 
1088*6881a400Schristos /* Do a deduplicating link of the function info and data objects
1089*6881a400Schristos    in the inputs.  */
1090*6881a400Schristos static int
1091*6881a400Schristos ctf_link_deduplicating_syms (ctf_dict_t *fp, ctf_dict_t **inputs,
1092*6881a400Schristos 			     size_t ninputs, int cu_mapped)
1093*6881a400Schristos {
1094*6881a400Schristos   size_t i;
1095*6881a400Schristos 
1096*6881a400Schristos   for (i = 0; i < ninputs; i++)
1097*6881a400Schristos     {
1098*6881a400Schristos       if (ctf_link_deduplicating_one_symtypetab (fp, inputs[i],
1099*6881a400Schristos 						 cu_mapped, 0) < 0)
1100*6881a400Schristos 	return -1;				/* errno is set for us.  */
1101*6881a400Schristos 
1102*6881a400Schristos       if (ctf_link_deduplicating_one_symtypetab (fp, inputs[i],
1103*6881a400Schristos 						 cu_mapped, 1) < 0)
1104*6881a400Schristos 	return -1;				/* errno is set for us.  */
1105*6881a400Schristos     }
1106*6881a400Schristos 
11077d62b00eSchristos   return 0;
11087d62b00eSchristos }
11097d62b00eSchristos 
11107d62b00eSchristos /* Do the per-CU part of a deduplicating link.  */
11117d62b00eSchristos static int
1112*6881a400Schristos ctf_link_deduplicating_per_cu (ctf_dict_t *fp)
11137d62b00eSchristos {
11147d62b00eSchristos   ctf_next_t *i = NULL;
11157d62b00eSchristos   int err;
11167d62b00eSchristos   void *out_cu;
11177d62b00eSchristos   void *in_cus;
11187d62b00eSchristos 
11197d62b00eSchristos   /* Links with a per-CU mapping in force get a first pass of deduplication,
11207d62b00eSchristos      dedupping the inputs for a given CU mapping into the output for that
11217d62b00eSchristos      mapping.  The outputs from this process get fed back into the final pass
11227d62b00eSchristos      that is carried out even for non-CU links.  */
11237d62b00eSchristos 
11247d62b00eSchristos   while ((err = ctf_dynhash_next (fp->ctf_link_out_cu_mapping, &i, &out_cu,
11257d62b00eSchristos 				  &in_cus)) == 0)
11267d62b00eSchristos     {
11277d62b00eSchristos       const char *out_name = (const char *) out_cu;
11287d62b00eSchristos       ctf_dynhash_t *in = (ctf_dynhash_t *) in_cus;
1129*6881a400Schristos       ctf_dict_t *out = NULL;
1130*6881a400Schristos       ctf_dict_t **inputs;
1131*6881a400Schristos       ctf_dict_t **outputs;
11327d62b00eSchristos       ctf_archive_t *in_arc;
11337d62b00eSchristos       ssize_t ninputs;
11347d62b00eSchristos       ctf_link_input_t *only_input;
11357d62b00eSchristos       uint32_t noutputs;
11367d62b00eSchristos       uint32_t *parents;
11377d62b00eSchristos 
11387d62b00eSchristos       if ((ninputs = ctf_link_deduplicating_count_inputs (fp, in,
11397d62b00eSchristos 							  &only_input)) == -1)
11407d62b00eSchristos 	goto err_open_inputs;
11417d62b00eSchristos 
11427d62b00eSchristos       /* CU mapping with no inputs?  Skip.  */
11437d62b00eSchristos       if (ninputs == 0)
11447d62b00eSchristos 	continue;
11457d62b00eSchristos 
11467d62b00eSchristos       if (labs ((long int) ninputs) > 0xfffffffe)
11477d62b00eSchristos 	{
11487d62b00eSchristos 	  ctf_err_warn (fp, 0, EFBIG, _("too many inputs in deduplicating "
11497d62b00eSchristos 					"link: %li"), (long int) ninputs);
11507d62b00eSchristos 	  ctf_set_errno (fp, EFBIG);
11517d62b00eSchristos 	  goto err_open_inputs;
11527d62b00eSchristos 	}
11537d62b00eSchristos 
11547d62b00eSchristos       /* Short-circuit: a cu-mapped link with only one input archive with
11557d62b00eSchristos 	 unconflicting contents is a do-nothing, and we can just leave the input
11567d62b00eSchristos 	 in place: we do have to change the cuname, though, so we unwrap it,
11577d62b00eSchristos 	 change the cuname, then stuff it back in the linker input again, via
11587d62b00eSchristos 	 the clin_fp short-circuit member.  ctf_link_deduplicating_open_inputs
11597d62b00eSchristos 	 will spot this member and jam it straight into the next link phase,
11607d62b00eSchristos 	 ignoring the corresponding archive.  */
11617d62b00eSchristos       if (only_input && ninputs == 1)
11627d62b00eSchristos 	{
11637d62b00eSchristos 	  ctf_next_t *ai = NULL;
11647d62b00eSchristos 	  int err;
11657d62b00eSchristos 
11667d62b00eSchristos 	  /* We can abuse an archive iterator to get the only member cheaply, no
11677d62b00eSchristos 	     matter what its name.  */
11687d62b00eSchristos 	  only_input->clin_fp = ctf_archive_next (only_input->clin_arc,
11697d62b00eSchristos 						  &ai, NULL, 0, &err);
11707d62b00eSchristos 	  if (!only_input->clin_fp)
11717d62b00eSchristos 	    {
11727d62b00eSchristos 	      ctf_err_warn (fp, 0, err, _("cannot open archive %s in "
11737d62b00eSchristos 					  "CU-mapped CTF link"),
11747d62b00eSchristos 			    only_input->clin_filename);
11757d62b00eSchristos 	      ctf_set_errno (fp, err);
11767d62b00eSchristos 	      goto err_open_inputs;
11777d62b00eSchristos 	    }
11787d62b00eSchristos 	  ctf_next_destroy (ai);
11797d62b00eSchristos 
11807d62b00eSchristos 	  if (strcmp (only_input->clin_filename, out_name) != 0)
11817d62b00eSchristos 	    {
11827d62b00eSchristos 	      /* Renaming. We need to add a new input, then null out the
11837d62b00eSchristos 		 clin_arc and clin_fp of the old one to stop it being
11847d62b00eSchristos 		 auto-closed on removal.  The new input needs its cuname changed
11857d62b00eSchristos 		 to out_name, which is doable only because the cuname is a
11867d62b00eSchristos 		 dynamic property which can be changed even in readonly
11877d62b00eSchristos 		 dicts. */
11887d62b00eSchristos 
11897d62b00eSchristos 	      ctf_cuname_set (only_input->clin_fp, out_name);
11907d62b00eSchristos 	      if (ctf_link_add_ctf_internal (fp, only_input->clin_arc,
11917d62b00eSchristos 					     only_input->clin_fp,
11927d62b00eSchristos 					     out_name) < 0)
11937d62b00eSchristos 		{
11947d62b00eSchristos 		  ctf_err_warn (fp, 0, 0, _("cannot add intermediate files "
11957d62b00eSchristos 					    "to link"));
11967d62b00eSchristos 		  goto err_open_inputs;
11977d62b00eSchristos 		}
11987d62b00eSchristos 	      only_input->clin_arc = NULL;
11997d62b00eSchristos 	      only_input->clin_fp = NULL;
12007d62b00eSchristos 	      ctf_dynhash_remove (fp->ctf_link_inputs,
12017d62b00eSchristos 				  only_input->clin_filename);
12027d62b00eSchristos 	    }
12037d62b00eSchristos 	  continue;
12047d62b00eSchristos 	}
12057d62b00eSchristos 
12067d62b00eSchristos       /* This is a real CU many-to-one mapping: we must dedup the inputs into
12077d62b00eSchristos 	 a new output to be used in the final link phase.  */
12087d62b00eSchristos 
12097d62b00eSchristos       if ((inputs = ctf_link_deduplicating_open_inputs (fp, in, ninputs,
12107d62b00eSchristos 							&parents)) == NULL)
12117d62b00eSchristos 	{
12127d62b00eSchristos 	  ctf_next_destroy (i);
12137d62b00eSchristos 	  goto err_inputs;
12147d62b00eSchristos 	}
12157d62b00eSchristos 
12167d62b00eSchristos       if ((out = ctf_create (&err)) == NULL)
12177d62b00eSchristos 	{
12187d62b00eSchristos 	  ctf_err_warn (fp, 0, err, _("cannot create per-CU CTF archive "
12197d62b00eSchristos 				      "for %s"),
12207d62b00eSchristos 			out_name);
12217d62b00eSchristos 	  ctf_set_errno (fp, err);
12227d62b00eSchristos 	  goto err_inputs;
12237d62b00eSchristos 	}
12247d62b00eSchristos 
12257d62b00eSchristos       /* Share the atoms table to reduce memory usage.  */
12267d62b00eSchristos       out->ctf_dedup_atoms = fp->ctf_dedup_atoms_alloc;
12277d62b00eSchristos 
12287d62b00eSchristos       /* No ctf_imports at this stage: this per-CU dictionary has no parents.
12297d62b00eSchristos 	 Parent/child deduplication happens in the link's final pass.  However,
12307d62b00eSchristos 	 the cuname *is* important, as it is propagated into the final
12317d62b00eSchristos 	 dictionary.  */
12327d62b00eSchristos       ctf_cuname_set (out, out_name);
12337d62b00eSchristos 
12347d62b00eSchristos       if (ctf_dedup (out, inputs, ninputs, parents, 1) < 0)
12357d62b00eSchristos 	{
12367d62b00eSchristos 	  ctf_set_errno (fp, ctf_errno (out));
12377d62b00eSchristos 	  ctf_err_warn (fp, 0, 0, _("CU-mapped deduplication failed for %s"),
12387d62b00eSchristos 			out_name);
12397d62b00eSchristos 	  goto err_inputs;
12407d62b00eSchristos 	}
12417d62b00eSchristos 
12427d62b00eSchristos       if ((outputs = ctf_dedup_emit (out, inputs, ninputs, parents,
12437d62b00eSchristos 				     &noutputs, 1)) == NULL)
12447d62b00eSchristos 	{
12457d62b00eSchristos 	  ctf_set_errno (fp, ctf_errno (out));
12467d62b00eSchristos 	  ctf_err_warn (fp, 0, 0, _("CU-mapped deduplicating link type emission "
12477d62b00eSchristos 				     "failed for %s"), out_name);
12487d62b00eSchristos 	  goto err_inputs;
12497d62b00eSchristos 	}
12507d62b00eSchristos       if (!ctf_assert (fp, noutputs == 1))
1251*6881a400Schristos 	{
1252*6881a400Schristos 	  size_t j;
1253*6881a400Schristos 	  for (j = 1; j < noutputs; j++)
1254*6881a400Schristos 	    ctf_dict_close (outputs[j]);
12557d62b00eSchristos 	  goto err_inputs_outputs;
1256*6881a400Schristos 	}
12577d62b00eSchristos 
12587d62b00eSchristos       if (!(fp->ctf_link_flags & CTF_LINK_OMIT_VARIABLES_SECTION)
12597d62b00eSchristos 	  && ctf_link_deduplicating_variables (out, inputs, ninputs, 1) < 0)
12607d62b00eSchristos 	{
12617d62b00eSchristos 	  ctf_set_errno (fp, ctf_errno (out));
12627d62b00eSchristos 	  ctf_err_warn (fp, 0, 0, _("CU-mapped deduplicating link variable "
12637d62b00eSchristos 				    "emission failed for %s"), out_name);
12647d62b00eSchristos 	  goto err_inputs_outputs;
12657d62b00eSchristos 	}
12667d62b00eSchristos 
1267*6881a400Schristos       ctf_dedup_fini (out, outputs, noutputs);
1268*6881a400Schristos 
1269*6881a400Schristos       /* For now, we omit symbol section linking for CU-mapped links, until it
1270*6881a400Schristos 	 is clear how to unify the symbol table across such links.  (Perhaps we
1271*6881a400Schristos 	 should emit an unconditionally indexed symtab, like the compiler
1272*6881a400Schristos 	 does.)  */
1273*6881a400Schristos 
12747d62b00eSchristos       if (ctf_link_deduplicating_close_inputs (fp, in, inputs, ninputs) < 0)
12757d62b00eSchristos 	{
12767d62b00eSchristos 	  free (inputs);
12777d62b00eSchristos 	  free (parents);
12787d62b00eSchristos 	  goto err_outputs;
12797d62b00eSchristos 	}
12807d62b00eSchristos       free (inputs);
12817d62b00eSchristos       free (parents);
12827d62b00eSchristos 
12837d62b00eSchristos       /* Splice any errors or warnings created during this link back into the
12847d62b00eSchristos 	 dict that the caller knows about.  */
12857d62b00eSchristos       ctf_list_splice (&fp->ctf_errs_warnings, &outputs[0]->ctf_errs_warnings);
12867d62b00eSchristos 
12877d62b00eSchristos       /* This output now becomes an input to the next link phase, with a name
12887d62b00eSchristos 	 equal to the CU name.  We have to wrap it in an archive wrapper
12897d62b00eSchristos 	 first.  */
12907d62b00eSchristos 
12917d62b00eSchristos       if ((in_arc = ctf_new_archive_internal (0, 0, NULL, outputs[0], NULL,
12927d62b00eSchristos 					      NULL, &err)) == NULL)
12937d62b00eSchristos 	{
12947d62b00eSchristos 	  ctf_set_errno (fp, err);
12957d62b00eSchristos 	  goto err_outputs;
12967d62b00eSchristos 	}
12977d62b00eSchristos 
12987d62b00eSchristos       if (ctf_link_add_ctf_internal (fp, in_arc, NULL,
12997d62b00eSchristos 				     ctf_cuname (outputs[0])) < 0)
13007d62b00eSchristos 	{
13017d62b00eSchristos 	  ctf_err_warn (fp, 0, 0, _("cannot add intermediate files to link"));
13027d62b00eSchristos 	  goto err_outputs;
13037d62b00eSchristos 	}
13047d62b00eSchristos 
1305*6881a400Schristos       ctf_dict_close (out);
13067d62b00eSchristos       free (outputs);
13077d62b00eSchristos       continue;
13087d62b00eSchristos 
13097d62b00eSchristos     err_inputs_outputs:
13107d62b00eSchristos       ctf_list_splice (&fp->ctf_errs_warnings, &outputs[0]->ctf_errs_warnings);
1311*6881a400Schristos       ctf_dict_close (outputs[0]);
13127d62b00eSchristos       free (outputs);
13137d62b00eSchristos     err_inputs:
13147d62b00eSchristos       ctf_link_deduplicating_close_inputs (fp, in, inputs, ninputs);
1315*6881a400Schristos       ctf_dict_close (out);
13167d62b00eSchristos       free (inputs);
13177d62b00eSchristos       free (parents);
13187d62b00eSchristos     err_open_inputs:
13197d62b00eSchristos       ctf_next_destroy (i);
13207d62b00eSchristos       return -1;
13217d62b00eSchristos 
13227d62b00eSchristos     err_outputs:
13237d62b00eSchristos       ctf_list_splice (&fp->ctf_errs_warnings, &outputs[0]->ctf_errs_warnings);
1324*6881a400Schristos       ctf_dict_close (outputs[0]);
13257d62b00eSchristos       free (outputs);
13267d62b00eSchristos       ctf_next_destroy (i);
13277d62b00eSchristos       return -1;				/* Errno is set for us.  */
13287d62b00eSchristos     }
13297d62b00eSchristos   if (err != ECTF_NEXT_END)
13307d62b00eSchristos     {
13317d62b00eSchristos       ctf_err_warn (fp, 0, err, _("iteration error in CU-mapped deduplicating "
13327d62b00eSchristos 				  "link"));
13337d62b00eSchristos       return ctf_set_errno (fp, err);
13347d62b00eSchristos     }
13357d62b00eSchristos 
13367d62b00eSchristos   return 0;
13377d62b00eSchristos }
13387d62b00eSchristos 
1339*6881a400Schristos /* Empty all the ctf_link_outputs.  */
1340*6881a400Schristos static int
1341*6881a400Schristos ctf_link_empty_outputs (ctf_dict_t *fp)
1342*6881a400Schristos {
1343*6881a400Schristos   ctf_next_t *i = NULL;
1344*6881a400Schristos   void *v;
1345*6881a400Schristos   int err;
1346*6881a400Schristos 
1347*6881a400Schristos   ctf_dynhash_empty (fp->ctf_link_outputs);
1348*6881a400Schristos 
1349*6881a400Schristos   while ((err = ctf_dynhash_next (fp->ctf_link_inputs, &i, NULL, &v)) == 0)
1350*6881a400Schristos     {
1351*6881a400Schristos       ctf_dict_t *in = (ctf_dict_t *) v;
1352*6881a400Schristos       in->ctf_link_in_out = NULL;
1353*6881a400Schristos     }
1354*6881a400Schristos   if (err != ECTF_NEXT_END)
1355*6881a400Schristos     {
1356*6881a400Schristos       fp->ctf_flags &= ~LCTF_LINKING;
1357*6881a400Schristos       ctf_err_warn (fp, 1, err, _("iteration error removing old outputs"));
1358*6881a400Schristos       ctf_set_errno (fp, err);
1359*6881a400Schristos       return -1;
1360*6881a400Schristos     }
1361*6881a400Schristos   return 0;
1362*6881a400Schristos }
1363*6881a400Schristos 
13647d62b00eSchristos /* Do a deduplicating link using the ctf-dedup machinery.  */
13657d62b00eSchristos static void
1366*6881a400Schristos ctf_link_deduplicating (ctf_dict_t *fp)
13677d62b00eSchristos {
13687d62b00eSchristos   size_t i;
1369*6881a400Schristos   ctf_dict_t **inputs, **outputs = NULL;
13707d62b00eSchristos   ssize_t ninputs;
13717d62b00eSchristos   uint32_t noutputs;
13727d62b00eSchristos   uint32_t *parents;
13737d62b00eSchristos 
13747d62b00eSchristos   if (ctf_dedup_atoms_init (fp) < 0)
13757d62b00eSchristos     {
13767d62b00eSchristos       ctf_err_warn (fp, 0, 0, _("allocating CTF dedup atoms table"));
13777d62b00eSchristos       return;					/* Errno is set for us.  */
13787d62b00eSchristos     }
13797d62b00eSchristos 
13807d62b00eSchristos   if (fp->ctf_link_out_cu_mapping
13817d62b00eSchristos       && (ctf_link_deduplicating_per_cu (fp) < 0))
13827d62b00eSchristos     return;					/* Errno is set for us.  */
13837d62b00eSchristos 
13847d62b00eSchristos   if ((ninputs = ctf_link_deduplicating_count_inputs (fp, NULL, NULL)) < 0)
13857d62b00eSchristos     return;					/* Errno is set for us.  */
13867d62b00eSchristos 
13877d62b00eSchristos   if ((inputs = ctf_link_deduplicating_open_inputs (fp, NULL, ninputs,
13887d62b00eSchristos 						    &parents)) == NULL)
13897d62b00eSchristos     return;					/* Errno is set for us.  */
13907d62b00eSchristos 
13917d62b00eSchristos   if (ninputs == 1 && ctf_cuname (inputs[0]) != NULL)
13927d62b00eSchristos     ctf_cuname_set (fp, ctf_cuname (inputs[0]));
13937d62b00eSchristos 
13947d62b00eSchristos   if (ctf_dedup (fp, inputs, ninputs, parents, 0) < 0)
13957d62b00eSchristos     {
13967d62b00eSchristos       ctf_err_warn (fp, 0, 0, _("deduplication failed for %s"),
13977d62b00eSchristos 		    ctf_link_input_name (fp));
13987d62b00eSchristos       goto err;
13997d62b00eSchristos     }
14007d62b00eSchristos 
14017d62b00eSchristos   if ((outputs = ctf_dedup_emit (fp, inputs, ninputs, parents, &noutputs,
14027d62b00eSchristos 				 0)) == NULL)
14037d62b00eSchristos     {
14047d62b00eSchristos       ctf_err_warn (fp, 0, 0, _("deduplicating link type emission failed "
14057d62b00eSchristos 				"for %s"), ctf_link_input_name (fp));
14067d62b00eSchristos       goto err;
14077d62b00eSchristos     }
14087d62b00eSchristos 
14097d62b00eSchristos   if (!ctf_assert (fp, outputs[0] == fp))
1410*6881a400Schristos     {
1411*6881a400Schristos       for (i = 1; i < noutputs; i++)
1412*6881a400Schristos 	ctf_dict_close (outputs[i]);
14137d62b00eSchristos       goto err;
1414*6881a400Schristos     }
14157d62b00eSchristos 
14167d62b00eSchristos   for (i = 0; i < noutputs; i++)
14177d62b00eSchristos     {
14187d62b00eSchristos       char *dynname;
14197d62b00eSchristos 
14207d62b00eSchristos       /* We already have access to this one.  Close the duplicate.  */
14217d62b00eSchristos       if (i == 0)
14227d62b00eSchristos 	{
1423*6881a400Schristos 	  ctf_dict_close (outputs[0]);
14247d62b00eSchristos 	  continue;
14257d62b00eSchristos 	}
14267d62b00eSchristos 
1427*6881a400Schristos       if ((dynname = ctf_new_per_cu_name (fp, ctf_cuname (outputs[i]))) == NULL)
14287d62b00eSchristos 	goto oom_one_output;
14297d62b00eSchristos 
14307d62b00eSchristos       if (ctf_dynhash_insert (fp->ctf_link_outputs, dynname, outputs[i]) < 0)
14317d62b00eSchristos 	goto oom_one_output;
14327d62b00eSchristos 
14337d62b00eSchristos       continue;
14347d62b00eSchristos 
14357d62b00eSchristos     oom_one_output:
14367d62b00eSchristos       ctf_set_errno (fp, ENOMEM);
14377d62b00eSchristos       ctf_err_warn (fp, 0, 0, _("out of memory allocating link outputs"));
14387d62b00eSchristos       free (dynname);
14397d62b00eSchristos 
14407d62b00eSchristos       for (; i < noutputs; i++)
1441*6881a400Schristos 	ctf_dict_close (outputs[i]);
14427d62b00eSchristos       goto err;
14437d62b00eSchristos     }
14447d62b00eSchristos 
14457d62b00eSchristos   if (!(fp->ctf_link_flags & CTF_LINK_OMIT_VARIABLES_SECTION)
14467d62b00eSchristos       && ctf_link_deduplicating_variables (fp, inputs, ninputs, 0) < 0)
14477d62b00eSchristos     {
14487d62b00eSchristos       ctf_err_warn (fp, 0, 0, _("deduplicating link variable emission failed for "
14497d62b00eSchristos 				"%s"), ctf_link_input_name (fp));
1450*6881a400Schristos       goto err_clean_outputs;
14517d62b00eSchristos     }
14527d62b00eSchristos 
1453*6881a400Schristos   if (ctf_link_deduplicating_syms (fp, inputs, ninputs, 0) < 0)
1454*6881a400Schristos     {
1455*6881a400Schristos       ctf_err_warn (fp, 0, 0, _("deduplicating link symbol emission failed for "
1456*6881a400Schristos 				"%s"), ctf_link_input_name (fp));
1457*6881a400Schristos       goto err_clean_outputs;
1458*6881a400Schristos     }
1459*6881a400Schristos 
1460*6881a400Schristos   ctf_dedup_fini (fp, outputs, noutputs);
1461*6881a400Schristos 
14627d62b00eSchristos   /* Now close all the inputs, including per-CU intermediates.  */
14637d62b00eSchristos 
14647d62b00eSchristos   if (ctf_link_deduplicating_close_inputs (fp, NULL, inputs, ninputs) < 0)
14657d62b00eSchristos     return;					/* errno is set for us.  */
14667d62b00eSchristos 
14677d62b00eSchristos   ninputs = 0;					/* Prevent double-close.  */
14687d62b00eSchristos   ctf_set_errno (fp, 0);
14697d62b00eSchristos 
14707d62b00eSchristos   /* Fall through.  */
14717d62b00eSchristos 
14727d62b00eSchristos  err:
14737d62b00eSchristos   for (i = 0; i < (size_t) ninputs; i++)
1474*6881a400Schristos     ctf_dict_close (inputs[i]);
14757d62b00eSchristos   free (inputs);
14767d62b00eSchristos   free (parents);
14777d62b00eSchristos   free (outputs);
14787d62b00eSchristos   return;
1479*6881a400Schristos 
1480*6881a400Schristos  err_clean_outputs:
1481*6881a400Schristos   ctf_link_empty_outputs (fp);
1482*6881a400Schristos   goto err;
14837d62b00eSchristos }
14847d62b00eSchristos 
1485*6881a400Schristos /* Merge types and variable sections in all dicts added to the link together.
1486*6881a400Schristos    The result of any previous link is discarded.  */
14877d62b00eSchristos int
1488*6881a400Schristos ctf_link (ctf_dict_t *fp, int flags)
14897d62b00eSchristos {
14907d62b00eSchristos   int err;
14917d62b00eSchristos 
14927d62b00eSchristos   fp->ctf_link_flags = flags;
14937d62b00eSchristos 
14947d62b00eSchristos   if (fp->ctf_link_inputs == NULL)
14957d62b00eSchristos     return 0;					/* Nothing to do. */
14967d62b00eSchristos 
1497*6881a400Schristos   if (fp->ctf_link_outputs != NULL)
1498*6881a400Schristos     ctf_link_empty_outputs (fp);
1499*6881a400Schristos   else
15007d62b00eSchristos     fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
15017d62b00eSchristos 					       ctf_hash_eq_string, free,
15027d62b00eSchristos 					       (ctf_hash_free_fun)
1503*6881a400Schristos 					       ctf_dict_close);
15047d62b00eSchristos 
15057d62b00eSchristos   if (fp->ctf_link_outputs == NULL)
15067d62b00eSchristos     return ctf_set_errno (fp, ENOMEM);
15077d62b00eSchristos 
15087d62b00eSchristos   /* Create empty CUs if requested.  We do not currently claim that multiple
15097d62b00eSchristos      links in succession with CTF_LINK_EMPTY_CU_MAPPINGS set in some calls and
15107d62b00eSchristos      not set in others will do anything especially sensible.  */
15117d62b00eSchristos 
1512*6881a400Schristos   fp->ctf_flags |= LCTF_LINKING;
15137d62b00eSchristos   if (fp->ctf_link_out_cu_mapping && (flags & CTF_LINK_EMPTY_CU_MAPPINGS))
15147d62b00eSchristos     {
1515*6881a400Schristos       ctf_next_t *i = NULL;
1516*6881a400Schristos       void *k;
15177d62b00eSchristos 
1518*6881a400Schristos       while ((err = ctf_dynhash_next (fp->ctf_link_out_cu_mapping, &i, &k,
15197d62b00eSchristos 				      NULL)) == 0)
15207d62b00eSchristos 	{
1521*6881a400Schristos 	  const char *to = (const char *) k;
1522*6881a400Schristos 	  if (ctf_create_per_cu (fp, NULL, to) == NULL)
15237d62b00eSchristos 	    {
1524*6881a400Schristos 	      fp->ctf_flags &= ~LCTF_LINKING;
15257d62b00eSchristos 	      ctf_next_destroy (i);
15267d62b00eSchristos 	      return -1;			/* Errno is set for us.  */
15277d62b00eSchristos 	    }
15287d62b00eSchristos 	}
15297d62b00eSchristos       if (err != ECTF_NEXT_END)
15307d62b00eSchristos 	{
1531*6881a400Schristos 	  fp->ctf_flags &= ~LCTF_LINKING;
15327d62b00eSchristos 	  ctf_err_warn (fp, 1, err, _("iteration error creating empty CUs"));
15337d62b00eSchristos 	  ctf_set_errno (fp, err);
15347d62b00eSchristos 	  return -1;
15357d62b00eSchristos 	}
15367d62b00eSchristos     }
15377d62b00eSchristos 
15387d62b00eSchristos   ctf_link_deduplicating (fp);
15397d62b00eSchristos 
1540*6881a400Schristos   fp->ctf_flags &= ~LCTF_LINKING;
15417d62b00eSchristos   if ((ctf_errno (fp) != 0) && (ctf_errno (fp) != ECTF_NOCTFDATA))
15427d62b00eSchristos     return -1;
15437d62b00eSchristos   return 0;
15447d62b00eSchristos }
15457d62b00eSchristos 
15467d62b00eSchristos typedef struct ctf_link_out_string_cb_arg
15477d62b00eSchristos {
15487d62b00eSchristos   const char *str;
15497d62b00eSchristos   uint32_t offset;
15507d62b00eSchristos   int err;
15517d62b00eSchristos } ctf_link_out_string_cb_arg_t;
15527d62b00eSchristos 
15537d62b00eSchristos /* Intern a string in the string table of an output per-CU CTF file.  */
15547d62b00eSchristos static void
15557d62b00eSchristos ctf_link_intern_extern_string (void *key _libctf_unused_, void *value,
15567d62b00eSchristos 			       void *arg_)
15577d62b00eSchristos {
1558*6881a400Schristos   ctf_dict_t *fp = (ctf_dict_t *) value;
15597d62b00eSchristos   ctf_link_out_string_cb_arg_t *arg = (ctf_link_out_string_cb_arg_t *) arg_;
15607d62b00eSchristos 
15617d62b00eSchristos   fp->ctf_flags |= LCTF_DIRTY;
15627d62b00eSchristos   if (!ctf_str_add_external (fp, arg->str, arg->offset))
15637d62b00eSchristos     arg->err = ENOMEM;
15647d62b00eSchristos }
15657d62b00eSchristos 
15667d62b00eSchristos /* Repeatedly call ADD_STRING to acquire strings from the external string table,
15677d62b00eSchristos    adding them to the atoms table for this CU and all subsidiary CUs.
15687d62b00eSchristos 
1569*6881a400Schristos    If ctf_link is also called, it must be called first if you want the new CTF
1570*6881a400Schristos    files ctf_link can create to get their strings dedupped against the ELF
15717d62b00eSchristos    strtab properly.  */
15727d62b00eSchristos int
1573*6881a400Schristos ctf_link_add_strtab (ctf_dict_t *fp, ctf_link_strtab_string_f *add_string,
15747d62b00eSchristos 		     void *arg)
15757d62b00eSchristos {
15767d62b00eSchristos   const char *str;
15777d62b00eSchristos   uint32_t offset;
15787d62b00eSchristos   int err = 0;
15797d62b00eSchristos 
15807d62b00eSchristos   while ((str = add_string (&offset, arg)) != NULL)
15817d62b00eSchristos     {
15827d62b00eSchristos       ctf_link_out_string_cb_arg_t iter_arg = { str, offset, 0 };
15837d62b00eSchristos 
15847d62b00eSchristos       fp->ctf_flags |= LCTF_DIRTY;
15857d62b00eSchristos       if (!ctf_str_add_external (fp, str, offset))
15867d62b00eSchristos 	err = ENOMEM;
15877d62b00eSchristos 
15887d62b00eSchristos       ctf_dynhash_iter (fp->ctf_link_outputs, ctf_link_intern_extern_string,
15897d62b00eSchristos 			&iter_arg);
15907d62b00eSchristos       if (iter_arg.err)
15917d62b00eSchristos 	err = iter_arg.err;
15927d62b00eSchristos     }
15937d62b00eSchristos 
1594*6881a400Schristos   if (err)
1595*6881a400Schristos     ctf_set_errno (fp, err);
1596*6881a400Schristos 
15977d62b00eSchristos   return -err;
15987d62b00eSchristos }
15997d62b00eSchristos 
1600*6881a400Schristos /* Inform the ctf-link machinery of a new symbol in the target symbol table
1601*6881a400Schristos    (which must be some symtab that is not usually stripped, and which
1602*6881a400Schristos    is in agreement with ctf_bfdopen_ctfsect).  May be called either before or
1603*6881a400Schristos    after ctf_link_add_strtab.  */
16047d62b00eSchristos int
1605*6881a400Schristos ctf_link_add_linker_symbol (ctf_dict_t *fp, ctf_link_sym_t *sym)
16067d62b00eSchristos {
1607*6881a400Schristos   ctf_in_flight_dynsym_t *cid;
1608*6881a400Schristos 
1609*6881a400Schristos   /* Cheat a little: if there is already an ENOMEM error code recorded against
1610*6881a400Schristos      this dict, we shouldn't even try to add symbols because there will be no
1611*6881a400Schristos      memory to do so: probably we failed to add some previous symbol.  This
1612*6881a400Schristos      makes out-of-memory exits 'sticky' across calls to this function, so the
1613*6881a400Schristos      caller doesn't need to worry about error conditions.  */
1614*6881a400Schristos 
1615*6881a400Schristos   if (ctf_errno (fp) == ENOMEM)
1616*6881a400Schristos     return -ENOMEM;				/* errno is set for us.  */
1617*6881a400Schristos 
1618*6881a400Schristos   if (ctf_symtab_skippable (sym))
16197d62b00eSchristos     return 0;
1620*6881a400Schristos 
1621*6881a400Schristos   if (sym->st_type != STT_OBJECT && sym->st_type != STT_FUNC)
1622*6881a400Schristos     return 0;
1623*6881a400Schristos 
1624*6881a400Schristos   /* Add the symbol to the in-flight list.  */
1625*6881a400Schristos 
1626*6881a400Schristos   if ((cid = malloc (sizeof (ctf_in_flight_dynsym_t))) == NULL)
1627*6881a400Schristos     goto oom;
1628*6881a400Schristos 
1629*6881a400Schristos   cid->cid_sym = *sym;
1630*6881a400Schristos   ctf_list_append (&fp->ctf_in_flight_dynsyms, cid);
1631*6881a400Schristos 
1632*6881a400Schristos   return 0;
1633*6881a400Schristos 
1634*6881a400Schristos  oom:
1635*6881a400Schristos   ctf_dynhash_destroy (fp->ctf_dynsyms);
1636*6881a400Schristos   fp->ctf_dynsyms = NULL;
1637*6881a400Schristos   ctf_set_errno (fp, ENOMEM);
1638*6881a400Schristos   return -ENOMEM;
1639*6881a400Schristos }
1640*6881a400Schristos 
1641*6881a400Schristos /* Impose an ordering on symbols.  The ordering takes effect immediately, but
1642*6881a400Schristos    since the ordering info does not include type IDs, lookups may return nothing
1643*6881a400Schristos    until such IDs are added by calls to ctf_add_*_sym.  Must be called after
1644*6881a400Schristos    ctf_link_add_strtab and ctf_link_add_linker_symbol.  */
1645*6881a400Schristos int
1646*6881a400Schristos ctf_link_shuffle_syms (ctf_dict_t *fp)
1647*6881a400Schristos {
1648*6881a400Schristos   ctf_in_flight_dynsym_t *did, *nid;
1649*6881a400Schristos   ctf_next_t *i = NULL;
1650*6881a400Schristos   int err = ENOMEM;
1651*6881a400Schristos   void *name_, *sym_;
1652*6881a400Schristos 
1653*6881a400Schristos   if (!fp->ctf_dynsyms)
1654*6881a400Schristos     {
1655*6881a400Schristos       fp->ctf_dynsyms = ctf_dynhash_create (ctf_hash_string,
1656*6881a400Schristos 					    ctf_hash_eq_string,
1657*6881a400Schristos 					    NULL, free);
1658*6881a400Schristos       if (!fp->ctf_dynsyms)
1659*6881a400Schristos 	{
1660*6881a400Schristos 	  ctf_set_errno (fp, ENOMEM);
1661*6881a400Schristos 	  return -ENOMEM;
1662*6881a400Schristos 	}
1663*6881a400Schristos     }
1664*6881a400Schristos 
1665*6881a400Schristos   /* Add all the symbols, excluding only those we already know are prohibited
1666*6881a400Schristos      from appearing in symtypetabs.  */
1667*6881a400Schristos 
1668*6881a400Schristos   for (did = ctf_list_next (&fp->ctf_in_flight_dynsyms); did != NULL; did = nid)
1669*6881a400Schristos     {
1670*6881a400Schristos       ctf_link_sym_t *new_sym;
1671*6881a400Schristos 
1672*6881a400Schristos       nid = ctf_list_next (did);
1673*6881a400Schristos       ctf_list_delete (&fp->ctf_in_flight_dynsyms, did);
1674*6881a400Schristos 
1675*6881a400Schristos       /* We might get a name or an external strtab offset.  The strtab offset is
1676*6881a400Schristos 	 guaranteed resolvable at this point, so turn it into a string.  */
1677*6881a400Schristos 
1678*6881a400Schristos       if (did->cid_sym.st_name == NULL)
1679*6881a400Schristos 	{
1680*6881a400Schristos 	  uint32_t off = CTF_SET_STID (did->cid_sym.st_nameidx, CTF_STRTAB_1);
1681*6881a400Schristos 
1682*6881a400Schristos 	  did->cid_sym.st_name = ctf_strraw (fp, off);
1683*6881a400Schristos 	  did->cid_sym.st_nameidx_set = 0;
1684*6881a400Schristos 	  if (!ctf_assert (fp, did->cid_sym.st_name != NULL))
1685*6881a400Schristos 	    return -ECTF_INTERNAL;		/* errno is set for us.  */
1686*6881a400Schristos 	}
1687*6881a400Schristos 
1688*6881a400Schristos       /* The symbol might have turned out to be nameless, so we have to recheck
1689*6881a400Schristos 	 for skippability here.  */
1690*6881a400Schristos       if (!ctf_symtab_skippable (&did->cid_sym))
1691*6881a400Schristos 	{
1692*6881a400Schristos 	  ctf_dprintf ("symbol from linker: %s (%x)\n", did->cid_sym.st_name,
1693*6881a400Schristos 		       did->cid_sym.st_symidx);
1694*6881a400Schristos 
1695*6881a400Schristos 	  if ((new_sym = malloc (sizeof (ctf_link_sym_t))) == NULL)
1696*6881a400Schristos 	    goto local_oom;
1697*6881a400Schristos 
1698*6881a400Schristos 	  memcpy (new_sym, &did->cid_sym, sizeof (ctf_link_sym_t));
1699*6881a400Schristos 	  if (ctf_dynhash_cinsert (fp->ctf_dynsyms, new_sym->st_name, new_sym) < 0)
1700*6881a400Schristos 	    goto local_oom;
1701*6881a400Schristos 
1702*6881a400Schristos 	  if (fp->ctf_dynsymmax < new_sym->st_symidx)
1703*6881a400Schristos 	    fp->ctf_dynsymmax = new_sym->st_symidx;
1704*6881a400Schristos 	}
1705*6881a400Schristos 
1706*6881a400Schristos       free (did);
1707*6881a400Schristos       continue;
1708*6881a400Schristos 
1709*6881a400Schristos     local_oom:
1710*6881a400Schristos       free (did);
1711*6881a400Schristos       free (new_sym);
1712*6881a400Schristos       goto err;
1713*6881a400Schristos     }
1714*6881a400Schristos 
1715*6881a400Schristos   /* If no symbols are reported, unwind what we have done and return.  This
1716*6881a400Schristos      makes it a bit easier for the serializer to tell that no symbols have been
1717*6881a400Schristos      reported and that it should look elsewhere for reported symbols.  */
1718*6881a400Schristos   if (!ctf_dynhash_elements (fp->ctf_dynsyms))
1719*6881a400Schristos     {
1720*6881a400Schristos       ctf_dprintf ("No symbols: not a final link.\n");
1721*6881a400Schristos       ctf_dynhash_destroy (fp->ctf_dynsyms);
1722*6881a400Schristos       fp->ctf_dynsyms = NULL;
1723*6881a400Schristos       return 0;
1724*6881a400Schristos     }
1725*6881a400Schristos 
1726*6881a400Schristos   /* Construct a mapping from shndx to the symbol info.  */
1727*6881a400Schristos   free (fp->ctf_dynsymidx);
1728*6881a400Schristos   if ((fp->ctf_dynsymidx = calloc (fp->ctf_dynsymmax + 1,
1729*6881a400Schristos 				   sizeof (ctf_link_sym_t *))) == NULL)
1730*6881a400Schristos     goto err;
1731*6881a400Schristos 
1732*6881a400Schristos   while ((err = ctf_dynhash_next (fp->ctf_dynsyms, &i, &name_, &sym_)) == 0)
1733*6881a400Schristos     {
1734*6881a400Schristos       const char *name = (const char *) name;
1735*6881a400Schristos       ctf_link_sym_t *symp = (ctf_link_sym_t *) sym_;
1736*6881a400Schristos 
1737*6881a400Schristos       if (!ctf_assert (fp, symp->st_symidx <= fp->ctf_dynsymmax))
1738*6881a400Schristos 	{
1739*6881a400Schristos 	  ctf_next_destroy (i);
1740*6881a400Schristos 	  err = ctf_errno (fp);
1741*6881a400Schristos 	  goto err;
1742*6881a400Schristos 	}
1743*6881a400Schristos       fp->ctf_dynsymidx[symp->st_symidx] = symp;
1744*6881a400Schristos     }
1745*6881a400Schristos   if (err != ECTF_NEXT_END)
1746*6881a400Schristos     {
1747*6881a400Schristos       ctf_err_warn (fp, 0, err, _("error iterating over shuffled symbols"));
1748*6881a400Schristos       goto err;
1749*6881a400Schristos     }
1750*6881a400Schristos   return 0;
1751*6881a400Schristos 
1752*6881a400Schristos  err:
1753*6881a400Schristos   /* Leave the in-flight symbols around: they'll be freed at
1754*6881a400Schristos      dict close time regardless.  */
1755*6881a400Schristos   ctf_dynhash_destroy (fp->ctf_dynsyms);
1756*6881a400Schristos   fp->ctf_dynsyms = NULL;
1757*6881a400Schristos   free (fp->ctf_dynsymidx);
1758*6881a400Schristos   fp->ctf_dynsymidx = NULL;
1759*6881a400Schristos   fp->ctf_dynsymmax = 0;
1760*6881a400Schristos   ctf_set_errno (fp, err);
1761*6881a400Schristos   return -err;
17627d62b00eSchristos }
17637d62b00eSchristos 
17647d62b00eSchristos typedef struct ctf_name_list_accum_cb_arg
17657d62b00eSchristos {
17667d62b00eSchristos   char **names;
1767*6881a400Schristos   ctf_dict_t *fp;
1768*6881a400Schristos   ctf_dict_t **files;
17697d62b00eSchristos   size_t i;
17707d62b00eSchristos   char **dynames;
17717d62b00eSchristos   size_t ndynames;
17727d62b00eSchristos } ctf_name_list_accum_cb_arg_t;
17737d62b00eSchristos 
17747d62b00eSchristos /* Accumulate the names and a count of the names in the link output hash.  */
17757d62b00eSchristos static void
17767d62b00eSchristos ctf_accumulate_archive_names (void *key, void *value, void *arg_)
17777d62b00eSchristos {
17787d62b00eSchristos   const char *name = (const char *) key;
1779*6881a400Schristos   ctf_dict_t *fp = (ctf_dict_t *) value;
17807d62b00eSchristos   char **names;
1781*6881a400Schristos   ctf_dict_t **files;
17827d62b00eSchristos   ctf_name_list_accum_cb_arg_t *arg = (ctf_name_list_accum_cb_arg_t *) arg_;
17837d62b00eSchristos 
17847d62b00eSchristos   if ((names = realloc (arg->names, sizeof (char *) * ++(arg->i))) == NULL)
17857d62b00eSchristos     {
17867d62b00eSchristos       (arg->i)--;
17877d62b00eSchristos       ctf_set_errno (arg->fp, ENOMEM);
17887d62b00eSchristos       return;
17897d62b00eSchristos     }
17907d62b00eSchristos 
1791*6881a400Schristos   if ((files = realloc (arg->files, sizeof (ctf_dict_t *) * arg->i)) == NULL)
17927d62b00eSchristos     {
17937d62b00eSchristos       (arg->i)--;
17947d62b00eSchristos       ctf_set_errno (arg->fp, ENOMEM);
17957d62b00eSchristos       return;
17967d62b00eSchristos     }
17977d62b00eSchristos 
17987d62b00eSchristos   /* Allow the caller to get in and modify the name at the last minute.  If the
17997d62b00eSchristos      caller *does* modify the name, we have to stash away the new name the
18007d62b00eSchristos      caller returned so we can free it later on.  (The original name is the key
18017d62b00eSchristos      of the ctf_link_outputs hash and is freed by the dynhash machinery.)  */
18027d62b00eSchristos 
18037d62b00eSchristos   if (fp->ctf_link_memb_name_changer)
18047d62b00eSchristos     {
18057d62b00eSchristos       char **dynames;
18067d62b00eSchristos       char *dyname;
18077d62b00eSchristos       void *nc_arg = fp->ctf_link_memb_name_changer_arg;
18087d62b00eSchristos 
18097d62b00eSchristos       dyname = fp->ctf_link_memb_name_changer (fp, name, nc_arg);
18107d62b00eSchristos 
18117d62b00eSchristos       if (dyname != NULL)
18127d62b00eSchristos 	{
18137d62b00eSchristos 	  if ((dynames = realloc (arg->dynames,
18147d62b00eSchristos 				  sizeof (char *) * ++(arg->ndynames))) == NULL)
18157d62b00eSchristos 	    {
18167d62b00eSchristos 	      (arg->ndynames)--;
18177d62b00eSchristos 	      ctf_set_errno (arg->fp, ENOMEM);
18187d62b00eSchristos 	      return;
18197d62b00eSchristos 	    }
18207d62b00eSchristos 	    arg->dynames = dynames;
18217d62b00eSchristos 	    name = (const char *) dyname;
18227d62b00eSchristos 	}
18237d62b00eSchristos     }
18247d62b00eSchristos 
18257d62b00eSchristos   arg->names = names;
18267d62b00eSchristos   arg->names[(arg->i) - 1] = (char *) name;
18277d62b00eSchristos   arg->files = files;
18287d62b00eSchristos   arg->files[(arg->i) - 1] = fp;
18297d62b00eSchristos }
18307d62b00eSchristos 
18317d62b00eSchristos /* Change the name of the parent CTF section, if the name transformer has got to
18327d62b00eSchristos    it.  */
18337d62b00eSchristos static void
18347d62b00eSchristos ctf_change_parent_name (void *key _libctf_unused_, void *value, void *arg)
18357d62b00eSchristos {
1836*6881a400Schristos   ctf_dict_t *fp = (ctf_dict_t *) value;
18377d62b00eSchristos   const char *name = (const char *) arg;
18387d62b00eSchristos 
18397d62b00eSchristos   ctf_parent_name_set (fp, name);
18407d62b00eSchristos }
18417d62b00eSchristos 
1842*6881a400Schristos /* Warn if we may suffer information loss because the CTF input files are too
1843*6881a400Schristos    old.  Usually we provide complete backward compatibility, but compiler
1844*6881a400Schristos    changes etc which never hit a release may have a flag in the header that
1845*6881a400Schristos    simply prevents those changes from being used.  */
1846*6881a400Schristos static void
1847*6881a400Schristos ctf_link_warn_outdated_inputs (ctf_dict_t *fp)
1848*6881a400Schristos {
1849*6881a400Schristos   ctf_next_t *i = NULL;
1850*6881a400Schristos   void *name_;
1851*6881a400Schristos   void *ifp_;
1852*6881a400Schristos   int err;
1853*6881a400Schristos 
1854*6881a400Schristos   while ((err = ctf_dynhash_next (fp->ctf_link_inputs, &i, &name_, &ifp_)) == 0)
1855*6881a400Schristos     {
1856*6881a400Schristos       const char *name = (const char *) name_;
1857*6881a400Schristos       ctf_dict_t *ifp = (ctf_dict_t *) ifp_;
1858*6881a400Schristos 
1859*6881a400Schristos       if (!(ifp->ctf_header->cth_flags & CTF_F_NEWFUNCINFO)
1860*6881a400Schristos 	  && (ifp->ctf_header->cth_varoff - ifp->ctf_header->cth_funcoff) > 0)
1861*6881a400Schristos 	ctf_err_warn (ifp, 1, 0, _("linker input %s has CTF func info but uses "
1862*6881a400Schristos 				   "an old, unreleased func info format: "
1863*6881a400Schristos 				   "this func info section will be dropped."),
1864*6881a400Schristos 		      name);
1865*6881a400Schristos     }
1866*6881a400Schristos   if (err != ECTF_NEXT_END)
1867*6881a400Schristos     ctf_err_warn (fp, 0, err, _("error checking for outdated inputs"));
1868*6881a400Schristos }
1869*6881a400Schristos 
18707d62b00eSchristos /* Write out a CTF archive (if there are per-CU CTF files) or a CTF file
18717d62b00eSchristos    (otherwise) into a new dynamically-allocated string, and return it.
18727d62b00eSchristos    Members with sizes above THRESHOLD are compressed.  */
18737d62b00eSchristos unsigned char *
1874*6881a400Schristos ctf_link_write (ctf_dict_t *fp, size_t *size, size_t threshold)
18757d62b00eSchristos {
18767d62b00eSchristos   ctf_name_list_accum_cb_arg_t arg;
18777d62b00eSchristos   char **names;
18787d62b00eSchristos   char *transformed_name = NULL;
1879*6881a400Schristos   ctf_dict_t **files;
18807d62b00eSchristos   FILE *f = NULL;
1881*6881a400Schristos   size_t i;
18827d62b00eSchristos   int err;
18837d62b00eSchristos   long fsize;
18847d62b00eSchristos   const char *errloc;
18857d62b00eSchristos   unsigned char *buf = NULL;
18867d62b00eSchristos 
18877d62b00eSchristos   memset (&arg, 0, sizeof (ctf_name_list_accum_cb_arg_t));
18887d62b00eSchristos   arg.fp = fp;
1889*6881a400Schristos   fp->ctf_flags |= LCTF_LINKING;
1890*6881a400Schristos 
1891*6881a400Schristos   ctf_link_warn_outdated_inputs (fp);
18927d62b00eSchristos 
18937d62b00eSchristos   if (fp->ctf_link_outputs)
18947d62b00eSchristos     {
18957d62b00eSchristos       ctf_dynhash_iter (fp->ctf_link_outputs, ctf_accumulate_archive_names, &arg);
18967d62b00eSchristos       if (ctf_errno (fp) < 0)
18977d62b00eSchristos 	{
18987d62b00eSchristos 	  errloc = "hash creation";
18997d62b00eSchristos 	  goto err;
19007d62b00eSchristos 	}
19017d62b00eSchristos     }
19027d62b00eSchristos 
1903*6881a400Schristos   /* No extra outputs? Just write a simple ctf_dict_t.  */
19047d62b00eSchristos   if (arg.i == 0)
1905*6881a400Schristos     {
1906*6881a400Schristos       unsigned char *ret = ctf_write_mem (fp, size, threshold);
1907*6881a400Schristos       fp->ctf_flags &= ~LCTF_LINKING;
1908*6881a400Schristos       return ret;
1909*6881a400Schristos     }
19107d62b00eSchristos 
19117d62b00eSchristos   /* Writing an archive.  Stick ourselves (the shared repository, parent of all
19127d62b00eSchristos      other archives) on the front of it with the default name.  */
19137d62b00eSchristos   if ((names = realloc (arg.names, sizeof (char *) * (arg.i + 1))) == NULL)
19147d62b00eSchristos     {
19157d62b00eSchristos       errloc = "name reallocation";
19167d62b00eSchristos       goto err_no;
19177d62b00eSchristos     }
19187d62b00eSchristos   arg.names = names;
19197d62b00eSchristos   memmove (&(arg.names[1]), arg.names, sizeof (char *) * (arg.i));
19207d62b00eSchristos 
19217d62b00eSchristos   arg.names[0] = (char *) _CTF_SECTION;
19227d62b00eSchristos   if (fp->ctf_link_memb_name_changer)
19237d62b00eSchristos     {
19247d62b00eSchristos       void *nc_arg = fp->ctf_link_memb_name_changer_arg;
19257d62b00eSchristos 
19267d62b00eSchristos       transformed_name = fp->ctf_link_memb_name_changer (fp, _CTF_SECTION,
19277d62b00eSchristos 							 nc_arg);
19287d62b00eSchristos 
19297d62b00eSchristos       if (transformed_name != NULL)
19307d62b00eSchristos 	{
19317d62b00eSchristos 	  arg.names[0] = transformed_name;
19327d62b00eSchristos 	  ctf_dynhash_iter (fp->ctf_link_outputs, ctf_change_parent_name,
19337d62b00eSchristos 			    transformed_name);
19347d62b00eSchristos 	}
19357d62b00eSchristos     }
19367d62b00eSchristos 
1937*6881a400Schristos   /* Propagate the link flags to all the dicts in this link.  */
1938*6881a400Schristos   for (i = 0; i < arg.i; i++)
19397d62b00eSchristos     {
1940*6881a400Schristos       arg.files[i]->ctf_link_flags = fp->ctf_link_flags;
1941*6881a400Schristos       arg.files[i]->ctf_flags |= LCTF_LINKING;
1942*6881a400Schristos     }
1943*6881a400Schristos 
1944*6881a400Schristos   if ((files = realloc (arg.files,
1945*6881a400Schristos 			sizeof (struct ctf_dict *) * (arg.i + 1))) == NULL)
1946*6881a400Schristos     {
1947*6881a400Schristos       errloc = "ctf_dict reallocation";
19487d62b00eSchristos       goto err_no;
19497d62b00eSchristos     }
19507d62b00eSchristos   arg.files = files;
1951*6881a400Schristos   memmove (&(arg.files[1]), arg.files, sizeof (ctf_dict_t *) * (arg.i));
19527d62b00eSchristos   arg.files[0] = fp;
19537d62b00eSchristos 
19547d62b00eSchristos   if ((f = tmpfile ()) == NULL)
19557d62b00eSchristos     {
19567d62b00eSchristos       errloc = "tempfile creation";
19577d62b00eSchristos       goto err_no;
19587d62b00eSchristos     }
19597d62b00eSchristos 
19607d62b00eSchristos   if ((err = ctf_arc_write_fd (fileno (f), arg.files, arg.i + 1,
19617d62b00eSchristos 			       (const char **) arg.names,
19627d62b00eSchristos 			       threshold)) < 0)
19637d62b00eSchristos     {
19647d62b00eSchristos       errloc = "archive writing";
19657d62b00eSchristos       ctf_set_errno (fp, err);
19667d62b00eSchristos       goto err;
19677d62b00eSchristos     }
19687d62b00eSchristos 
19697d62b00eSchristos   if (fseek (f, 0, SEEK_END) < 0)
19707d62b00eSchristos     {
19717d62b00eSchristos       errloc = "seeking to end";
19727d62b00eSchristos       goto err_no;
19737d62b00eSchristos     }
19747d62b00eSchristos 
19757d62b00eSchristos   if ((fsize = ftell (f)) < 0)
19767d62b00eSchristos     {
19777d62b00eSchristos       errloc = "filesize determination";
19787d62b00eSchristos       goto err_no;
19797d62b00eSchristos     }
19807d62b00eSchristos 
19817d62b00eSchristos   if (fseek (f, 0, SEEK_SET) < 0)
19827d62b00eSchristos     {
19837d62b00eSchristos       errloc = "filepos resetting";
19847d62b00eSchristos       goto err_no;
19857d62b00eSchristos     }
19867d62b00eSchristos 
19877d62b00eSchristos   if ((buf = malloc (fsize)) == NULL)
19887d62b00eSchristos     {
19897d62b00eSchristos       errloc = "CTF archive buffer allocation";
19907d62b00eSchristos       goto err_no;
19917d62b00eSchristos     }
19927d62b00eSchristos 
19937d62b00eSchristos   while (!feof (f) && fread (buf, fsize, 1, f) == 0)
19947d62b00eSchristos     if (ferror (f))
19957d62b00eSchristos       {
19967d62b00eSchristos 	errloc = "reading archive from temporary file";
19977d62b00eSchristos 	goto err_no;
19987d62b00eSchristos       }
19997d62b00eSchristos 
20007d62b00eSchristos   *size = fsize;
20017d62b00eSchristos   free (arg.names);
20027d62b00eSchristos   free (arg.files);
20037d62b00eSchristos   free (transformed_name);
20047d62b00eSchristos   if (arg.ndynames)
20057d62b00eSchristos     {
20067d62b00eSchristos       size_t i;
20077d62b00eSchristos       for (i = 0; i < arg.ndynames; i++)
20087d62b00eSchristos 	free (arg.dynames[i]);
20097d62b00eSchristos       free (arg.dynames);
20107d62b00eSchristos     }
20117d62b00eSchristos   fclose (f);
20127d62b00eSchristos   return buf;
20137d62b00eSchristos 
20147d62b00eSchristos  err_no:
20157d62b00eSchristos   ctf_set_errno (fp, errno);
2016*6881a400Schristos 
2017*6881a400Schristos   /* Turn off the is-linking flag on all the dicts in this link.  */
2018*6881a400Schristos   for (i = 0; i < arg.i; i++)
2019*6881a400Schristos     arg.files[i]->ctf_flags &= ~LCTF_LINKING;
20207d62b00eSchristos  err:
20217d62b00eSchristos   free (buf);
20227d62b00eSchristos   if (f)
20237d62b00eSchristos     fclose (f);
20247d62b00eSchristos   free (arg.names);
20257d62b00eSchristos   free (arg.files);
20267d62b00eSchristos   free (transformed_name);
20277d62b00eSchristos   if (arg.ndynames)
20287d62b00eSchristos     {
20297d62b00eSchristos       size_t i;
20307d62b00eSchristos       for (i = 0; i < arg.ndynames; i++)
20317d62b00eSchristos 	free (arg.dynames[i]);
20327d62b00eSchristos       free (arg.dynames);
20337d62b00eSchristos     }
20347d62b00eSchristos   ctf_err_warn (fp, 0, 0, _("cannot write archive in link: %s failure"),
20357d62b00eSchristos 		errloc);
20367d62b00eSchristos   return NULL;
20377d62b00eSchristos }
2038