aboutsummaryrefslogtreecommitdiff
path: root/libctf
diff options
context:
space:
mode:
authorNick Alcock <nick.alcock@oracle.com>2019-04-24 11:35:37 +0100
committerNick Alcock <nick.alcock@oracle.com>2019-05-28 17:09:30 +0100
commit6dbf2b734063522b4f3d7403ce7a2b436802b839 (patch)
treeffd324ef83a909f9bdee848fb2287e87877af5d8 /libctf
parent6c33b742ce19cc2fd226d84f2991572239199a62 (diff)
downloadgdb-6dbf2b734063522b4f3d7403ce7a2b436802b839.zip
gdb-6dbf2b734063522b4f3d7403ce7a2b436802b839.tar.gz
gdb-6dbf2b734063522b4f3d7403ce7a2b436802b839.tar.bz2
libctf: labels
This facility allows you to associate regions of type IDs with *labels*, a labelled tiling of the type ID space. You can use these to define CTF containers with distinct parents for distinct ranges of the ID space, or to assist with parallelization of CTF processing, or for any other purpose you can think of. Notably absent from here (though declared in the API header) is any way to define new labels: this will probably be introduced soon, as part of the linker deduplication work. (One existed in the past, but was deeply tied to the Solaris CTF file generator and had to be torn out.) libctf/ * ctf-labels.c: New. include/ * ctf-api.h (ctf_label_f): New. (ctf_label_set): New. (ctf_label_get): New. (ctf_label_topmost): New. (ctf_label_info): New. (ctf_label_iter): New.
Diffstat (limited to 'libctf')
-rw-r--r--libctf/ChangeLog4
-rw-r--r--libctf/ctf-labels.c138
2 files changed, 142 insertions, 0 deletions
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index a6eb11e..e4976c4 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,5 +1,9 @@
2019-05-28 Nick Alcock <nick.alcock@oracle.com>
+ * ctf-labels.c: New.
+
+2019-05-28 Nick Alcock <nick.alcock@oracle.com>
+
* ctf-impl.h (_libctf_version): New declaration.
* ctf-subr.c (_libctf_version): Define it.
(ctf_version): New.
diff --git a/libctf/ctf-labels.c b/libctf/ctf-labels.c
new file mode 100644
index 0000000..9b9fffe
--- /dev/null
+++ b/libctf/ctf-labels.c
@@ -0,0 +1,138 @@
+/* Labelled ranges of type IDs.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+
+ This file is part of libctf.
+
+ libctf is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include <ctf-impl.h>
+#include <string.h>
+
+static int
+extract_label_info (ctf_file_t *fp, const ctf_lblent_t **ctl,
+ uint32_t *num_labels)
+{
+ const ctf_header_t *h;
+
+ h = (const ctf_header_t *) fp->ctf_data.cts_data;
+
+ *ctl = (const ctf_lblent_t *) (fp->ctf_buf + h->cth_lbloff);
+ *num_labels = (h->cth_objtoff - h->cth_lbloff) / sizeof (ctf_lblent_t);
+
+ return 0;
+}
+
+/* Returns the topmost label, or NULL if any errors are encountered. */
+
+const char *
+ctf_label_topmost (ctf_file_t *fp)
+{
+ const ctf_lblent_t *ctlp = NULL;
+ const char *s;
+ uint32_t num_labels = 0;
+
+ if (extract_label_info (fp, &ctlp, &num_labels) == CTF_ERR)
+ return NULL; /* errno is set for us. */
+
+ if (num_labels == 0)
+ {
+ (void) ctf_set_errno (fp, ECTF_NOLABELDATA);
+ return NULL;
+ }
+
+ if ((s = ctf_strraw (fp, (ctlp + num_labels - 1)->ctl_label)) == NULL)
+ (void) ctf_set_errno (fp, ECTF_CORRUPT);
+
+ return s;
+}
+
+/* Iterate over all labels. We pass the label string and the lblinfo_t struct
+ to the specified callback function. */
+int
+ctf_label_iter (ctf_file_t *fp, ctf_label_f *func, void *arg)
+{
+ const ctf_lblent_t *ctlp = NULL;
+ uint32_t i;
+ uint32_t num_labels = 0;
+ ctf_lblinfo_t linfo;
+ const char *lname;
+ int rc;
+
+ if (extract_label_info (fp, &ctlp, &num_labels) == CTF_ERR)
+ return CTF_ERR; /* errno is set for us. */
+
+ if (num_labels == 0)
+ return (ctf_set_errno (fp, ECTF_NOLABELDATA));
+
+ for (i = 0; i < num_labels; i++, ctlp++)
+ {
+ if ((lname = ctf_strraw (fp, ctlp->ctl_label)) == NULL)
+ {
+ ctf_dprintf ("failed to decode label %u with "
+ "type %u\n", ctlp->ctl_label, ctlp->ctl_type);
+ return (ctf_set_errno (fp, ECTF_CORRUPT));
+ }
+
+ linfo.ctb_type = ctlp->ctl_type;
+ if ((rc = func (lname, &linfo, arg)) != 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+typedef struct linfo_cb_arg
+{
+ const char *lca_name; /* Label we want to retrieve info for. */
+ ctf_lblinfo_t *lca_info; /* Where to store the info about the label. */
+} linfo_cb_arg_t;
+
+static int
+label_info_cb (const char *lname, const ctf_lblinfo_t *linfo, void *arg)
+{
+ /* If lname matches the label we are looking for, copy the
+ lblinfo_t struct for the caller. */
+
+ if (strcmp (lname, ((linfo_cb_arg_t *) arg)->lca_name) == 0)
+ {
+ /* * Allow caller not to allocate storage to test if label exists. */
+
+ if (((linfo_cb_arg_t *) arg)->lca_info != NULL)
+ memcpy (((linfo_cb_arg_t *) arg)->lca_info, linfo,
+ sizeof (ctf_lblinfo_t));
+ return 1; /* Indicate we found a match. */
+ }
+
+ return 0;
+}
+
+/* Retrieve information about the label with name "lname". */
+int
+ctf_label_info (ctf_file_t *fp, const char *lname, ctf_lblinfo_t *linfo)
+{
+ linfo_cb_arg_t cb_arg;
+ int rc;
+
+ cb_arg.lca_name = lname;
+ cb_arg.lca_info = linfo;
+
+ if ((rc = ctf_label_iter (fp, label_info_cb, &cb_arg)) == CTF_ERR)
+ return rc;
+
+ if (rc != 1)
+ return (ctf_set_errno (fp, ECTF_NOLABEL));
+
+ return 0;
+}