/src/binutils-gdb/libctf/ctf-labels.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Labelled ranges of type IDs. |
2 | | Copyright (C) 2019-2025 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_dict_t *fp, const ctf_lblent_t **ctl, |
25 | | uint32_t *num_labels) |
26 | 0 | { |
27 | 0 | const ctf_header_t *h; |
28 | |
|
29 | 0 | h = (const ctf_header_t *) fp->ctf_data.cts_data; |
30 | |
|
31 | 0 | *ctl = (const ctf_lblent_t *) (fp->ctf_buf + h->cth_lbloff); |
32 | 0 | *num_labels = (h->cth_objtoff - h->cth_lbloff) / sizeof (ctf_lblent_t); |
33 | |
|
34 | 0 | return 0; |
35 | 0 | } |
36 | | |
37 | | /* Returns the topmost label, or NULL if any errors are encountered. */ |
38 | | |
39 | | const char * |
40 | | ctf_label_topmost (ctf_dict_t *fp) |
41 | 0 | { |
42 | 0 | const ctf_lblent_t *ctlp = NULL; |
43 | 0 | const char *s; |
44 | 0 | uint32_t num_labels = 0; |
45 | |
|
46 | 0 | if (extract_label_info (fp, &ctlp, &num_labels) < 0) |
47 | 0 | return NULL; /* errno is set for us. */ |
48 | | |
49 | 0 | if (num_labels == 0) |
50 | 0 | { |
51 | 0 | (void) ctf_set_errno (fp, ECTF_NOLABELDATA); |
52 | 0 | return NULL; |
53 | 0 | } |
54 | | |
55 | 0 | if ((s = ctf_strraw (fp, (ctlp + num_labels - 1)->ctl_label)) == NULL) |
56 | 0 | (void) ctf_set_errno (fp, ECTF_CORRUPT); |
57 | |
|
58 | 0 | return s; |
59 | 0 | } |
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_dict_t *fp, ctf_label_f *func, void *arg) |
65 | 0 | { |
66 | 0 | const ctf_lblent_t *ctlp = NULL; |
67 | 0 | uint32_t i; |
68 | 0 | uint32_t num_labels = 0; |
69 | 0 | ctf_lblinfo_t linfo; |
70 | 0 | const char *lname; |
71 | 0 | int rc; |
72 | |
|
73 | 0 | if (extract_label_info (fp, &ctlp, &num_labels) < 0) |
74 | 0 | return -1; /* errno is set for us. */ |
75 | | |
76 | 0 | if (num_labels == 0) |
77 | 0 | return (ctf_set_errno (fp, ECTF_NOLABELDATA)); |
78 | | |
79 | 0 | for (i = 0; i < num_labels; i++, ctlp++) |
80 | 0 | { |
81 | 0 | if ((lname = ctf_strraw (fp, ctlp->ctl_label)) == NULL) |
82 | 0 | { |
83 | | /* Not marked for translation: label code not used yet. */ |
84 | 0 | ctf_err_warn (fp, 0, ECTF_CORRUPT, |
85 | 0 | "failed to decode label %u with type %u", |
86 | 0 | ctlp->ctl_label, ctlp->ctl_type); |
87 | 0 | return (ctf_set_errno (fp, ECTF_CORRUPT)); |
88 | 0 | } |
89 | | |
90 | 0 | linfo.ctb_type = ctlp->ctl_type; |
91 | 0 | if ((rc = func (lname, &linfo, arg)) != 0) |
92 | 0 | return rc; |
93 | 0 | } |
94 | | |
95 | 0 | return 0; |
96 | 0 | } |
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 | 0 | { |
107 | | /* If lname matches the label we are looking for, copy the |
108 | | lblinfo_t struct for the caller. */ |
109 | |
|
110 | 0 | if (strcmp (lname, ((linfo_cb_arg_t *) arg)->lca_name) == 0) |
111 | 0 | { |
112 | | /* * Allow caller not to allocate storage to test if label exists. */ |
113 | |
|
114 | 0 | if (((linfo_cb_arg_t *) arg)->lca_info != NULL) |
115 | 0 | memcpy (((linfo_cb_arg_t *) arg)->lca_info, linfo, |
116 | 0 | sizeof (ctf_lblinfo_t)); |
117 | 0 | return 1; /* Indicate we found a match. */ |
118 | 0 | } |
119 | | |
120 | 0 | return 0; |
121 | 0 | } |
122 | | |
123 | | /* Retrieve information about the label with name "lname". */ |
124 | | int |
125 | | ctf_label_info (ctf_dict_t *fp, const char *lname, ctf_lblinfo_t *linfo) |
126 | 0 | { |
127 | 0 | linfo_cb_arg_t cb_arg; |
128 | 0 | int rc; |
129 | |
|
130 | 0 | cb_arg.lca_name = lname; |
131 | 0 | cb_arg.lca_info = linfo; |
132 | |
|
133 | 0 | if ((rc = ctf_label_iter (fp, label_info_cb, &cb_arg)) < 0) |
134 | 0 | return rc; |
135 | | |
136 | 0 | if (rc != 1) |
137 | 0 | return (ctf_set_errno (fp, ECTF_NOLABEL)); |
138 | | |
139 | 0 | return 0; |
140 | 0 | } |