• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

修订版ec0179e0bd11dcbd0d7d2f55ec0ca3daa94c5616 (tree)
时间2019-09-23 22:12:54
作者Nick Alcock <nick.alcock@orac...>
CommiterNick Alcock

Log Message

libctf: add linking of the variable section

The compiler describes the name and type of all file-scope variables in
this section. Merging it at link time requires using the type mapping
added in the previous commit to determine the appropriate type for the
variable in the output, given its type in the input: we check the shared
container first, and if the type doesn't exist there, it must be a
conflicted type in the per-CU child, and the variable should go there
too. We also put the variable in the per-CU child if a variable with
the same name but a different type already exists in the parent: we
ignore any such conflict in the child because CTF cannot represent such
things, nor can they happen unless a third-party linking program has
overridden the mapping of CU to CTF archive member name (using machinery
added in a later commit).

v3: rewritten using an algorithm that actually works in the case of

conflicting names. Some code motion from the next commit. Set
the per-CU parent name.

v4: check for strdup failure.

include/
* ctf-api.h (ECTF_INTERNAL): New.

libctf/
* ctf-link.c (ctf_create_per_cu): New, refactored out of...
(ctf_link_one_type): ... here, with parent-name setting added.
(check_variable): New.
(ctf_link_one_variable): Likewise.
(ctf_link_one_input_archive_member): Call it.
* ctf-error.c (_ctf_errlist): Updated with new errors.

更改概述

差异

--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,5 +1,9 @@
11 2019-07-13 Nick Alcock <nick.alcock@oracle.com>
22
3+ * ctf-api.h (ECTF_INTERNAL): New.
4+
5+2019-07-13 Nick Alcock <nick.alcock@oracle.com>
6+
37 * ctf-api.h (struct ctf_link_sym): New, a symbol in flight to the
48 libctf linking machinery.
59 (CTF_LINK_SHARE_UNCONFLICTED): New.
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -203,7 +203,8 @@ enum
203203 ECTF_SLICEOVERFLOW, /* Overflow of type bitness or offset in slice. */
204204 ECTF_DUMPSECTUNKNOWN, /* Unknown section number in dump. */
205205 ECTF_DUMPSECTCHANGED, /* Section changed in middle of dump. */
206- ECTF_NOTYET /* Feature not yet implemented. */
206+ ECTF_NOTYET, /* Feature not yet implemented. */
207+ ECTF_INTERNAL /* Internal error in link. */
207208 };
208209
209210 /* The CTF data model is inferred to be the caller's data model or the data
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,5 +1,14 @@
11 2019-07-13 Nick Alcock <nick.alcock@oracle.com>
22
3+ * ctf-link.c (ctf_create_per_cu): New, refactored out of...
4+ (ctf_link_one_type): ... here, with parent-name setting added.
5+ (check_variable): New.
6+ (ctf_link_one_variable): Likewise.
7+ (ctf_link_one_input_archive_member): Call it.
8+ * ctf-error.c (_ctf_errlist): Updated with new errors.
9+
10+2019-07-13 Nick Alcock <nick.alcock@oracle.com>
11+
312 * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping.
413 (struct ctf_link_type_mapping_key): New.
514 (ctf_hash_type_mapping_key): Likewise.
--- a/libctf/ctf-error.c
+++ b/libctf/ctf-error.c
@@ -69,7 +69,8 @@ static const char *const _ctf_errlist[] = {
6969 "Overflow of type bitness or offset in slice", /* ECTF_SLICEOVERFLOW */
7070 "Unknown section number in dump", /* ECTF_DUMPSECTUNKNOWN */
7171 "Section changed in middle of dump", /* ECTF_DUMPSECTCHANGED */
72- "Feature not yet implemented" /* ECTF_NOTYET */
72+ "Feature not yet implemented", /* ECTF_NOTYET */
73+ "Internal error in link" /* ECTF_INTERNAL */
7374 };
7475
7576 static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]);
--- a/libctf/ctf-link.c
+++ b/libctf/ctf-link.c
@@ -175,6 +175,46 @@ ctf_link_add_ctf (ctf_file_t *fp, ctf_archive_t *ctf, const char *name)
175175 return (ctf_set_errno (fp, ENOMEM));
176176 }
177177
178+/* Return a per-CU output CTF dictionary suitable for the given CU, creating and
179+ interning it if need be. */
180+
181+static ctf_file_t *
182+ctf_create_per_cu (ctf_file_t *fp, const char *filename, const char *cuname)
183+{
184+ ctf_file_t *cu_fp;
185+ char *dynname = NULL;
186+
187+ if ((cu_fp = ctf_dynhash_lookup (fp->ctf_link_outputs, filename)) == NULL)
188+ {
189+ int err;
190+
191+ if ((cu_fp = ctf_create (&err)) == NULL)
192+ {
193+ ctf_dprintf ("Cannot create per-CU CTF archive for CU %s from "
194+ "input file %s: %s\n", cuname, filename,
195+ ctf_errmsg (err));
196+ ctf_set_errno (fp, err);
197+ return NULL;
198+ }
199+
200+ if ((dynname = strdup (filename)) == NULL)
201+ goto oom;
202+ if (ctf_dynhash_insert (fp->ctf_link_outputs, dynname, cu_fp) < 0)
203+ goto oom;
204+
205+ ctf_import (cu_fp, fp);
206+ ctf_cuname_set (cu_fp, cuname);
207+ ctf_parent_name_set (cu_fp, _CTF_SECTION);
208+ }
209+ return cu_fp;
210+
211+ oom:
212+ free (dynname);
213+ ctf_file_close (cu_fp);
214+ ctf_set_errno (fp, ENOMEM);
215+ return NULL;
216+}
217+
178218 typedef struct ctf_link_in_member_cb_arg
179219 {
180220 ctf_file_t *out_fp;
@@ -227,29 +267,9 @@ ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_)
227267 ctf_set_errno (arg->out_fp, 0);
228268 }
229269
230- if ((per_cu_out_fp = ctf_dynhash_lookup (arg->out_fp->ctf_link_outputs,
231- arg->arcname)) == NULL)
232- {
233- int err;
234-
235- if ((per_cu_out_fp = ctf_create (&err)) == NULL)
236- {
237- ctf_dprintf ("Cannot create per-CU CTF archive for member %s: %s\n",
238- arg->arcname, ctf_errmsg (err));
239- ctf_set_errno (arg->out_fp, err);
240- return -1;
241- }
242-
243- if (ctf_dynhash_insert (arg->out_fp->ctf_link_outputs, arg->arcname,
244- per_cu_out_fp) < 0)
245- {
246- ctf_set_errno (arg->out_fp, ENOMEM);
247- return -1;
248- }
249-
250- ctf_import (per_cu_out_fp, arg->out_fp);
251- ctf_cuname_set (per_cu_out_fp, arg->cu_name);
252- }
270+ if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->arcname,
271+ arg->cu_name)) == NULL)
272+ return -1; /* Errno is set for us. */
253273
254274 if (ctf_add_type (per_cu_out_fp, arg->in_fp, type) != CTF_ERR)
255275 return 0;
@@ -264,6 +284,95 @@ ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_)
264284 return 0; /* As above: do not lose types. */
265285 }
266286
287+/* Check if we can safely add a variable with the given type to this container. */
288+
289+static int
290+check_variable (const char *name, ctf_file_t *fp, ctf_id_t type,
291+ ctf_dvdef_t **out_dvd)
292+{
293+ ctf_dvdef_t *dvd;
294+
295+ dvd = ctf_dynhash_lookup (fp->ctf_dvhash, name);
296+ *out_dvd = dvd;
297+ if (!dvd)
298+ return 1;
299+
300+ if (dvd->dvd_type != type)
301+ {
302+ /* Variable here. Wrong type: cannot add. Just skip it, because there is
303+ no way to express this in CTF. (This might be the parent, in which
304+ case we'll try adding in the child first, and only then give up.) */
305+ ctf_dprintf ("Inexpressible duplicate variable %s skipped.\n", name);
306+ }
307+
308+ return 0; /* Already exists. */
309+}
310+
311+/* Link one variable in. */
312+
313+static int
314+ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
315+{
316+ ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
317+ ctf_file_t *per_cu_out_fp;
318+ ctf_id_t dst_type = 0;
319+ ctf_file_t *check_fp;
320+ ctf_dvdef_t *dvd;
321+
322+ /* In unconflicted link mode, if this type is mapped to a type in the parent
323+ container, we want to try to add to that first: if it reports a duplicate,
324+ or if the type is in a child already, add straight to the child. */
325+
326+ check_fp = arg->out_fp;
327+
328+ dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
329+ if (dst_type != 0)
330+ {
331+ if (check_fp == arg->out_fp)
332+ {
333+ if (check_variable (name, check_fp, dst_type, &dvd))
334+ {
335+ /* No variable here: we can add it. */
336+ if (ctf_add_variable (check_fp, name, dst_type) < 0)
337+ return (ctf_set_errno (arg->out_fp, ctf_errno (check_fp)));
338+ return 0;
339+ }
340+
341+ /* Already present? Nothing to do. */
342+ if (dvd && dvd->dvd_type == type)
343+ return 0;
344+ }
345+ }
346+
347+ /* Can't add to the parent due to a name clash, or because it references a
348+ type only present in the child. Try adding to the child, creating if need
349+ be. */
350+
351+ if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->arcname,
352+ arg->cu_name)) == NULL)
353+ return -1; /* Errno is set for us. */
354+
355+ /* If the type was not found, check for it in the child too. */
356+ if (dst_type == 0)
357+ {
358+ check_fp = per_cu_out_fp;
359+ dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
360+
361+ if (dst_type == 0)
362+ {
363+ ctf_dprintf ("Type %lx for variable %s in input file %s not "
364+ "found: skipped.\n", type, name, arg->file_name);
365+ /* Do not terminate the link: just skip the variable. */
366+ return 0;
367+ }
368+ }
369+
370+ if (check_variable (name, per_cu_out_fp, dst_type, &dvd))
371+ if (ctf_add_variable (per_cu_out_fp, name, dst_type) < 0)
372+ return (ctf_set_errno (arg->out_fp, ctf_errno (per_cu_out_fp)));
373+ return 0;
374+}
375+
267376 /* Merge every type and variable in this archive member into the link, so we can
268377 relink things that have already had ld run on them. We use the archive
269378 member name, sans any leading '.ctf.', as the CU name for ambiguous types if
@@ -317,7 +426,8 @@ ctf_link_one_input_archive_member (ctf_file_t *in_fp, const char *name, void *ar
317426 arg->cu_name += strlen (".ctf.");
318427 arg->in_fp = in_fp;
319428
320- err = ctf_type_iter_all (in_fp, ctf_link_one_type, arg);
429+ if ((err = ctf_type_iter_all (in_fp, ctf_link_one_type, arg)) > -1)
430+ err = ctf_variable_iter (in_fp, ctf_link_one_variable, arg);
321431
322432 arg->in_input_cu_file = 0;
323433 free (arg->arcname);