• 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

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

Log Message

libctf: add CU-mapping machinery

Once the deduplicator is capable of actually detecting conflicting types
with the same name (i.e., not yet) we will place such conflicting types,
and types that depend on them, into CTF dictionaries that are the child
of the main dictionary we usually emit: currently, this will lead to the
.ctf section becoming a CTF archive rather than a single dictionary,
with the default-named archive member (_CTF_SECTION, or NULL) being the
main shared dictionary with most of the types in it.

By default, the sections are named after the compilation unit they come
from (complete path and all), with the cuname field in the CTF header
providing further evidence of the name without requiring the caller to
engage in tiresome parsing. But some callers may not wish the mapping
from input CU to output sub-dictionary to be purely CU-based.

The machinery here allows this to be freely changed, in two ways:

- callers can call ctf_link_add_cu_mapping to specify that a single
input compilation unit should have its types placed in some other CU
if they conflict: the CU will always be created, even if empty, so
the consuming program can depend on its existence. You can map
multiple input CUs to one output CU to force all their types to be
merged together: if some of *those* types conflict, the behaviour is
currently unspecified (the new deduplicator will specify it).
- callers can call ctf_link_set_memb_name_changer to provide a function
which is passed every CTF sub-dictionary name in turn (including
_CTF_SECTION) and can return a new name, or NULL if no change is
    1. The mapping from input to output names should not map two
      input names to the same output name: if this happens, the two are not
      merged but will result in an archive with two members with the same
      name (technically valid, but it's hard to access the second
      same-named member: you have to do an iteration over archive members).

This is used by the kernel's ctfarchive machinery (not yet upstream) to
encode CTF under member names like {module name}.ctf rather than
.ctf.CU, but it is anticipated that other large projects may wish to
have their own storage for CTF outside of .ctf sections and may wish to
have new naming schemes that suit their special-purpose consumers.

New in v3.
v4: check for strdup failure.

include/
* ctf-api.h (ctf_link_add_cu_mapping): New.
(ctf_link_memb_name_changer_f): New.
(ctf_link_set_memb_name_changer): New.

libctf/
* ctf-impl.h (ctf_file_t) <ctf_link_cu_mappping>: New.
<ctf_link_memb_name_changer>: Likewise.
<ctf_link_memb_name_changer_arg>: Likewise.
* ctf-create.c (ctf_update): Update accordingly.
* ctf-open.c (ctf_file_close): Likewise.
* ctf-link.c (ctf_create_per_cu): Apply the cu mapping.
(ctf_link_add_cu_mapping): New.
(ctf_link_set_memb_name_changer): Likewise.

(ctf_change_parent_name): New.

(ctf_name_list_accum_cb_arg_t) <dynames>: New, storage for names
allocated by the caller's ctf_link_memb_name_changer.
<ndynames>: Likewise.
(ctf_accumulate_archive_names): Call the ctf_link_memb_name_changer.
(ctf_link_write): Likewise (for _CTF_SECTION only): also call

ctf_change_parent_name. Free any resulting names.

更改概述

差异

--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,9 @@
1+2019-07-30 Nick Alcock <nick.alcock@oracle.com>
2+
3+ * ctf-api.h (ctf_link_add_cu_mapping): New.
4+ (ctf_link_memb_name_changer_f): New.
5+ (ctf_link_set_memb_name_changer): New.
6+
17 2019-07-13 Nick Alcock <nick.alcock@oracle.com>
28
39 * ctf-api.h (ECTF_INTERNAL): New.
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -421,6 +421,16 @@ extern int ctf_link_shuffle_syms (ctf_file_t *, ctf_link_iter_symbol_f *,
421421 extern unsigned char *ctf_link_write (ctf_file_t *, size_t *size,
422422 size_t threshold);
423423
424+/* Specialist linker functions. These functions are not used by ld, but can be
425+ used by other prgorams making use of the linker machinery for other purposes
426+ to customize its output. */
427+extern int ctf_link_add_cu_mapping (ctf_file_t *, const char *from,
428+ const char *to);
429+typedef char *ctf_link_memb_name_changer_f (ctf_file_t *,
430+ const char *, void *);
431+extern void ctf_link_set_memb_name_changer
432+ (ctf_file_t *, ctf_link_memb_name_changer_f *, void *);
433+
424434 extern void ctf_setdebug (int debug);
425435 extern int ctf_getdebug (void);
426436
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,3 +1,21 @@
1+2019-07-30 Nick Alcock <nick.alcock@oracle.com>
2+
3+ * ctf-impl.h (ctf_file_t) <ctf_link_cu_mappping>: New.
4+ <ctf_link_memb_name_changer>: Likewise.
5+ <ctf_link_memb_name_changer_arg>: Likewise.
6+ * ctf-create.c (ctf_update): Update accordingly.
7+ * ctf-open.c (ctf_file_close): Likewise.
8+ * ctf-link.c (ctf_create_per_cu): Apply the cu mapping.
9+ (ctf_link_add_cu_mapping): New.
10+ (ctf_link_set_memb_name_changer): Likewise.
11+ (ctf_change_parent_name): New.
12+ (ctf_name_list_accum_cb_arg_t) <dynames>: New, storage for names
13+ allocated by the caller's ctf_link_memb_name_changer.
14+ <ndynames>: Likewise.
15+ (ctf_accumulate_archive_names): Call the ctf_link_memb_name_changer.
16+ (ctf_link_write): Likewise (for _CTF_SECTION only): also call
17+ ctf_change_parent_name. Free any resulting names.
18+
119 2019-07-13 Nick Alcock <nick.alcock@oracle.com>
220
321 * ctf-link.c (ctf_create_per_cu): New, refactored out of...
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -473,7 +473,10 @@ ctf_update (ctf_file_t *fp)
473473 nfp->ctf_link_inputs = fp->ctf_link_inputs;
474474 nfp->ctf_link_outputs = fp->ctf_link_outputs;
475475 nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab;
476+ nfp->ctf_link_cu_mapping = fp->ctf_link_cu_mapping;
476477 nfp->ctf_link_type_mapping = fp->ctf_link_type_mapping;
478+ nfp->ctf_link_memb_name_changer = fp->ctf_link_memb_name_changer;
479+ nfp->ctf_link_memb_name_changer_arg = fp->ctf_link_memb_name_changer_arg;
477480
478481 nfp->ctf_snapshot_lu = fp->ctf_snapshots;
479482
@@ -486,6 +489,7 @@ ctf_update (ctf_file_t *fp)
486489 fp->ctf_link_inputs = NULL;
487490 fp->ctf_link_outputs = NULL;
488491 fp->ctf_syn_ext_strtab = NULL;
492+ fp->ctf_link_cu_mapping = NULL;
489493 fp->ctf_link_type_mapping = NULL;
490494
491495 fp->ctf_dvhash = NULL;
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -281,6 +281,10 @@ struct ctf_file
281281 ctf_dynhash_t *ctf_link_inputs; /* Inputs to this link. */
282282 ctf_dynhash_t *ctf_link_outputs; /* Additional outputs from this link. */
283283 ctf_dynhash_t *ctf_link_type_mapping; /* Map input types to output types. */
284+ ctf_dynhash_t *ctf_link_cu_mapping; /* Map CU names to CTF dict names. */
285+ /* Allow the caller to Change the name of link archive members. */
286+ ctf_link_memb_name_changer_f *ctf_link_memb_name_changer;
287+ void *ctf_link_memb_name_changer_arg; /* Argument for it. */
284288 char *ctf_tmp_typeslice; /* Storage for slicing up type names. */
285289 size_t ctf_tmp_typeslicelen; /* Size of the typeslice. */
286290 void *ctf_specific; /* Data for ctf_get/setspecific(). */
--- a/libctf/ctf-link.c
+++ b/libctf/ctf-link.c
@@ -182,9 +182,26 @@ static ctf_file_t *
182182 ctf_create_per_cu (ctf_file_t *fp, const char *filename, const char *cuname)
183183 {
184184 ctf_file_t *cu_fp;
185+ const char *ctf_name = NULL;
185186 char *dynname = NULL;
186187
187- if ((cu_fp = ctf_dynhash_lookup (fp->ctf_link_outputs, filename)) == NULL)
188+ /* First, check the mapping table and translate the per-CU name we use
189+ accordingly. We check both the input filename and the CU name. Only if
190+ neither are set do we fall back to the input filename as the per-CU
191+ dictionary name. We prefer the filename because this is easier for likely
192+ callers to determine. */
193+
194+ if (fp->ctf_link_cu_mapping)
195+ {
196+ if (((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, filename)) == NULL) &&
197+ ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, cuname)) == NULL))
198+ ctf_name = filename;
199+ }
200+
201+ if (ctf_name == NULL)
202+ ctf_name = filename;
203+
204+ if ((cu_fp = ctf_dynhash_lookup (fp->ctf_link_outputs, ctf_name)) == NULL)
188205 {
189206 int err;
190207
@@ -197,7 +214,7 @@ ctf_create_per_cu (ctf_file_t *fp, const char *filename, const char *cuname)
197214 return NULL;
198215 }
199216
200- if ((dynname = strdup (filename)) == NULL)
217+ if ((dynname = strdup (ctf_name)) == NULL)
201218 goto oom;
202219 if (ctf_dynhash_insert (fp->ctf_link_outputs, dynname, cu_fp) < 0)
203220 goto oom;
@@ -215,6 +232,79 @@ ctf_create_per_cu (ctf_file_t *fp, const char *filename, const char *cuname)
215232 return NULL;
216233 }
217234
235+/* Add a mapping directing that the CU named FROM should have its
236+ conflicting/non-duplicate types (depending on link mode) go into a container
237+ named TO. Many FROMs can share a TO: in this case, the effect on conflicting
238+ types is not yet defined (but in time an auto-renaming algorithm will be
239+ added: ugly, but there is really no right thing one can do in this
240+ situation).
241+
242+ We forcibly add a container named TO in every case, even though it may well
243+ wind up empty, because clients that use this facility usually expect to find
244+ every TO container present, even if empty, and malfunction otherwise. */
245+
246+int
247+ctf_link_add_cu_mapping (ctf_file_t *fp, const char *from, const char *to)
248+{
249+ int err;
250+ char *f, *t;
251+
252+ if (fp->ctf_link_cu_mapping == NULL)
253+ fp->ctf_link_cu_mapping = ctf_dynhash_create (ctf_hash_string,
254+ ctf_hash_eq_string, free,
255+ free);
256+ if (fp->ctf_link_cu_mapping == NULL)
257+ return ctf_set_errno (fp, ENOMEM);
258+
259+ if (fp->ctf_link_outputs == NULL)
260+ fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
261+ ctf_hash_eq_string, free,
262+ ctf_file_close_thunk);
263+
264+ if (fp->ctf_link_outputs == NULL)
265+ return ctf_set_errno (fp, ENOMEM);
266+
267+ f = strdup (from);
268+ t = strdup (to);
269+ if (!f || !t)
270+ goto oom;
271+
272+ if (ctf_create_per_cu (fp, t, t) == NULL)
273+ goto oom_noerrno; /* Errno is set for us. */
274+
275+ err = ctf_dynhash_insert (fp->ctf_link_cu_mapping, f, t);
276+ if (err)
277+ {
278+ ctf_set_errno (fp, err);
279+ goto oom_noerrno;
280+ }
281+
282+ return 0;
283+
284+ oom:
285+ ctf_set_errno (fp, errno);
286+ oom_noerrno:
287+ free (f);
288+ free (t);
289+ return -1;
290+}
291+
292+/* Set a function which is called to transform the names of archive members.
293+ This is useful for applying regular transformations to many names, where
294+ ctf_link_add_cu_mapping applies arbitrarily irregular changes to single
295+ names. The member name changer is applied at ctf_link_write time, so it
296+ cannot conflate multiple CUs into one the way ctf_link_add_cu_mapping can.
297+ The changer function accepts a name and should return a new
298+ dynamically-allocated name, or NULL if the name should be left unchanged. */
299+void
300+ctf_link_set_memb_name_changer (ctf_file_t *fp,
301+ ctf_link_memb_name_changer_f *changer,
302+ void *arg)
303+{
304+ fp->ctf_link_memb_name_changer = changer;
305+ fp->ctf_link_memb_name_changer_arg = arg;
306+}
307+
218308 typedef struct ctf_link_in_member_cb_arg
219309 {
220310 ctf_file_t *out_fp;
@@ -228,7 +318,6 @@ typedef struct ctf_link_in_member_cb_arg
228318 int in_input_cu_file;
229319 } ctf_link_in_member_cb_arg_t;
230320
231-
232321 /* Link one type into the link. We rely on ctf_add_type() to detect
233322 duplicates. This is not terribly reliable yet (unnmamed types will be
234323 mindlessly duplicated), but will improve shortly. */
@@ -267,7 +356,7 @@ ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_)
267356 ctf_set_errno (arg->out_fp, 0);
268357 }
269358
270- if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->arcname,
359+ if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->file_name,
271360 arg->cu_name)) == NULL)
272361 return -1; /* Errno is set for us. */
273362
@@ -348,7 +437,7 @@ ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
348437 type only present in the child. Try adding to the child, creating if need
349438 be. */
350439
351- if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->arcname,
440+ if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->file_name,
352441 arg->cu_name)) == NULL)
353442 return -1; /* Errno is set for us. */
354443
@@ -590,6 +679,8 @@ typedef struct ctf_name_list_accum_cb_arg
590679 ctf_file_t *fp;
591680 ctf_file_t **files;
592681 size_t i;
682+ char **dynames;
683+ size_t ndynames;
593684 } ctf_name_list_accum_cb_arg_t;
594685
595686 /* Accumulate the names and a count of the names in the link output hash,
@@ -623,12 +714,51 @@ ctf_accumulate_archive_names (void *key, void *value, void *arg_)
623714 ctf_set_errno (arg->fp, ENOMEM);
624715 return;
625716 }
717+
718+ /* Allow the caller to get in and modify the name at the last minute. If the
719+ caller *does* modify the name, we have to stash away the new name the
720+ caller returned so we can free it later on. (The original name is the key
721+ of the ctf_link_outputs hash and is freed by the dynhash machinery.) */
722+
723+ if (fp->ctf_link_memb_name_changer)
724+ {
725+ char **dynames;
726+ char *dyname;
727+ void *nc_arg = fp->ctf_link_memb_name_changer_arg;
728+
729+ dyname = fp->ctf_link_memb_name_changer (fp, name, nc_arg);
730+
731+ if (dyname != NULL)
732+ {
733+ if ((dynames = realloc (arg->dynames,
734+ sizeof (char *) * ++(arg->ndynames))) == NULL)
735+ {
736+ (arg->ndynames)--;
737+ ctf_set_errno (arg->fp, ENOMEM);
738+ return;
739+ }
740+ arg->dynames = dynames;
741+ name = (const char *) dyname;
742+ }
743+ }
744+
626745 arg->names = names;
627746 arg->names[(arg->i) - 1] = (char *) name;
628747 arg->files = files;
629748 arg->files[(arg->i) - 1] = fp;
630749 }
631750
751+/* Change the name of the parent CTF section, if the name transformer has got to
752+ it. */
753+static void
754+ctf_change_parent_name (void *key _libctf_unused_, void *value, void *arg)
755+{
756+ ctf_file_t *fp = (ctf_file_t *) value;
757+ const char *name = (const char *) arg;
758+
759+ ctf_parent_name_set (fp, name);
760+}
761+
632762 /* Write out a CTF archive (if there are per-CU CTF files) or a CTF file
633763 (otherwise) into a new dynamically-allocated string, and return it.
634764 Members with sizes above THRESHOLD are compressed. */
@@ -637,6 +767,7 @@ ctf_link_write (ctf_file_t *fp, size_t *size, size_t threshold)
637767 {
638768 ctf_name_list_accum_cb_arg_t arg;
639769 char **names;
770+ char *transformed_name = NULL;
640771 ctf_file_t **files;
641772 FILE *f = NULL;
642773 int err;
@@ -676,7 +807,22 @@ ctf_link_write (ctf_file_t *fp, size_t *size, size_t threshold)
676807 }
677808 arg.names = names;
678809 memmove (&(arg.names[1]), arg.names, sizeof (char *) * (arg.i));
810+
679811 arg.names[0] = (char *) _CTF_SECTION;
812+ if (fp->ctf_link_memb_name_changer)
813+ {
814+ void *nc_arg = fp->ctf_link_memb_name_changer_arg;
815+
816+ transformed_name = fp->ctf_link_memb_name_changer (fp, _CTF_SECTION,
817+ nc_arg);
818+
819+ if (transformed_name != NULL)
820+ {
821+ arg.names[0] = transformed_name;
822+ ctf_dynhash_iter (fp->ctf_link_outputs, ctf_change_parent_name,
823+ transformed_name);
824+ }
825+ }
680826
681827 if ((files = realloc (arg.files,
682828 sizeof (struct ctf_file *) * (arg.i + 1))) == NULL)
@@ -737,6 +883,14 @@ ctf_link_write (ctf_file_t *fp, size_t *size, size_t threshold)
737883 *size = fsize;
738884 free (arg.names);
739885 free (arg.files);
886+ free (transformed_name);
887+ if (arg.ndynames)
888+ {
889+ size_t i;
890+ for (i = 0; i < arg.ndynames; i++)
891+ free (arg.dynames[i]);
892+ free (arg.dynames);
893+ }
740894 return buf;
741895
742896 err_no:
@@ -747,6 +901,14 @@ ctf_link_write (ctf_file_t *fp, size_t *size, size_t threshold)
747901 fclose (f);
748902 free (arg.names);
749903 free (arg.files);
904+ free (transformed_name);
905+ if (arg.ndynames)
906+ {
907+ size_t i;
908+ for (i = 0; i < arg.ndynames; i++)
909+ free (arg.dynames[i]);
910+ free (arg.dynames);
911+ }
750912 ctf_dprintf ("Cannot write archive in link: %s failure: %s\n", errloc,
751913 ctf_errmsg (ctf_errno (fp)));
752914 return NULL;
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -1629,6 +1629,7 @@ ctf_file_close (ctf_file_t *fp)
16291629 ctf_dynhash_destroy (fp->ctf_link_inputs);
16301630 ctf_dynhash_destroy (fp->ctf_link_outputs);
16311631 ctf_dynhash_destroy (fp->ctf_link_type_mapping);
1632+ ctf_dynhash_destroy (fp->ctf_link_cu_mapping);
16321633
16331634 ctf_free (fp->ctf_sxlate);
16341635 ctf_free (fp->ctf_txlate);