Commit | Line | Data |
---|---|---|
6dbf2b73 | 1 | /* Labelled ranges of type IDs. |
b3adc24a | 2 | Copyright (C) 2019-2020 Free Software Foundation, Inc. |
6dbf2b73 NA |
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 | |
139633c3 | 24 | extract_label_info (ctf_dict_t *fp, const ctf_lblent_t **ctl, |
6dbf2b73 NA |
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 * | |
139633c3 | 40 | ctf_label_topmost (ctf_dict_t *fp) |
6dbf2b73 NA |
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 | |
139633c3 | 64 | ctf_label_iter (ctf_dict_t *fp, ctf_label_f *func, void *arg) |
6dbf2b73 NA |
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 | { | |
926c9e76 NA |
83 | /* Not marked for translation: label code not used yet. */ |
84 | ctf_err_warn (fp, 0, ECTF_CORRUPT, | |
85 | "failed to decode label %u with type %u", | |
86 | ctlp->ctl_label, ctlp->ctl_type); | |
6dbf2b73 NA |
87 | return (ctf_set_errno (fp, ECTF_CORRUPT)); |
88 | } | |
89 | ||
90 | linfo.ctb_type = ctlp->ctl_type; | |
91 | if ((rc = func (lname, &linfo, arg)) != 0) | |
92 | return rc; | |
93 | } | |
94 | ||
95 | return 0; | |
96 | } | |
97 | ||
98 | typedef struct linfo_cb_arg | |
99 | { | |
100 | const char *lca_name; /* Label we want to retrieve info for. */ | |
101 | ctf_lblinfo_t *lca_info; /* Where to store the info about the label. */ | |
102 | } linfo_cb_arg_t; | |
103 | ||
104 | static int | |
105 | label_info_cb (const char *lname, const ctf_lblinfo_t *linfo, void *arg) | |
106 | { | |
107 | /* If lname matches the label we are looking for, copy the | |
108 | lblinfo_t struct for the caller. */ | |
109 | ||
110 | if (strcmp (lname, ((linfo_cb_arg_t *) arg)->lca_name) == 0) | |
111 | { | |
112 | /* * Allow caller not to allocate storage to test if label exists. */ | |
113 | ||
114 | if (((linfo_cb_arg_t *) arg)->lca_info != NULL) | |
115 | memcpy (((linfo_cb_arg_t *) arg)->lca_info, linfo, | |
116 | sizeof (ctf_lblinfo_t)); | |
117 | return 1; /* Indicate we found a match. */ | |
118 | } | |
119 | ||
120 | return 0; | |
121 | } | |
122 | ||
123 | /* Retrieve information about the label with name "lname". */ | |
124 | int | |
139633c3 | 125 | ctf_label_info (ctf_dict_t *fp, const char *lname, ctf_lblinfo_t *linfo) |
6dbf2b73 NA |
126 | { |
127 | linfo_cb_arg_t cb_arg; | |
128 | int rc; | |
129 | ||
130 | cb_arg.lca_name = lname; | |
131 | cb_arg.lca_info = linfo; | |
132 | ||
a0486bac | 133 | if ((rc = ctf_label_iter (fp, label_info_cb, &cb_arg)) < 0) |
6dbf2b73 NA |
134 | return rc; |
135 | ||
136 | if (rc != 1) | |
137 | return (ctf_set_errno (fp, ECTF_NOLABEL)); | |
138 | ||
139 | return 0; | |
140 | } |