Home | History | Annotate | Line # | Download | only in libctf
      1      1.1  christos /* Labelled ranges of type IDs.
      2  1.1.1.4  christos    Copyright (C) 2019-2025 Free Software Foundation, Inc.
      3      1.1  christos 
      4      1.1  christos    This file is part of libctf.
      5      1.1  christos 
      6      1.1  christos    libctf is free software; you can redistribute it and/or modify it under
      7      1.1  christos    the terms of the GNU General Public License as published by the Free
      8      1.1  christos    Software Foundation; either version 3, or (at your option) any later
      9      1.1  christos    version.
     10      1.1  christos 
     11      1.1  christos    This program is distributed in the hope that it will be useful, but
     12      1.1  christos    WITHOUT ANY WARRANTY; without even the implied warranty of
     13      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     14      1.1  christos    See the GNU General Public License for more details.
     15      1.1  christos 
     16      1.1  christos    You should have received a copy of the GNU General Public License
     17      1.1  christos    along with this program; see the file COPYING.  If not see
     18      1.1  christos    <http://www.gnu.org/licenses/>.  */
     19      1.1  christos 
     20      1.1  christos #include <ctf-impl.h>
     21      1.1  christos #include <string.h>
     22      1.1  christos 
     23      1.1  christos static int
     24  1.1.1.2  christos extract_label_info (ctf_dict_t *fp, const ctf_lblent_t **ctl,
     25      1.1  christos 		    uint32_t *num_labels)
     26      1.1  christos {
     27      1.1  christos   const ctf_header_t *h;
     28      1.1  christos 
     29      1.1  christos   h = (const ctf_header_t *) fp->ctf_data.cts_data;
     30      1.1  christos 
     31      1.1  christos   *ctl = (const ctf_lblent_t *) (fp->ctf_buf + h->cth_lbloff);
     32      1.1  christos   *num_labels = (h->cth_objtoff - h->cth_lbloff) / sizeof (ctf_lblent_t);
     33      1.1  christos 
     34      1.1  christos   return 0;
     35      1.1  christos }
     36      1.1  christos 
     37      1.1  christos /* Returns the topmost label, or NULL if any errors are encountered.  */
     38      1.1  christos 
     39      1.1  christos const char *
     40  1.1.1.2  christos ctf_label_topmost (ctf_dict_t *fp)
     41      1.1  christos {
     42      1.1  christos   const ctf_lblent_t *ctlp = NULL;
     43      1.1  christos   const char *s;
     44      1.1  christos   uint32_t num_labels = 0;
     45      1.1  christos 
     46      1.1  christos   if (extract_label_info (fp, &ctlp, &num_labels) < 0)
     47      1.1  christos     return NULL;				/* errno is set for us.  */
     48      1.1  christos 
     49      1.1  christos   if (num_labels == 0)
     50      1.1  christos     {
     51      1.1  christos       (void) ctf_set_errno (fp, ECTF_NOLABELDATA);
     52      1.1  christos       return NULL;
     53      1.1  christos     }
     54      1.1  christos 
     55      1.1  christos   if ((s = ctf_strraw (fp, (ctlp + num_labels - 1)->ctl_label)) == NULL)
     56      1.1  christos     (void) ctf_set_errno (fp, ECTF_CORRUPT);
     57      1.1  christos 
     58      1.1  christos   return s;
     59      1.1  christos }
     60      1.1  christos 
     61      1.1  christos /* Iterate over all labels.  We pass the label string and the lblinfo_t struct
     62      1.1  christos    to the specified callback function.  */
     63      1.1  christos int
     64  1.1.1.2  christos ctf_label_iter (ctf_dict_t *fp, ctf_label_f *func, void *arg)
     65      1.1  christos {
     66      1.1  christos   const ctf_lblent_t *ctlp = NULL;
     67      1.1  christos   uint32_t i;
     68      1.1  christos   uint32_t num_labels = 0;
     69      1.1  christos   ctf_lblinfo_t linfo;
     70      1.1  christos   const char *lname;
     71      1.1  christos   int rc;
     72      1.1  christos 
     73      1.1  christos   if (extract_label_info (fp, &ctlp, &num_labels) < 0)
     74      1.1  christos     return -1;			/* errno is set for us.  */
     75      1.1  christos 
     76      1.1  christos   if (num_labels == 0)
     77      1.1  christos     return (ctf_set_errno (fp, ECTF_NOLABELDATA));
     78      1.1  christos 
     79      1.1  christos   for (i = 0; i < num_labels; i++, ctlp++)
     80      1.1  christos     {
     81      1.1  christos       if ((lname = ctf_strraw (fp, ctlp->ctl_label)) == NULL)
     82      1.1  christos 	{
     83      1.1  christos 	  /* Not marked for translation: label code not used yet.  */
     84      1.1  christos 	  ctf_err_warn (fp, 0, ECTF_CORRUPT,
     85      1.1  christos 			"failed to decode label %u with type %u",
     86      1.1  christos 			ctlp->ctl_label, ctlp->ctl_type);
     87      1.1  christos 	  return (ctf_set_errno (fp, ECTF_CORRUPT));
     88      1.1  christos 	}
     89      1.1  christos 
     90      1.1  christos       linfo.ctb_type = ctlp->ctl_type;
     91      1.1  christos       if ((rc = func (lname, &linfo, arg)) != 0)
     92      1.1  christos 	return rc;
     93      1.1  christos     }
     94      1.1  christos 
     95      1.1  christos   return 0;
     96      1.1  christos }
     97      1.1  christos 
     98      1.1  christos typedef struct linfo_cb_arg
     99      1.1  christos {
    100      1.1  christos   const char *lca_name;		/* Label we want to retrieve info for.  */
    101      1.1  christos   ctf_lblinfo_t *lca_info;	/* Where to store the info about the label.  */
    102      1.1  christos } linfo_cb_arg_t;
    103      1.1  christos 
    104      1.1  christos static int
    105      1.1  christos label_info_cb (const char *lname, const ctf_lblinfo_t *linfo, void *arg)
    106      1.1  christos {
    107      1.1  christos   /* If lname matches the label we are looking for, copy the
    108      1.1  christos     lblinfo_t struct for the caller.  */
    109      1.1  christos 
    110      1.1  christos   if (strcmp (lname, ((linfo_cb_arg_t *) arg)->lca_name) == 0)
    111      1.1  christos     {
    112      1.1  christos       /* * Allow caller not to allocate storage to test if label exists.  */
    113      1.1  christos 
    114      1.1  christos       if (((linfo_cb_arg_t *) arg)->lca_info != NULL)
    115      1.1  christos 	memcpy (((linfo_cb_arg_t *) arg)->lca_info, linfo,
    116      1.1  christos 	       sizeof (ctf_lblinfo_t));
    117      1.1  christos       return 1;		/* Indicate we found a match.  */
    118      1.1  christos     }
    119      1.1  christos 
    120      1.1  christos   return 0;
    121      1.1  christos }
    122      1.1  christos 
    123      1.1  christos /* Retrieve information about the label with name "lname". */
    124      1.1  christos int
    125  1.1.1.2  christos ctf_label_info (ctf_dict_t *fp, const char *lname, ctf_lblinfo_t *linfo)
    126      1.1  christos {
    127      1.1  christos   linfo_cb_arg_t cb_arg;
    128      1.1  christos   int rc;
    129      1.1  christos 
    130      1.1  christos   cb_arg.lca_name = lname;
    131      1.1  christos   cb_arg.lca_info = linfo;
    132      1.1  christos 
    133      1.1  christos   if ((rc = ctf_label_iter (fp, label_info_cb, &cb_arg)) < 0)
    134      1.1  christos     return rc;
    135      1.1  christos 
    136      1.1  christos   if (rc != 1)
    137      1.1  christos     return (ctf_set_errno (fp, ECTF_NOLABEL));
    138      1.1  christos 
    139      1.1  christos   return 0;
    140      1.1  christos }
    141