source: mainline/kernel/generic/src/debug/util.c

Last change on this file was 40eab9f, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 20 months ago

Print symbol names and line numbers in stacktraces for init tasks

Only useful in select few situations, but useful nonetheless.

  • Property mode set to 100644
File size: 6.4 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
35bool skip_data(unsigned form, const uint8_t **const data,
36 const uint8_t *data_end, unsigned width)
37{
38 // Skip data we don't care about reading.
39
40 size_t len;
41
42 switch (form) {
43 case DW_FORM_string:
44 skip_string(data, data_end);
45 break;
46
47 case DW_FORM_strp:
48 case DW_FORM_line_strp:
49 case DW_FORM_strp_sup:
50 case DW_FORM_sec_offset:
51 safe_increment(data, data_end, width);
52 break;
53
54 case DW_FORM_strx:
55 case DW_FORM_sdata:
56 case DW_FORM_udata:
57 skip_leb128(data, data_end);
58 break;
59
60 case DW_FORM_strx1:
61 case DW_FORM_data1:
62 case DW_FORM_flag:
63 safe_increment(data, data_end, 1);
64 break;
65
66 case DW_FORM_strx2:
67 case DW_FORM_data2:
68 safe_increment(data, data_end, 2);
69 break;
70
71 case DW_FORM_strx3:
72 safe_increment(data, data_end, 3);
73 break;
74
75 case DW_FORM_strx4:
76 case DW_FORM_data4:
77 safe_increment(data, data_end, 4);
78 break;
79
80 case DW_FORM_data8:
81 safe_increment(data, data_end, 8);
82 break;
83
84 case DW_FORM_data16:
85 safe_increment(data, data_end, 16);
86 break;
87
88 case DW_FORM_block:
89 len = read_uleb128(data, data_end);
90 safe_increment(data, data_end, len);
91 break;
92
93 case DW_FORM_block1:
94 len = read_byte(data, data_end);
95 safe_increment(data, data_end, len);
96 break;
97
98 case DW_FORM_block2:
99 len = read_uint16(data, data_end);
100 safe_increment(data, data_end, len);
101 break;
102
103 case DW_FORM_block4:
104 len = read_uint32(data, data_end);
105 safe_increment(data, data_end, len);
106 break;
107
108 default:
109 // Unknown FORM.
110 *data = data_end;
111 return false;
112 }
113
114 return true;
115}
116
117void print_format(const char *name, const uint8_t *format, const uint8_t *format_end)
118{
119 DEBUGF("%s: ", name);
120
121 while (format < format_end) {
122 uint64_t lnct = read_uleb128(&format, format_end);
123 uint64_t form = read_uleb128(&format, format_end);
124
125 const char *fname = dw_form_name(form);
126
127 if (fname)
128 DEBUGF("%s:%s, ", dw_lnct_name(lnct), fname);
129 else
130 DEBUGF("%s:unknown DW_FORM_(%" PRIu64 "), ", dw_lnct_name(lnct), form);
131 }
132
133 DEBUGF("\n");
134}
135
136void print_formatted_list(debug_sections_t *scs, const char *name,
137 const uint8_t *data, const uint8_t *const data_end,
138 const uint8_t *format, const uint8_t *format_end,
139 unsigned width)
140{
141 DEBUGF("%s: ", name);
142
143 while (data < data_end) {
144 const uint8_t *old_data = data;
145 const uint8_t *format_ptr = format;
146
147 while (format_ptr < format_end) {
148 uint64_t lnct = read_uleb128(&format_ptr, format_end);
149 uint64_t form = read_uleb128(&format_ptr, format_end);
150
151 DEBUGF("%s:%s:", dw_lnct_name(lnct), dw_form_name(form));
152 print_formed_data(scs, form, &data, data_end, width);
153 DEBUGF("\n");
154 }
155
156 if (data <= old_data)
157 break;
158 }
159
160 DEBUGF("\n");
161}
162
163void print_block(const uint8_t **const data,
164 const uint8_t *data_end, unsigned bytes)
165{
166 while (bytes > 0 && *data < data_end) {
167 DEBUGF("%02x ", **data);
168 (*data)++;
169 bytes--;
170 }
171}
172
173void print_formed_data(debug_sections_t *scs, unsigned form, const uint8_t **const data,
174 const uint8_t *data_end, unsigned width)
175{
176 size_t len;
177 uint64_t offset;
178
179 switch (form) {
180 case DW_FORM_string:
181 DEBUGF("\"%s\"", read_string(data, data_end));
182 break;
183
184 case DW_FORM_strp:
185 case DW_FORM_strp_sup:
186 offset = read_uint(data, data_end, width);
187 if (offset >= scs->debug_str_size)
188 DEBUGF("<out of range>");
189 else
190 DEBUGF("\"%s\"", scs->debug_str + offset);
191 break;
192
193 case DW_FORM_line_strp:
194 offset = read_uint(data, data_end, width);
195 if (offset >= scs->debug_line_str_size)
196 DEBUGF("<out of range>");
197 else
198 DEBUGF("\"%s\"", scs->debug_line_str + offset);
199 break;
200
201 case DW_FORM_sec_offset:
202 if (width == 4)
203 DEBUGF("0x%08" PRIx64, read_uint(data, data_end, width));
204 else
205 DEBUGF("0x%016" PRIx64, read_uint(data, data_end, width));
206 break;
207
208 case DW_FORM_strx:
209 case DW_FORM_udata:
210 DEBUGF("%" PRIu64, read_uleb128(data, data_end));
211 break;
212
213 case DW_FORM_sdata:
214 DEBUGF("%" PRId64, read_sleb128(data, data_end));
215 break;
216
217 case DW_FORM_strx1:
218 case DW_FORM_data1:
219 case DW_FORM_flag:
220 DEBUGF("%u", read_byte(data, data_end));
221 break;
222
223 case DW_FORM_strx2:
224 case DW_FORM_data2:
225 DEBUGF("%u", read_uint16(data, data_end));
226 break;
227
228 case DW_FORM_strx3:
229 DEBUGF("%u", read_uint24(data, data_end));
230 break;
231
232 case DW_FORM_strx4:
233 case DW_FORM_data4:
234 DEBUGF("%u", read_uint32(data, data_end));
235 break;
236
237 case DW_FORM_data8:
238 DEBUGF("%" PRIu64, read_uint64(data, data_end));
239 break;
240
241 case DW_FORM_data16:
242 uint64_t data1 = read_uint64(data, data_end);
243 uint64_t data2 = read_uint64(data, data_end);
244 DEBUGF("0x%016" PRIx64 "%016" PRIx64, data2, data1);
245 break;
246
247 case DW_FORM_block:
248 len = read_uleb128(data, data_end);
249 print_block(data, data_end, len);
250 break;
251
252 case DW_FORM_block1:
253 len = read_byte(data, data_end);
254 print_block(data, data_end, len);
255 break;
256
257 case DW_FORM_block2:
258 len = read_uint16(data, data_end);
259 print_block(data, data_end, len);
260 break;
261
262 case DW_FORM_block4:
263 len = read_uint32(data, data_end);
264 print_block(data, data_end, len);
265 break;
266
267 default:
268 DEBUGF("unexpected form");
269 *data = data_end;
270 }
271}
Note: See TracBrowser for help on using the repository browser.