16f4ced0bSchristos /* Labelled ranges of type IDs.
2*cb63e24eSchristos Copyright (C) 2019-2024 Free Software Foundation, Inc.
36f4ced0bSchristos
46f4ced0bSchristos This file is part of libctf.
56f4ced0bSchristos
66f4ced0bSchristos libctf is free software; you can redistribute it and/or modify it under
76f4ced0bSchristos the terms of the GNU General Public License as published by the Free
86f4ced0bSchristos Software Foundation; either version 3, or (at your option) any later
96f4ced0bSchristos version.
106f4ced0bSchristos
116f4ced0bSchristos This program is distributed in the hope that it will be useful, but
126f4ced0bSchristos WITHOUT ANY WARRANTY; without even the implied warranty of
136f4ced0bSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
146f4ced0bSchristos See the GNU General Public License for more details.
156f4ced0bSchristos
166f4ced0bSchristos You should have received a copy of the GNU General Public License
176f4ced0bSchristos along with this program; see the file COPYING. If not see
186f4ced0bSchristos <http://www.gnu.org/licenses/>. */
196f4ced0bSchristos
206f4ced0bSchristos #include <ctf-impl.h>
216f4ced0bSchristos #include <string.h>
226f4ced0bSchristos
236f4ced0bSchristos static int
extract_label_info(ctf_dict_t * fp,const ctf_lblent_t ** ctl,uint32_t * num_labels)244f645668Schristos extract_label_info (ctf_dict_t *fp, const ctf_lblent_t **ctl,
256f4ced0bSchristos uint32_t *num_labels)
266f4ced0bSchristos {
276f4ced0bSchristos const ctf_header_t *h;
286f4ced0bSchristos
296f4ced0bSchristos h = (const ctf_header_t *) fp->ctf_data.cts_data;
306f4ced0bSchristos
316f4ced0bSchristos *ctl = (const ctf_lblent_t *) (fp->ctf_buf + h->cth_lbloff);
326f4ced0bSchristos *num_labels = (h->cth_objtoff - h->cth_lbloff) / sizeof (ctf_lblent_t);
336f4ced0bSchristos
346f4ced0bSchristos return 0;
356f4ced0bSchristos }
366f4ced0bSchristos
376f4ced0bSchristos /* Returns the topmost label, or NULL if any errors are encountered. */
386f4ced0bSchristos
396f4ced0bSchristos const char *
ctf_label_topmost(ctf_dict_t * fp)404f645668Schristos ctf_label_topmost (ctf_dict_t *fp)
416f4ced0bSchristos {
426f4ced0bSchristos const ctf_lblent_t *ctlp = NULL;
436f4ced0bSchristos const char *s;
446f4ced0bSchristos uint32_t num_labels = 0;
456f4ced0bSchristos
466f4ced0bSchristos if (extract_label_info (fp, &ctlp, &num_labels) < 0)
476f4ced0bSchristos return NULL; /* errno is set for us. */
486f4ced0bSchristos
496f4ced0bSchristos if (num_labels == 0)
506f4ced0bSchristos {
516f4ced0bSchristos (void) ctf_set_errno (fp, ECTF_NOLABELDATA);
526f4ced0bSchristos return NULL;
536f4ced0bSchristos }
546f4ced0bSchristos
556f4ced0bSchristos if ((s = ctf_strraw (fp, (ctlp + num_labels - 1)->ctl_label)) == NULL)
566f4ced0bSchristos (void) ctf_set_errno (fp, ECTF_CORRUPT);
576f4ced0bSchristos
586f4ced0bSchristos return s;
596f4ced0bSchristos }
606f4ced0bSchristos
616f4ced0bSchristos /* Iterate over all labels. We pass the label string and the lblinfo_t struct
626f4ced0bSchristos to the specified callback function. */
636f4ced0bSchristos int
ctf_label_iter(ctf_dict_t * fp,ctf_label_f * func,void * arg)644f645668Schristos ctf_label_iter (ctf_dict_t *fp, ctf_label_f *func, void *arg)
656f4ced0bSchristos {
666f4ced0bSchristos const ctf_lblent_t *ctlp = NULL;
676f4ced0bSchristos uint32_t i;
686f4ced0bSchristos uint32_t num_labels = 0;
696f4ced0bSchristos ctf_lblinfo_t linfo;
706f4ced0bSchristos const char *lname;
716f4ced0bSchristos int rc;
726f4ced0bSchristos
736f4ced0bSchristos if (extract_label_info (fp, &ctlp, &num_labels) < 0)
746f4ced0bSchristos return -1; /* errno is set for us. */
756f4ced0bSchristos
766f4ced0bSchristos if (num_labels == 0)
776f4ced0bSchristos return (ctf_set_errno (fp, ECTF_NOLABELDATA));
786f4ced0bSchristos
796f4ced0bSchristos for (i = 0; i < num_labels; i++, ctlp++)
806f4ced0bSchristos {
816f4ced0bSchristos if ((lname = ctf_strraw (fp, ctlp->ctl_label)) == NULL)
826f4ced0bSchristos {
834f645668Schristos /* Not marked for translation: label code not used yet. */
844f645668Schristos ctf_err_warn (fp, 0, ECTF_CORRUPT,
854f645668Schristos "failed to decode label %u with type %u",
864f645668Schristos ctlp->ctl_label, ctlp->ctl_type);
876f4ced0bSchristos return (ctf_set_errno (fp, ECTF_CORRUPT));
886f4ced0bSchristos }
896f4ced0bSchristos
906f4ced0bSchristos linfo.ctb_type = ctlp->ctl_type;
916f4ced0bSchristos if ((rc = func (lname, &linfo, arg)) != 0)
926f4ced0bSchristos return rc;
936f4ced0bSchristos }
946f4ced0bSchristos
956f4ced0bSchristos return 0;
966f4ced0bSchristos }
976f4ced0bSchristos
986f4ced0bSchristos typedef struct linfo_cb_arg
996f4ced0bSchristos {
1006f4ced0bSchristos const char *lca_name; /* Label we want to retrieve info for. */
1016f4ced0bSchristos ctf_lblinfo_t *lca_info; /* Where to store the info about the label. */
1026f4ced0bSchristos } linfo_cb_arg_t;
1036f4ced0bSchristos
1046f4ced0bSchristos static int
label_info_cb(const char * lname,const ctf_lblinfo_t * linfo,void * arg)1056f4ced0bSchristos label_info_cb (const char *lname, const ctf_lblinfo_t *linfo, void *arg)
1066f4ced0bSchristos {
1076f4ced0bSchristos /* If lname matches the label we are looking for, copy the
1086f4ced0bSchristos lblinfo_t struct for the caller. */
1096f4ced0bSchristos
1106f4ced0bSchristos if (strcmp (lname, ((linfo_cb_arg_t *) arg)->lca_name) == 0)
1116f4ced0bSchristos {
1126f4ced0bSchristos /* * Allow caller not to allocate storage to test if label exists. */
1136f4ced0bSchristos
1146f4ced0bSchristos if (((linfo_cb_arg_t *) arg)->lca_info != NULL)
1156f4ced0bSchristos memcpy (((linfo_cb_arg_t *) arg)->lca_info, linfo,
1166f4ced0bSchristos sizeof (ctf_lblinfo_t));
1176f4ced0bSchristos return 1; /* Indicate we found a match. */
1186f4ced0bSchristos }
1196f4ced0bSchristos
1206f4ced0bSchristos return 0;
1216f4ced0bSchristos }
1226f4ced0bSchristos
1236f4ced0bSchristos /* Retrieve information about the label with name "lname". */
1246f4ced0bSchristos int
ctf_label_info(ctf_dict_t * fp,const char * lname,ctf_lblinfo_t * linfo)1254f645668Schristos ctf_label_info (ctf_dict_t *fp, const char *lname, ctf_lblinfo_t *linfo)
1266f4ced0bSchristos {
1276f4ced0bSchristos linfo_cb_arg_t cb_arg;
1286f4ced0bSchristos int rc;
1296f4ced0bSchristos
1306f4ced0bSchristos cb_arg.lca_name = lname;
1316f4ced0bSchristos cb_arg.lca_info = linfo;
1326f4ced0bSchristos
1336f4ced0bSchristos if ((rc = ctf_label_iter (fp, label_info_cb, &cb_arg)) < 0)
1346f4ced0bSchristos return rc;
1356f4ced0bSchristos
1366f4ced0bSchristos if (rc != 1)
1376f4ced0bSchristos return (ctf_set_errno (fp, ECTF_NOLABEL));
1386f4ced0bSchristos
1396f4ced0bSchristos return 0;
1406f4ced0bSchristos }
141