source: mainline/kernel/generic/src/debug/util.c@ 001957b6

topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 001957b6 was 001957b6, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 20 months ago

ccheck

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Copyright (c) 2023 Jiří Zárevúcky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "util.h"
30
31#include <stdio.h>
32#include <debug/sections.h>
33#include <debug/names.h>
34
35/*
36 * These declarations cause global definitions for the functions to be emitted
37 * in this compilation unit, so if the compiler decides not to inline some of
38 * them, only one external copy exists. See C99 inline rules.
39 */
40extern inline uint8_t read_byte(const uint8_t **, const uint8_t *);
41extern inline uint16_t read_uint16(const uint8_t **, const uint8_t *);
42extern inline uint32_t read_uint24(const uint8_t **, const uint8_t *);
43extern inline uint32_t read_uint32(const uint8_t **, const uint8_t *);
44extern inline uint64_t read_uint64(const uint8_t **, const uint8_t *);
45extern inline uint64_t read_uint(const uint8_t **, const uint8_t *, unsigned);
46extern inline uint64_t read_uleb128(const uint8_t **, const uint8_t *);
47extern inline int64_t read_sleb128(const uint8_t **, const uint8_t *);
48extern inline void skip_leb128(const uint8_t **, const uint8_t *);
49extern inline uint64_t read_initial_length(const uint8_t **, const uint8_t *, unsigned *);
50extern inline const char *read_string(const uint8_t **, const uint8_t *);
51extern inline void skip_string(const uint8_t **, const uint8_t *);
52extern inline void safe_increment(const uint8_t **, const uint8_t *, ptrdiff_t);
53
54extern inline void skip_format(const uint8_t **, const uint8_t *, unsigned);
55extern inline void skip_formatted_entry(const uint8_t **, const uint8_t *,
56 const uint8_t *, const uint8_t *, unsigned);
57extern inline void skip_formatted_list(const uint8_t **, const uint8_t *,
58 unsigned, const uint8_t *, const uint8_t *, unsigned);
59
60bool skip_data(unsigned form, const uint8_t **const data,
61 const uint8_t *data_end, unsigned width)
62{
63 // Skip data we don't care about reading.
64
65 size_t len;
66
67 switch (form) {
68 case DW_FORM_string:
69 skip_string(data, data_end);
70 break;
71
72 case DW_FORM_strp:
73 case DW_FORM_line_strp:
74 case DW_FORM_strp_sup:
75 case DW_FORM_sec_offset:
76 safe_increment(data, data_end, width);
77 break;
78
79 case DW_FORM_strx:
80 case DW_FORM_sdata:
81 case DW_FORM_udata:
82 skip_leb128(data, data_end);
83 break;
84
85 case DW_FORM_strx1:
86 case DW_FORM_data1:
87 case DW_FORM_flag:
88 safe_increment(data, data_end, 1);
89 break;
90
91 case DW_FORM_strx2:
92 case DW_FORM_data2:
93 safe_increment(data, data_end, 2);
94 break;
95
96 case DW_FORM_strx3:
97 safe_increment(data, data_end, 3);
98 break;
99
100 case DW_FORM_strx4:
101 case DW_FORM_data4:
102 safe_increment(data, data_end, 4);
103 break;
104
105 case DW_FORM_data8:
106 safe_increment(data, data_end, 8);
107 break;
108
109 case DW_FORM_data16:
110 safe_increment(data, data_end, 16);
111 break;
112
113 case DW_FORM_block:
114 len = read_uleb128(data, data_end);
115 safe_increment(data, data_end, len);
116 break;
117
118 case DW_FORM_block1:
119 len = read_byte(data, data_end);
120 safe_increment(data, data_end, len);
121 break;
122
123 case DW_FORM_block2:
124 len = read_uint16(data, data_end);
125 safe_increment(data, data_end, len);
126 break;
127
128 case DW_FORM_block4:
129 len = read_uint32(data, data_end);
130 safe_increment(data, data_end, len);
131 break;
132
133 default:
134 // Unknown FORM.
135 *data = data_end;
136 return false;
137 }
138
139 return true;
140}
141
142void print_format(const char *name, const uint8_t *format, const uint8_t *format_end)
143{
144 DEBUGF("%s: ", name);
145
146 while (format < format_end) {
147 uint64_t lnct = read_uleb128(&format, format_end);
148 uint64_t form = read_uleb128(&format, format_end);
149
150 const char *fname = dw_form_name(form);
151
152 if (fname)
153 DEBUGF("%s:%s, ", dw_lnct_name(lnct), fname);
154 else
155 DEBUGF("%s:unknown DW_FORM_(%" PRIu64 "), ", dw_lnct_name(lnct), form);
156 }
157
158 DEBUGF("\n");
159}
160
161void print_formatted_list(const char *name,
162 const uint8_t *data, const uint8_t *const data_end,
163 const uint8_t *format, const uint8_t *format_end,
164 unsigned width)
165{
166 DEBUGF("%s: ", name);
167
168 while (data < data_end) {
169 const uint8_t *old_data = data;
170 const uint8_t *format_ptr = format;
171
172 while (format_ptr < format_end) {
173 uint64_t lnct = read_uleb128(&format_ptr, format_end);
174 uint64_t form = read_uleb128(&format_ptr, format_end);
175
176 DEBUGF("%s:%s:", dw_lnct_name(lnct), dw_form_name(form));
177 print_formed_data(form, &data, data_end, width);
178 DEBUGF("\n");
179 }
180
181 if (data <= old_data)
182 break;
183 }
184
185 DEBUGF("\n");
186}
187
188void print_block(const uint8_t **const data,
189 const uint8_t *data_end, unsigned bytes)
190{
191 while (bytes > 0 && *data < data_end) {
192 DEBUGF("%02x ", **data);
193 (*data)++;
194 bytes--;
195 }
196}
197
198void print_formed_data(unsigned form, const uint8_t **const data,
199 const uint8_t *data_end, unsigned width)
200{
201 size_t len;
202 uint64_t offset;
203
204 switch (form) {
205 case DW_FORM_string:
206 DEBUGF("\"%s\"", read_string(data, data_end));
207 break;
208
209 case DW_FORM_strp:
210 case DW_FORM_strp_sup:
211 offset = read_uint(data, data_end, width);
212 if (offset >= debug_str_size)
213 DEBUGF("<out of range>");
214 else
215 DEBUGF("\"%s\"", debug_str + offset);
216 break;
217
218 case DW_FORM_line_strp:
219 offset = read_uint(data, data_end, width);
220 if (offset >= debug_line_str_size)
221 DEBUGF("<out of range>");
222 else
223 DEBUGF("\"%s\"", debug_line_str + offset);
224 break;
225
226 case DW_FORM_sec_offset:
227 if (width == 4)
228 DEBUGF("0x%08" PRIx64, read_uint(data, data_end, width));
229 else
230 DEBUGF("0x%016" PRIx64, read_uint(data, data_end, width));
231 break;
232
233 case DW_FORM_strx:
234 case DW_FORM_udata:
235 DEBUGF("%" PRIu64, read_uleb128(data, data_end));
236 break;
237
238 case DW_FORM_sdata:
239 DEBUGF("%" PRId64, read_sleb128(data, data_end));
240 break;
241
242 case DW_FORM_strx1:
243 case DW_FORM_data1:
244 case DW_FORM_flag:
245 DEBUGF("%u", read_byte(data, data_end));
246 break;
247
248 case DW_FORM_strx2:
249 case DW_FORM_data2:
250 DEBUGF("%u", read_uint16(data, data_end));
251 break;
252
253 case DW_FORM_strx3:
254 DEBUGF("%u", read_uint24(data, data_end));
255 break;
256
257 case DW_FORM_strx4:
258 case DW_FORM_data4:
259 DEBUGF("%u", read_uint32(data, data_end));
260 break;
261
262 case DW_FORM_data8:
263 DEBUGF("%" PRIu64, read_uint64(data, data_end));
264 break;
265
266 case DW_FORM_data16:
267 uint64_t data1 = read_uint64(data, data_end);
268 uint64_t data2 = read_uint64(data, data_end);
269 DEBUGF("0x%016" PRIx64 "%016" PRIx64, data2, data1);
270 break;
271
272 case DW_FORM_block:
273 len = read_uleb128(data, data_end);
274 print_block(data, data_end, len);
275 break;
276
277 case DW_FORM_block1:
278 len = read_byte(data, data_end);
279 print_block(data, data_end, len);
280 break;
281
282 case DW_FORM_block2:
283 len = read_uint16(data, data_end);
284 print_block(data, data_end, len);
285 break;
286
287 case DW_FORM_block4:
288 len = read_uint32(data, data_end);
289 print_block(data, data_end, len);
290 break;
291
292 default:
293 DEBUGF("unexpected form");
294 *data = data_end;
295 }
296}
Note: See TracBrowser for help on using the repository browser.