]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
libctf: link: BTF support
authorNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 17:22:07 +0000 (18:22 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 20:23:07 +0000 (21:23 +0100)
This is in two parts, one new API function and one change.

New API:
+int ctf_link_output_is_btf (ctf_dict_t *);

Changed API:
unsigned char *ctf_link_write (ctf_dict_t *, size_t *size,
-       size_t threshold);
+       size_t threshold, int *is_btf);

The idea here is that callers can call ctf_link_output_is_btf on a
ctf_link()ed (deduplicated) dict to tell whether a link will yield
BTF-compatible output before actually generating that output, so
they can e.g. decide whether to avoid trying to compress the dict
if they know it would be BTF otherwise (since compressing a dict
renders it non-BTF-compatible).

ctf_link_write() gains an optional is_btf output parameter that
reports whether the dict that was finally generated is actually BTF
after all, perhaps because the caller didn't call
ctf_link_output_is_btf or wants to be robust against possible future
changes that may add other reasons why a written-out dict can't be BTF
at the last minute.

These are simple wrappers around already-existing machinery earlier in
this series.

include/ctf-api.h
libctf/ctf-impl.h
libctf/ctf-link.c
libctf/libctf.ver

index e9fadefa67877b3840e99753e8722da7daf34494..3db50062f14fa5b8401ca803034b1b774c37c583 100644 (file)
@@ -1117,7 +1117,10 @@ extern int ctf_write_suppress_kind (ctf_dict_t *fp, int kind, int prohibited);
    object files into a single .ctf section which is an archive possibly
    containing members containing types whose names collide across multiple
    compilation units, but they are usable by other programs as well and are not
-   private to the linker.  */
+   private to the linker.
+
+   They should be called in the order they appear below, though some are
+   optional.  */
 
 /* Add a CTF archive to the link with a given NAME (usually the name of the
    containing object file).  The dict added to is usually a new dict created
@@ -1136,7 +1139,7 @@ extern int ctf_link_add_ctf (ctf_dict_t *, ctf_archive_t *, const char *name);
 extern int ctf_link (ctf_dict_t *, int flags);
 
 /* Symtab linker handling, called after ctf_link to set up the symbol type
-   information used by ctf_*_lookup_symbol.  */
+   information used by ctf_*_lookup_symbol.  Optional.  */
 
 /* Add strings to the link from the ELF string table, repeatedly calling
    ADD_STRING to add each string and its corresponding offset in turn.  */
@@ -1153,19 +1156,28 @@ extern int ctf_link_add_strtab (ctf_dict_t *,
 extern int ctf_link_add_linker_symbol (ctf_dict_t *, ctf_link_sym_t *);
 
 /* Impose an ordering on symbols, as defined by the strtab and symbol
-   added by earlier calls to the above two functions.  */
+   added by earlier calls to the above two functions.  Optional.  */
 
 extern int ctf_link_shuffle_syms (ctf_dict_t *);
 
+/* Determine the file format of the dict that will be written out after the
+   calls above is compatible with pure BTF or would require CTF.  (Other things
+   may nonetheless require CTF, in particular, compression.)  */
+
+extern int ctf_link_output_is_btf (ctf_dict_t *);
+
 /* Return the serialized form of this ctf_linked dict as a new
    dynamically-allocated string, compressed if size over THRESHOLD.
 
    May be a CTF dict or a CTF archive (this library mostly papers over the
    differences so you can open both the same way, treat both as ctf_archive_t
-   and so on).  */
+   and so on).
+
+   If IS_BTF is set on return, the output is BTF-compatible and can be stored
+   in a .BTF section.  */
 
 extern unsigned char *ctf_link_write (ctf_dict_t *, size_t *size,
-                                     size_t threshold);
+                                     size_t threshold, int *is_btf);
 
 /* Specialist linker functions.  These functions are not used by ld, but can be
    used by other programs making use of the linker machinery for other purposes
index d029db52f7ebcf35235e69660312b1e04262492a..e0145bdd4e6e6a75a17fa737ea7d16e7ab35e163 100644 (file)
@@ -793,6 +793,7 @@ extern void ctf_str_purge_refs (ctf_dict_t *fp);
 extern void ctf_str_rollback (ctf_dict_t *, ctf_snapshot_id_t);
 extern const ctf_strs_writable_t *ctf_str_write_strtab (ctf_dict_t *);
 
+extern int ctf_serialize_output_format (ctf_dict_t *fp, int force_ctf);
 extern int ctf_preserialize (ctf_dict_t *fp, int force_ctf);
 extern void ctf_depreserialize (ctf_dict_t *fp);
 
index b3092fce4652a7b902cc209fa12d4450e81e4a19..f552cacca4686f59b913287921b65511afa1aca5 100644 (file)
 const char *
 ctf_link_input_name (ctf_dict_t *fp)
 {
-  if (fp->ctf_parent && fp->ctf_parent->ctf_cuname)
-    return fp->ctf_parent->ctf_cuname;
-  else if (fp->ctf_cuname)
-    return fp->ctf_cuname;
+  if (fp->ctf_parent && fp->ctf_parent->ctf_cu_name)
+    return fp->ctf_parent->ctf_cu_name;
+  else if (fp->ctf_cu_name)
+    return fp->ctf_cu_name;
   else
     return "(unnamed)";
 }
@@ -1501,6 +1501,11 @@ ctf_link_add_linker_symbol (ctf_dict_t *fp, ctf_link_sym_t *sym)
   if (sym->st_type != STT_OBJECT && sym->st_type != STT_FUNC)
     return 0;
 
+  /* If emitting BTF, there is no symtypetab so linker symbols are ignored.  */
+
+  if (fp->ctf_serialize.cs_is_btf)
+    return 0;
+
   /* Add the symbol to the in-flight list.  */
 
   if ((cid = malloc (sizeof (ctf_in_flight_dynsym_t))) == NULL)
@@ -1533,6 +1538,11 @@ ctf_link_shuffle_syms (ctf_dict_t *fp)
   if (fp->ctf_stypes > 0)
     return ctf_set_errno (fp, ECTF_RDONLY);
 
+  /* If emitting BTF, there is no symtypetab to shuffle.  */
+
+  if (fp->ctf_serialize.cs_is_btf)
+    return 0;
+
   if (!fp->ctf_dynsyms)
     {
       fp->ctf_dynsyms = ctf_dynhash_create (ctf_hash_string,
@@ -1732,6 +1742,28 @@ ctf_elf64_to_link_sym (ctf_dict_t *fp, ctf_link_sym_t *dst, const Elf64_Sym *src
   return dst;
 }
 
+/* Determine whether the archive that will be built from this linked dict is compatible
+   with pure BTF or would require CTF.  (Other things may nonetheless require CTF, in
+   particular, compression.)  */
+int
+ctf_link_output_is_btf (ctf_dict_t *fp)
+{
+  /* Can't call when nothing has been linked yet.  */
+
+  if (!fp->ctf_link_outputs)
+    return (ctf_set_errno (fp, EINVAL));
+
+  /* Cannot be BTF if child dicts are present.  */
+
+  if (ctf_dynhash_elements (fp->ctf_link_outputs) != 0)
+    return 0;
+
+  if (ctf_serialize_output_format (fp, 0) < 0)
+    return -1;                                 /* errno is set for us.  */
+
+  return fp->ctf_serialize.cs_is_btf;
+}
+
 typedef struct ctf_name_list_accum_cb_arg
 {
   char **names;
@@ -1863,9 +1895,12 @@ ctf_link_warn_outdated_inputs (ctf_dict_t *fp)
 
 /* Write out a CTF archive (if there are per-CU CTF files) or a CTF file
    (otherwise) into a new dynamically-allocated string, and return it.
-   Members with sizes above THRESHOLD are compressed.  */
+   Members with sizes above THRESHOLD are compressed.
+
+   The optional arg IS_BTF is set to 1 if the written output is valid BTF
+   (no archives, no CTF-specific types).  */
 unsigned char *
-ctf_link_write (ctf_dict_t *fp, size_t *size, size_t threshold)
+ctf_link_write (ctf_dict_t *fp, size_t *size, size_t threshold, int *is_btf)
 {
   ctf_name_list_accum_cb_arg_t arg;
   char **names;
@@ -1894,11 +1929,18 @@ ctf_link_write (ctf_dict_t *fp, size_t *size, size_t threshold)
        }
     }
 
+  if (is_btf)
+    *is_btf = 0;
+
   /* No extra outputs?  Just write a simple ctf_dict_t.  */
   if (arg.i == 0)
     {
       unsigned char *ret = ctf_write_mem (fp, size, threshold);
       fp->ctf_flags &= ~LCTF_LINKING;
+
+      if (is_btf && fp->ctf_serialize.cs_is_btf)
+       *is_btf = 1;
+
       return ret;
     }
 
index 3ad5176a14188e7613c4d7c67769781c254a8675..1d0ddc403b1c97747ba1285ef4672b23023f3cc8 100644 (file)
@@ -201,6 +201,7 @@ LIBCTF_2.0 {
        ctf_link;
        ctf_link_add_strtab;
        ctf_link_shuffle_syms;
+       ctf_link_output_is_btf;
        ctf_link_write;
 
        ctf_link_add_linker_symbol;