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