source: mainline/kernel/generic/src/debug/util.h@ 0373af9

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

ccheck

  • Property mode set to 100644
File size: 6.6 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#ifndef DEBUG_UTIL_H_
30#define DEBUG_UTIL_H_
31
32#include <assert.h>
33#include <stdint.h>
34#include <debug/constants.h>
35#include <debug.h>
36
37#define DEBUGF dummy_printf
38
39extern bool skip_data(unsigned, const uint8_t **const, const uint8_t *, unsigned);
40extern void print_format(const char *, const uint8_t *, const uint8_t *);
41extern void print_formatted_list(const char *, const uint8_t *, const uint8_t *,
42 const uint8_t *, const uint8_t *, unsigned);
43
44extern void print_block(const uint8_t **, const uint8_t *, unsigned);
45extern void print_formed_data(unsigned, const uint8_t **const, const uint8_t *, unsigned);
46
47inline uint8_t read_byte(const uint8_t **data, const uint8_t *data_end)
48{
49 if (*data >= data_end) {
50 return 0;
51 } else {
52 return *((*data)++);
53 }
54}
55
56/* Casting to these structures allows us to read unaligned integers safely. */
57struct u16 {
58 uint16_t val;
59} __attribute__((packed));
60
61struct u32 {
62 uint32_t val;
63} __attribute__((packed));
64
65struct u64 {
66 uint64_t val;
67} __attribute__((packed));
68
69inline uint16_t read_uint16(const uint8_t **data, const uint8_t *data_end)
70{
71 if (*data + 2 > data_end) {
72 /* Safe exit path for malformed input. */
73 *data = data_end;
74 return 0;
75 }
76
77 uint16_t v = ((struct u16 *) *data)->val;
78 *data += 2;
79 return v;
80}
81
82inline uint32_t read_uint24(const uint8_t **data, const uint8_t *data_end)
83{
84 if (*data + 3 > data_end) {
85 /* Safe exit path for malformed input. */
86 *data = data_end;
87 return 0;
88 }
89
90#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
91 uint32_t v = (*data)[0] | (*data)[1] << 8 | (*data)[2] << 16;
92#else
93 uint32_t v = (*data)[2] | (*data)[1] << 8 | (*data)[0] << 16;
94#endif
95
96 *data += 3;
97 return v;
98}
99
100inline uint32_t read_uint32(const uint8_t **data, const uint8_t *data_end)
101{
102 if (*data + 4 > data_end) {
103 /* Safe exit path for malformed input. */
104 *data = data_end;
105 return 0;
106 }
107
108 uint32_t v = ((struct u32 *) *data)->val;
109 *data += 4;
110 return v;
111}
112
113inline uint64_t read_uint64(const uint8_t **data, const uint8_t *data_end)
114{
115 if (*data + 8 > data_end) {
116 /* Safe exit path for malformed input. */
117 *data = data_end;
118 return 0;
119 }
120
121 uint64_t v = ((struct u64 *) *data)->val;
122 *data += 8;
123 return v;
124}
125
126inline uint64_t read_uint(const uint8_t **data, const uint8_t *data_end, unsigned bytes)
127{
128 switch (bytes) {
129 case 1:
130 return read_byte(data, data_end);
131 case 2:
132 return read_uint16(data, data_end);
133 case 4:
134 return read_uint32(data, data_end);
135 case 8:
136 return read_uint64(data, data_end);
137 default:
138 panic("unimplemented");
139 }
140}
141
142inline uint64_t read_uleb128(const uint8_t **data, const uint8_t *data_end)
143{
144 uint64_t result = 0;
145 unsigned shift = 0;
146
147 while (*data < data_end) {
148 uint8_t byte = *((*data)++);
149 result |= (byte & 0x7f) << shift;
150 shift += 7;
151
152 if ((byte & 0x80) == 0)
153 break;
154 }
155
156 return result;
157}
158
159inline int64_t read_sleb128(const uint8_t **data, const uint8_t *data_end)
160{
161 uint64_t result = 0;
162 unsigned shift = 0;
163
164 while (*data < data_end) {
165 uint8_t byte = *((*data)++);
166 result |= (byte & 0x7f) << shift;
167 shift += 7;
168
169 if ((byte & 0x80) == 0) {
170 if (shift < 64 && (byte & 0x40) != 0) {
171 /* sign extend */
172 result |= -(1 << shift);
173 }
174 break;
175 }
176 }
177
178 return (int64_t) result;
179}
180
181inline void skip_leb128(const uint8_t **data, const uint8_t *data_end)
182{
183 while (*data < data_end) {
184 uint8_t byte = *((*data)++);
185 if ((byte & 0x80) == 0)
186 break;
187 }
188}
189
190inline uint64_t read_initial_length(const uint8_t **data, const uint8_t *data_end, unsigned *width)
191{
192 uint32_t initial = read_uint32(data, data_end);
193 if (initial == 0xffffffffu) {
194 *width = 8;
195 return read_uint64(data, data_end);
196 } else {
197 *width = 4;
198 return initial;
199 }
200}
201
202inline const char *read_string(const uint8_t **data, const uint8_t *data_end)
203{
204 const char *start = (const char *) *data;
205
206 // NUL-terminated string.
207 while (*data < data_end && **data != 0)
208 (*data)++;
209
210 if (*data < data_end) {
211 // Skip the terminating zero.
212 (*data)++;
213 return start;
214 } else {
215 // No terminating zero, we can't use this.
216 return NULL;
217 }
218}
219
220inline void skip_string(const uint8_t **data, const uint8_t *data_end)
221{
222 (void) read_string(data, data_end);
223}
224
225inline void safe_increment(const uint8_t **data,
226 const uint8_t *data_end, ptrdiff_t increment)
227{
228 assert(data_end >= *data);
229
230 if (increment >= data_end - *data) {
231 *data = data_end;
232 } else {
233 (*data) += increment;
234 }
235}
236
237inline void skip_format(const uint8_t **data, const uint8_t *const data_end,
238 unsigned count)
239{
240 for (unsigned i = 0; i < count; i++) {
241 (void) read_uleb128(data, data_end);
242 (void) read_uleb128(data, data_end);
243 }
244}
245
246inline void skip_formatted_entry(const uint8_t **data, const uint8_t *const data_end,
247 const uint8_t *format, const uint8_t *format_end, unsigned width)
248{
249 while (format < format_end) {
250 /* Ignore content type code */
251 (void) read_uleb128(&format, format_end);
252
253 uint64_t form = read_uleb128(&format, format_end);
254 skip_data(form, data, data_end, width);
255 }
256}
257
258inline void skip_formatted_list(const uint8_t **data, const uint8_t *const data_end,
259 unsigned count, const uint8_t *format, const uint8_t *format_end,
260 unsigned width)
261{
262 for (unsigned i = 0; i < count; i++) {
263 skip_formatted_entry(data, data_end, format, format_end, width);
264 }
265}
266
267#endif /* DEBUG_UTIL_H_ */
Note: See TracBrowser for help on using the repository browser.