xref: /netbsd-src/external/gpl3/binutils/dist/libctf/ctf-labels.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
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