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