/src/binutils-gdb/libctf/ctf-link.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* CTF linking. |
2 | | Copyright (C) 2019-2025 Free Software Foundation, Inc. |
3 | | |
4 | | This file is part of libctf. |
5 | | |
6 | | libctf is free software; you can redistribute it and/or modify it under |
7 | | the terms of the GNU General Public License as published by the Free |
8 | | Software Foundation; either version 3, or (at your option) any later |
9 | | version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, but |
12 | | WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
14 | | See the GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with this program; see the file COPYING. If not see |
18 | | <http://www.gnu.org/licenses/>. */ |
19 | | |
20 | | #include <ctf-impl.h> |
21 | | #include <string.h> |
22 | | |
23 | | #if defined (PIC) |
24 | | #pragma weak ctf_open |
25 | | #endif |
26 | | |
27 | | /* CTF linking consists of adding CTF archives full of content to be merged into |
28 | | this one to the current file (which must be writable) by calling |
29 | | ctf_link_add_ctf. Once this is done, a call to ctf_link will merge the type |
30 | | tables together, generating new CTF files as needed, with this one as a |
31 | | parent, to contain types from the inputs which conflict. ctf_link_add_strtab |
32 | | takes a callback which provides string/offset pairs to be added to the |
33 | | external symbol table and deduplicated from all CTF string tables in the |
34 | | output link; ctf_link_shuffle_syms takes a callback which provides symtab |
35 | | entries in ascending order, and shuffles the function and data sections to |
36 | | match; and ctf_link_write emits a CTF file (if there are no conflicts |
37 | | requiring per-compilation-unit sub-CTF files) or CTF archives (otherwise) and |
38 | | returns it, suitable for addition in the .ctf section of the output. */ |
39 | | |
40 | | /* Return the name of the compilation unit this CTF dict or its parent applies |
41 | | to, or a non-null string otherwise: prefer the parent. Used in debugging |
42 | | output. Sometimes used for outputs too. */ |
43 | | const char * |
44 | | ctf_link_input_name (ctf_dict_t *fp) |
45 | 0 | { |
46 | 0 | if (fp->ctf_parent && fp->ctf_parent->ctf_cuname) |
47 | 0 | return fp->ctf_parent->ctf_cuname; |
48 | 0 | else if (fp->ctf_cuname) |
49 | 0 | return fp->ctf_cuname; |
50 | 0 | else |
51 | 0 | return "(unnamed)"; |
52 | 0 | } |
53 | | |
54 | | /* Return the cuname of a dict, or the string "unnamed-CU" if none. */ |
55 | | |
56 | | static const char * |
57 | | ctf_unnamed_cuname (ctf_dict_t *fp) |
58 | 0 | { |
59 | 0 | const char *cuname = ctf_cuname (fp); |
60 | |
|
61 | 0 | if (!cuname) |
62 | 0 | cuname = "unnamed-CU"; |
63 | |
|
64 | 0 | return cuname; |
65 | 0 | } |
66 | | |
67 | | /* The linker inputs look like this. clin_fp is used for short-circuited |
68 | | CU-mapped links that can entirely avoid the first link phase in some |
69 | | situations in favour of just passing on the contained ctf_dict_t: it is |
70 | | always the sole ctf_dict_t inside the corresponding clin_arc. If set, it |
71 | | gets assigned directly to the final link inputs and freed from there, so it |
72 | | never gets explicitly freed in the ctf_link_input. */ |
73 | | typedef struct ctf_link_input |
74 | | { |
75 | | char *clin_filename; |
76 | | ctf_archive_t *clin_arc; |
77 | | ctf_dict_t *clin_fp; |
78 | | int n; |
79 | | } ctf_link_input_t; |
80 | | |
81 | | static void |
82 | | ctf_link_input_close (void *input) |
83 | 0 | { |
84 | 0 | ctf_link_input_t *i = (ctf_link_input_t *) input; |
85 | 0 | if (i->clin_arc) |
86 | 0 | ctf_arc_close (i->clin_arc); |
87 | 0 | free (i->clin_filename); |
88 | 0 | free (i); |
89 | 0 | } |
90 | | |
91 | | /* Like ctf_link_add_ctf, below, but with no error-checking, so it can be called |
92 | | in the middle of an ongoing link. */ |
93 | | static int |
94 | | ctf_link_add_ctf_internal (ctf_dict_t *fp, ctf_archive_t *ctf, |
95 | | ctf_dict_t *fp_input, const char *name) |
96 | 0 | { |
97 | 0 | int existing = 0; |
98 | 0 | ctf_link_input_t *input; |
99 | 0 | char *filename, *keyname; |
100 | | |
101 | | /* Existing: return it, or (if a different dict with the same name |
102 | | is already there) make up a new unique name. Always use the actual name |
103 | | for the filename, because that needs to be ctf_open()ed. */ |
104 | |
|
105 | 0 | if ((input = ctf_dynhash_lookup (fp->ctf_link_inputs, name)) != NULL) |
106 | 0 | { |
107 | 0 | if ((fp_input != NULL && (input->clin_fp == fp_input)) |
108 | 0 | || (ctf != NULL && (input->clin_arc == ctf))) |
109 | 0 | return 0; |
110 | 0 | existing = 1; |
111 | 0 | } |
112 | | |
113 | 0 | if ((filename = strdup (name)) == NULL) |
114 | 0 | goto oom; |
115 | | |
116 | 0 | if ((input = calloc (1, sizeof (ctf_link_input_t))) == NULL) |
117 | 0 | goto oom1; |
118 | | |
119 | 0 | input->clin_arc = ctf; |
120 | 0 | input->clin_fp = fp_input; |
121 | 0 | input->clin_filename = filename; |
122 | 0 | input->n = ctf_dynhash_elements (fp->ctf_link_inputs); |
123 | |
|
124 | 0 | if (existing) |
125 | 0 | { |
126 | 0 | if (asprintf (&keyname, "%s#%li", name, (long int) |
127 | 0 | ctf_dynhash_elements (fp->ctf_link_inputs)) < 0) |
128 | 0 | goto oom2; |
129 | 0 | } |
130 | 0 | else if ((keyname = strdup (name)) == NULL) |
131 | 0 | goto oom2; |
132 | | |
133 | 0 | if (ctf_dynhash_insert (fp->ctf_link_inputs, keyname, input) < 0) |
134 | 0 | goto oom3; |
135 | | |
136 | 0 | return 0; |
137 | | |
138 | 0 | oom3: |
139 | 0 | free (keyname); |
140 | 0 | oom2: |
141 | 0 | free (input); |
142 | 0 | oom1: |
143 | 0 | free (filename); |
144 | 0 | oom: |
145 | 0 | return ctf_set_errno (fp, ENOMEM); |
146 | 0 | } |
147 | | |
148 | | /* Add a file, memory buffer, or unopened file (by name) to a link. |
149 | | |
150 | | You can call this with: |
151 | | |
152 | | CTF and NAME: link the passed ctf_archive_t, with the given NAME. |
153 | | NAME alone: open NAME as a CTF file when needed. |
154 | | BUF and NAME: open the BUF (of length N) as CTF, with the given NAME. (Not |
155 | | yet implemented.) |
156 | | |
157 | | Passed in CTF args are owned by the dictionary and will be freed by it. |
158 | | The BUF arg is *not* owned by the dictionary, and the user should not free |
159 | | its referent until the link is done. |
160 | | |
161 | | The order of calls to this function influences the order of types in the |
162 | | final link output, but otherwise is not important. |
163 | | |
164 | | Repeated additions of the same NAME have no effect; repeated additions of |
165 | | different dicts with the same NAME add all the dicts with unique NAMEs |
166 | | derived from NAME. |
167 | | |
168 | | Private for now, but may in time become public once support for BUF is |
169 | | implemented. */ |
170 | | |
171 | | static int |
172 | | ctf_link_add (ctf_dict_t *fp, ctf_archive_t *ctf, const char *name, |
173 | | void *buf _libctf_unused_, size_t n _libctf_unused_) |
174 | 0 | { |
175 | 0 | if (buf) |
176 | 0 | return (ctf_set_errno (fp, ECTF_NOTYET)); |
177 | | |
178 | 0 | if (!((ctf && name && !buf) |
179 | 0 | || (name && !buf && !ctf) |
180 | 0 | || (buf && name && !ctf))) |
181 | 0 | return (ctf_set_errno (fp, EINVAL)); |
182 | | |
183 | | /* We can only lazily open files if libctf.so is in use rather than |
184 | | libctf-nobfd.so. This is a little tricky: in shared libraries, we can use |
185 | | a weak symbol so that -lctf -lctf-nobfd works, but in static libraries we |
186 | | must distinguish between the two libraries explicitly. */ |
187 | | |
188 | | #if defined (PIC) |
189 | | if (!buf && !ctf && name && !ctf_open) |
190 | | return (ctf_set_errno (fp, ECTF_NEEDSBFD)); |
191 | | #elif NOBFD |
192 | | if (!buf && !ctf && name) |
193 | | return (ctf_set_errno (fp, ECTF_NEEDSBFD)); |
194 | | #endif |
195 | | |
196 | 0 | if (fp->ctf_link_outputs) |
197 | 0 | return (ctf_set_errno (fp, ECTF_LINKADDEDLATE)); |
198 | 0 | if (fp->ctf_link_inputs == NULL) |
199 | 0 | fp->ctf_link_inputs = ctf_dynhash_create (ctf_hash_string, |
200 | 0 | ctf_hash_eq_string, free, |
201 | 0 | ctf_link_input_close); |
202 | |
|
203 | 0 | if (fp->ctf_link_inputs == NULL) |
204 | 0 | return (ctf_set_errno (fp, ENOMEM)); |
205 | | |
206 | 0 | return ctf_link_add_ctf_internal (fp, ctf, NULL, name); |
207 | 0 | } |
208 | | |
209 | | /* Add an opened CTF archive or unopened file (by name) to a link. |
210 | | If CTF is NULL and NAME is non-null, an unopened file is meant: |
211 | | otherwise, the specified archive is assumed to have the given NAME. |
212 | | |
213 | | Passed in CTF args are owned by the dictionary and will be freed by it. |
214 | | |
215 | | The order of calls to this function influences the order of types in the |
216 | | final link output, but otherwise is not important. */ |
217 | | |
218 | | int |
219 | | ctf_link_add_ctf (ctf_dict_t *fp, ctf_archive_t *ctf, const char *name) |
220 | 0 | { |
221 | 0 | return ctf_link_add (fp, ctf, name, NULL, 0); |
222 | 0 | } |
223 | | |
224 | | /* Lazily open a CTF archive for linking, if not already open. |
225 | | |
226 | | Returns the number of files contained within the opened archive (0 for none), |
227 | | or -1 on error, as usual. */ |
228 | | static ssize_t |
229 | | ctf_link_lazy_open (ctf_dict_t *fp, ctf_link_input_t *input) |
230 | 0 | { |
231 | 0 | size_t count; |
232 | 0 | int err; |
233 | |
|
234 | 0 | if (input->clin_arc) |
235 | 0 | return ctf_archive_count (input->clin_arc); |
236 | | |
237 | 0 | if (input->clin_fp) |
238 | 0 | return 1; |
239 | | |
240 | | /* See ctf_link_add_ctf. */ |
241 | 0 | #if defined (PIC) || !NOBFD |
242 | 0 | input->clin_arc = ctf_open (input->clin_filename, NULL, &err); |
243 | | #else |
244 | | ctf_err_warn (fp, 0, ECTF_NEEDSBFD, _("cannot open %s lazily"), |
245 | | input->clin_filename); |
246 | | return ctf_set_errno (fp, ECTF_NEEDSBFD); |
247 | | #endif |
248 | | |
249 | | /* Having no CTF sections is not an error. We just don't need to do |
250 | | anything. */ |
251 | |
|
252 | 0 | if (!input->clin_arc) |
253 | 0 | { |
254 | 0 | if (err == ECTF_NOCTFDATA) |
255 | 0 | return 0; |
256 | | |
257 | 0 | ctf_err_warn (fp, 0, err, _("opening CTF %s failed"), |
258 | 0 | input->clin_filename); |
259 | 0 | return ctf_set_errno (fp, err); |
260 | 0 | } |
261 | | |
262 | 0 | if ((count = ctf_archive_count (input->clin_arc)) == 0) |
263 | 0 | ctf_arc_close (input->clin_arc); |
264 | |
|
265 | 0 | return (ssize_t) count; |
266 | 0 | } |
267 | | |
268 | | /* Find a non-clashing unique name for a per-CU output dict, to prevent distinct |
269 | | members corresponding to inputs with identical cunames from overwriting each |
270 | | other. The name should be something like NAME. */ |
271 | | |
272 | | static char * |
273 | | ctf_new_per_cu_name (ctf_dict_t *fp, const char *name) |
274 | 0 | { |
275 | 0 | char *dynname; |
276 | 0 | long int i = 0; |
277 | |
|
278 | 0 | if ((dynname = strdup (name)) == NULL) |
279 | 0 | return NULL; |
280 | | |
281 | 0 | while ((ctf_dynhash_lookup (fp->ctf_link_outputs, dynname)) != NULL) |
282 | 0 | { |
283 | 0 | free (dynname); |
284 | 0 | if (asprintf (&dynname, "%s#%li", name, i++) < 0) |
285 | 0 | return NULL; |
286 | 0 | } |
287 | | |
288 | 0 | return dynname; |
289 | 0 | } |
290 | | |
291 | | /* Return a per-CU output CTF dictionary suitable for the given INPUT or CU, |
292 | | creating and interning it if need be. */ |
293 | | |
294 | | static ctf_dict_t * |
295 | | ctf_create_per_cu (ctf_dict_t *fp, ctf_dict_t *input, const char *cu_name) |
296 | 0 | { |
297 | 0 | ctf_dict_t *cu_fp; |
298 | 0 | const char *ctf_name = NULL; |
299 | 0 | char *dynname = NULL; |
300 | | |
301 | | /* Already has a per-CU mapping? Just return it. */ |
302 | |
|
303 | 0 | if (input && input->ctf_link_in_out) |
304 | 0 | return input->ctf_link_in_out; |
305 | | |
306 | | /* Check the mapping table and translate the per-CU name we use |
307 | | accordingly. */ |
308 | | |
309 | 0 | if (cu_name == NULL) |
310 | 0 | cu_name = ctf_unnamed_cuname (input); |
311 | |
|
312 | 0 | if (fp->ctf_link_in_cu_mapping) |
313 | 0 | { |
314 | 0 | if ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_in_cu_mapping, |
315 | 0 | cu_name)) == NULL) |
316 | 0 | ctf_name = cu_name; |
317 | 0 | } |
318 | |
|
319 | 0 | if (ctf_name == NULL) |
320 | 0 | ctf_name = cu_name; |
321 | | |
322 | | /* Look up the per-CU dict. If we don't know of one, or it is for a different input |
323 | | CU which just happens to have the same name, create a new one. If we are creating |
324 | | a dict with no input specified, anything will do. */ |
325 | |
|
326 | 0 | if ((cu_fp = ctf_dynhash_lookup (fp->ctf_link_outputs, ctf_name)) == NULL |
327 | 0 | || (input && cu_fp->ctf_link_in_out != fp)) |
328 | 0 | { |
329 | 0 | int err; |
330 | |
|
331 | 0 | if ((cu_fp = ctf_create (&err)) == NULL) |
332 | 0 | { |
333 | 0 | ctf_set_errno (fp, err); |
334 | 0 | ctf_err_warn (fp, 0, 0, _("cannot create per-CU CTF archive for " |
335 | 0 | "input CU %s"), cu_name); |
336 | 0 | return NULL; |
337 | 0 | } |
338 | | |
339 | | /* The deduplicator is ready for strict enumerator value checking. */ |
340 | 0 | cu_fp->ctf_flags |= LCTF_STRICT_NO_DUP_ENUMERATORS; |
341 | 0 | ctf_import_unref (cu_fp, fp); |
342 | |
|
343 | 0 | if ((dynname = ctf_new_per_cu_name (fp, ctf_name)) == NULL) |
344 | 0 | goto oom; |
345 | | |
346 | 0 | ctf_cuname_set (cu_fp, cu_name); |
347 | |
|
348 | 0 | ctf_parent_name_set (cu_fp, _CTF_SECTION); |
349 | 0 | cu_fp->ctf_link_in_out = fp; |
350 | 0 | fp->ctf_link_in_out = cu_fp; |
351 | |
|
352 | 0 | if (ctf_dynhash_insert (fp->ctf_link_outputs, dynname, cu_fp) < 0) |
353 | 0 | goto oom; |
354 | 0 | } |
355 | 0 | return cu_fp; |
356 | | |
357 | 0 | oom: |
358 | 0 | free (dynname); |
359 | 0 | ctf_dict_close (cu_fp); |
360 | 0 | ctf_set_errno (fp, ENOMEM); |
361 | 0 | return NULL; |
362 | 0 | } |
363 | | |
364 | | /* Add a mapping directing that the CU named FROM should have its |
365 | | conflicting/non-duplicate types (depending on link mode) go into a dict |
366 | | named TO. Many FROMs can share a TO, but adding the same FROM with |
367 | | a different TO will replace the old mapping. |
368 | | |
369 | | We forcibly add a dict named TO in every case, even though it may well |
370 | | wind up empty, because clients that use this facility usually expect to find |
371 | | every TO dict present, even if empty, and malfunction otherwise. */ |
372 | | |
373 | | int |
374 | | ctf_link_add_cu_mapping (ctf_dict_t *fp, const char *from, const char *to) |
375 | 0 | { |
376 | 0 | int err; |
377 | 0 | char *f = NULL, *t = NULL, *existing; |
378 | 0 | ctf_dynhash_t *one_out; |
379 | | |
380 | | /* Mappings cannot be set up if per-CU output dicts already exist. */ |
381 | 0 | if (fp->ctf_link_outputs && ctf_dynhash_elements (fp->ctf_link_outputs) != 0) |
382 | 0 | return (ctf_set_errno (fp, ECTF_LINKADDEDLATE)); |
383 | | |
384 | 0 | if (fp->ctf_link_in_cu_mapping == NULL) |
385 | 0 | fp->ctf_link_in_cu_mapping = ctf_dynhash_create (ctf_hash_string, |
386 | 0 | ctf_hash_eq_string, free, |
387 | 0 | free); |
388 | 0 | if (fp->ctf_link_in_cu_mapping == NULL) |
389 | 0 | goto oom; |
390 | | |
391 | 0 | if (fp->ctf_link_out_cu_mapping == NULL) |
392 | 0 | fp->ctf_link_out_cu_mapping = ctf_dynhash_create (ctf_hash_string, |
393 | 0 | ctf_hash_eq_string, free, |
394 | 0 | (ctf_hash_free_fun) |
395 | 0 | ctf_dynhash_destroy); |
396 | 0 | if (fp->ctf_link_out_cu_mapping == NULL) |
397 | 0 | goto oom; |
398 | | |
399 | | /* If this FROM already exists, remove the mapping from both the FROM->TO |
400 | | and the TO->FROM lists: the user wants to change it. */ |
401 | | |
402 | 0 | if ((existing = ctf_dynhash_lookup (fp->ctf_link_in_cu_mapping, from)) != NULL) |
403 | 0 | { |
404 | 0 | one_out = ctf_dynhash_lookup (fp->ctf_link_out_cu_mapping, existing); |
405 | 0 | if (!ctf_assert (fp, one_out)) |
406 | 0 | return -1; /* errno is set for us. */ |
407 | | |
408 | 0 | ctf_dynhash_remove (one_out, from); |
409 | 0 | ctf_dynhash_remove (fp->ctf_link_in_cu_mapping, from); |
410 | 0 | } |
411 | | |
412 | 0 | f = strdup (from); |
413 | 0 | t = strdup (to); |
414 | 0 | if (!f || !t) |
415 | 0 | goto oom; |
416 | | |
417 | | /* Track both in a list from FROM to TO and in a list from TO to a list of |
418 | | FROM. The former is used to create TUs with the mapped-to name at need: |
419 | | the latter is used in deduplicating links to pull in all input CUs |
420 | | corresponding to a single output CU. */ |
421 | | |
422 | 0 | if ((err = ctf_dynhash_insert (fp->ctf_link_in_cu_mapping, f, t)) < 0) |
423 | 0 | { |
424 | 0 | ctf_set_errno (fp, err); |
425 | 0 | goto oom_noerrno; |
426 | 0 | } |
427 | | |
428 | | /* f and t are now owned by the in_cu_mapping: reallocate them. */ |
429 | 0 | f = strdup (from); |
430 | 0 | t = strdup (to); |
431 | 0 | if (!f || !t) |
432 | 0 | goto oom; |
433 | | |
434 | 0 | if ((one_out = ctf_dynhash_lookup (fp->ctf_link_out_cu_mapping, t)) == NULL) |
435 | 0 | { |
436 | 0 | if ((one_out = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string, |
437 | 0 | free, NULL)) == NULL) |
438 | 0 | goto oom; |
439 | 0 | if ((err = ctf_dynhash_insert (fp->ctf_link_out_cu_mapping, |
440 | 0 | t, one_out)) < 0) |
441 | 0 | { |
442 | 0 | ctf_dynhash_destroy (one_out); |
443 | 0 | ctf_set_errno (fp, err); |
444 | 0 | goto oom_noerrno; |
445 | 0 | } |
446 | 0 | } |
447 | 0 | else |
448 | 0 | { |
449 | 0 | free (t); |
450 | 0 | t = NULL; |
451 | 0 | } |
452 | | |
453 | 0 | if (ctf_dynhash_insert (one_out, f, NULL) < 0) |
454 | 0 | { |
455 | 0 | ctf_set_errno (fp, err); |
456 | 0 | goto oom_noerrno; |
457 | 0 | } |
458 | | |
459 | 0 | return 0; |
460 | | |
461 | 0 | oom: |
462 | 0 | ctf_set_errno (fp, errno); |
463 | 0 | oom_noerrno: |
464 | 0 | free (f); |
465 | 0 | free (t); |
466 | 0 | return -1; |
467 | 0 | } |
468 | | |
469 | | /* Set a function which is called to transform the names of archive members. |
470 | | This is useful for applying regular transformations to many names, where |
471 | | ctf_link_add_cu_mapping applies arbitrarily irregular changes to single |
472 | | names. The member name changer is applied at ctf_link_write time, so it |
473 | | cannot conflate multiple CUs into one the way ctf_link_add_cu_mapping can. |
474 | | The changer function accepts a name and should return a new |
475 | | dynamically-allocated name, or NULL if the name should be left unchanged. */ |
476 | | void |
477 | | ctf_link_set_memb_name_changer (ctf_dict_t *fp, |
478 | | ctf_link_memb_name_changer_f *changer, |
479 | | void *arg) |
480 | 0 | { |
481 | 0 | fp->ctf_link_memb_name_changer = changer; |
482 | 0 | fp->ctf_link_memb_name_changer_arg = arg; |
483 | 0 | } |
484 | | |
485 | | /* Set a function which is used to filter out unwanted variables from the link. */ |
486 | | int |
487 | | ctf_link_set_variable_filter (ctf_dict_t *fp, ctf_link_variable_filter_f *filter, |
488 | | void *arg) |
489 | 0 | { |
490 | 0 | fp->ctf_link_variable_filter = filter; |
491 | 0 | fp->ctf_link_variable_filter_arg = arg; |
492 | 0 | return 0; |
493 | 0 | } |
494 | | |
495 | | /* Check if we can safely add a variable with the given type to this dict. */ |
496 | | |
497 | | static int |
498 | | check_variable (const char *name, ctf_dict_t *fp, ctf_id_t type, |
499 | | ctf_dvdef_t **out_dvd) |
500 | 0 | { |
501 | 0 | ctf_dvdef_t *dvd; |
502 | |
|
503 | 0 | dvd = ctf_dynhash_lookup (fp->ctf_dvhash, name); |
504 | 0 | *out_dvd = dvd; |
505 | 0 | if (!dvd) |
506 | 0 | return 1; |
507 | | |
508 | 0 | if (dvd->dvd_type != type) |
509 | 0 | { |
510 | | /* Variable here. Wrong type: cannot add. Just skip it, because there is |
511 | | no way to express this in CTF. Don't even warn: this case is too |
512 | | common. (This might be the parent, in which case we'll try adding in |
513 | | the child first, and only then give up.) */ |
514 | 0 | ctf_dprintf ("Inexpressible duplicate variable %s skipped.\n", name); |
515 | 0 | } |
516 | |
|
517 | 0 | return 0; /* Already exists. */ |
518 | 0 | } |
519 | | |
520 | | /* Link one variable named NAME of type TYPE found in IN_FP into FP. */ |
521 | | |
522 | | static int |
523 | | ctf_link_one_variable (ctf_dict_t *fp, ctf_dict_t *in_fp, const char *name, |
524 | | ctf_id_t type, int cu_mapped) |
525 | 0 | { |
526 | 0 | ctf_dict_t *per_cu_out_fp; |
527 | 0 | ctf_id_t dst_type = 0; |
528 | 0 | ctf_dvdef_t *dvd; |
529 | | |
530 | | /* See if this variable is filtered out. */ |
531 | |
|
532 | 0 | if (fp->ctf_link_variable_filter) |
533 | 0 | { |
534 | 0 | void *farg = fp->ctf_link_variable_filter_arg; |
535 | 0 | if (fp->ctf_link_variable_filter (in_fp, name, type, farg)) |
536 | 0 | return 0; |
537 | 0 | } |
538 | | |
539 | | /* If this type is mapped to a type in the parent dict, we want to try to add |
540 | | to that first: if it reports a duplicate, or if the type is in a child |
541 | | already, add straight to the child. */ |
542 | | |
543 | 0 | if ((dst_type = ctf_dedup_type_mapping (fp, in_fp, type)) == CTF_ERR) |
544 | 0 | return -1; /* errno is set for us. */ |
545 | | |
546 | 0 | if (dst_type != 0) |
547 | 0 | { |
548 | 0 | if (!ctf_assert (fp, ctf_type_isparent (fp, dst_type))) |
549 | 0 | return -1; /* errno is set for us. */ |
550 | | |
551 | 0 | if (check_variable (name, fp, dst_type, &dvd)) |
552 | 0 | { |
553 | | /* No variable here: we can add it. */ |
554 | 0 | if (ctf_add_variable (fp, name, dst_type) < 0) |
555 | 0 | return -1; /* errno is set for us. */ |
556 | 0 | return 0; |
557 | 0 | } |
558 | | |
559 | | /* Already present? Nothing to do. */ |
560 | 0 | if (dvd && dvd->dvd_type == dst_type) |
561 | 0 | return 0; |
562 | 0 | } |
563 | | |
564 | | /* Can't add to the parent due to a name clash, or because it references a |
565 | | type only present in the child. Try adding to the child, creating if need |
566 | | be. If we can't do that, skip it. Don't add to a child if we're doing a |
567 | | CU-mapped link, since that has only one output. */ |
568 | | |
569 | 0 | if (cu_mapped) |
570 | 0 | { |
571 | 0 | ctf_dprintf ("Variable %s in input file %s depends on a type %lx hidden " |
572 | 0 | "due to conflicts: skipped.\n", name, |
573 | 0 | ctf_unnamed_cuname (in_fp), type); |
574 | 0 | return 0; |
575 | 0 | } |
576 | | |
577 | 0 | if ((per_cu_out_fp = ctf_create_per_cu (fp, in_fp, NULL)) == NULL) |
578 | 0 | return -1; /* errno is set for us. */ |
579 | | |
580 | | /* If the type was not found, check for it in the child too. */ |
581 | 0 | if (dst_type == 0) |
582 | 0 | { |
583 | 0 | if ((dst_type = ctf_dedup_type_mapping (per_cu_out_fp, |
584 | 0 | in_fp, type)) == CTF_ERR) |
585 | 0 | return -1; /* errno is set for us. */ |
586 | | |
587 | 0 | if (dst_type == 0) |
588 | 0 | { |
589 | 0 | ctf_err_warn (fp, 1, 0, _("type %lx for variable %s in input file %s " |
590 | 0 | "not found: skipped"), type, name, |
591 | 0 | ctf_unnamed_cuname (in_fp)); |
592 | | /* Do not terminate the link: just skip the variable. */ |
593 | 0 | return 0; |
594 | 0 | } |
595 | 0 | } |
596 | | |
597 | 0 | if (check_variable (name, per_cu_out_fp, dst_type, &dvd)) |
598 | 0 | if (ctf_add_variable (per_cu_out_fp, name, dst_type) < 0) |
599 | 0 | return (ctf_set_errno (fp, ctf_errno (per_cu_out_fp))); |
600 | 0 | return 0; |
601 | 0 | } |
602 | | |
603 | | typedef struct link_sort_inputs_cb_arg |
604 | | { |
605 | | int is_cu_mapped; |
606 | | ctf_dict_t *fp; |
607 | | } link_sort_inputs_cb_arg_t; |
608 | | |
609 | | /* Sort the inputs by N (the link order). For CU-mapped links, this is a |
610 | | mapping of input to output name, not a mapping of input name to input |
611 | | ctf_link_input_t: compensate accordingly. */ |
612 | | static int |
613 | | ctf_link_sort_inputs (const ctf_next_hkv_t *one, const ctf_next_hkv_t *two, |
614 | | void *arg) |
615 | 0 | { |
616 | 0 | ctf_link_input_t *input_1; |
617 | 0 | ctf_link_input_t *input_2; |
618 | 0 | link_sort_inputs_cb_arg_t *cu_mapped = (link_sort_inputs_cb_arg_t *) arg; |
619 | |
|
620 | 0 | if (!cu_mapped || !cu_mapped->is_cu_mapped) |
621 | 0 | { |
622 | 0 | input_1 = (ctf_link_input_t *) one->hkv_value; |
623 | 0 | input_2 = (ctf_link_input_t *) two->hkv_value; |
624 | 0 | } |
625 | 0 | else |
626 | 0 | { |
627 | 0 | const char *name_1 = (const char *) one->hkv_key; |
628 | 0 | const char *name_2 = (const char *) two->hkv_key; |
629 | |
|
630 | 0 | input_1 = ctf_dynhash_lookup (cu_mapped->fp->ctf_link_inputs, name_1); |
631 | 0 | input_2 = ctf_dynhash_lookup (cu_mapped->fp->ctf_link_inputs, name_2); |
632 | | |
633 | | /* There is no guarantee that CU-mappings actually have corresponding |
634 | | inputs: the relative ordering in that case is unimportant. */ |
635 | 0 | if (!input_1) |
636 | 0 | return -1; |
637 | 0 | if (!input_2) |
638 | 0 | return 1; |
639 | 0 | } |
640 | | |
641 | 0 | if (input_1->n < input_2->n) |
642 | 0 | return -1; |
643 | 0 | else if (input_1->n > input_2->n) |
644 | 0 | return 1; |
645 | 0 | else |
646 | 0 | return 0; |
647 | 0 | } |
648 | | |
649 | | /* Count the number of input dicts in the ctf_link_inputs, or that subset of the |
650 | | ctf_link_inputs given by CU_NAMES if set. Return the number of input dicts, |
651 | | and optionally the name and ctf_link_input_t of the single input archive if |
652 | | only one exists (no matter how many dicts it contains). */ |
653 | | static ssize_t |
654 | | ctf_link_deduplicating_count_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names, |
655 | | ctf_link_input_t **only_one_input) |
656 | 0 | { |
657 | 0 | ctf_dynhash_t *inputs = fp->ctf_link_inputs; |
658 | 0 | ctf_next_t *i = NULL; |
659 | 0 | void *name, *input; |
660 | 0 | ctf_link_input_t *one_input = NULL; |
661 | 0 | const char *one_name = NULL; |
662 | 0 | ssize_t count = 0, narcs = 0; |
663 | 0 | int err; |
664 | |
|
665 | 0 | if (cu_names) |
666 | 0 | inputs = cu_names; |
667 | |
|
668 | 0 | while ((err = ctf_dynhash_next (inputs, &i, &name, &input)) == 0) |
669 | 0 | { |
670 | 0 | ssize_t one_count; |
671 | |
|
672 | 0 | one_name = (const char *) name; |
673 | | /* If we are processing CU names, get the real input. */ |
674 | 0 | if (cu_names) |
675 | 0 | one_input = ctf_dynhash_lookup (fp->ctf_link_inputs, one_name); |
676 | 0 | else |
677 | 0 | one_input = (ctf_link_input_t *) input; |
678 | |
|
679 | 0 | if (!one_input) |
680 | 0 | continue; |
681 | | |
682 | 0 | one_count = ctf_link_lazy_open (fp, one_input); |
683 | |
|
684 | 0 | if (one_count < 0) |
685 | 0 | { |
686 | 0 | ctf_next_destroy (i); |
687 | 0 | return -1; /* errno is set for us. */ |
688 | 0 | } |
689 | | |
690 | 0 | count += one_count; |
691 | 0 | narcs++; |
692 | 0 | } |
693 | 0 | if (err != ECTF_NEXT_END) |
694 | 0 | { |
695 | 0 | ctf_err_warn (fp, 0, err, _("iteration error counting deduplicating " |
696 | 0 | "CTF link inputs")); |
697 | 0 | return ctf_set_errno (fp, err); |
698 | 0 | } |
699 | | |
700 | 0 | if (!count) |
701 | 0 | return 0; |
702 | | |
703 | 0 | if (narcs == 1) |
704 | 0 | { |
705 | 0 | if (only_one_input) |
706 | 0 | *only_one_input = one_input; |
707 | 0 | } |
708 | 0 | else if (only_one_input) |
709 | 0 | *only_one_input = NULL; |
710 | |
|
711 | 0 | return count; |
712 | 0 | } |
713 | | |
714 | | /* Allocate and populate an inputs array big enough for a given set of inputs: |
715 | | either a specific set of CU names (those from that set found in the |
716 | | ctf_link_inputs), or the entire ctf_link_inputs (if cu_names is not set). |
717 | | The number of inputs (from ctf_link_deduplicating_count_inputs, above) is |
718 | | passed in NINPUTS: an array of uint32_t containing parent pointers |
719 | | (corresponding to those members of the inputs that have parents) is allocated |
720 | | and returned in PARENTS. |
721 | | |
722 | | The inputs are *archives*, not files: the archive can have multiple members |
723 | | if it is the result of a previous incremental link. We want to add every one |
724 | | in turn, including the shared parent. (The dedup machinery knows that a type |
725 | | used by a single dictionary and its parent should not be shared in |
726 | | CTF_LINK_SHARE_DUPLICATED mode.) |
727 | | |
728 | | If no inputs exist that correspond to these CUs, return NULL with the errno |
729 | | set to ECTF_NOCTFDATA. */ |
730 | | static ctf_dict_t ** |
731 | | ctf_link_deduplicating_open_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names, |
732 | | ssize_t ninputs, uint32_t **parents) |
733 | 0 | { |
734 | 0 | ctf_dynhash_t *inputs = fp->ctf_link_inputs; |
735 | 0 | ctf_next_t *i = NULL; |
736 | 0 | void *name, *input; |
737 | 0 | link_sort_inputs_cb_arg_t sort_arg; |
738 | 0 | ctf_dict_t **dedup_inputs = NULL; |
739 | 0 | ctf_dict_t **walk; |
740 | 0 | uint32_t *parents_ = NULL; |
741 | 0 | int err; |
742 | |
|
743 | 0 | if (cu_names) |
744 | 0 | inputs = cu_names; |
745 | |
|
746 | 0 | if ((dedup_inputs = calloc (ninputs, sizeof (ctf_dict_t *))) == NULL) |
747 | 0 | goto oom; |
748 | | |
749 | 0 | if ((parents_ = calloc (ninputs, sizeof (uint32_t))) == NULL) |
750 | 0 | goto oom; |
751 | | |
752 | 0 | walk = dedup_inputs; |
753 | | |
754 | | /* Counting done: push every input into the array, in the order they were |
755 | | passed to ctf_link_add_ctf (and ultimately ld). */ |
756 | |
|
757 | 0 | sort_arg.is_cu_mapped = (cu_names != NULL); |
758 | 0 | sort_arg.fp = fp; |
759 | |
|
760 | 0 | while ((err = ctf_dynhash_next_sorted (inputs, &i, &name, &input, |
761 | 0 | ctf_link_sort_inputs, &sort_arg)) == 0) |
762 | 0 | { |
763 | 0 | const char *one_name = (const char *) name; |
764 | 0 | ctf_link_input_t *one_input; |
765 | 0 | ctf_dict_t *one_fp; |
766 | 0 | ctf_dict_t *parent_fp = NULL; |
767 | 0 | uint32_t parent_i = 0; |
768 | 0 | ctf_next_t *j = NULL; |
769 | | |
770 | | /* If we are processing CU names, get the real input. All the inputs |
771 | | will have been opened, if they contained any CTF at all. */ |
772 | 0 | if (cu_names) |
773 | 0 | one_input = ctf_dynhash_lookup (fp->ctf_link_inputs, one_name); |
774 | 0 | else |
775 | 0 | one_input = (ctf_link_input_t *) input; |
776 | |
|
777 | 0 | if (!one_input || (!one_input->clin_arc && !one_input->clin_fp)) |
778 | 0 | continue; |
779 | | |
780 | | /* Short-circuit: if clin_fp is set, just use it. */ |
781 | 0 | if (one_input->clin_fp) |
782 | 0 | { |
783 | 0 | parents_[walk - dedup_inputs] = walk - dedup_inputs; |
784 | 0 | *walk = one_input->clin_fp; |
785 | 0 | walk++; |
786 | 0 | continue; |
787 | 0 | } |
788 | | |
789 | | /* Get and insert the parent archive (if any), if this archive has |
790 | | multiple members. We assume, as elsewhere, that the parent is named |
791 | | _CTF_SECTION. */ |
792 | | |
793 | 0 | if ((parent_fp = ctf_dict_open (one_input->clin_arc, _CTF_SECTION, |
794 | 0 | &err)) == NULL) |
795 | 0 | { |
796 | 0 | if (err != ECTF_NOMEMBNAM) |
797 | 0 | { |
798 | 0 | ctf_next_destroy (i); |
799 | 0 | ctf_set_errno (fp, err); |
800 | 0 | goto err; |
801 | 0 | } |
802 | 0 | } |
803 | 0 | else |
804 | 0 | { |
805 | 0 | *walk = parent_fp; |
806 | 0 | parent_i = walk - dedup_inputs; |
807 | 0 | walk++; |
808 | 0 | } |
809 | | |
810 | | /* We disregard the input archive name: either it is the parent (which we |
811 | | already have), or we want to put everything into one TU sharing the |
812 | | cuname anyway (if this is a CU-mapped link), or this is the final phase |
813 | | of a relink with CU-mapping off (i.e. ld -r) in which case the cuname |
814 | | is correctly set regardless. */ |
815 | 0 | while ((one_fp = ctf_archive_next (one_input->clin_arc, &j, NULL, |
816 | 0 | 1, &err)) != NULL) |
817 | 0 | { |
818 | 0 | if (one_fp->ctf_flags & LCTF_CHILD) |
819 | 0 | { |
820 | | /* The contents of the parents array for elements not |
821 | | corresponding to children is undefined. If there is no parent |
822 | | (itself a sign of a likely linker bug or corrupt input), we set |
823 | | it to itself. */ |
824 | |
|
825 | 0 | ctf_import (one_fp, parent_fp); |
826 | 0 | if (parent_fp) |
827 | 0 | parents_[walk - dedup_inputs] = parent_i; |
828 | 0 | else |
829 | 0 | parents_[walk - dedup_inputs] = walk - dedup_inputs; |
830 | 0 | } |
831 | 0 | *walk = one_fp; |
832 | 0 | walk++; |
833 | 0 | } |
834 | 0 | if (err != ECTF_NEXT_END) |
835 | 0 | { |
836 | 0 | ctf_next_destroy (i); |
837 | 0 | goto iterr; |
838 | 0 | } |
839 | 0 | } |
840 | 0 | if (err != ECTF_NEXT_END) |
841 | 0 | goto iterr; |
842 | | |
843 | 0 | *parents = parents_; |
844 | |
|
845 | 0 | return dedup_inputs; |
846 | | |
847 | 0 | oom: |
848 | 0 | err = ENOMEM; |
849 | |
|
850 | 0 | iterr: |
851 | 0 | ctf_set_errno (fp, err); |
852 | |
|
853 | 0 | err: |
854 | 0 | free (dedup_inputs); |
855 | 0 | free (parents_); |
856 | 0 | ctf_err_warn (fp, 0, 0, _("error in deduplicating CTF link " |
857 | 0 | "input allocation")); |
858 | 0 | return NULL; |
859 | 0 | } |
860 | | |
861 | | /* Close INPUTS that have already been linked, first the passed array, and then |
862 | | that subset of the ctf_link_inputs archives they came from cited by the |
863 | | CU_NAMES. If CU_NAMES is not specified, close all the ctf_link_inputs in one |
864 | | go, leaving it empty. */ |
865 | | static int |
866 | | ctf_link_deduplicating_close_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names, |
867 | | ctf_dict_t **inputs, ssize_t ninputs) |
868 | 0 | { |
869 | 0 | ctf_next_t *it = NULL; |
870 | 0 | void *name; |
871 | 0 | int err; |
872 | 0 | ssize_t i; |
873 | | |
874 | | /* This is the inverse of ctf_link_deduplicating_open_inputs: so first, close |
875 | | all the individual input dicts, opened by the archive iterator. */ |
876 | 0 | for (i = 0; i < ninputs; i++) |
877 | 0 | ctf_dict_close (inputs[i]); |
878 | | |
879 | | /* Now close the archives they are part of. */ |
880 | 0 | if (cu_names) |
881 | 0 | { |
882 | 0 | while ((err = ctf_dynhash_next (cu_names, &it, &name, NULL)) == 0) |
883 | 0 | { |
884 | | /* Remove the input from the linker inputs, if it exists, which also |
885 | | closes it. */ |
886 | |
|
887 | 0 | ctf_dynhash_remove (fp->ctf_link_inputs, (const char *) name); |
888 | 0 | } |
889 | 0 | if (err != ECTF_NEXT_END) |
890 | 0 | { |
891 | 0 | ctf_set_errno (fp, err); |
892 | 0 | ctf_err_warn (fp, 0, 0, _("iteration error in deduplicating link " |
893 | 0 | "input freeing")); |
894 | 0 | } |
895 | 0 | } |
896 | 0 | else |
897 | 0 | ctf_dynhash_empty (fp->ctf_link_inputs); |
898 | |
|
899 | 0 | return 0; |
900 | 0 | } |
901 | | |
902 | | /* Do a deduplicating link of all variables in the inputs. |
903 | | |
904 | | Also, if we are not omitting the variable section, integrate all symbols from |
905 | | the symtypetabs into the variable section too. (Duplication with the |
906 | | symtypetab section in the output will be eliminated at serialization time.) */ |
907 | | |
908 | | static int |
909 | | ctf_link_deduplicating_variables (ctf_dict_t *fp, ctf_dict_t **inputs, |
910 | | size_t ninputs, int cu_mapped) |
911 | 0 | { |
912 | 0 | size_t i; |
913 | |
|
914 | 0 | for (i = 0; i < ninputs; i++) |
915 | 0 | { |
916 | 0 | ctf_next_t *it = NULL; |
917 | 0 | ctf_id_t type; |
918 | 0 | const char *name; |
919 | | |
920 | | /* First the variables on the inputs. */ |
921 | |
|
922 | 0 | while ((type = ctf_variable_next (inputs[i], &it, &name)) != CTF_ERR) |
923 | 0 | { |
924 | 0 | if (ctf_link_one_variable (fp, inputs[i], name, type, cu_mapped) < 0) |
925 | 0 | { |
926 | 0 | ctf_next_destroy (it); |
927 | 0 | return -1; /* errno is set for us. */ |
928 | 0 | } |
929 | 0 | } |
930 | 0 | if (ctf_errno (inputs[i]) != ECTF_NEXT_END) |
931 | 0 | return ctf_set_errno (fp, ctf_errno (inputs[i])); |
932 | | |
933 | | /* Next the symbols. We integrate data symbols even though the compiler |
934 | | is currently doing the same, to allow the compiler to stop in |
935 | | future. */ |
936 | | |
937 | 0 | while ((type = ctf_symbol_next (inputs[i], &it, &name, 0)) != CTF_ERR) |
938 | 0 | { |
939 | 0 | if (ctf_link_one_variable (fp, inputs[i], name, type, 1) < 0) |
940 | 0 | { |
941 | 0 | ctf_next_destroy (it); |
942 | 0 | return -1; /* errno is set for us. */ |
943 | 0 | } |
944 | 0 | } |
945 | 0 | if (ctf_errno (inputs[i]) != ECTF_NEXT_END) |
946 | 0 | return ctf_set_errno (fp, ctf_errno (inputs[i])); |
947 | | |
948 | | /* Finally the function symbols. */ |
949 | | |
950 | 0 | while ((type = ctf_symbol_next (inputs[i], &it, &name, 1)) != CTF_ERR) |
951 | 0 | { |
952 | 0 | if (ctf_link_one_variable (fp, inputs[i], name, type, 1) < 0) |
953 | 0 | { |
954 | 0 | ctf_next_destroy (it); |
955 | 0 | return -1; /* errno is set for us. */ |
956 | 0 | } |
957 | 0 | } |
958 | 0 | if (ctf_errno (inputs[i]) != ECTF_NEXT_END) |
959 | 0 | return ctf_set_errno (fp, ctf_errno (inputs[i])); |
960 | 0 | } |
961 | 0 | return 0; |
962 | 0 | } |
963 | | |
964 | | /* Check for symbol conflicts during linking. Three possibilities: already |
965 | | exists, conflicting, or nonexistent. We don't have a dvd structure we can |
966 | | use as a flag like check_variable does, so we use a tristate return |
967 | | value instead: -1: conflicting; 1: nonexistent: 0: already exists. */ |
968 | | |
969 | | static int |
970 | | check_sym (ctf_dict_t *fp, const char *name, ctf_id_t type, int functions) |
971 | 0 | { |
972 | 0 | ctf_dynhash_t *thishash = functions ? fp->ctf_funchash : fp->ctf_objthash; |
973 | 0 | ctf_dynhash_t *thathash = functions ? fp->ctf_objthash : fp->ctf_funchash; |
974 | 0 | void *value; |
975 | | |
976 | | /* Wrong type (function when object is wanted, etc). */ |
977 | 0 | if (ctf_dynhash_lookup_kv (thathash, name, NULL, NULL)) |
978 | 0 | return -1; |
979 | | |
980 | | /* Not present at all yet. */ |
981 | 0 | if (!ctf_dynhash_lookup_kv (thishash, name, NULL, &value)) |
982 | 0 | return 1; |
983 | | |
984 | | /* Already present. */ |
985 | 0 | if ((ctf_id_t) (uintptr_t) value == type) |
986 | 0 | return 0; |
987 | | |
988 | | /* Wrong type. */ |
989 | 0 | return -1; |
990 | 0 | } |
991 | | |
992 | | /* Do a deduplicating link of one symtypetab (function info or data object) in |
993 | | one input dict. */ |
994 | | |
995 | | static int |
996 | | ctf_link_deduplicating_one_symtypetab (ctf_dict_t *fp, ctf_dict_t *input, |
997 | | int cu_mapped, int functions) |
998 | 0 | { |
999 | 0 | ctf_next_t *it = NULL; |
1000 | 0 | const char *name; |
1001 | 0 | ctf_id_t type; |
1002 | |
|
1003 | 0 | while ((type = ctf_symbol_next (input, &it, &name, functions)) != CTF_ERR) |
1004 | 0 | { |
1005 | 0 | ctf_id_t dst_type; |
1006 | 0 | ctf_dict_t *per_cu_out_fp; |
1007 | 0 | int sym; |
1008 | | |
1009 | | /* Look in the parent first. */ |
1010 | |
|
1011 | 0 | if ((dst_type = ctf_dedup_type_mapping (fp, input, type)) == CTF_ERR) |
1012 | 0 | return -1; /* errno is set for us. */ |
1013 | | |
1014 | 0 | if (dst_type != 0) |
1015 | 0 | { |
1016 | 0 | if (!ctf_assert (fp, ctf_type_isparent (fp, dst_type))) |
1017 | 0 | return -1; /* errno is set for us. */ |
1018 | | |
1019 | 0 | sym = check_sym (fp, name, dst_type, functions); |
1020 | | |
1021 | | /* Already present: next symbol. */ |
1022 | 0 | if (sym == 0) |
1023 | 0 | continue; |
1024 | | /* Not present: add it. */ |
1025 | 0 | else if (sym > 0) |
1026 | 0 | { |
1027 | 0 | if (ctf_add_funcobjt_sym (fp, functions, |
1028 | 0 | name, dst_type) < 0) |
1029 | 0 | return -1; /* errno is set for us. */ |
1030 | 0 | continue; |
1031 | 0 | } |
1032 | 0 | } |
1033 | | |
1034 | | /* Can't add to the parent due to a name clash (most unlikely), or because |
1035 | | it references a type only present in the child. Try adding to the |
1036 | | child, creating if need be. If we can't do that, skip it. Don't add |
1037 | | to a child if we're doing a CU-mapped link, since that has only one |
1038 | | output. */ |
1039 | 0 | if (cu_mapped) |
1040 | 0 | { |
1041 | 0 | ctf_dprintf ("Symbol %s in input file %s depends on a type %lx " |
1042 | 0 | "hidden due to conflicts: skipped.\n", name, |
1043 | 0 | ctf_unnamed_cuname (input), type); |
1044 | 0 | continue; |
1045 | 0 | } |
1046 | | |
1047 | 0 | if ((per_cu_out_fp = ctf_create_per_cu (fp, input, NULL)) == NULL) |
1048 | 0 | return -1; /* errno is set for us. */ |
1049 | | |
1050 | | /* If the type was not found, check for it in the child too. */ |
1051 | 0 | if (dst_type == 0) |
1052 | 0 | { |
1053 | 0 | if ((dst_type = ctf_dedup_type_mapping (per_cu_out_fp, |
1054 | 0 | input, type)) == CTF_ERR) |
1055 | 0 | return -1; /* errno is set for us. */ |
1056 | | |
1057 | 0 | if (dst_type == 0) |
1058 | 0 | { |
1059 | 0 | ctf_err_warn (fp, 1, 0, |
1060 | 0 | _("type %lx for symbol %s in input file %s " |
1061 | 0 | "not found: skipped"), type, name, |
1062 | 0 | ctf_unnamed_cuname (input)); |
1063 | 0 | continue; |
1064 | 0 | } |
1065 | 0 | } |
1066 | | |
1067 | 0 | sym = check_sym (per_cu_out_fp, name, dst_type, functions); |
1068 | | |
1069 | | /* Already present: next symbol. */ |
1070 | 0 | if (sym == 0) |
1071 | 0 | continue; |
1072 | | /* Not present: add it. */ |
1073 | 0 | else if (sym > 0) |
1074 | 0 | { |
1075 | 0 | if (ctf_add_funcobjt_sym (per_cu_out_fp, functions, |
1076 | 0 | name, dst_type) < 0) |
1077 | 0 | return -1; /* errno is set for us. */ |
1078 | 0 | } |
1079 | 0 | else |
1080 | 0 | { |
1081 | | /* Perhaps this should be an assertion failure. */ |
1082 | 0 | ctf_err_warn (fp, 0, ECTF_DUPLICATE, |
1083 | 0 | _("symbol %s in input file %s found conflicting " |
1084 | 0 | "even when trying in per-CU dict."), name, |
1085 | 0 | ctf_unnamed_cuname (input)); |
1086 | 0 | return (ctf_set_errno (fp, ECTF_DUPLICATE)); |
1087 | 0 | } |
1088 | 0 | } |
1089 | 0 | if (ctf_errno (input) != ECTF_NEXT_END) |
1090 | 0 | { |
1091 | 0 | ctf_set_errno (fp, ctf_errno (input)); |
1092 | 0 | ctf_err_warn (fp, 0, 0, functions ? |
1093 | 0 | _("iterating over function symbols") : |
1094 | 0 | _("iterating over data symbols")); |
1095 | 0 | return -1; |
1096 | 0 | } |
1097 | | |
1098 | 0 | return 0; |
1099 | 0 | } |
1100 | | |
1101 | | /* Do a deduplicating link of the function info and data objects |
1102 | | in the inputs. */ |
1103 | | static int |
1104 | | ctf_link_deduplicating_syms (ctf_dict_t *fp, ctf_dict_t **inputs, |
1105 | | size_t ninputs, int cu_mapped) |
1106 | 0 | { |
1107 | 0 | size_t i; |
1108 | |
|
1109 | 0 | for (i = 0; i < ninputs; i++) |
1110 | 0 | { |
1111 | 0 | if (ctf_link_deduplicating_one_symtypetab (fp, inputs[i], |
1112 | 0 | cu_mapped, 0) < 0) |
1113 | 0 | return -1; /* errno is set for us. */ |
1114 | | |
1115 | 0 | if (ctf_link_deduplicating_one_symtypetab (fp, inputs[i], |
1116 | 0 | cu_mapped, 1) < 0) |
1117 | 0 | return -1; /* errno is set for us. */ |
1118 | 0 | } |
1119 | | |
1120 | 0 | return 0; |
1121 | 0 | } |
1122 | | |
1123 | | /* Do the per-CU part of a deduplicating link. */ |
1124 | | static int |
1125 | | ctf_link_deduplicating_per_cu (ctf_dict_t *fp) |
1126 | 0 | { |
1127 | 0 | ctf_next_t *i = NULL; |
1128 | 0 | int err; |
1129 | 0 | void *out_cu; |
1130 | 0 | void *in_cus; |
1131 | | |
1132 | | /* Links with a per-CU mapping in force get a first pass of deduplication, |
1133 | | dedupping the inputs for a given CU mapping into the output for that |
1134 | | mapping. The outputs from this process get fed back into the final pass |
1135 | | that is carried out even for non-CU links. */ |
1136 | |
|
1137 | 0 | while ((err = ctf_dynhash_next (fp->ctf_link_out_cu_mapping, &i, &out_cu, |
1138 | 0 | &in_cus)) == 0) |
1139 | 0 | { |
1140 | 0 | const char *out_name = (const char *) out_cu; |
1141 | 0 | ctf_dynhash_t *in = (ctf_dynhash_t *) in_cus; |
1142 | 0 | ctf_dict_t *out = NULL; |
1143 | 0 | ctf_dict_t **inputs; |
1144 | 0 | ctf_dict_t **outputs; |
1145 | 0 | ctf_archive_t *in_arc; |
1146 | 0 | ssize_t ninputs; |
1147 | 0 | ctf_link_input_t *only_input; |
1148 | 0 | uint32_t noutputs; |
1149 | 0 | uint32_t *parents; |
1150 | |
|
1151 | 0 | if ((ninputs = ctf_link_deduplicating_count_inputs (fp, in, |
1152 | 0 | &only_input)) == -1) |
1153 | 0 | goto err_open_inputs; |
1154 | | |
1155 | | /* CU mapping with no inputs? Skip. */ |
1156 | 0 | if (ninputs == 0) |
1157 | 0 | continue; |
1158 | | |
1159 | 0 | if (labs ((long int) ninputs) > 0xfffffffe) |
1160 | 0 | { |
1161 | 0 | ctf_set_errno (fp, EFBIG); |
1162 | 0 | ctf_err_warn (fp, 0, 0, _("too many inputs in deduplicating " |
1163 | 0 | "link: %li"), (long int) ninputs); |
1164 | 0 | goto err_open_inputs; |
1165 | 0 | } |
1166 | | |
1167 | | /* Short-circuit: a cu-mapped link with only one input archive with |
1168 | | unconflicting contents is a do-nothing, and we can just leave the input |
1169 | | in place: we do have to change the cuname, though, so we unwrap it, |
1170 | | change the cuname, then stuff it back in the linker input again, via |
1171 | | the clin_fp short-circuit member. ctf_link_deduplicating_open_inputs |
1172 | | will spot this member and jam it straight into the next link phase, |
1173 | | ignoring the corresponding archive. */ |
1174 | 0 | if (only_input && ninputs == 1) |
1175 | 0 | { |
1176 | 0 | ctf_next_t *ai = NULL; |
1177 | 0 | int err; |
1178 | | |
1179 | | /* We can abuse an archive iterator to get the only member cheaply, no |
1180 | | matter what its name. */ |
1181 | 0 | only_input->clin_fp = ctf_archive_next (only_input->clin_arc, |
1182 | 0 | &ai, NULL, 0, &err); |
1183 | 0 | if (!only_input->clin_fp) |
1184 | 0 | { |
1185 | 0 | ctf_set_errno (fp, err); |
1186 | 0 | ctf_err_warn (fp, 0, 0, _("cannot open archive %s in " |
1187 | 0 | "CU-mapped CTF link"), |
1188 | 0 | only_input->clin_filename); |
1189 | 0 | goto err_open_inputs; |
1190 | 0 | } |
1191 | 0 | ctf_next_destroy (ai); |
1192 | |
|
1193 | 0 | if (strcmp (only_input->clin_filename, out_name) != 0) |
1194 | 0 | { |
1195 | | /* Renaming. We need to add a new input, then null out the |
1196 | | clin_arc and clin_fp of the old one to stop it being |
1197 | | auto-closed on removal. The new input needs its cuname changed |
1198 | | to out_name, which is doable only because the cuname is a |
1199 | | dynamic property which can be changed even in readonly |
1200 | | dicts. */ |
1201 | |
|
1202 | 0 | ctf_cuname_set (only_input->clin_fp, out_name); |
1203 | 0 | if (ctf_link_add_ctf_internal (fp, only_input->clin_arc, |
1204 | 0 | only_input->clin_fp, |
1205 | 0 | out_name) < 0) |
1206 | 0 | { |
1207 | 0 | ctf_err_warn (fp, 0, 0, _("cannot add intermediate files " |
1208 | 0 | "to link")); |
1209 | 0 | goto err_open_inputs; |
1210 | 0 | } |
1211 | 0 | only_input->clin_arc = NULL; |
1212 | 0 | only_input->clin_fp = NULL; |
1213 | 0 | ctf_dynhash_remove (fp->ctf_link_inputs, |
1214 | 0 | only_input->clin_filename); |
1215 | 0 | } |
1216 | 0 | continue; |
1217 | 0 | } |
1218 | | |
1219 | | /* This is a real CU many-to-one mapping: we must dedup the inputs into |
1220 | | a new output to be used in the final link phase. */ |
1221 | | |
1222 | 0 | if ((inputs = ctf_link_deduplicating_open_inputs (fp, in, ninputs, |
1223 | 0 | &parents)) == NULL) |
1224 | 0 | { |
1225 | 0 | ctf_next_destroy (i); |
1226 | 0 | goto err_open_inputs; |
1227 | 0 | } |
1228 | | |
1229 | 0 | if ((out = ctf_create (&err)) == NULL) |
1230 | 0 | { |
1231 | 0 | ctf_err_warn (fp, 0, err, _("cannot create per-CU CTF archive " |
1232 | 0 | "for %s"), |
1233 | 0 | out_name); |
1234 | 0 | ctf_set_errno (fp, err); |
1235 | 0 | goto err_inputs; |
1236 | 0 | } |
1237 | | |
1238 | | /* The deduplicator is ready for strict enumerator value checking. */ |
1239 | 0 | out->ctf_flags |= LCTF_STRICT_NO_DUP_ENUMERATORS; |
1240 | | |
1241 | | /* Share the atoms table to reduce memory usage. */ |
1242 | 0 | out->ctf_dedup_atoms = fp->ctf_dedup_atoms_alloc; |
1243 | | |
1244 | | /* No ctf_imports at this stage: this per-CU dictionary has no parents. |
1245 | | Parent/child deduplication happens in the link's final pass. However, |
1246 | | the cuname *is* important, as it is propagated into the final |
1247 | | dictionary. */ |
1248 | 0 | ctf_cuname_set (out, out_name); |
1249 | |
|
1250 | 0 | if (ctf_dedup (out, inputs, ninputs, 1) < 0) |
1251 | 0 | { |
1252 | 0 | ctf_set_errno (fp, ctf_errno (out)); |
1253 | 0 | ctf_err_warn (fp, 0, 0, _("CU-mapped deduplication failed for %s"), |
1254 | 0 | out_name); |
1255 | 0 | goto err_inputs; |
1256 | 0 | } |
1257 | | |
1258 | 0 | if ((outputs = ctf_dedup_emit (out, inputs, ninputs, parents, |
1259 | 0 | &noutputs, 1)) == NULL) |
1260 | 0 | { |
1261 | 0 | ctf_set_errno (fp, ctf_errno (out)); |
1262 | 0 | ctf_err_warn (fp, 0, 0, _("CU-mapped deduplicating link type emission " |
1263 | 0 | "failed for %s"), out_name); |
1264 | 0 | goto err_inputs; |
1265 | 0 | } |
1266 | 0 | if (!ctf_assert (fp, noutputs == 1)) |
1267 | 0 | { |
1268 | 0 | size_t j; |
1269 | 0 | for (j = 1; j < noutputs; j++) |
1270 | 0 | ctf_dict_close (outputs[j]); |
1271 | 0 | goto err_inputs_outputs; |
1272 | 0 | } |
1273 | | |
1274 | 0 | if (!(fp->ctf_link_flags & CTF_LINK_OMIT_VARIABLES_SECTION) |
1275 | 0 | && ctf_link_deduplicating_variables (out, inputs, ninputs, 1) < 0) |
1276 | 0 | { |
1277 | 0 | ctf_set_errno (fp, ctf_errno (out)); |
1278 | 0 | ctf_err_warn (fp, 0, 0, _("CU-mapped deduplicating link variable " |
1279 | 0 | "emission failed for %s"), out_name); |
1280 | 0 | goto err_inputs_outputs; |
1281 | 0 | } |
1282 | | |
1283 | 0 | ctf_dedup_fini (out, outputs, noutputs); |
1284 | | |
1285 | | /* For now, we omit symbol section linking for CU-mapped links, until it |
1286 | | is clear how to unify the symbol table across such links. (Perhaps we |
1287 | | should emit an unconditionally indexed symtab, like the compiler |
1288 | | does.) */ |
1289 | |
|
1290 | 0 | if (ctf_link_deduplicating_close_inputs (fp, in, inputs, ninputs) < 0) |
1291 | 0 | { |
1292 | 0 | free (inputs); |
1293 | 0 | free (parents); |
1294 | 0 | goto err_outputs; |
1295 | 0 | } |
1296 | 0 | free (inputs); |
1297 | 0 | free (parents); |
1298 | | |
1299 | | /* Splice any errors or warnings created during this link back into the |
1300 | | dict that the caller knows about. */ |
1301 | 0 | ctf_list_splice (&fp->ctf_errs_warnings, &outputs[0]->ctf_errs_warnings); |
1302 | | |
1303 | | /* This output now becomes an input to the next link phase, with a name |
1304 | | equal to the CU name. We have to wrap it in an archive wrapper |
1305 | | first. */ |
1306 | |
|
1307 | 0 | if ((in_arc = ctf_new_archive_internal (0, 0, NULL, outputs[0], NULL, |
1308 | 0 | NULL, &err)) == NULL) |
1309 | 0 | { |
1310 | 0 | ctf_set_errno (fp, err); |
1311 | 0 | goto err_outputs; |
1312 | 0 | } |
1313 | | |
1314 | 0 | if (ctf_link_add_ctf_internal (fp, in_arc, NULL, |
1315 | 0 | ctf_cuname (outputs[0])) < 0) |
1316 | 0 | { |
1317 | 0 | ctf_err_warn (fp, 0, 0, _("cannot add intermediate files to link")); |
1318 | 0 | goto err_outputs; |
1319 | 0 | } |
1320 | | |
1321 | 0 | ctf_dict_close (out); |
1322 | 0 | free (outputs); |
1323 | 0 | continue; |
1324 | | |
1325 | 0 | err_inputs_outputs: |
1326 | 0 | ctf_list_splice (&fp->ctf_errs_warnings, &outputs[0]->ctf_errs_warnings); |
1327 | 0 | ctf_dict_close (outputs[0]); |
1328 | 0 | free (outputs); |
1329 | 0 | err_inputs: |
1330 | 0 | ctf_link_deduplicating_close_inputs (fp, in, inputs, ninputs); |
1331 | 0 | ctf_dict_close (out); |
1332 | 0 | free (inputs); |
1333 | 0 | free (parents); |
1334 | 0 | err_open_inputs: |
1335 | 0 | ctf_next_destroy (i); |
1336 | 0 | return -1; |
1337 | | |
1338 | 0 | err_outputs: |
1339 | 0 | ctf_list_splice (&fp->ctf_errs_warnings, &outputs[0]->ctf_errs_warnings); |
1340 | 0 | ctf_dict_close (outputs[0]); |
1341 | 0 | free (outputs); |
1342 | 0 | ctf_next_destroy (i); |
1343 | 0 | return -1; /* Errno is set for us. */ |
1344 | 0 | } |
1345 | 0 | if (err != ECTF_NEXT_END) |
1346 | 0 | { |
1347 | 0 | ctf_err_warn (fp, 0, err, _("iteration error in CU-mapped deduplicating " |
1348 | 0 | "link")); |
1349 | 0 | return ctf_set_errno (fp, err); |
1350 | 0 | } |
1351 | | |
1352 | 0 | return 0; |
1353 | 0 | } |
1354 | | |
1355 | | /* Empty all the ctf_link_outputs. */ |
1356 | | static int |
1357 | | ctf_link_empty_outputs (ctf_dict_t *fp) |
1358 | 0 | { |
1359 | 0 | ctf_next_t *i = NULL; |
1360 | 0 | void *v; |
1361 | 0 | int err; |
1362 | |
|
1363 | 0 | ctf_dynhash_empty (fp->ctf_link_outputs); |
1364 | |
|
1365 | 0 | while ((err = ctf_dynhash_next (fp->ctf_link_inputs, &i, NULL, &v)) == 0) |
1366 | 0 | { |
1367 | 0 | ctf_dict_t *in = (ctf_dict_t *) v; |
1368 | 0 | in->ctf_link_in_out = NULL; |
1369 | 0 | } |
1370 | 0 | if (err != ECTF_NEXT_END) |
1371 | 0 | { |
1372 | 0 | fp->ctf_flags &= ~LCTF_LINKING; |
1373 | 0 | ctf_err_warn (fp, 1, err, _("iteration error removing old outputs")); |
1374 | 0 | return ctf_set_errno (fp, err); |
1375 | 0 | } |
1376 | 0 | return 0; |
1377 | 0 | } |
1378 | | |
1379 | | /* Do a deduplicating link using the ctf-dedup machinery. */ |
1380 | | static void |
1381 | | ctf_link_deduplicating (ctf_dict_t *fp) |
1382 | 0 | { |
1383 | 0 | size_t i; |
1384 | 0 | ctf_dict_t **inputs, **outputs = NULL; |
1385 | 0 | ssize_t ninputs; |
1386 | 0 | uint32_t noutputs; |
1387 | 0 | uint32_t *parents; |
1388 | 0 | int cu_phase = 0; |
1389 | |
|
1390 | 0 | if (ctf_dedup_atoms_init (fp) < 0) |
1391 | 0 | { |
1392 | 0 | ctf_err_warn (fp, 0, 0, _("allocating CTF dedup atoms table")); |
1393 | 0 | return; /* Errno is set for us. */ |
1394 | 0 | } |
1395 | | |
1396 | | /* Trigger a CU-mapped link if need be: one pass of dedups squashing inputs into |
1397 | | single child dicts corresponding to each CU mapping, and one pass that |
1398 | | treats those as if they are ordinary inputs and links them together. |
1399 | | |
1400 | | This latter pass does need to act very slightly differently from normal, so we |
1401 | | keep track of the "CU phase", with 0 being a normal link, 1 being the |
1402 | | squash-together phase, and 2 being the final act-as-if-it-were-normal pass. */ |
1403 | | |
1404 | 0 | if (fp->ctf_link_out_cu_mapping) |
1405 | 0 | { |
1406 | 0 | if (ctf_link_deduplicating_per_cu (fp) < 0) |
1407 | 0 | return; /* Errno is set for us. */ |
1408 | 0 | cu_phase = 2; |
1409 | 0 | } |
1410 | | |
1411 | 0 | if ((ninputs = ctf_link_deduplicating_count_inputs (fp, NULL, NULL)) < 0) |
1412 | 0 | return; /* Errno is set for us. */ |
1413 | | |
1414 | 0 | if ((inputs = ctf_link_deduplicating_open_inputs (fp, NULL, ninputs, |
1415 | 0 | &parents)) == NULL) |
1416 | 0 | return; /* Errno is set for us. */ |
1417 | | |
1418 | 0 | if (ninputs == 1 && ctf_cuname (inputs[0]) != NULL) |
1419 | 0 | ctf_cuname_set (fp, ctf_cuname (inputs[0])); |
1420 | |
|
1421 | 0 | if (ctf_dedup (fp, inputs, ninputs, cu_phase) < 0) |
1422 | 0 | { |
1423 | 0 | ctf_err_warn (fp, 0, 0, _("deduplication failed for %s"), |
1424 | 0 | ctf_link_input_name (fp)); |
1425 | 0 | goto err; |
1426 | 0 | } |
1427 | | |
1428 | 0 | if ((outputs = ctf_dedup_emit (fp, inputs, ninputs, parents, &noutputs, |
1429 | 0 | cu_phase)) == NULL) |
1430 | 0 | { |
1431 | 0 | ctf_err_warn (fp, 0, 0, _("deduplicating link type emission failed " |
1432 | 0 | "for %s"), ctf_link_input_name (fp)); |
1433 | 0 | goto err; |
1434 | 0 | } |
1435 | | |
1436 | 0 | if (!ctf_assert (fp, outputs[0] == fp)) |
1437 | 0 | { |
1438 | 0 | for (i = 1; i < noutputs; i++) |
1439 | 0 | ctf_dict_close (outputs[i]); |
1440 | 0 | goto err; |
1441 | 0 | } |
1442 | | |
1443 | 0 | for (i = 0; i < noutputs; i++) |
1444 | 0 | { |
1445 | 0 | char *dynname; |
1446 | | |
1447 | | /* We already have access to this one. Close the duplicate. */ |
1448 | 0 | if (i == 0) |
1449 | 0 | { |
1450 | 0 | ctf_dict_close (outputs[0]); |
1451 | 0 | continue; |
1452 | 0 | } |
1453 | | |
1454 | 0 | if ((dynname = ctf_new_per_cu_name (fp, ctf_cuname (outputs[i]))) == NULL) |
1455 | 0 | goto oom_one_output; |
1456 | | |
1457 | 0 | if (ctf_dynhash_insert (fp->ctf_link_outputs, dynname, outputs[i]) < 0) |
1458 | 0 | goto oom_one_output; |
1459 | | |
1460 | 0 | continue; |
1461 | | |
1462 | 0 | oom_one_output: |
1463 | 0 | ctf_set_errno (fp, ENOMEM); |
1464 | 0 | ctf_err_warn (fp, 0, 0, _("out of memory allocating link outputs")); |
1465 | 0 | free (dynname); |
1466 | |
|
1467 | 0 | for (; i < noutputs; i++) |
1468 | 0 | ctf_dict_close (outputs[i]); |
1469 | 0 | goto err; |
1470 | 0 | } |
1471 | | |
1472 | 0 | if (!(fp->ctf_link_flags & CTF_LINK_OMIT_VARIABLES_SECTION) |
1473 | 0 | && ctf_link_deduplicating_variables (fp, inputs, ninputs, 0) < 0) |
1474 | 0 | { |
1475 | 0 | ctf_err_warn (fp, 0, 0, _("deduplicating link variable emission failed for " |
1476 | 0 | "%s"), ctf_link_input_name (fp)); |
1477 | 0 | goto err_clean_outputs; |
1478 | 0 | } |
1479 | | |
1480 | 0 | if (ctf_link_deduplicating_syms (fp, inputs, ninputs, 0) < 0) |
1481 | 0 | { |
1482 | 0 | ctf_err_warn (fp, 0, 0, _("deduplicating link symbol emission failed for " |
1483 | 0 | "%s"), ctf_link_input_name (fp)); |
1484 | 0 | goto err_clean_outputs; |
1485 | 0 | } |
1486 | | |
1487 | 0 | ctf_dedup_fini (fp, outputs, noutputs); |
1488 | | |
1489 | | /* Now close all the inputs, including per-CU intermediates. */ |
1490 | |
|
1491 | 0 | if (ctf_link_deduplicating_close_inputs (fp, NULL, inputs, ninputs) < 0) |
1492 | 0 | return; /* errno is set for us. */ |
1493 | | |
1494 | 0 | ninputs = 0; /* Prevent double-close. */ |
1495 | 0 | ctf_set_errno (fp, 0); |
1496 | | |
1497 | | /* Fall through. */ |
1498 | |
|
1499 | 0 | err: |
1500 | 0 | for (i = 0; i < (size_t) ninputs; i++) |
1501 | 0 | ctf_dict_close (inputs[i]); |
1502 | 0 | free (inputs); |
1503 | 0 | free (parents); |
1504 | 0 | free (outputs); |
1505 | 0 | return; |
1506 | | |
1507 | 0 | err_clean_outputs: |
1508 | 0 | ctf_link_empty_outputs (fp); |
1509 | 0 | goto err; |
1510 | 0 | } |
1511 | | |
1512 | | /* Merge types and variable sections in all dicts added to the link together. |
1513 | | The result of any previous link is discarded. */ |
1514 | | int |
1515 | | ctf_link (ctf_dict_t *fp, int flags) |
1516 | 0 | { |
1517 | 0 | int err; |
1518 | 0 | int oldflags = fp->ctf_flags; |
1519 | |
|
1520 | 0 | fp->ctf_link_flags = flags; |
1521 | |
|
1522 | 0 | if (fp->ctf_link_inputs == NULL) |
1523 | 0 | return 0; /* Nothing to do. */ |
1524 | | |
1525 | 0 | if (fp->ctf_link_outputs != NULL) |
1526 | 0 | ctf_link_empty_outputs (fp); |
1527 | 0 | else |
1528 | 0 | fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string, |
1529 | 0 | ctf_hash_eq_string, free, |
1530 | 0 | (ctf_hash_free_fun) |
1531 | 0 | ctf_dict_close); |
1532 | |
|
1533 | 0 | if (fp->ctf_link_outputs == NULL) |
1534 | 0 | return ctf_set_errno (fp, ENOMEM); |
1535 | | |
1536 | 0 | fp->ctf_flags |= LCTF_LINKING & LCTF_STRICT_NO_DUP_ENUMERATORS; |
1537 | 0 | ctf_link_deduplicating (fp); |
1538 | 0 | fp->ctf_flags = oldflags; |
1539 | |
|
1540 | 0 | if ((ctf_errno (fp) != 0) && (ctf_errno (fp) != ECTF_NOCTFDATA)) |
1541 | 0 | return -1; |
1542 | | |
1543 | | /* Create empty CUs if requested. We do not currently claim that multiple |
1544 | | links in succession with CTF_LINK_EMPTY_CU_MAPPINGS set in some calls and |
1545 | | not set in others will do anything especially sensible. */ |
1546 | | |
1547 | 0 | if (fp->ctf_link_out_cu_mapping && (flags & CTF_LINK_EMPTY_CU_MAPPINGS)) |
1548 | 0 | { |
1549 | 0 | ctf_next_t *i = NULL; |
1550 | 0 | void *k; |
1551 | |
|
1552 | 0 | while ((err = ctf_dynhash_next (fp->ctf_link_out_cu_mapping, &i, &k, |
1553 | 0 | NULL)) == 0) |
1554 | 0 | { |
1555 | 0 | const char *to = (const char *) k; |
1556 | 0 | if (ctf_create_per_cu (fp, NULL, to) == NULL) |
1557 | 0 | { |
1558 | 0 | fp->ctf_flags = oldflags; |
1559 | 0 | ctf_next_destroy (i); |
1560 | 0 | return -1; /* Errno is set for us. */ |
1561 | 0 | } |
1562 | 0 | } |
1563 | 0 | if (err != ECTF_NEXT_END) |
1564 | 0 | { |
1565 | 0 | fp->ctf_flags = oldflags; |
1566 | 0 | ctf_err_warn (fp, 1, err, _("iteration error creating empty CUs")); |
1567 | 0 | return ctf_set_errno (fp, err); |
1568 | 0 | } |
1569 | 0 | } |
1570 | | |
1571 | 0 | return 0; |
1572 | 0 | } |
1573 | | |
1574 | | typedef struct ctf_link_out_string_cb_arg |
1575 | | { |
1576 | | const char *str; |
1577 | | uint32_t offset; |
1578 | | int err; |
1579 | | } ctf_link_out_string_cb_arg_t; |
1580 | | |
1581 | | /* Intern a string in the string table of an output per-CU CTF file. */ |
1582 | | static void |
1583 | | ctf_link_intern_extern_string (void *key _libctf_unused_, void *value, |
1584 | | void *arg_) |
1585 | 0 | { |
1586 | 0 | ctf_dict_t *fp = (ctf_dict_t *) value; |
1587 | 0 | ctf_link_out_string_cb_arg_t *arg = (ctf_link_out_string_cb_arg_t *) arg_; |
1588 | |
|
1589 | 0 | if (!ctf_str_add_external (fp, arg->str, arg->offset)) |
1590 | 0 | arg->err = ENOMEM; |
1591 | 0 | } |
1592 | | |
1593 | | /* Repeatedly call ADD_STRING to acquire strings from the external string table, |
1594 | | adding them to the atoms table for this CU and all subsidiary CUs. |
1595 | | |
1596 | | Must be called on a dict that has not yet been serialized. |
1597 | | |
1598 | | If ctf_link is also called, it must be called first if you want the new CTF |
1599 | | files ctf_link can create to get their strings dedupped against the ELF |
1600 | | strtab properly. */ |
1601 | | int |
1602 | | ctf_link_add_strtab (ctf_dict_t *fp, ctf_link_strtab_string_f *add_string, |
1603 | | void *arg) |
1604 | 0 | { |
1605 | 0 | const char *str; |
1606 | 0 | uint32_t offset; |
1607 | 0 | int err = 0; |
1608 | |
|
1609 | 0 | if (fp->ctf_stypes > 0) |
1610 | 0 | return ctf_set_errno (fp, ECTF_RDONLY); |
1611 | | |
1612 | 0 | while ((str = add_string (&offset, arg)) != NULL) |
1613 | 0 | { |
1614 | 0 | ctf_link_out_string_cb_arg_t iter_arg = { str, offset, 0 }; |
1615 | |
|
1616 | 0 | if (!ctf_str_add_external (fp, str, offset)) |
1617 | 0 | err = ENOMEM; |
1618 | |
|
1619 | 0 | ctf_dynhash_iter (fp->ctf_link_outputs, ctf_link_intern_extern_string, |
1620 | 0 | &iter_arg); |
1621 | 0 | if (iter_arg.err) |
1622 | 0 | err = iter_arg.err; |
1623 | 0 | } |
1624 | |
|
1625 | 0 | if (err) |
1626 | 0 | ctf_set_errno (fp, err); |
1627 | |
|
1628 | 0 | return -err; |
1629 | 0 | } |
1630 | | |
1631 | | /* Inform the ctf-link machinery of a new symbol in the target symbol table |
1632 | | (which must be some symtab that is not usually stripped, and which |
1633 | | is in agreement with ctf_bfdopen_ctfsect). May be called either before or |
1634 | | after ctf_link_add_strtab. As with that function, must be called on a dict which |
1635 | | has not yet been serialized. */ |
1636 | | int |
1637 | | ctf_link_add_linker_symbol (ctf_dict_t *fp, ctf_link_sym_t *sym) |
1638 | 0 | { |
1639 | 0 | ctf_in_flight_dynsym_t *cid; |
1640 | | |
1641 | | /* Cheat a little: if there is already an ENOMEM error code recorded against |
1642 | | this dict, we shouldn't even try to add symbols because there will be no |
1643 | | memory to do so: probably we failed to add some previous symbol. This |
1644 | | makes out-of-memory exits 'sticky' across calls to this function, so the |
1645 | | caller doesn't need to worry about error conditions. */ |
1646 | |
|
1647 | 0 | if (ctf_errno (fp) == ENOMEM) |
1648 | 0 | return -ENOMEM; /* errno is set for us. */ |
1649 | | |
1650 | 0 | if (fp->ctf_stypes > 0) |
1651 | 0 | return ctf_set_errno (fp, ECTF_RDONLY); |
1652 | | |
1653 | 0 | if (ctf_symtab_skippable (sym)) |
1654 | 0 | return 0; |
1655 | | |
1656 | 0 | if (sym->st_type != STT_OBJECT && sym->st_type != STT_FUNC) |
1657 | 0 | return 0; |
1658 | | |
1659 | | /* Add the symbol to the in-flight list. */ |
1660 | | |
1661 | 0 | if ((cid = malloc (sizeof (ctf_in_flight_dynsym_t))) == NULL) |
1662 | 0 | goto oom; |
1663 | | |
1664 | 0 | cid->cid_sym = *sym; |
1665 | 0 | ctf_list_append (&fp->ctf_in_flight_dynsyms, cid); |
1666 | |
|
1667 | 0 | return 0; |
1668 | | |
1669 | 0 | oom: |
1670 | 0 | ctf_dynhash_destroy (fp->ctf_dynsyms); |
1671 | 0 | fp->ctf_dynsyms = NULL; |
1672 | 0 | ctf_set_errno (fp, ENOMEM); |
1673 | 0 | return -ENOMEM; |
1674 | 0 | } |
1675 | | |
1676 | | /* Impose an ordering on symbols. The ordering takes effect immediately, but |
1677 | | since the ordering info does not include type IDs, lookups may return nothing |
1678 | | until such IDs are added by calls to ctf_add_*_sym. Must be called after |
1679 | | ctf_link_add_strtab and ctf_link_add_linker_symbol. */ |
1680 | | int |
1681 | | ctf_link_shuffle_syms (ctf_dict_t *fp) |
1682 | 0 | { |
1683 | 0 | ctf_in_flight_dynsym_t *did, *nid; |
1684 | 0 | ctf_next_t *i = NULL; |
1685 | 0 | int err = ENOMEM; |
1686 | 0 | void *name_, *sym_; |
1687 | |
|
1688 | 0 | if (fp->ctf_stypes > 0) |
1689 | 0 | return ctf_set_errno (fp, ECTF_RDONLY); |
1690 | | |
1691 | 0 | if (!fp->ctf_dynsyms) |
1692 | 0 | { |
1693 | 0 | fp->ctf_dynsyms = ctf_dynhash_create (ctf_hash_string, |
1694 | 0 | ctf_hash_eq_string, |
1695 | 0 | NULL, free); |
1696 | 0 | if (!fp->ctf_dynsyms) |
1697 | 0 | { |
1698 | 0 | ctf_set_errno (fp, ENOMEM); |
1699 | 0 | return -ENOMEM; |
1700 | 0 | } |
1701 | 0 | } |
1702 | | |
1703 | | /* Add all the symbols, excluding only those we already know are prohibited |
1704 | | from appearing in symtypetabs. */ |
1705 | | |
1706 | 0 | for (did = ctf_list_next (&fp->ctf_in_flight_dynsyms); did != NULL; did = nid) |
1707 | 0 | { |
1708 | 0 | ctf_link_sym_t *new_sym; |
1709 | |
|
1710 | 0 | nid = ctf_list_next (did); |
1711 | 0 | ctf_list_delete (&fp->ctf_in_flight_dynsyms, did); |
1712 | | |
1713 | | /* We might get a name or an external strtab offset. The strtab offset is |
1714 | | guaranteed resolvable at this point, so turn it into a string. */ |
1715 | |
|
1716 | 0 | if (did->cid_sym.st_name == NULL) |
1717 | 0 | { |
1718 | 0 | uint32_t off = CTF_SET_STID (did->cid_sym.st_nameidx, CTF_STRTAB_1); |
1719 | |
|
1720 | 0 | did->cid_sym.st_name = ctf_strraw (fp, off); |
1721 | 0 | did->cid_sym.st_nameidx_set = 0; |
1722 | 0 | if (!ctf_assert (fp, did->cid_sym.st_name != NULL)) |
1723 | 0 | return -ECTF_INTERNAL; /* errno is set for us. */ |
1724 | 0 | } |
1725 | | |
1726 | | /* The symbol might have turned out to be nameless, so we have to recheck |
1727 | | for skippability here. */ |
1728 | 0 | if (!ctf_symtab_skippable (&did->cid_sym)) |
1729 | 0 | { |
1730 | 0 | ctf_dprintf ("symbol from linker: %s (%x)\n", did->cid_sym.st_name, |
1731 | 0 | did->cid_sym.st_symidx); |
1732 | |
|
1733 | 0 | if ((new_sym = malloc (sizeof (ctf_link_sym_t))) == NULL) |
1734 | 0 | goto local_oom; |
1735 | | |
1736 | 0 | memcpy (new_sym, &did->cid_sym, sizeof (ctf_link_sym_t)); |
1737 | 0 | if (ctf_dynhash_cinsert (fp->ctf_dynsyms, new_sym->st_name, new_sym) < 0) |
1738 | 0 | goto local_oom; |
1739 | | |
1740 | 0 | if (fp->ctf_dynsymmax < new_sym->st_symidx) |
1741 | 0 | fp->ctf_dynsymmax = new_sym->st_symidx; |
1742 | 0 | } |
1743 | | |
1744 | 0 | free (did); |
1745 | 0 | continue; |
1746 | | |
1747 | 0 | local_oom: |
1748 | 0 | free (did); |
1749 | 0 | free (new_sym); |
1750 | 0 | goto err; |
1751 | 0 | } |
1752 | | |
1753 | | /* If no symbols are reported, unwind what we have done and return. This |
1754 | | makes it a bit easier for the serializer to tell that no symbols have been |
1755 | | reported and that it should look elsewhere for reported symbols. */ |
1756 | 0 | if (!ctf_dynhash_elements (fp->ctf_dynsyms)) |
1757 | 0 | { |
1758 | 0 | ctf_dprintf ("No symbols: not a final link.\n"); |
1759 | 0 | ctf_dynhash_destroy (fp->ctf_dynsyms); |
1760 | 0 | fp->ctf_dynsyms = NULL; |
1761 | 0 | return 0; |
1762 | 0 | } |
1763 | | |
1764 | | /* Construct a mapping from shndx to the symbol info. */ |
1765 | 0 | free (fp->ctf_dynsymidx); |
1766 | 0 | if ((fp->ctf_dynsymidx = calloc (fp->ctf_dynsymmax + 1, |
1767 | 0 | sizeof (ctf_link_sym_t *))) == NULL) |
1768 | 0 | goto err; |
1769 | | |
1770 | 0 | while ((err = ctf_dynhash_next (fp->ctf_dynsyms, &i, &name_, &sym_)) == 0) |
1771 | 0 | { |
1772 | 0 | const char *name = (const char *) name; |
1773 | 0 | ctf_link_sym_t *symp = (ctf_link_sym_t *) sym_; |
1774 | |
|
1775 | 0 | if (!ctf_assert (fp, symp->st_symidx <= fp->ctf_dynsymmax)) |
1776 | 0 | { |
1777 | 0 | ctf_next_destroy (i); |
1778 | 0 | err = ctf_errno (fp); |
1779 | 0 | goto err; |
1780 | 0 | } |
1781 | 0 | fp->ctf_dynsymidx[symp->st_symidx] = symp; |
1782 | 0 | } |
1783 | 0 | if (err != ECTF_NEXT_END) |
1784 | 0 | { |
1785 | 0 | ctf_err_warn (fp, 0, err, _("error iterating over shuffled symbols")); |
1786 | 0 | goto err; |
1787 | 0 | } |
1788 | 0 | return 0; |
1789 | | |
1790 | 0 | err: |
1791 | | /* Leave the in-flight symbols around: they'll be freed at |
1792 | | dict close time regardless. */ |
1793 | 0 | ctf_dynhash_destroy (fp->ctf_dynsyms); |
1794 | 0 | fp->ctf_dynsyms = NULL; |
1795 | 0 | free (fp->ctf_dynsymidx); |
1796 | 0 | fp->ctf_dynsymidx = NULL; |
1797 | 0 | fp->ctf_dynsymmax = 0; |
1798 | 0 | ctf_set_errno (fp, err); |
1799 | 0 | return -err; |
1800 | 0 | } |
1801 | | |
1802 | | typedef struct ctf_name_list_accum_cb_arg |
1803 | | { |
1804 | | char **names; |
1805 | | ctf_dict_t *fp; |
1806 | | ctf_dict_t **files; |
1807 | | size_t i; |
1808 | | char **dynames; |
1809 | | size_t ndynames; |
1810 | | } ctf_name_list_accum_cb_arg_t; |
1811 | | |
1812 | | /* Accumulate the names and a count of the names in the link output hash. */ |
1813 | | static void |
1814 | | ctf_accumulate_archive_names (void *key, void *value, void *arg_) |
1815 | 0 | { |
1816 | 0 | const char *name = (const char *) key; |
1817 | 0 | ctf_dict_t *fp = (ctf_dict_t *) value; |
1818 | 0 | char **names; |
1819 | 0 | ctf_dict_t **files; |
1820 | 0 | ctf_name_list_accum_cb_arg_t *arg = (ctf_name_list_accum_cb_arg_t *) arg_; |
1821 | |
|
1822 | 0 | if ((names = realloc (arg->names, sizeof (char *) * ++(arg->i))) == NULL) |
1823 | 0 | { |
1824 | 0 | (arg->i)--; |
1825 | 0 | ctf_set_errno (arg->fp, ENOMEM); |
1826 | 0 | return; |
1827 | 0 | } |
1828 | | |
1829 | 0 | if ((files = realloc (arg->files, sizeof (ctf_dict_t *) * arg->i)) == NULL) |
1830 | 0 | { |
1831 | 0 | (arg->i)--; |
1832 | 0 | ctf_set_errno (arg->fp, ENOMEM); |
1833 | 0 | return; |
1834 | 0 | } |
1835 | | |
1836 | | /* Allow the caller to get in and modify the name at the last minute. If the |
1837 | | caller *does* modify the name, we have to stash away the new name the |
1838 | | caller returned so we can free it later on. (The original name is the key |
1839 | | of the ctf_link_outputs hash and is freed by the dynhash machinery.) */ |
1840 | | |
1841 | 0 | if (fp->ctf_link_memb_name_changer) |
1842 | 0 | { |
1843 | 0 | char **dynames; |
1844 | 0 | char *dyname; |
1845 | 0 | void *nc_arg = fp->ctf_link_memb_name_changer_arg; |
1846 | |
|
1847 | 0 | dyname = fp->ctf_link_memb_name_changer (fp, name, nc_arg); |
1848 | |
|
1849 | 0 | if (dyname != NULL) |
1850 | 0 | { |
1851 | 0 | if ((dynames = realloc (arg->dynames, |
1852 | 0 | sizeof (char *) * ++(arg->ndynames))) == NULL) |
1853 | 0 | { |
1854 | 0 | (arg->ndynames)--; |
1855 | 0 | ctf_set_errno (arg->fp, ENOMEM); |
1856 | 0 | return; |
1857 | 0 | } |
1858 | 0 | arg->dynames = dynames; |
1859 | 0 | name = (const char *) dyname; |
1860 | 0 | } |
1861 | 0 | } |
1862 | | |
1863 | 0 | arg->names = names; |
1864 | 0 | arg->names[(arg->i) - 1] = (char *) name; |
1865 | 0 | arg->files = files; |
1866 | 0 | arg->files[(arg->i) - 1] = fp; |
1867 | 0 | } |
1868 | | |
1869 | | /* Change the name of the parent CTF section, if the name transformer has got to |
1870 | | it. */ |
1871 | | static void |
1872 | | ctf_change_parent_name (void *key _libctf_unused_, void *value, void *arg) |
1873 | 0 | { |
1874 | 0 | ctf_dict_t *fp = (ctf_dict_t *) value; |
1875 | 0 | const char *name = (const char *) arg; |
1876 | |
|
1877 | 0 | ctf_parent_name_set (fp, name); |
1878 | 0 | } |
1879 | | |
1880 | | /* Warn if we may suffer information loss because the CTF input files are too |
1881 | | old. Usually we provide complete backward compatibility, but compiler |
1882 | | changes etc which never hit a release may have a flag in the header that |
1883 | | simply prevents those changes from being used. */ |
1884 | | static void |
1885 | | ctf_link_warn_outdated_inputs (ctf_dict_t *fp) |
1886 | 0 | { |
1887 | 0 | ctf_next_t *i = NULL; |
1888 | 0 | void *name_; |
1889 | 0 | void *input_; |
1890 | 0 | int err; |
1891 | |
|
1892 | 0 | while ((err = ctf_dynhash_next (fp->ctf_link_inputs, &i, &name_, &input_)) == 0) |
1893 | 0 | { |
1894 | 0 | const char *name = (const char *) name_; |
1895 | 0 | ctf_link_input_t *input = (ctf_link_input_t *) input_; |
1896 | 0 | ctf_next_t *j = NULL; |
1897 | 0 | ctf_dict_t *ifp; |
1898 | 0 | int err; |
1899 | | |
1900 | | /* We only care about CTF archives by this point: lazy-opened archives |
1901 | | have always been opened by this point, and short-circuited entries have |
1902 | | a matching corresponding archive member. Entries with NULL clin_arc can |
1903 | | exist, and constitute old entries renamed via a name changer: the |
1904 | | renamed entries exist elsewhere in the list, so we can just skip |
1905 | | those. */ |
1906 | |
|
1907 | 0 | if (!input->clin_arc) |
1908 | 0 | continue; |
1909 | | |
1910 | | /* All entries in the archive will necessarily contain the same |
1911 | | CTF_F_NEWFUNCINFO flag, so we only need to check the first. We don't |
1912 | | even need to do that if we can't open it for any reason at all: the |
1913 | | link will fail later on regardless, since an input can't be opened. */ |
1914 | | |
1915 | 0 | ifp = ctf_archive_next (input->clin_arc, &j, NULL, 0, &err); |
1916 | 0 | if (!ifp) |
1917 | 0 | continue; |
1918 | 0 | ctf_next_destroy (j); |
1919 | |
|
1920 | 0 | if (!(ifp->ctf_header->cth_flags & CTF_F_NEWFUNCINFO) |
1921 | 0 | && (ifp->ctf_header->cth_varoff - ifp->ctf_header->cth_funcoff) > 0) |
1922 | 0 | ctf_err_warn (fp, 1, 0, _("linker input %s has CTF func info but uses " |
1923 | 0 | "an old, unreleased func info format: " |
1924 | 0 | "this func info section will be dropped."), |
1925 | 0 | name); |
1926 | 0 | } |
1927 | 0 | if (err != ECTF_NEXT_END) |
1928 | 0 | ctf_err_warn (fp, 0, err, _("error checking for outdated inputs")); |
1929 | 0 | } |
1930 | | |
1931 | | /* Write out a CTF archive (if there are per-CU CTF files) or a CTF file |
1932 | | (otherwise) into a new dynamically-allocated string, and return it. |
1933 | | Members with sizes above THRESHOLD are compressed. */ |
1934 | | unsigned char * |
1935 | | ctf_link_write (ctf_dict_t *fp, size_t *size, size_t threshold) |
1936 | 0 | { |
1937 | 0 | ctf_name_list_accum_cb_arg_t arg; |
1938 | 0 | char **names; |
1939 | 0 | char *transformed_name = NULL; |
1940 | 0 | ctf_dict_t **files; |
1941 | 0 | FILE *f = NULL; |
1942 | 0 | size_t i; |
1943 | 0 | int err; |
1944 | 0 | long fsize; |
1945 | 0 | const char *errloc; |
1946 | 0 | unsigned char *buf = NULL; |
1947 | |
|
1948 | 0 | memset (&arg, 0, sizeof (ctf_name_list_accum_cb_arg_t)); |
1949 | 0 | arg.fp = fp; |
1950 | 0 | fp->ctf_flags |= LCTF_LINKING; |
1951 | |
|
1952 | 0 | ctf_link_warn_outdated_inputs (fp); |
1953 | |
|
1954 | 0 | if (fp->ctf_link_outputs) |
1955 | 0 | { |
1956 | 0 | ctf_dynhash_iter (fp->ctf_link_outputs, ctf_accumulate_archive_names, &arg); |
1957 | 0 | if (ctf_errno (fp) < 0) |
1958 | 0 | { |
1959 | 0 | errloc = "hash creation"; |
1960 | 0 | goto err; |
1961 | 0 | } |
1962 | 0 | } |
1963 | | |
1964 | | /* No extra outputs? Just write a simple ctf_dict_t. */ |
1965 | 0 | if (arg.i == 0) |
1966 | 0 | { |
1967 | 0 | unsigned char *ret = ctf_write_mem (fp, size, threshold); |
1968 | 0 | fp->ctf_flags &= ~LCTF_LINKING; |
1969 | 0 | return ret; |
1970 | 0 | } |
1971 | | |
1972 | | /* Writing an archive. Stick ourselves (the shared repository, parent of all |
1973 | | other archives) on the front of it with the default name. */ |
1974 | 0 | if ((names = realloc (arg.names, sizeof (char *) * (arg.i + 1))) == NULL) |
1975 | 0 | { |
1976 | 0 | errloc = "name reallocation"; |
1977 | 0 | goto err_no; |
1978 | 0 | } |
1979 | 0 | arg.names = names; |
1980 | 0 | memmove (&(arg.names[1]), arg.names, sizeof (char *) * (arg.i)); |
1981 | |
|
1982 | 0 | arg.names[0] = (char *) _CTF_SECTION; |
1983 | 0 | if (fp->ctf_link_memb_name_changer) |
1984 | 0 | { |
1985 | 0 | void *nc_arg = fp->ctf_link_memb_name_changer_arg; |
1986 | |
|
1987 | 0 | transformed_name = fp->ctf_link_memb_name_changer (fp, _CTF_SECTION, |
1988 | 0 | nc_arg); |
1989 | |
|
1990 | 0 | if (transformed_name != NULL) |
1991 | 0 | { |
1992 | 0 | arg.names[0] = transformed_name; |
1993 | 0 | ctf_dynhash_iter (fp->ctf_link_outputs, ctf_change_parent_name, |
1994 | 0 | transformed_name); |
1995 | 0 | } |
1996 | 0 | } |
1997 | | |
1998 | | /* Propagate the link flags to all the dicts in this link. */ |
1999 | 0 | for (i = 0; i < arg.i; i++) |
2000 | 0 | { |
2001 | 0 | arg.files[i]->ctf_link_flags = fp->ctf_link_flags; |
2002 | 0 | arg.files[i]->ctf_flags |= LCTF_LINKING; |
2003 | 0 | } |
2004 | |
|
2005 | 0 | if ((files = realloc (arg.files, |
2006 | 0 | sizeof (struct ctf_dict *) * (arg.i + 1))) == NULL) |
2007 | 0 | { |
2008 | 0 | errloc = "ctf_dict reallocation"; |
2009 | 0 | goto err_no; |
2010 | 0 | } |
2011 | 0 | arg.files = files; |
2012 | 0 | memmove (&(arg.files[1]), arg.files, sizeof (ctf_dict_t *) * (arg.i)); |
2013 | 0 | arg.files[0] = fp; |
2014 | |
|
2015 | 0 | if ((f = tmpfile ()) == NULL) |
2016 | 0 | { |
2017 | 0 | errloc = "tempfile creation"; |
2018 | 0 | goto err_no; |
2019 | 0 | } |
2020 | | |
2021 | 0 | if ((err = ctf_arc_write_fd (fileno (f), arg.files, arg.i + 1, |
2022 | 0 | (const char **) arg.names, |
2023 | 0 | threshold)) < 0) |
2024 | 0 | { |
2025 | 0 | errloc = "archive writing"; |
2026 | 0 | ctf_set_errno (fp, err); |
2027 | 0 | goto err; |
2028 | 0 | } |
2029 | | |
2030 | 0 | if (fseek (f, 0, SEEK_END) < 0) |
2031 | 0 | { |
2032 | 0 | errloc = "seeking to end"; |
2033 | 0 | goto err_no; |
2034 | 0 | } |
2035 | | |
2036 | 0 | if ((fsize = ftell (f)) < 0) |
2037 | 0 | { |
2038 | 0 | errloc = "filesize determination"; |
2039 | 0 | goto err_no; |
2040 | 0 | } |
2041 | | |
2042 | 0 | if (fseek (f, 0, SEEK_SET) < 0) |
2043 | 0 | { |
2044 | 0 | errloc = "filepos resetting"; |
2045 | 0 | goto err_no; |
2046 | 0 | } |
2047 | | |
2048 | 0 | if ((buf = malloc (fsize)) == NULL) |
2049 | 0 | { |
2050 | 0 | errloc = "CTF archive buffer allocation"; |
2051 | 0 | goto err_no; |
2052 | 0 | } |
2053 | | |
2054 | 0 | while (!feof (f) && fread (buf, fsize, 1, f) == 0) |
2055 | 0 | if (ferror (f)) |
2056 | 0 | { |
2057 | 0 | errloc = "reading archive from temporary file"; |
2058 | 0 | goto err_no; |
2059 | 0 | } |
2060 | | |
2061 | | /* Turn off the is-linking flag on all the dicts in this link: if the strict enum |
2062 | | checking flag is off on the parent, turn it off on all the children too. */ |
2063 | 0 | for (i = 0; i < arg.i; i++) |
2064 | 0 | { |
2065 | 0 | arg.files[i]->ctf_flags &= ~LCTF_LINKING; |
2066 | 0 | if (!(fp->ctf_flags & LCTF_STRICT_NO_DUP_ENUMERATORS)) |
2067 | 0 | arg.files[i]->ctf_flags &= ~LCTF_STRICT_NO_DUP_ENUMERATORS; |
2068 | 0 | } |
2069 | |
|
2070 | 0 | *size = fsize; |
2071 | 0 | free (arg.names); |
2072 | 0 | free (arg.files); |
2073 | 0 | free (transformed_name); |
2074 | 0 | if (arg.ndynames) |
2075 | 0 | { |
2076 | 0 | size_t i; |
2077 | 0 | for (i = 0; i < arg.ndynames; i++) |
2078 | 0 | free (arg.dynames[i]); |
2079 | 0 | free (arg.dynames); |
2080 | 0 | } |
2081 | 0 | fclose (f); |
2082 | 0 | return buf; |
2083 | | |
2084 | 0 | err_no: |
2085 | 0 | ctf_set_errno (fp, errno); |
2086 | | |
2087 | | /* Turn off the is-linking flag on all the dicts in this link, as above. */ |
2088 | 0 | for (i = 0; i < arg.i; i++) |
2089 | 0 | { |
2090 | 0 | arg.files[i]->ctf_flags &= ~LCTF_LINKING; |
2091 | 0 | if (!(fp->ctf_flags & LCTF_STRICT_NO_DUP_ENUMERATORS)) |
2092 | 0 | arg.files[i]->ctf_flags &= ~LCTF_STRICT_NO_DUP_ENUMERATORS; |
2093 | 0 | } |
2094 | 0 | err: |
2095 | 0 | free (buf); |
2096 | 0 | if (f) |
2097 | 0 | fclose (f); |
2098 | 0 | free (arg.names); |
2099 | 0 | free (arg.files); |
2100 | 0 | free (transformed_name); |
2101 | 0 | if (arg.ndynames) |
2102 | 0 | { |
2103 | 0 | size_t i; |
2104 | 0 | for (i = 0; i < arg.ndynames; i++) |
2105 | 0 | free (arg.dynames[i]); |
2106 | 0 | free (arg.dynames); |
2107 | 0 | } |
2108 | 0 | ctf_err_warn (fp, 0, 0, _("cannot write archive in link: %s failure"), |
2109 | 0 | errloc); |
2110 | 0 | return NULL; |
2111 | 0 | } |