xref: /dflybsd-src/contrib/binutils-2.34/libctf/ctf-link.c (revision b52ef7118d1621abed722c5bbbd542210290ecef)
1*fae548d3Szrj /* CTF linking.
2*fae548d3Szrj    Copyright (C) 2019-2020 Free Software Foundation, Inc.
3*fae548d3Szrj 
4*fae548d3Szrj    This file is part of libctf.
5*fae548d3Szrj 
6*fae548d3Szrj    libctf is free software; you can redistribute it and/or modify it under
7*fae548d3Szrj    the terms of the GNU General Public License as published by the Free
8*fae548d3Szrj    Software Foundation; either version 3, or (at your option) any later
9*fae548d3Szrj    version.
10*fae548d3Szrj 
11*fae548d3Szrj    This program is distributed in the hope that it will be useful, but
12*fae548d3Szrj    WITHOUT ANY WARRANTY; without even the implied warranty of
13*fae548d3Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14*fae548d3Szrj    See the GNU General Public License for more details.
15*fae548d3Szrj 
16*fae548d3Szrj    You should have received a copy of the GNU General Public License
17*fae548d3Szrj    along with this program; see the file COPYING.  If not see
18*fae548d3Szrj    <http://www.gnu.org/licenses/>.  */
19*fae548d3Szrj 
20*fae548d3Szrj #include <ctf-impl.h>
21*fae548d3Szrj #include <string.h>
22*fae548d3Szrj 
23*fae548d3Szrj /* Type tracking machinery.  */
24*fae548d3Szrj 
25*fae548d3Szrj /* Record the correspondence between a source and ctf_add_type()-added
26*fae548d3Szrj    destination type: both types are translated into parent type IDs if need be,
27*fae548d3Szrj    so they relate to the actual container they are in.  Outside controlled
28*fae548d3Szrj    circumstances (like linking) it is probably not useful to do more than
29*fae548d3Szrj    compare these pointers, since there is nothing stopping the user closing the
30*fae548d3Szrj    source container whenever they want to.
31*fae548d3Szrj 
32*fae548d3Szrj    Our OOM handling here is just to not do anything, because this is called deep
33*fae548d3Szrj    enough in the call stack that doing anything useful is painfully difficult:
34*fae548d3Szrj    the worst consequence if we do OOM is a bit of type duplication anyway.  */
35*fae548d3Szrj 
36*fae548d3Szrj void
ctf_add_type_mapping(ctf_file_t * src_fp,ctf_id_t src_type,ctf_file_t * dst_fp,ctf_id_t dst_type)37*fae548d3Szrj ctf_add_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type,
38*fae548d3Szrj 		      ctf_file_t *dst_fp, ctf_id_t dst_type)
39*fae548d3Szrj {
40*fae548d3Szrj   if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
41*fae548d3Szrj     src_fp = src_fp->ctf_parent;
42*fae548d3Szrj 
43*fae548d3Szrj   src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
44*fae548d3Szrj 
45*fae548d3Szrj   if (LCTF_TYPE_ISPARENT (dst_fp, dst_type) && dst_fp->ctf_parent)
46*fae548d3Szrj     dst_fp = dst_fp->ctf_parent;
47*fae548d3Szrj 
48*fae548d3Szrj   dst_type = LCTF_TYPE_TO_INDEX(dst_fp, dst_type);
49*fae548d3Szrj 
50*fae548d3Szrj   /* This dynhash is a bit tricky: it has a multivalued (structural) key, so we
51*fae548d3Szrj      need to use the sized-hash machinery to generate key hashing and equality
52*fae548d3Szrj      functions.  */
53*fae548d3Szrj 
54*fae548d3Szrj   if (dst_fp->ctf_link_type_mapping == NULL)
55*fae548d3Szrj     {
56*fae548d3Szrj       ctf_hash_fun f = ctf_hash_type_mapping_key;
57*fae548d3Szrj       ctf_hash_eq_fun e = ctf_hash_eq_type_mapping_key;
58*fae548d3Szrj 
59*fae548d3Szrj       if ((dst_fp->ctf_link_type_mapping = ctf_dynhash_create (f, e, free,
60*fae548d3Szrj 							       NULL)) == NULL)
61*fae548d3Szrj 	return;
62*fae548d3Szrj     }
63*fae548d3Szrj 
64*fae548d3Szrj   ctf_link_type_mapping_key_t *key;
65*fae548d3Szrj   key = calloc (1, sizeof (struct ctf_link_type_mapping_key));
66*fae548d3Szrj   if (!key)
67*fae548d3Szrj     return;
68*fae548d3Szrj 
69*fae548d3Szrj   key->cltm_fp = src_fp;
70*fae548d3Szrj   key->cltm_idx = src_type;
71*fae548d3Szrj 
72*fae548d3Szrj   ctf_dynhash_insert (dst_fp->ctf_link_type_mapping, key,
73*fae548d3Szrj 		      (void *) (uintptr_t) dst_type);
74*fae548d3Szrj }
75*fae548d3Szrj 
76*fae548d3Szrj /* Look up a type mapping: return 0 if none.  The DST_FP is modified to point to
77*fae548d3Szrj    the parent if need be.  The ID returned is from the dst_fp's perspective.  */
78*fae548d3Szrj ctf_id_t
ctf_type_mapping(ctf_file_t * src_fp,ctf_id_t src_type,ctf_file_t ** dst_fp)79*fae548d3Szrj ctf_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type, ctf_file_t **dst_fp)
80*fae548d3Szrj {
81*fae548d3Szrj   ctf_link_type_mapping_key_t key;
82*fae548d3Szrj   ctf_file_t *target_fp = *dst_fp;
83*fae548d3Szrj   ctf_id_t dst_type = 0;
84*fae548d3Szrj 
85*fae548d3Szrj   if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
86*fae548d3Szrj     src_fp = src_fp->ctf_parent;
87*fae548d3Szrj 
88*fae548d3Szrj   src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
89*fae548d3Szrj   key.cltm_fp = src_fp;
90*fae548d3Szrj   key.cltm_idx = src_type;
91*fae548d3Szrj 
92*fae548d3Szrj   if (target_fp->ctf_link_type_mapping)
93*fae548d3Szrj     dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
94*fae548d3Szrj 					       &key);
95*fae548d3Szrj 
96*fae548d3Szrj   if (dst_type != 0)
97*fae548d3Szrj     {
98*fae548d3Szrj       dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
99*fae548d3Szrj 				     target_fp->ctf_parent != NULL);
100*fae548d3Szrj       *dst_fp = target_fp;
101*fae548d3Szrj       return dst_type;
102*fae548d3Szrj     }
103*fae548d3Szrj 
104*fae548d3Szrj   if (target_fp->ctf_parent)
105*fae548d3Szrj     target_fp = target_fp->ctf_parent;
106*fae548d3Szrj   else
107*fae548d3Szrj     return 0;
108*fae548d3Szrj 
109*fae548d3Szrj   if (target_fp->ctf_link_type_mapping)
110*fae548d3Szrj     dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
111*fae548d3Szrj 					       &key);
112*fae548d3Szrj 
113*fae548d3Szrj   if (dst_type)
114*fae548d3Szrj     dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
115*fae548d3Szrj 				   target_fp->ctf_parent != NULL);
116*fae548d3Szrj 
117*fae548d3Szrj   *dst_fp = target_fp;
118*fae548d3Szrj   return dst_type;
119*fae548d3Szrj }
120*fae548d3Szrj 
121*fae548d3Szrj /* Linker machinery.
122*fae548d3Szrj 
123*fae548d3Szrj    CTF linking consists of adding CTF archives full of content to be merged into
124*fae548d3Szrj    this one to the current file (which must be writable) by calling
125*fae548d3Szrj    ctf_link_add_ctf().  Once this is done, a call to ctf_link() will merge the
126*fae548d3Szrj    type tables together, generating new CTF files as needed, with this one as a
127*fae548d3Szrj    parent, to contain types from the inputs which conflict.
128*fae548d3Szrj    ctf_link_add_strtab() takes a callback which provides string/offset pairs to
129*fae548d3Szrj    be added to the external symbol table and deduplicated from all CTF string
130*fae548d3Szrj    tables in the output link; ctf_link_shuffle_syms() takes a callback which
131*fae548d3Szrj    provides symtab entries in ascending order, and shuffles the function and
132*fae548d3Szrj    data sections to match; and ctf_link_write() emits a CTF file (if there are
133*fae548d3Szrj    no conflicts requiring per-compilation-unit sub-CTF files) or CTF archives
134*fae548d3Szrj    (otherwise) and returns it, suitable for addition in the .ctf section of the
135*fae548d3Szrj    output.  */
136*fae548d3Szrj 
137*fae548d3Szrj /* Add a file to a link.  */
138*fae548d3Szrj 
ctf_arc_close_thunk(void * arc)139*fae548d3Szrj static void ctf_arc_close_thunk (void *arc)
140*fae548d3Szrj {
141*fae548d3Szrj   ctf_arc_close ((ctf_archive_t *) arc);
142*fae548d3Szrj }
143*fae548d3Szrj 
ctf_file_close_thunk(void * file)144*fae548d3Szrj static void ctf_file_close_thunk (void *file)
145*fae548d3Szrj {
146*fae548d3Szrj   ctf_file_close ((ctf_file_t *) file);
147*fae548d3Szrj }
148*fae548d3Szrj 
149*fae548d3Szrj int
ctf_link_add_ctf(ctf_file_t * fp,ctf_archive_t * ctf,const char * name)150*fae548d3Szrj ctf_link_add_ctf (ctf_file_t *fp, ctf_archive_t *ctf, const char *name)
151*fae548d3Szrj {
152*fae548d3Szrj   char *dupname = NULL;
153*fae548d3Szrj 
154*fae548d3Szrj   if (fp->ctf_link_outputs)
155*fae548d3Szrj     return (ctf_set_errno (fp, ECTF_LINKADDEDLATE));
156*fae548d3Szrj   if (fp->ctf_link_inputs == NULL)
157*fae548d3Szrj     fp->ctf_link_inputs = ctf_dynhash_create (ctf_hash_string,
158*fae548d3Szrj 					      ctf_hash_eq_string, free,
159*fae548d3Szrj 					      ctf_arc_close_thunk);
160*fae548d3Szrj 
161*fae548d3Szrj   if (fp->ctf_link_inputs == NULL)
162*fae548d3Szrj     goto oom;
163*fae548d3Szrj 
164*fae548d3Szrj   if ((dupname = strdup (name)) == NULL)
165*fae548d3Szrj     goto oom;
166*fae548d3Szrj 
167*fae548d3Szrj   if (ctf_dynhash_insert (fp->ctf_link_inputs, dupname, ctf) < 0)
168*fae548d3Szrj     goto oom;
169*fae548d3Szrj 
170*fae548d3Szrj   return 0;
171*fae548d3Szrj  oom:
172*fae548d3Szrj   free (fp->ctf_link_inputs);
173*fae548d3Szrj   fp->ctf_link_inputs = NULL;
174*fae548d3Szrj   free (dupname);
175*fae548d3Szrj   return (ctf_set_errno (fp, ENOMEM));
176*fae548d3Szrj }
177*fae548d3Szrj 
178*fae548d3Szrj /* Return a per-CU output CTF dictionary suitable for the given CU, creating and
179*fae548d3Szrj    interning it if need be.  */
180*fae548d3Szrj 
181*fae548d3Szrj static ctf_file_t *
ctf_create_per_cu(ctf_file_t * fp,const char * filename,const char * cuname)182*fae548d3Szrj ctf_create_per_cu (ctf_file_t *fp, const char *filename, const char *cuname)
183*fae548d3Szrj {
184*fae548d3Szrj   ctf_file_t *cu_fp;
185*fae548d3Szrj   const char *ctf_name = NULL;
186*fae548d3Szrj   char *dynname = NULL;
187*fae548d3Szrj 
188*fae548d3Szrj   /* First, check the mapping table and translate the per-CU name we use
189*fae548d3Szrj      accordingly.  We check both the input filename and the CU name.  Only if
190*fae548d3Szrj      neither are set do we fall back to the input filename as the per-CU
191*fae548d3Szrj      dictionary name.  We prefer the filename because this is easier for likely
192*fae548d3Szrj      callers to determine.  */
193*fae548d3Szrj 
194*fae548d3Szrj   if (fp->ctf_link_cu_mapping)
195*fae548d3Szrj     {
196*fae548d3Szrj       if (((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, filename)) == NULL) &&
197*fae548d3Szrj 	  ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, cuname)) == NULL))
198*fae548d3Szrj 	ctf_name = filename;
199*fae548d3Szrj     }
200*fae548d3Szrj 
201*fae548d3Szrj   if (ctf_name == NULL)
202*fae548d3Szrj     ctf_name = filename;
203*fae548d3Szrj 
204*fae548d3Szrj   if ((cu_fp = ctf_dynhash_lookup (fp->ctf_link_outputs, ctf_name)) == NULL)
205*fae548d3Szrj     {
206*fae548d3Szrj       int err;
207*fae548d3Szrj 
208*fae548d3Szrj       if ((cu_fp = ctf_create (&err)) == NULL)
209*fae548d3Szrj 	{
210*fae548d3Szrj 	  ctf_dprintf ("Cannot create per-CU CTF archive for CU %s from "
211*fae548d3Szrj 		       "input file %s: %s\n", cuname, filename,
212*fae548d3Szrj 		       ctf_errmsg (err));
213*fae548d3Szrj 	  ctf_set_errno (fp, err);
214*fae548d3Szrj 	  return NULL;
215*fae548d3Szrj 	}
216*fae548d3Szrj 
217*fae548d3Szrj       if ((dynname = strdup (ctf_name)) == NULL)
218*fae548d3Szrj 	goto oom;
219*fae548d3Szrj       if (ctf_dynhash_insert (fp->ctf_link_outputs, dynname, cu_fp) < 0)
220*fae548d3Szrj 	goto oom;
221*fae548d3Szrj 
222*fae548d3Szrj       ctf_import (cu_fp, fp);
223*fae548d3Szrj       ctf_cuname_set (cu_fp, cuname);
224*fae548d3Szrj       ctf_parent_name_set (cu_fp, _CTF_SECTION);
225*fae548d3Szrj     }
226*fae548d3Szrj   return cu_fp;
227*fae548d3Szrj 
228*fae548d3Szrj  oom:
229*fae548d3Szrj   free (dynname);
230*fae548d3Szrj   ctf_file_close (cu_fp);
231*fae548d3Szrj   ctf_set_errno (fp, ENOMEM);
232*fae548d3Szrj   return NULL;
233*fae548d3Szrj }
234*fae548d3Szrj 
235*fae548d3Szrj /* Add a mapping directing that the CU named FROM should have its
236*fae548d3Szrj    conflicting/non-duplicate types (depending on link mode) go into a container
237*fae548d3Szrj    named TO.  Many FROMs can share a TO: in this case, the effect on conflicting
238*fae548d3Szrj    types is not yet defined (but in time an auto-renaming algorithm will be
239*fae548d3Szrj    added: ugly, but there is really no right thing one can do in this
240*fae548d3Szrj    situation).
241*fae548d3Szrj 
242*fae548d3Szrj    We forcibly add a container named TO in every case, even though it may well
243*fae548d3Szrj    wind up empty, because clients that use this facility usually expect to find
244*fae548d3Szrj    every TO container present, even if empty, and malfunction otherwise.  */
245*fae548d3Szrj 
246*fae548d3Szrj int
ctf_link_add_cu_mapping(ctf_file_t * fp,const char * from,const char * to)247*fae548d3Szrj ctf_link_add_cu_mapping (ctf_file_t *fp, const char *from, const char *to)
248*fae548d3Szrj {
249*fae548d3Szrj   int err;
250*fae548d3Szrj   char *f, *t;
251*fae548d3Szrj 
252*fae548d3Szrj   if (fp->ctf_link_cu_mapping == NULL)
253*fae548d3Szrj     fp->ctf_link_cu_mapping = ctf_dynhash_create (ctf_hash_string,
254*fae548d3Szrj 						  ctf_hash_eq_string, free,
255*fae548d3Szrj 						  free);
256*fae548d3Szrj   if (fp->ctf_link_cu_mapping == NULL)
257*fae548d3Szrj     return ctf_set_errno (fp, ENOMEM);
258*fae548d3Szrj 
259*fae548d3Szrj   if (fp->ctf_link_outputs == NULL)
260*fae548d3Szrj     fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
261*fae548d3Szrj 					       ctf_hash_eq_string, free,
262*fae548d3Szrj 					       ctf_file_close_thunk);
263*fae548d3Szrj 
264*fae548d3Szrj   if (fp->ctf_link_outputs == NULL)
265*fae548d3Szrj     return ctf_set_errno (fp, ENOMEM);
266*fae548d3Szrj 
267*fae548d3Szrj   f = strdup (from);
268*fae548d3Szrj   t = strdup (to);
269*fae548d3Szrj   if (!f || !t)
270*fae548d3Szrj     goto oom;
271*fae548d3Szrj 
272*fae548d3Szrj   if (ctf_create_per_cu (fp, t, t) == NULL)
273*fae548d3Szrj     goto oom_noerrno;				/* Errno is set for us.  */
274*fae548d3Szrj 
275*fae548d3Szrj   err = ctf_dynhash_insert (fp->ctf_link_cu_mapping, f, t);
276*fae548d3Szrj   if (err)
277*fae548d3Szrj     {
278*fae548d3Szrj       ctf_set_errno (fp, err);
279*fae548d3Szrj       goto oom_noerrno;
280*fae548d3Szrj     }
281*fae548d3Szrj 
282*fae548d3Szrj   return 0;
283*fae548d3Szrj 
284*fae548d3Szrj  oom:
285*fae548d3Szrj   ctf_set_errno (fp, errno);
286*fae548d3Szrj  oom_noerrno:
287*fae548d3Szrj   free (f);
288*fae548d3Szrj   free (t);
289*fae548d3Szrj   return -1;
290*fae548d3Szrj }
291*fae548d3Szrj 
292*fae548d3Szrj /* Set a function which is called to transform the names of archive members.
293*fae548d3Szrj    This is useful for applying regular transformations to many names, where
294*fae548d3Szrj    ctf_link_add_cu_mapping applies arbitrarily irregular changes to single
295*fae548d3Szrj    names.  The member name changer is applied at ctf_link_write time, so it
296*fae548d3Szrj    cannot conflate multiple CUs into one the way ctf_link_add_cu_mapping can.
297*fae548d3Szrj    The changer function accepts a name and should return a new
298*fae548d3Szrj    dynamically-allocated name, or NULL if the name should be left unchanged.  */
299*fae548d3Szrj void
ctf_link_set_memb_name_changer(ctf_file_t * fp,ctf_link_memb_name_changer_f * changer,void * arg)300*fae548d3Szrj ctf_link_set_memb_name_changer (ctf_file_t *fp,
301*fae548d3Szrj 				ctf_link_memb_name_changer_f *changer,
302*fae548d3Szrj 				void *arg)
303*fae548d3Szrj {
304*fae548d3Szrj   fp->ctf_link_memb_name_changer = changer;
305*fae548d3Szrj   fp->ctf_link_memb_name_changer_arg = arg;
306*fae548d3Szrj }
307*fae548d3Szrj 
308*fae548d3Szrj typedef struct ctf_link_in_member_cb_arg
309*fae548d3Szrj {
310*fae548d3Szrj   ctf_file_t *out_fp;
311*fae548d3Szrj   const char *file_name;
312*fae548d3Szrj   ctf_file_t *in_fp;
313*fae548d3Szrj   ctf_file_t *main_input_fp;
314*fae548d3Szrj   const char *cu_name;
315*fae548d3Szrj   char *arcname;
316*fae548d3Szrj   int done_main_member;
317*fae548d3Szrj   int share_mode;
318*fae548d3Szrj   int in_input_cu_file;
319*fae548d3Szrj } ctf_link_in_member_cb_arg_t;
320*fae548d3Szrj 
321*fae548d3Szrj /* Link one type into the link.  We rely on ctf_add_type() to detect
322*fae548d3Szrj    duplicates.  This is not terribly reliable yet (unnmamed types will be
323*fae548d3Szrj    mindlessly duplicated), but will improve shortly.  */
324*fae548d3Szrj 
325*fae548d3Szrj static int
ctf_link_one_type(ctf_id_t type,int isroot _libctf_unused_,void * arg_)326*fae548d3Szrj ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_)
327*fae548d3Szrj {
328*fae548d3Szrj   ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
329*fae548d3Szrj   ctf_file_t *per_cu_out_fp;
330*fae548d3Szrj   int err;
331*fae548d3Szrj 
332*fae548d3Szrj   if (arg->share_mode != CTF_LINK_SHARE_UNCONFLICTED)
333*fae548d3Szrj     {
334*fae548d3Szrj       ctf_dprintf ("Share-duplicated mode not yet implemented.\n");
335*fae548d3Szrj       return ctf_set_errno (arg->out_fp, ECTF_NOTYET);
336*fae548d3Szrj     }
337*fae548d3Szrj 
338*fae548d3Szrj   /* Simply call ctf_add_type: if it reports a conflict and we're adding to the
339*fae548d3Szrj      main CTF file, add to the per-CU archive member instead, creating it if
340*fae548d3Szrj      necessary.  If we got this type from a per-CU archive member, add it
341*fae548d3Szrj      straight back to the corresponding member in the output.  */
342*fae548d3Szrj 
343*fae548d3Szrj   if (!arg->in_input_cu_file)
344*fae548d3Szrj     {
345*fae548d3Szrj       if (ctf_add_type (arg->out_fp, arg->in_fp, type) != CTF_ERR)
346*fae548d3Szrj 	return 0;
347*fae548d3Szrj 
348*fae548d3Szrj       err = ctf_errno (arg->out_fp);
349*fae548d3Szrj       if (err != ECTF_CONFLICT)
350*fae548d3Szrj 	{
351*fae548d3Szrj 	  if (err != ECTF_NONREPRESENTABLE)
352*fae548d3Szrj 	    ctf_dprintf ("Cannot link type %lx from archive member %s, input file %s "
353*fae548d3Szrj 			 "into output link: %s\n", type, arg->arcname, arg->file_name,
354*fae548d3Szrj 			 ctf_errmsg (err));
355*fae548d3Szrj 	  /* We must ignore this problem or we end up losing future types, then
356*fae548d3Szrj 	     trying to link the variables in, then exploding.  Better to link as
357*fae548d3Szrj 	     much as possible.  XXX when we add a proper link warning
358*fae548d3Szrj 	     infrastructure, we should report the error here!  */
359*fae548d3Szrj 	  return 0;
360*fae548d3Szrj 	}
361*fae548d3Szrj       ctf_set_errno (arg->out_fp, 0);
362*fae548d3Szrj     }
363*fae548d3Szrj 
364*fae548d3Szrj   if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->file_name,
365*fae548d3Szrj 					  arg->cu_name)) == NULL)
366*fae548d3Szrj     return -1;					/* Errno is set for us.  */
367*fae548d3Szrj 
368*fae548d3Szrj   if (ctf_add_type (per_cu_out_fp, arg->in_fp, type) != CTF_ERR)
369*fae548d3Szrj     return 0;
370*fae548d3Szrj 
371*fae548d3Szrj   err = ctf_errno (per_cu_out_fp);
372*fae548d3Szrj   if (err != ECTF_NONREPRESENTABLE)
373*fae548d3Szrj     ctf_dprintf ("Cannot link type %lx from CTF archive member %s, input file %s "
374*fae548d3Szrj 		 "into output per-CU CTF archive member %s: %s: skipped\n", type,
375*fae548d3Szrj 		 arg->arcname, arg->file_name, arg->arcname,
376*fae548d3Szrj 		 ctf_errmsg (err));
377*fae548d3Szrj   if (err == ECTF_CONFLICT)
378*fae548d3Szrj       /* Conflicts are possible at this stage only if a non-ld user has combined
379*fae548d3Szrj 	 multiple TUs into a single output dictionary.  Even in this case we do not
380*fae548d3Szrj 	 want to stop the link or propagate the error.  */
381*fae548d3Szrj       ctf_set_errno (arg->out_fp, 0);
382*fae548d3Szrj 
383*fae548d3Szrj   return 0;					/* As above: do not lose types.  */
384*fae548d3Szrj }
385*fae548d3Szrj 
386*fae548d3Szrj /* Check if we can safely add a variable with the given type to this container.  */
387*fae548d3Szrj 
388*fae548d3Szrj static int
check_variable(const char * name,ctf_file_t * fp,ctf_id_t type,ctf_dvdef_t ** out_dvd)389*fae548d3Szrj check_variable (const char *name, ctf_file_t *fp, ctf_id_t type,
390*fae548d3Szrj 		ctf_dvdef_t **out_dvd)
391*fae548d3Szrj {
392*fae548d3Szrj   ctf_dvdef_t *dvd;
393*fae548d3Szrj 
394*fae548d3Szrj   dvd = ctf_dynhash_lookup (fp->ctf_dvhash, name);
395*fae548d3Szrj   *out_dvd = dvd;
396*fae548d3Szrj   if (!dvd)
397*fae548d3Szrj     return 1;
398*fae548d3Szrj 
399*fae548d3Szrj   if (dvd->dvd_type != type)
400*fae548d3Szrj     {
401*fae548d3Szrj       /* Variable here.  Wrong type: cannot add.  Just skip it, because there is
402*fae548d3Szrj 	 no way to express this in CTF.  (This might be the parent, in which
403*fae548d3Szrj 	 case we'll try adding in the child first, and only then give up.)  */
404*fae548d3Szrj       ctf_dprintf ("Inexpressible duplicate variable %s skipped.\n", name);
405*fae548d3Szrj     }
406*fae548d3Szrj 
407*fae548d3Szrj   return 0;				      /* Already exists.  */
408*fae548d3Szrj }
409*fae548d3Szrj 
410*fae548d3Szrj /* Link one variable in.  */
411*fae548d3Szrj 
412*fae548d3Szrj static int
ctf_link_one_variable(const char * name,ctf_id_t type,void * arg_)413*fae548d3Szrj ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
414*fae548d3Szrj {
415*fae548d3Szrj   ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
416*fae548d3Szrj   ctf_file_t *per_cu_out_fp;
417*fae548d3Szrj   ctf_id_t dst_type = 0;
418*fae548d3Szrj   ctf_file_t *check_fp;
419*fae548d3Szrj   ctf_dvdef_t *dvd;
420*fae548d3Szrj 
421*fae548d3Szrj   /* In unconflicted link mode, if this type is mapped to a type in the parent
422*fae548d3Szrj      container, we want to try to add to that first: if it reports a duplicate,
423*fae548d3Szrj      or if the type is in a child already, add straight to the child.  */
424*fae548d3Szrj 
425*fae548d3Szrj   check_fp = arg->out_fp;
426*fae548d3Szrj 
427*fae548d3Szrj   dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
428*fae548d3Szrj   if (dst_type != 0)
429*fae548d3Szrj     {
430*fae548d3Szrj       if (check_fp == arg->out_fp)
431*fae548d3Szrj 	{
432*fae548d3Szrj 	  if (check_variable (name, check_fp, dst_type, &dvd))
433*fae548d3Szrj 	    {
434*fae548d3Szrj 	      /* No variable here: we can add it.  */
435*fae548d3Szrj 	      if (ctf_add_variable (check_fp, name, dst_type) < 0)
436*fae548d3Szrj 		return (ctf_set_errno (arg->out_fp, ctf_errno (check_fp)));
437*fae548d3Szrj 	      return 0;
438*fae548d3Szrj 	    }
439*fae548d3Szrj 
440*fae548d3Szrj 	  /* Already present?  Nothing to do.  */
441*fae548d3Szrj 	  if (dvd && dvd->dvd_type == type)
442*fae548d3Szrj 	    return 0;
443*fae548d3Szrj 	}
444*fae548d3Szrj     }
445*fae548d3Szrj 
446*fae548d3Szrj   /* Can't add to the parent due to a name clash, or because it references a
447*fae548d3Szrj      type only present in the child.  Try adding to the child, creating if need
448*fae548d3Szrj      be.  */
449*fae548d3Szrj 
450*fae548d3Szrj   if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->file_name,
451*fae548d3Szrj 					  arg->cu_name)) == NULL)
452*fae548d3Szrj     return -1;					/* Errno is set for us.  */
453*fae548d3Szrj 
454*fae548d3Szrj   /* If the type was not found, check for it in the child too. */
455*fae548d3Szrj   if (dst_type == 0)
456*fae548d3Szrj     {
457*fae548d3Szrj       check_fp = per_cu_out_fp;
458*fae548d3Szrj       dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
459*fae548d3Szrj 
460*fae548d3Szrj       if (dst_type == 0)
461*fae548d3Szrj 	{
462*fae548d3Szrj 	  ctf_dprintf ("Type %lx for variable %s in input file %s not "
463*fae548d3Szrj 		       "found: skipped.\n", type, name, arg->file_name);
464*fae548d3Szrj 	  /* Do not terminate the link: just skip the variable.  */
465*fae548d3Szrj 	  return 0;
466*fae548d3Szrj 	}
467*fae548d3Szrj     }
468*fae548d3Szrj 
469*fae548d3Szrj   if (check_variable (name, per_cu_out_fp, dst_type, &dvd))
470*fae548d3Szrj     if (ctf_add_variable (per_cu_out_fp, name, dst_type) < 0)
471*fae548d3Szrj       return (ctf_set_errno (arg->out_fp, ctf_errno (per_cu_out_fp)));
472*fae548d3Szrj   return 0;
473*fae548d3Szrj }
474*fae548d3Szrj 
475*fae548d3Szrj /* Merge every type and variable in this archive member into the link, so we can
476*fae548d3Szrj    relink things that have already had ld run on them.  We use the archive
477*fae548d3Szrj    member name, sans any leading '.ctf.', as the CU name for ambiguous types if
478*fae548d3Szrj    there is one and it's not the default: otherwise, we use the name of the
479*fae548d3Szrj    input file.  */
480*fae548d3Szrj static int
ctf_link_one_input_archive_member(ctf_file_t * in_fp,const char * name,void * arg_)481*fae548d3Szrj ctf_link_one_input_archive_member (ctf_file_t *in_fp, const char *name, void *arg_)
482*fae548d3Szrj {
483*fae548d3Szrj   ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
484*fae548d3Szrj   int err = 0;
485*fae548d3Szrj 
486*fae548d3Szrj   if (strcmp (name, _CTF_SECTION) == 0)
487*fae548d3Szrj     {
488*fae548d3Szrj       /* This file is the default member of this archive, and has already been
489*fae548d3Szrj 	 explicitly processed.
490*fae548d3Szrj 
491*fae548d3Szrj 	 In the default sharing mode of CTF_LINK_SHARE_UNCONFLICTED, it does no
492*fae548d3Szrj 	 harm to rescan an existing shared repo again: all the types will just
493*fae548d3Szrj 	 end up in the same place.  But in CTF_LINK_SHARE_DUPLICATED mode, this
494*fae548d3Szrj 	 causes the system to erroneously conclude that all types are duplicated
495*fae548d3Szrj 	 and should be shared, even if they are not.  */
496*fae548d3Szrj 
497*fae548d3Szrj       if (arg->done_main_member)
498*fae548d3Szrj 	return 0;
499*fae548d3Szrj       arg->arcname = strdup (".ctf.");
500*fae548d3Szrj       if (arg->arcname)
501*fae548d3Szrj 	{
502*fae548d3Szrj 	  char *new_name;
503*fae548d3Szrj 
504*fae548d3Szrj 	  new_name = ctf_str_append (arg->arcname, arg->file_name);
505*fae548d3Szrj 	  if (new_name)
506*fae548d3Szrj 	    arg->arcname = new_name;
507*fae548d3Szrj 	  else
508*fae548d3Szrj 	    free (arg->arcname);
509*fae548d3Szrj 	}
510*fae548d3Szrj     }
511*fae548d3Szrj   else
512*fae548d3Szrj     {
513*fae548d3Szrj       arg->arcname = strdup (name);
514*fae548d3Szrj 
515*fae548d3Szrj       /* Get ambiguous types from our parent.  */
516*fae548d3Szrj       ctf_import (in_fp, arg->main_input_fp);
517*fae548d3Szrj       arg->in_input_cu_file = 1;
518*fae548d3Szrj     }
519*fae548d3Szrj 
520*fae548d3Szrj   if (!arg->arcname)
521*fae548d3Szrj     return ctf_set_errno (in_fp, ENOMEM);
522*fae548d3Szrj 
523*fae548d3Szrj   arg->cu_name = name;
524*fae548d3Szrj   if (strncmp (arg->cu_name, ".ctf.", strlen (".ctf.")) == 0)
525*fae548d3Szrj     arg->cu_name += strlen (".ctf.");
526*fae548d3Szrj   arg->in_fp = in_fp;
527*fae548d3Szrj 
528*fae548d3Szrj   if ((err = ctf_type_iter_all (in_fp, ctf_link_one_type, arg)) > -1)
529*fae548d3Szrj     err = ctf_variable_iter (in_fp, ctf_link_one_variable, arg);
530*fae548d3Szrj 
531*fae548d3Szrj   arg->in_input_cu_file = 0;
532*fae548d3Szrj   free (arg->arcname);
533*fae548d3Szrj 
534*fae548d3Szrj   if (err < 0)
535*fae548d3Szrj       return -1;				/* Errno is set for us.  */
536*fae548d3Szrj 
537*fae548d3Szrj   return 0;
538*fae548d3Szrj }
539*fae548d3Szrj 
540*fae548d3Szrj /* Dump the unnecessary link type mapping after one input file is processed.  */
541*fae548d3Szrj static void
empty_link_type_mapping(void * key _libctf_unused_,void * value,void * arg _libctf_unused_)542*fae548d3Szrj empty_link_type_mapping (void *key _libctf_unused_, void *value,
543*fae548d3Szrj 			 void *arg _libctf_unused_)
544*fae548d3Szrj {
545*fae548d3Szrj   ctf_file_t *fp = (ctf_file_t *) value;
546*fae548d3Szrj 
547*fae548d3Szrj   if (fp->ctf_link_type_mapping)
548*fae548d3Szrj     ctf_dynhash_empty (fp->ctf_link_type_mapping);
549*fae548d3Szrj }
550*fae548d3Szrj 
551*fae548d3Szrj /* Link one input file's types into the output file.  */
552*fae548d3Szrj static void
ctf_link_one_input_archive(void * key,void * value,void * arg_)553*fae548d3Szrj ctf_link_one_input_archive (void *key, void *value, void *arg_)
554*fae548d3Szrj {
555*fae548d3Szrj   const char *file_name = (const char *) key;
556*fae548d3Szrj   ctf_archive_t *arc = (ctf_archive_t *) value;
557*fae548d3Szrj   ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
558*fae548d3Szrj   int err;
559*fae548d3Szrj 
560*fae548d3Szrj   arg->file_name = file_name;
561*fae548d3Szrj   arg->done_main_member = 0;
562*fae548d3Szrj   if ((arg->main_input_fp = ctf_arc_open_by_name (arc, NULL, &err)) == NULL)
563*fae548d3Szrj     if (err != ECTF_ARNNAME)
564*fae548d3Szrj       {
565*fae548d3Szrj 	ctf_dprintf ("Cannot open main archive member in input file %s in the "
566*fae548d3Szrj 		     "link: skipping: %s.\n", arg->file_name,
567*fae548d3Szrj 		     ctf_errmsg (err));
568*fae548d3Szrj 	return;
569*fae548d3Szrj       }
570*fae548d3Szrj 
571*fae548d3Szrj   if (ctf_link_one_input_archive_member (arg->main_input_fp,
572*fae548d3Szrj 					 _CTF_SECTION, arg) < 0)
573*fae548d3Szrj     {
574*fae548d3Szrj       ctf_file_close (arg->main_input_fp);
575*fae548d3Szrj       return;
576*fae548d3Szrj     }
577*fae548d3Szrj   arg->done_main_member = 1;
578*fae548d3Szrj   if (ctf_archive_iter (arc, ctf_link_one_input_archive_member, arg) < 0)
579*fae548d3Szrj     ctf_dprintf ("Cannot traverse archive in input file %s: link "
580*fae548d3Szrj 		 "cannot continue: %s.\n", arg->file_name,
581*fae548d3Szrj 		 ctf_errmsg (ctf_errno (arg->out_fp)));
582*fae548d3Szrj   else
583*fae548d3Szrj     {
584*fae548d3Szrj       /* The only error indication to the caller is the errno: so ensure that it
585*fae548d3Szrj 	 is zero if there was no actual error from the caller.  */
586*fae548d3Szrj       ctf_set_errno (arg->out_fp, 0);
587*fae548d3Szrj     }
588*fae548d3Szrj   ctf_file_close (arg->main_input_fp);
589*fae548d3Szrj 
590*fae548d3Szrj   /* Discard the now-unnecessary mapping table data.  */
591*fae548d3Szrj   if (arg->out_fp->ctf_link_type_mapping)
592*fae548d3Szrj     ctf_dynhash_empty (arg->out_fp->ctf_link_type_mapping);
593*fae548d3Szrj   ctf_dynhash_iter (arg->out_fp->ctf_link_outputs, empty_link_type_mapping, NULL);
594*fae548d3Szrj }
595*fae548d3Szrj 
596*fae548d3Szrj /* Merge types and variable sections in all files added to the link
597*fae548d3Szrj    together.  */
598*fae548d3Szrj int
ctf_link(ctf_file_t * fp,int share_mode)599*fae548d3Szrj ctf_link (ctf_file_t *fp, int share_mode)
600*fae548d3Szrj {
601*fae548d3Szrj   ctf_link_in_member_cb_arg_t arg;
602*fae548d3Szrj 
603*fae548d3Szrj   memset (&arg, 0, sizeof (struct ctf_link_in_member_cb_arg));
604*fae548d3Szrj   arg.out_fp = fp;
605*fae548d3Szrj   arg.share_mode = share_mode;
606*fae548d3Szrj 
607*fae548d3Szrj   if (fp->ctf_link_inputs == NULL)
608*fae548d3Szrj     return 0;					/* Nothing to do. */
609*fae548d3Szrj 
610*fae548d3Szrj   if (fp->ctf_link_outputs == NULL)
611*fae548d3Szrj     fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
612*fae548d3Szrj 					       ctf_hash_eq_string, free,
613*fae548d3Szrj 					       ctf_file_close_thunk);
614*fae548d3Szrj 
615*fae548d3Szrj   if (fp->ctf_link_outputs == NULL)
616*fae548d3Szrj     return ctf_set_errno (fp, ENOMEM);
617*fae548d3Szrj 
618*fae548d3Szrj   ctf_dynhash_iter (fp->ctf_link_inputs, ctf_link_one_input_archive,
619*fae548d3Szrj 		    &arg);
620*fae548d3Szrj 
621*fae548d3Szrj   if (ctf_errno (fp) != 0)
622*fae548d3Szrj     return -1;
623*fae548d3Szrj   return 0;
624*fae548d3Szrj }
625*fae548d3Szrj 
626*fae548d3Szrj typedef struct ctf_link_out_string_cb_arg
627*fae548d3Szrj {
628*fae548d3Szrj   const char *str;
629*fae548d3Szrj   uint32_t offset;
630*fae548d3Szrj   int err;
631*fae548d3Szrj } ctf_link_out_string_cb_arg_t;
632*fae548d3Szrj 
633*fae548d3Szrj /* Intern a string in the string table of an output per-CU CTF file.  */
634*fae548d3Szrj static void
ctf_link_intern_extern_string(void * key _libctf_unused_,void * value,void * arg_)635*fae548d3Szrj ctf_link_intern_extern_string (void *key _libctf_unused_, void *value,
636*fae548d3Szrj 			       void *arg_)
637*fae548d3Szrj {
638*fae548d3Szrj   ctf_file_t *fp = (ctf_file_t *) value;
639*fae548d3Szrj   ctf_link_out_string_cb_arg_t *arg = (ctf_link_out_string_cb_arg_t *) arg_;
640*fae548d3Szrj 
641*fae548d3Szrj   fp->ctf_flags |= LCTF_DIRTY;
642*fae548d3Szrj   if (!ctf_str_add_external (fp, arg->str, arg->offset))
643*fae548d3Szrj     arg->err = ENOMEM;
644*fae548d3Szrj }
645*fae548d3Szrj 
646*fae548d3Szrj /* Repeatedly call ADD_STRING to acquire strings from the external string table,
647*fae548d3Szrj    adding them to the atoms table for this CU and all subsidiary CUs.
648*fae548d3Szrj 
649*fae548d3Szrj    If ctf_link() is also called, it must be called first if you want the new CTF
650*fae548d3Szrj    files ctf_link() can create to get their strings dedupped against the ELF
651*fae548d3Szrj    strtab properly.  */
652*fae548d3Szrj int
ctf_link_add_strtab(ctf_file_t * fp,ctf_link_strtab_string_f * add_string,void * arg)653*fae548d3Szrj ctf_link_add_strtab (ctf_file_t *fp, ctf_link_strtab_string_f *add_string,
654*fae548d3Szrj 		     void *arg)
655*fae548d3Szrj {
656*fae548d3Szrj   const char *str;
657*fae548d3Szrj   uint32_t offset;
658*fae548d3Szrj   int err = 0;
659*fae548d3Szrj 
660*fae548d3Szrj   while ((str = add_string (&offset, arg)) != NULL)
661*fae548d3Szrj     {
662*fae548d3Szrj       ctf_link_out_string_cb_arg_t iter_arg = { str, offset, 0 };
663*fae548d3Szrj 
664*fae548d3Szrj       fp->ctf_flags |= LCTF_DIRTY;
665*fae548d3Szrj       if (!ctf_str_add_external (fp, str, offset))
666*fae548d3Szrj 	err = ENOMEM;
667*fae548d3Szrj 
668*fae548d3Szrj       ctf_dynhash_iter (fp->ctf_link_outputs, ctf_link_intern_extern_string,
669*fae548d3Szrj 			&iter_arg);
670*fae548d3Szrj       if (iter_arg.err)
671*fae548d3Szrj 	err = iter_arg.err;
672*fae548d3Szrj     }
673*fae548d3Szrj 
674*fae548d3Szrj   return -err;
675*fae548d3Szrj }
676*fae548d3Szrj 
677*fae548d3Szrj /* Not yet implemented.  */
678*fae548d3Szrj int
ctf_link_shuffle_syms(ctf_file_t * fp _libctf_unused_,ctf_link_iter_symbol_f * add_sym _libctf_unused_,void * arg _libctf_unused_)679*fae548d3Szrj ctf_link_shuffle_syms (ctf_file_t *fp _libctf_unused_,
680*fae548d3Szrj 		       ctf_link_iter_symbol_f *add_sym _libctf_unused_,
681*fae548d3Szrj 		       void *arg _libctf_unused_)
682*fae548d3Szrj {
683*fae548d3Szrj   return 0;
684*fae548d3Szrj }
685*fae548d3Szrj 
686*fae548d3Szrj typedef struct ctf_name_list_accum_cb_arg
687*fae548d3Szrj {
688*fae548d3Szrj   char **names;
689*fae548d3Szrj   ctf_file_t *fp;
690*fae548d3Szrj   ctf_file_t **files;
691*fae548d3Szrj   size_t i;
692*fae548d3Szrj   char **dynames;
693*fae548d3Szrj   size_t ndynames;
694*fae548d3Szrj } ctf_name_list_accum_cb_arg_t;
695*fae548d3Szrj 
696*fae548d3Szrj /* Accumulate the names and a count of the names in the link output hash.  */
697*fae548d3Szrj static void
ctf_accumulate_archive_names(void * key,void * value,void * arg_)698*fae548d3Szrj ctf_accumulate_archive_names (void *key, void *value, void *arg_)
699*fae548d3Szrj {
700*fae548d3Szrj   const char *name = (const char *) key;
701*fae548d3Szrj   ctf_file_t *fp = (ctf_file_t *) value;
702*fae548d3Szrj   char **names;
703*fae548d3Szrj   ctf_file_t **files;
704*fae548d3Szrj   ctf_name_list_accum_cb_arg_t *arg = (ctf_name_list_accum_cb_arg_t *) arg_;
705*fae548d3Szrj 
706*fae548d3Szrj   if ((names = realloc (arg->names, sizeof (char *) * ++(arg->i))) == NULL)
707*fae548d3Szrj     {
708*fae548d3Szrj       (arg->i)--;
709*fae548d3Szrj       ctf_set_errno (arg->fp, ENOMEM);
710*fae548d3Szrj       return;
711*fae548d3Szrj     }
712*fae548d3Szrj 
713*fae548d3Szrj   if ((files = realloc (arg->files, sizeof (ctf_file_t *) * arg->i)) == NULL)
714*fae548d3Szrj     {
715*fae548d3Szrj       (arg->i)--;
716*fae548d3Szrj       ctf_set_errno (arg->fp, ENOMEM);
717*fae548d3Szrj       return;
718*fae548d3Szrj     }
719*fae548d3Szrj 
720*fae548d3Szrj   /* Allow the caller to get in and modify the name at the last minute.  If the
721*fae548d3Szrj      caller *does* modify the name, we have to stash away the new name the
722*fae548d3Szrj      caller returned so we can free it later on.  (The original name is the key
723*fae548d3Szrj      of the ctf_link_outputs hash and is freed by the dynhash machinery.)  */
724*fae548d3Szrj 
725*fae548d3Szrj   if (fp->ctf_link_memb_name_changer)
726*fae548d3Szrj     {
727*fae548d3Szrj       char **dynames;
728*fae548d3Szrj       char *dyname;
729*fae548d3Szrj       void *nc_arg = fp->ctf_link_memb_name_changer_arg;
730*fae548d3Szrj 
731*fae548d3Szrj       dyname = fp->ctf_link_memb_name_changer (fp, name, nc_arg);
732*fae548d3Szrj 
733*fae548d3Szrj       if (dyname != NULL)
734*fae548d3Szrj 	{
735*fae548d3Szrj 	  if ((dynames = realloc (arg->dynames,
736*fae548d3Szrj 				  sizeof (char *) * ++(arg->ndynames))) == NULL)
737*fae548d3Szrj 	    {
738*fae548d3Szrj 	      (arg->ndynames)--;
739*fae548d3Szrj 	      ctf_set_errno (arg->fp, ENOMEM);
740*fae548d3Szrj 	      return;
741*fae548d3Szrj 	    }
742*fae548d3Szrj 	    arg->dynames = dynames;
743*fae548d3Szrj 	    name = (const char *) dyname;
744*fae548d3Szrj 	}
745*fae548d3Szrj     }
746*fae548d3Szrj 
747*fae548d3Szrj   arg->names = names;
748*fae548d3Szrj   arg->names[(arg->i) - 1] = (char *) name;
749*fae548d3Szrj   arg->files = files;
750*fae548d3Szrj   arg->files[(arg->i) - 1] = fp;
751*fae548d3Szrj }
752*fae548d3Szrj 
753*fae548d3Szrj /* Change the name of the parent CTF section, if the name transformer has got to
754*fae548d3Szrj    it.  */
755*fae548d3Szrj static void
ctf_change_parent_name(void * key _libctf_unused_,void * value,void * arg)756*fae548d3Szrj ctf_change_parent_name (void *key _libctf_unused_, void *value, void *arg)
757*fae548d3Szrj {
758*fae548d3Szrj   ctf_file_t *fp = (ctf_file_t *) value;
759*fae548d3Szrj   const char *name = (const char *) arg;
760*fae548d3Szrj 
761*fae548d3Szrj   ctf_parent_name_set (fp, name);
762*fae548d3Szrj }
763*fae548d3Szrj 
764*fae548d3Szrj /* Write out a CTF archive (if there are per-CU CTF files) or a CTF file
765*fae548d3Szrj    (otherwise) into a new dynamically-allocated string, and return it.
766*fae548d3Szrj    Members with sizes above THRESHOLD are compressed.  */
767*fae548d3Szrj unsigned char *
ctf_link_write(ctf_file_t * fp,size_t * size,size_t threshold)768*fae548d3Szrj ctf_link_write (ctf_file_t *fp, size_t *size, size_t threshold)
769*fae548d3Szrj {
770*fae548d3Szrj   ctf_name_list_accum_cb_arg_t arg;
771*fae548d3Szrj   char **names;
772*fae548d3Szrj   char *transformed_name = NULL;
773*fae548d3Szrj   ctf_file_t **files;
774*fae548d3Szrj   FILE *f = NULL;
775*fae548d3Szrj   int err;
776*fae548d3Szrj   long fsize;
777*fae548d3Szrj   const char *errloc;
778*fae548d3Szrj   unsigned char *buf = NULL;
779*fae548d3Szrj 
780*fae548d3Szrj   memset (&arg, 0, sizeof (ctf_name_list_accum_cb_arg_t));
781*fae548d3Szrj   arg.fp = fp;
782*fae548d3Szrj 
783*fae548d3Szrj   if (fp->ctf_link_outputs)
784*fae548d3Szrj     {
785*fae548d3Szrj       ctf_dynhash_iter (fp->ctf_link_outputs, ctf_accumulate_archive_names, &arg);
786*fae548d3Szrj       if (ctf_errno (fp) < 0)
787*fae548d3Szrj 	{
788*fae548d3Szrj 	  errloc = "hash creation";
789*fae548d3Szrj 	  goto err;
790*fae548d3Szrj 	}
791*fae548d3Szrj     }
792*fae548d3Szrj 
793*fae548d3Szrj   /* No extra outputs? Just write a simple ctf_file_t.  */
794*fae548d3Szrj   if (arg.i == 0)
795*fae548d3Szrj     return ctf_write_mem (fp, size, threshold);
796*fae548d3Szrj 
797*fae548d3Szrj   /* Writing an archive.  Stick ourselves (the shared repository, parent of all
798*fae548d3Szrj      other archives) on the front of it with the default name.  */
799*fae548d3Szrj   if ((names = realloc (arg.names, sizeof (char *) * (arg.i + 1))) == NULL)
800*fae548d3Szrj     {
801*fae548d3Szrj       errloc = "name reallocation";
802*fae548d3Szrj       goto err_no;
803*fae548d3Szrj     }
804*fae548d3Szrj   arg.names = names;
805*fae548d3Szrj   memmove (&(arg.names[1]), arg.names, sizeof (char *) * (arg.i));
806*fae548d3Szrj 
807*fae548d3Szrj   arg.names[0] = (char *) _CTF_SECTION;
808*fae548d3Szrj   if (fp->ctf_link_memb_name_changer)
809*fae548d3Szrj     {
810*fae548d3Szrj       void *nc_arg = fp->ctf_link_memb_name_changer_arg;
811*fae548d3Szrj 
812*fae548d3Szrj       transformed_name = fp->ctf_link_memb_name_changer (fp, _CTF_SECTION,
813*fae548d3Szrj 							 nc_arg);
814*fae548d3Szrj 
815*fae548d3Szrj       if (transformed_name != NULL)
816*fae548d3Szrj 	{
817*fae548d3Szrj 	  arg.names[0] = transformed_name;
818*fae548d3Szrj 	  ctf_dynhash_iter (fp->ctf_link_outputs, ctf_change_parent_name,
819*fae548d3Szrj 			    transformed_name);
820*fae548d3Szrj 	}
821*fae548d3Szrj     }
822*fae548d3Szrj 
823*fae548d3Szrj   if ((files = realloc (arg.files,
824*fae548d3Szrj 			sizeof (struct ctf_file *) * (arg.i + 1))) == NULL)
825*fae548d3Szrj     {
826*fae548d3Szrj       errloc = "ctf_file reallocation";
827*fae548d3Szrj       goto err_no;
828*fae548d3Szrj     }
829*fae548d3Szrj   arg.files = files;
830*fae548d3Szrj   memmove (&(arg.files[1]), arg.files, sizeof (ctf_file_t *) * (arg.i));
831*fae548d3Szrj   arg.files[0] = fp;
832*fae548d3Szrj 
833*fae548d3Szrj   if ((f = tmpfile ()) == NULL)
834*fae548d3Szrj     {
835*fae548d3Szrj       errloc = "tempfile creation";
836*fae548d3Szrj       goto err_no;
837*fae548d3Szrj     }
838*fae548d3Szrj 
839*fae548d3Szrj   if ((err = ctf_arc_write_fd (fileno (f), arg.files, arg.i + 1,
840*fae548d3Szrj 			       (const char **) arg.names,
841*fae548d3Szrj 			       threshold)) < 0)
842*fae548d3Szrj     {
843*fae548d3Szrj       errloc = "archive writing";
844*fae548d3Szrj       ctf_set_errno (fp, err);
845*fae548d3Szrj       goto err;
846*fae548d3Szrj     }
847*fae548d3Szrj 
848*fae548d3Szrj   if (fseek (f, 0, SEEK_END) < 0)
849*fae548d3Szrj     {
850*fae548d3Szrj       errloc = "seeking to end";
851*fae548d3Szrj       goto err_no;
852*fae548d3Szrj     }
853*fae548d3Szrj 
854*fae548d3Szrj   if ((fsize = ftell (f)) < 0)
855*fae548d3Szrj     {
856*fae548d3Szrj       errloc = "filesize determination";
857*fae548d3Szrj       goto err_no;
858*fae548d3Szrj     }
859*fae548d3Szrj 
860*fae548d3Szrj   if (fseek (f, 0, SEEK_SET) < 0)
861*fae548d3Szrj     {
862*fae548d3Szrj       errloc = "filepos resetting";
863*fae548d3Szrj       goto err_no;
864*fae548d3Szrj     }
865*fae548d3Szrj 
866*fae548d3Szrj   if ((buf = malloc (fsize)) == NULL)
867*fae548d3Szrj     {
868*fae548d3Szrj       errloc = "CTF archive buffer allocation";
869*fae548d3Szrj       goto err_no;
870*fae548d3Szrj     }
871*fae548d3Szrj 
872*fae548d3Szrj   while (!feof (f) && fread (buf, fsize, 1, f) == 0)
873*fae548d3Szrj     if (ferror (f))
874*fae548d3Szrj       {
875*fae548d3Szrj 	errloc = "reading archive from temporary file";
876*fae548d3Szrj 	goto err_no;
877*fae548d3Szrj       }
878*fae548d3Szrj 
879*fae548d3Szrj   *size = fsize;
880*fae548d3Szrj   free (arg.names);
881*fae548d3Szrj   free (arg.files);
882*fae548d3Szrj   free (transformed_name);
883*fae548d3Szrj   if (arg.ndynames)
884*fae548d3Szrj     {
885*fae548d3Szrj       size_t i;
886*fae548d3Szrj       for (i = 0; i < arg.ndynames; i++)
887*fae548d3Szrj 	free (arg.dynames[i]);
888*fae548d3Szrj       free (arg.dynames);
889*fae548d3Szrj     }
890*fae548d3Szrj   return buf;
891*fae548d3Szrj 
892*fae548d3Szrj  err_no:
893*fae548d3Szrj   ctf_set_errno (fp, errno);
894*fae548d3Szrj  err:
895*fae548d3Szrj   free (buf);
896*fae548d3Szrj   if (f)
897*fae548d3Szrj     fclose (f);
898*fae548d3Szrj   free (arg.names);
899*fae548d3Szrj   free (arg.files);
900*fae548d3Szrj   free (transformed_name);
901*fae548d3Szrj   if (arg.ndynames)
902*fae548d3Szrj     {
903*fae548d3Szrj       size_t i;
904*fae548d3Szrj       for (i = 0; i < arg.ndynames; i++)
905*fae548d3Szrj 	free (arg.dynames[i]);
906*fae548d3Szrj       free (arg.dynames);
907*fae548d3Szrj     }
908*fae548d3Szrj   ctf_dprintf ("Cannot write archive in link: %s failure: %s\n", errloc,
909*fae548d3Szrj 	       ctf_errmsg (ctf_errno (fp)));
910*fae548d3Szrj   return NULL;
911*fae548d3Szrj }
912