public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Nick Alcock <nick.alcock@oracle.com>
To: binutils@sourceware.org
Subject: [PATCH 45/59] libctf, link: redo cu-mapping handling
Date: Wed,  1 Jul 2020 00:31:32 +0100	[thread overview]
Message-ID: <20200630233146.338613-46-nick.alcock@oracle.com> (raw)
In-Reply-To: <20200630233146.338613-1-nick.alcock@oracle.com>

Now a bunch of stuff that doesn't apply to ld or any normal use of
libctf, piled into one commit so that it's easier to ignore.

The cu-mapping machinery associates incoming compilation unit names with
outgoing names of CTF dictionaries that should correspond to them, for
non-gdb CTF consumers that would like to group multiple TUs into a
single child dict if conflicting types are found in it (the existing use
case is one kernel module, one child CTF dict, even if the kernel module
is composed of multiple CUs).

The upcoming deduplicator needs to track not only the mapping from
incoming CU name to outgoing dict name, but the inverse mapping from
outgoing dict name to incoming CU name, so it can work over every CTF
dict we might see in the output and link into it.

So rejig the ctf-link machinery to do that.  Simultaneously (because
they are closely associated and were written at the same time), we add a
new CTF_LINK_EMPTY_CU_MAPPINGS flag to ctf_link, which tells the
ctf_link machinery to create empty child dicts for each outgoing CU
mapping even if no CUs that correspond to it exist in the link.  This is
a bit (OK, quite a lot) of a waste of space, but some existing consumers
require it.  (Nobody else should use it.)

Its value is not consecutive with existing CTF_LINK flag values because
we're about to add more flags that are conceptually closer to the
existing ones than this one is.

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

libctf/
	* ctf-impl.h (ctf_file_t): Improve comments.
	<ctf_link_cu_mapping>: Split into...
	<ctf_link_in_cu_mapping>: ... this...
	<ctf_link_out_cu_mapping>: ... and this.
	* ctf-create.c (ctf_serialize): Adjust.
	* ctf-open.c (ctf_file_close): Likewise.
	* ctf-link.c (ctf_create_per_cu): Look things up in the
	in_cu_mapping instead of the cu_mapping.
	(ctf_link_add_cu_mapping): The deduplicating link will define
	what happens if many FROMs share a TO.
	(ctf_link_add_cu_mapping): Create in_cu_mapping and
	out_cu_mapping. Do not create ctf_link_outputs here any more, or
	create per-CU dicts here: they are already created when needed.
	(ctf_link_one_variable): Log a debug message if we skip a
	variable due to its type being concealed in a CU-mapped link.
	(This is probably too common a case to make into a warning.)
	(ctf_link): Create empty per-CU dicts if requested.
---
 include/ctf-api.h   |   6 ++-
 libctf/ctf-create.c |   6 ++-
 libctf/ctf-impl.h   |  21 +++++++--
 libctf/ctf-link.c   | 107 +++++++++++++++++++++++++++++++++-----------
 libctf/ctf-open.c   |   3 +-
 5 files changed, 111 insertions(+), 32 deletions(-)

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 7d3e1c8bfcd..700a2b1ef5d 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -78,7 +78,7 @@ typedef struct ctf_link_sym
   uint32_t st_value;
 } ctf_link_sym_t;
 
-/* Indication of how to share types when linking.  */
+/* Flags applying to this specific link.  */
 
 /* Share all types that are not in conflict.  The default.  */
 #define CTF_LINK_SHARE_UNCONFLICTED 0x0
@@ -86,6 +86,10 @@ typedef struct ctf_link_sym
 /* Share only types that are used by multiple inputs.  Not implemented yet.  */
 #define CTF_LINK_SHARE_DUPLICATED 0x1
 
+/* Create empty outputs for all registered CU mappings even if no types are
+   emitted into them.  */
+#define CTF_LINK_EMPTY_CU_MAPPINGS 0x4
+
 /* Symbolic names for CTF sections.  */
 
 typedef enum ctf_sect_names
diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 85fd060262e..10c6bbf552e 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -538,7 +538,8 @@ ctf_serialize (ctf_file_t *fp)
   nfp->ctf_errs_warnings = fp->ctf_errs_warnings;
   nfp->ctf_str_prov_offset = fp->ctf_str_prov_offset;
   nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab;
-  nfp->ctf_link_cu_mapping = fp->ctf_link_cu_mapping;
+  nfp->ctf_link_in_cu_mapping = fp->ctf_link_in_cu_mapping;
+  nfp->ctf_link_out_cu_mapping = fp->ctf_link_out_cu_mapping;
   nfp->ctf_link_type_mapping = fp->ctf_link_type_mapping;
   nfp->ctf_link_memb_name_changer = fp->ctf_link_memb_name_changer;
   nfp->ctf_link_memb_name_changer_arg = fp->ctf_link_memb_name_changer_arg;
@@ -565,7 +566,8 @@ ctf_serialize (ctf_file_t *fp)
   fp->ctf_link_inputs = NULL;
   fp->ctf_link_outputs = NULL;
   fp->ctf_syn_ext_strtab = NULL;
-  fp->ctf_link_cu_mapping = NULL;
+  fp->ctf_link_in_cu_mapping = NULL;
+  fp->ctf_link_out_cu_mapping = NULL;
   fp->ctf_link_type_mapping = NULL;
   fp->ctf_parent_unreffed = 1;
 
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index cb7de23dbbb..46bceb49861 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -311,12 +311,27 @@ struct ctf_file
   ctf_list_t ctf_errs_warnings;	  /* CTF errors and warnings.  */
   ctf_dynhash_t *ctf_link_inputs; /* Inputs to this link.  */
   ctf_dynhash_t *ctf_link_outputs; /* Additional outputs from this link.  */
-  ctf_dynhash_t *ctf_link_type_mapping; /* Map input types to output types.  */
-  ctf_dynhash_t *ctf_link_cu_mapping;	/* Map CU names to CTF dict names.  */
-  /* Allow the caller to Change the name of link archive members.  */
+
+  /* Map input types to output types: populated in each output dict.
+     Key is a ctf_link_type_key_t: value is a type ID.  Used by
+     nondeduplicating links and ad-hoc ctf_add_type calls only.  */
+  ctf_dynhash_t *ctf_link_type_mapping;
+
+  /* Map input CU names to output CTF dict names: populated in the top-level
+     output dict.
+
+     Key and value are dynamically-allocated strings.  */
+  ctf_dynhash_t *ctf_link_in_cu_mapping;
+
+  /* Map output CTF dict names to input CU names: populated in the top-level
+     output dict.  A hash of string to hash (set) of strings.  Key and
+     individual value members are shared with ctf_link_in_cu_mapping.  */
+  ctf_dynhash_t *ctf_link_out_cu_mapping;
+
   /* CTF linker flags.  */
   int ctf_link_flags;
 
+  /* Allow the caller to change the name of link archive members.  */
   ctf_link_memb_name_changer_f *ctf_link_memb_name_changer;
   void *ctf_link_memb_name_changer_arg; /* Argument for it.  */
   ctf_dynhash_t *ctf_add_processing; /* Types ctf_add_type is working on now.  */
diff --git a/libctf/ctf-link.c b/libctf/ctf-link.c
index fa15c9bf9bb..3c96604b36a 100644
--- a/libctf/ctf-link.c
+++ b/libctf/ctf-link.c
@@ -296,10 +296,12 @@ ctf_create_per_cu (ctf_file_t *fp, const char *filename, const char *cuname)
      dictionary name.  We prefer the filename because this is easier for likely
      callers to determine.  */
 
-  if (fp->ctf_link_cu_mapping)
+  if (fp->ctf_link_in_cu_mapping)
     {
-      if (((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, filename)) == NULL) &&
-	  ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, cuname)) == NULL))
+      if (((ctf_name = ctf_dynhash_lookup (fp->ctf_link_in_cu_mapping,
+					   filename)) == NULL) &&
+	  ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_in_cu_mapping,
+					   cuname)) == NULL))
 	ctf_name = filename;
     }
 
@@ -339,10 +341,7 @@ ctf_create_per_cu (ctf_file_t *fp, const char *filename, const char *cuname)
 
 /* Add a mapping directing that the CU named FROM should have its
    conflicting/non-duplicate types (depending on link mode) go into a container
-   named TO.  Many FROMs can share a TO: in this case, the effect on conflicting
-   types is not yet defined (but in time an auto-renaming algorithm will be
-   added: ugly, but there is really no right thing one can do in this
-   situation).
+   named TO.  Many FROMs can share a TO.
 
    We forcibly add a container named TO in every case, even though it may well
    wind up empty, because clients that use this facility usually expect to find
@@ -352,34 +351,63 @@ int
 ctf_link_add_cu_mapping (ctf_file_t *fp, const char *from, const char *to)
 {
   int err;
-  char *f, *t;
+  char *f = NULL, *t = NULL;
+  ctf_dynhash_t *one_out;
+
+  if (fp->ctf_link_in_cu_mapping == NULL)
+    fp->ctf_link_in_cu_mapping = ctf_dynhash_create (ctf_hash_string,
+						     ctf_hash_eq_string, free,
+						     free);
+  if (fp->ctf_link_in_cu_mapping == NULL)
+    goto oom;
 
-  if (fp->ctf_link_cu_mapping == NULL)
-    fp->ctf_link_cu_mapping = ctf_dynhash_create (ctf_hash_string,
-						  ctf_hash_eq_string, free,
-						  free);
-  if (fp->ctf_link_cu_mapping == NULL)
-    return ctf_set_errno (fp, ENOMEM);
+  if (fp->ctf_link_out_cu_mapping == NULL)
+    fp->ctf_link_out_cu_mapping = ctf_dynhash_create (ctf_hash_string,
+						      ctf_hash_eq_string, free,
+						      (ctf_hash_free_fun)
+						      ctf_dynhash_destroy);
+  if (fp->ctf_link_out_cu_mapping == NULL)
+    goto oom;
 
-  if (fp->ctf_link_outputs == NULL)
-    fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
-					       ctf_hash_eq_string, free,
-					       (ctf_hash_free_fun)
-					       ctf_file_close);
+  f = strdup (from);
+  t = strdup (to);
+  if (!f || !t)
+    goto oom;
 
-  if (fp->ctf_link_outputs == NULL)
-    return ctf_set_errno (fp, ENOMEM);
+  /* Track both in a list from FROM to TO and in a list from TO to a list of
+     FROM.  The former is used to create TUs with the mapped-to name at need:
+     the latter is used in deduplicating links to pull in all input CUs
+     corresponding to a single output CU.  */
+
+  if ((err = ctf_dynhash_insert (fp->ctf_link_in_cu_mapping, f, t)) < 0)
+    {
+      ctf_set_errno (fp, err);
+      goto oom_noerrno;
+    }
 
+  /* f and t are now owned by the in_cu_mapping: reallocate them.  */
   f = strdup (from);
   t = strdup (to);
   if (!f || !t)
     goto oom;
 
-  if (ctf_create_per_cu (fp, t, t) == NULL)
-    goto oom_noerrno;				/* Errno is set for us.  */
+  if ((one_out = ctf_dynhash_lookup (fp->ctf_link_out_cu_mapping, t)) == NULL)
+    {
+      if ((one_out = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
+					 free, NULL)) == NULL)
+	goto oom;
+      if ((err = ctf_dynhash_insert (fp->ctf_link_out_cu_mapping,
+				     t, one_out)) < 0)
+	{
+	  ctf_dynhash_destroy (one_out);
+	  ctf_set_errno (fp, err);
+	  goto oom_noerrno;
+	}
+    }
+  else
+    free (t);
 
-  err = ctf_dynhash_insert (fp->ctf_link_cu_mapping, f, t);
-  if (err)
+  if (ctf_dynhash_insert (one_out, f, NULL) < 0)
     {
       ctf_set_errno (fp, err);
       goto oom_noerrno;
@@ -777,6 +805,8 @@ int
 ctf_link (ctf_file_t *fp, int flags)
 {
   ctf_link_in_member_cb_arg_t arg;
+  ctf_next_t *i = NULL;
+  int err;
 
   memset (&arg, 0, sizeof (struct ctf_link_in_member_cb_arg));
   arg.out_fp = fp;
@@ -794,6 +824,33 @@ ctf_link (ctf_file_t *fp, int flags)
   if (fp->ctf_link_outputs == NULL)
     return ctf_set_errno (fp, ENOMEM);
 
+  /* Create empty CUs if requested.  We do not currently claim that multiple
+     links in succession with CTF_LINK_EMPTY_CU_MAPPINGS set in some calls and
+     not set in others will do anything especially sensible.  */
+
+  if (fp->ctf_link_out_cu_mapping && (flags & CTF_LINK_EMPTY_CU_MAPPINGS))
+    {
+      void *v;
+
+      while ((err = ctf_dynhash_next (fp->ctf_link_out_cu_mapping, &i, &v,
+				      NULL)) == 0)
+	{
+	  const char *to = (const char *) v;
+	  if (ctf_create_per_cu (fp, to, to) == NULL)
+	    {
+	      ctf_next_destroy (i);
+	      return -1;			/* Errno is set for us.  */
+	    }
+	}
+      if (err != ECTF_NEXT_END)
+	{
+	  ctf_err_warn (fp, 1, "Iteration error creating empty CUs: %s",
+			ctf_errmsg (err));
+	  ctf_set_errno (fp, err);
+	  return -1;
+	}
+    }
+
   ctf_dynhash_iter (fp->ctf_link_inputs, ctf_link_one_input_archive,
 		    &arg);
 
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
index 87bff2f122d..285e0e0ff71 100644
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -1716,7 +1716,8 @@ ctf_file_close (ctf_file_t *fp)
   ctf_dynhash_destroy (fp->ctf_link_inputs);
   ctf_dynhash_destroy (fp->ctf_link_outputs);
   ctf_dynhash_destroy (fp->ctf_link_type_mapping);
-  ctf_dynhash_destroy (fp->ctf_link_cu_mapping);
+  ctf_dynhash_destroy (fp->ctf_link_in_cu_mapping);
+  ctf_dynhash_destroy (fp->ctf_link_out_cu_mapping);
   ctf_dynhash_destroy (fp->ctf_add_processing);
 
   for (err = ctf_list_next (&fp->ctf_errs_warnings); err != NULL; err = nerr)
-- 
2.27.0.247.g3dff7de930


  parent reply	other threads:[~2020-06-30 23:32 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-30 23:30 [PATCH 00/59] Deduplicating CTF linker Nick Alcock
2020-06-30 23:30 ` [PATCH 01/59] include, libctf: typo fixes Nick Alcock
2020-06-30 23:30 ` [PATCH 02/59] libctf: restructure error handling to reduce relocations Nick Alcock
2020-07-22  9:31   ` [PATCH 02/59] fixup! " Nick Alcock
2020-06-30 23:30 ` [PATCH 03/59] libctf, create: support addition of references to the unimplemented type Nick Alcock
2020-06-30 23:30 ` [PATCH 04/59] libctf, create: do not corrupt function types' arglists at insertion time Nick Alcock
2020-06-30 23:30 ` [PATCH 05/59] libctf, create: add explicit casts for variables' and slices' types Nick Alcock
2020-06-30 23:30 ` [PATCH 06/59] libctf, types: allow ctf_type_reference of dynamic slices Nick Alcock
2020-06-30 23:30 ` [PATCH 07/59] libctf, open: drop unnecessary historical wart around forwards Nick Alcock
2020-06-30 23:30 ` [PATCH 08/59] libctf, create: member names of "" and NULL should be the same Nick Alcock
2020-06-30 23:30 ` [PATCH 09/59] libctf, create: fix addition of anonymous struct/union members Nick Alcock
2020-06-30 23:30 ` [PATCH 10/59] libctf, create: empty dicts are dirty to start with Nick Alcock
2020-06-30 23:30 ` [PATCH 11/59] libctf, types: support slices of anything terminating in an int Nick Alcock
2020-06-30 23:30 ` [PATCH 12/59] libctf, types: ints, floats and typedefs with no name are invalid Nick Alcock
2020-06-30 23:31 ` [PATCH 13/59] libctf, archive: stop ctf_arc_bufopen triggering crazy unmaps Nick Alcock
2020-06-30 23:31 ` [PATCH 14/59] libctf: having debugging enabled is unlikely Nick Alcock
2020-06-30 23:31 ` [PATCH 15/59] libctf: add ctf_type_name_raw Nick Alcock
2020-06-30 23:31 ` [PATCH 16/59] libctf: add ctf_type_kind_forwarded Nick Alcock
2020-06-30 23:31 ` [PATCH 17/59] libctf: add ctf_member_count Nick Alcock
2020-06-30 23:31 ` [PATCH 18/59] libctf: add ctf_archive_count Nick Alcock
2020-06-30 23:31 ` [PATCH 19/59] libctf: fix __extension__ with non-GNU C compilers Nick Alcock
2020-06-30 23:31 ` [PATCH 20/59] libctf: add new dynhash functions Nick Alcock
2020-06-30 23:31 ` [PATCH 21/59] libctf, hash: improve insertion of existing keys into dynhashes Nick Alcock
2020-06-30 23:31 ` [PATCH 22/59] libctf, hash: save per-item space when no key/item freeing function Nick Alcock
2020-06-30 23:31 ` [PATCH 23/59] libctf, hash: introduce the ctf_dynset Nick Alcock
2020-06-30 23:31 ` [PATCH 24/59] libctf: move existing inlines into ctf-inlines.h Nick Alcock
2020-06-30 23:31 ` [PATCH 25/59] libctf: add ctf_forwardable_kind Nick Alcock
2020-06-30 23:31 ` [PATCH 26/59] libctf: add ctf_ref Nick Alcock
2020-06-30 23:31 ` [PATCH 27/59] libctf, next: introduce new class of easier-to-use iterators Nick Alcock
2020-07-22  9:29   ` [PATCH 27/59] fixup! " Nick Alcock
2020-06-30 23:31 ` [PATCH 28/59] libctf, next, hash: add dynhash and dynset _next iteration Nick Alcock
2020-06-30 23:31 ` [PATCH 29/59] libctf: pass the thunk down properly when wrapping qsort_r Nick Alcock
2020-06-30 23:31 ` [PATCH 30/59] libctf: error out on corrupt CTF with invalid header flags Nick Alcock
2020-06-30 23:31 ` [PATCH 31/59] libctf, types: ensure the emission of ECTF_NOPARENT Nick Alcock
2020-06-30 23:31 ` [PATCH 32/59] libctf, ld, binutils: add textual error/warning reporting for libctf Nick Alcock
2020-06-30 23:31 ` [PATCH 33/59] libctf, types: enhance ctf_type_aname to print function arg types Nick Alcock
2020-06-30 23:31 ` [PATCH 34/59] libctf, decl: avoid leaks of the formatted string on error Nick Alcock
2020-06-30 23:31 ` [PATCH 35/59] libctf, dump: migrate towards dumping errors rather than truncation Nick Alcock
2020-06-30 23:31 ` [PATCH 36/59] libctf, dump: fix slice dumping Nick Alcock
2020-06-30 23:31 ` [PATCH 37/59] libctf, open: fix opening CTF in binaries with no symtab Nick Alcock
2020-06-30 23:31 ` [PATCH 38/59] libctf, archive: fix bad error message Nick Alcock
2020-06-30 23:31 ` [PATCH 39/59] libctf: check for vasprintf Nick Alcock
2020-06-30 23:31 ` [PATCH 40/59] libctf: rename the type_mapping_key to type_key Nick Alcock
2020-07-22  9:35   ` [PATCH 40/59] fixup! " Nick Alcock
2020-06-30 23:31 ` [PATCH 41/59] libctf: sort out potential refcount loops Nick Alcock
2020-06-30 23:31 ` [PATCH 42/59] libctf: drop error-prone ctf_strerror Nick Alcock
2020-06-30 23:31 ` [PATCH 43/59] libctf, link: add lazy linking: clean up input members: err/warn cleanup Nick Alcock
2020-06-30 23:31 ` [PATCH 44/59] libctf, link: fix ctf_link_write fd leak Nick Alcock
2020-06-30 23:31 ` Nick Alcock [this message]
2020-06-30 23:31 ` [PATCH 46/59] ctf, link: fix spurious conflicts of variables in the variable section Nick Alcock
2020-07-01 10:40   ` Nick Alcock
2020-06-30 23:31 ` [PATCH 47/59] libctf, link: add the ability to filter out variables from the link Nick Alcock
2020-06-30 23:31 ` [PATCH 48/59] libctf: add SHA-1 support for libctf Nick Alcock
2020-06-30 23:31 ` [PATCH 49/59] libctf, dedup: add new configure option --enable-libctf-hash-debugging Nick Alcock
2020-07-22  9:30   ` [PATCH 49/59] fixup! " Nick Alcock
2020-06-30 23:31 ` [PATCH 50/59] libctf, dedup: add deduplicator Nick Alcock
2020-07-22  9:33   ` [PATCH 50/59] squash! " Nick Alcock
2020-07-22  9:33   ` [PATCH 50/59] fixup! " Nick Alcock
2020-07-22  9:34   ` Nick Alcock
2020-06-30 23:31 ` [PATCH 51/59] libctf, link: add CTF_LINK_OMIT_VARIABLES_SECTION Nick Alcock
2020-06-30 23:31 ` [PATCH 52/59] libctf, link: tie in the deduplicating linker Nick Alcock
2020-07-22  9:36   ` [PATCH 52/59] fixup! " Nick Alcock
2020-06-30 23:31 ` [PATCH 53/59] binutils: objdump: ctf: drop incorrect linefeeds Nick Alcock
2020-06-30 23:31 ` [PATCH 54/59] ld: Reformat CTF errors into warnings Nick Alcock
2020-06-30 23:31 ` [PATCH 55/59] ld: new options --ctf-variables and --ctf-share-types Nick Alcock
2020-06-30 23:31 ` [PATCH 56/59] binutils, testsuite: allow compilation before doing run_dump_test Nick Alcock
2020-06-30 23:31 ` [PATCH 57/59] ld: new CTF testsuite Nick Alcock
2020-06-30 23:31 ` [PATCH 58/59] ld, testsuite: only run CTF tests when ld and GCC support CTF Nick Alcock
2020-07-22  9:32   ` [PATCH 58/59] fixup! " Nick Alcock
2020-06-30 23:31 ` [PATCH 59/59] ld: do not produce one empty output .ctf section for every input .ctf Nick Alcock
2020-07-14 21:31 ` [PATCH 00/59] Deduplicating CTF linker Nick Alcock
2020-07-20  5:49   ` Alan Modra
2020-07-20 21:06     ` Nick Alcock
2020-07-22  9:39 ` [PATCH 0/4] fallout of various portability testing Nick Alcock
2020-07-22  9:39   ` [PATCH 1/4] ld, testsuite: do not run CTF tests at all on non-ELF for now Nick Alcock
2020-07-22  9:39   ` [PATCH 2/4] libctf, binutils: fix big-endian libctf archive opening Nick Alcock
2020-07-22  9:39   ` [PATCH 3/4] libctf: fix isspace casts Nick Alcock
2020-07-22  9:39   ` [PATCH 4/4] libctf: fixes for systems on which sizeof (void *) > sizeof (long) Nick Alcock
2020-07-22 14:06   ` [PATCH 0/4] fallout of various portability testing Nick Alcock
2020-07-22 17:08 ` [PATCH 00/59] Deduplicating CTF linker Nick Alcock

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200630233146.338613-46-nick.alcock@oracle.com \
    --to=nick.alcock@oracle.com \
    --cc=binutils@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).