source: mainline/kernel/generic/src/lib/ubsan.c@ bec6379

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

Make it possible to set a breakpoint on ubsan_panic()

  • Property mode set to 100644
File size: 6.8 KB
Line 
1// SPDX-License-Identifier: BSD-2-Clause
2/*
3 * Copyright (c) 2016, Linaro Limited
4 */
5
6/* Modified for HelenOS use by Jiří Zárevúcky. */
7
8#include <stdbool.h>
9#include <stdint.h>
10#include <stddef.h>
11#include <panic.h>
12#include <memw.h>
13
14#define PRINTF(...) printf(__VA_ARGS__)
15
16struct source_location {
17 const char *file_name;
18 uint32_t line;
19 uint32_t column;
20};
21
22struct type_descriptor {
23 uint16_t type_kind;
24 uint16_t type_info;
25 char type_name[];
26};
27
28struct type_mismatch_data {
29 struct source_location loc;
30 struct type_descriptor *type;
31 unsigned long alignment;
32 unsigned char type_check_kind;
33};
34
35struct type_mismatch_data_v1 {
36 struct source_location loc;
37 struct type_descriptor *type;
38 unsigned char log_alignment;
39 unsigned char type_check_kind;
40};
41
42struct overflow_data {
43 struct source_location loc;
44 struct type_descriptor *type;
45};
46
47struct shift_out_of_bounds_data {
48 struct source_location loc;
49 struct type_descriptor *lhs_type;
50 struct type_descriptor *rhs_type;
51};
52
53struct out_of_bounds_data {
54 struct source_location loc;
55 struct type_descriptor *array_type;
56 struct type_descriptor *index_type;
57};
58
59struct unreachable_data {
60 struct source_location loc;
61};
62
63struct vla_bound_data {
64 struct source_location loc;
65 struct type_descriptor *type;
66};
67
68struct invalid_value_data {
69 struct source_location loc;
70 struct type_descriptor *type;
71};
72
73struct nonnull_arg_data {
74 struct source_location loc;
75};
76
77struct nonnull_return_data {
78 struct source_location loc;
79 struct source_location attr_loc;
80};
81
82struct pointer_overflow_data {
83 struct source_location loc;
84};
85
86/*
87 * When compiling with -fsanitize=undefined the compiler expects functions
88 * with the following signatures. The functions are never called directly,
89 * only when undefined behavior is detected in instrumented code.
90 */
91void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, unsigned long ptr);
92void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data, unsigned long ptr);
93void __ubsan_handle_add_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
94void __ubsan_handle_sub_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
95void __ubsan_handle_mul_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
96void __ubsan_handle_negate_overflow(struct overflow_data *data, unsigned long old_val);
97void __ubsan_handle_divrem_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs);
98void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, unsigned long lhs, unsigned long rhs);
99void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, unsigned long idx);
100void __ubsan_handle_unreachable(struct unreachable_data *data);
101void __ubsan_handle_missing_return(struct unreachable_data *data);
102void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, unsigned long bound);
103void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, unsigned long val);
104#if __GCC_VERSION < 60000
105void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data, size_t arg_no);
106#else
107void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data);
108#endif
109void __ubsan_handle_nonnull_return(struct nonnull_return_data *data);
110void __ubsan_handle_nonnull_return_v1(struct nonnull_return_data *data,
111 struct source_location *loc);
112void __ubsan_handle_pointer_overflow(struct pointer_overflow_data *data,
113 unsigned long base, unsigned long result);
114void __ubsan_handle_builtin_unreachable(struct unreachable_data *data);
115
116/* A real function for potential breakpoint location. */
117__attribute__((noinline))
118 static void ubsan_panic(void)
119{
120 panic("... aborting ...");
121}
122
123static void print_loc(const char *func, struct source_location *loc)
124{
125 const char *f = func;
126 const char func_prefix[] = "__ubsan_handle";
127
128 if (!memcmp(f, func_prefix, sizeof(func_prefix) - 1))
129 f += sizeof(func_prefix);
130
131 PRINTF("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32 "\n",
132 f, loc->file_name, loc->line, loc->column);
133}
134
135void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
136 unsigned long ptr)
137{
138 print_loc(__func__, &data->loc);
139 ubsan_panic();
140}
141
142void __ubsan_handle_add_overflow(struct overflow_data *data,
143 unsigned long lhs,
144 unsigned long rhs)
145{
146 print_loc(__func__, &data->loc);
147 ubsan_panic();
148}
149
150void __ubsan_handle_sub_overflow(struct overflow_data *data,
151 unsigned long lhs,
152 unsigned long rhs)
153{
154 print_loc(__func__, &data->loc);
155 ubsan_panic();
156}
157
158void __ubsan_handle_mul_overflow(struct overflow_data *data,
159 unsigned long lhs,
160 unsigned long rhs)
161{
162 print_loc(__func__, &data->loc);
163 ubsan_panic();
164}
165
166void __ubsan_handle_negate_overflow(struct overflow_data *data,
167 unsigned long old_val)
168{
169 print_loc(__func__, &data->loc);
170 ubsan_panic();
171}
172
173void __ubsan_handle_divrem_overflow(struct overflow_data *data,
174 unsigned long lhs,
175 unsigned long rhs)
176{
177 print_loc(__func__, &data->loc);
178 ubsan_panic();
179}
180
181void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
182 unsigned long lhs,
183 unsigned long rhs)
184{
185 print_loc(__func__, &data->loc);
186 PRINTF("LHS type: %s, value: %lu, RHS type: %s, value: %lu\n",
187 data->lhs_type->type_name, lhs, data->rhs_type->type_name, rhs);
188 ubsan_panic();
189}
190
191void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data,
192 unsigned long idx)
193{
194 print_loc(__func__, &data->loc);
195 ubsan_panic();
196}
197
198void __ubsan_handle_unreachable(struct unreachable_data *data)
199{
200 print_loc(__func__, &data->loc);
201 ubsan_panic();
202}
203
204void __ubsan_handle_missing_return(struct unreachable_data *data)
205{
206 print_loc(__func__, &data->loc);
207 ubsan_panic();
208}
209
210void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
211 unsigned long bound)
212{
213 print_loc(__func__, &data->loc);
214 ubsan_panic();
215}
216
217void __ubsan_handle_load_invalid_value(struct invalid_value_data *data,
218 unsigned long val)
219{
220 print_loc(__func__, &data->loc);
221 ubsan_panic();
222}
223
224#if __GCC_VERSION < 60000
225void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data, size_t arg_no)
226{
227 print_loc(__func__, &data->loc);
228 ubsan_panic();
229}
230#else
231void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data)
232{
233 print_loc(__func__, &data->loc);
234 ubsan_panic();
235}
236#endif
237
238void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
239{
240 print_loc(__func__, &data->loc);
241 ubsan_panic();
242}
243
244void __ubsan_handle_nonnull_return_v1(struct nonnull_return_data *data,
245 struct source_location *loc)
246{
247 print_loc(__func__, &data->loc);
248 ubsan_panic();
249}
250
251void __ubsan_handle_pointer_overflow(struct pointer_overflow_data *data,
252 unsigned long base, unsigned long result)
253{
254 print_loc(__func__, &data->loc);
255 ubsan_panic();
256}
257
258void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data,
259 unsigned long ptr)
260{
261 print_loc(__func__, &data->loc);
262 ubsan_panic();
263}
264
265void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
266{
267 print_loc(__func__, &data->loc);
268 ubsan_panic();
269}
Note: See TracBrowser for help on using the repository browser.