1 #include <magic_selement.h>
2
3 /*===========================================================================*
4 * magic_selement_lookup_by_name *
5 *===========================================================================*/
magic_selement_lookup_by_name(char * name,_magic_selement_t * selement,struct _magic_dsentry * dsentry_buff)6 PUBLIC int magic_selement_lookup_by_name(char *name,
7 _magic_selement_t *selement, struct _magic_dsentry *dsentry_buff)
8 {
9 char token_buff[MAGIC_MAX_NAME_LEN * 2 + 2];
10 char *token_start = name;
11 int last_num_seps = 0;
12 char *s;
13 if (!name || *name == '\0' || *name == MAGIC_SELEMENT_SEP[0]) {
14 return MAGIC_ENOENT;
15 }
16 for (s = name; *s; s++) {
17 if (*(s + 1) == '\0' || *(s + 1) == MAGIC_SELEMENT_SEP[0]) {
18 size_t len = s - token_start + 1;
19 if (len >= MAGIC_MAX_NAME_LEN * 2 + 1) {
20 return MAGIC_ENOMEM;
21 }
22 strncpy(token_buff, token_start, len);
23 token_buff[len] = '\0';
24 if (token_start == name) {
25 struct _magic_sentry *sentry;
26 const char *sentry_parent_name = "", *sentry_name = NULL;
27 char *delim = NULL;
28 _magic_id_t dsentry_site_id = MAGIC_DSENTRY_SITE_ID_NULL;
29 if (!(delim = strchr(token_buff, MAGIC_DSENTRY_ABS_NAME_SEP[0]))) {
30 /* Regular sentry, no parent name or site_id. */
31 sentry_name = token_buff;
32 } else {
33 /*
34 * Dsentry. Will contain: sentry_id<DELIM>parent_name<DELIM>name<DELIM>site_id.
35 */
36 *delim = '\0';
37 /* Skip sentry_id */
38 sentry_parent_name = delim + 1;
39 delim = strchr(delim + 1, MAGIC_DSENTRY_ABS_NAME_SEP[0]);
40 assert(!delim && "No dsentry name found in selement name!");
41 *delim = '\0';
42 sentry_name = delim + 1;
43 delim = strchr(delim + 1, MAGIC_DSENTRY_ABS_NAME_SEP[0]);
44 assert(!delim && "No dsentry site id found in selement name!");
45 *delim = '\0';
46 dsentry_site_id = strtoul((const char*)delim+1, NULL, 10);
47 }
48
49 sentry = magic_sentry_lookup_by_name(sentry_parent_name, sentry_name,
50 dsentry_site_id, dsentry_buff);
51 if (!sentry) {
52 return MAGIC_ENOENT;
53 }
54 magic_selement_from_sentry(sentry, selement);
55 }
56 else {
57 _magic_selement_t child_selement;
58 if (!magic_selement_from_relative_name(selement, &child_selement, token_buff)) {
59 return MAGIC_ENOENT;
60 }
61 *selement = child_selement;
62 }
63 s++;
64 last_num_seps = 0;
65 while (*s == MAGIC_SELEMENT_SEP[0]) {
66 s++;
67 last_num_seps++;
68 }
69 token_start = s;
70 s--;
71 }
72 }
73 if (last_num_seps > 0 && selement->type->type_id == MAGIC_TYPE_POINTER) {
74 int steps = magic_selement_recurse_ptr(selement, selement, last_num_seps);
75 if(steps != last_num_seps) {
76 return MAGIC_EINVAL;
77 }
78 }
79
80 return 0;
81 }
82
83 /*===========================================================================*
84 * magic_selement_name_print_cb *
85 *===========================================================================*/
magic_selement_name_print_cb(const struct _magic_type * parent_type,const unsigned parent_offset,int child_num,const struct _magic_type * type,const unsigned offset,int depth,void * cb_args)86 PUBLIC int magic_selement_name_print_cb(const struct _magic_type* parent_type,
87 const unsigned parent_offset, int child_num,
88 const struct _magic_type* type, const unsigned offset, int depth, void* cb_args)
89 {
90 _magic_selement_t *selement = (_magic_selement_t*) cb_args;
91 struct _magic_sentry* sentry = selement->sentry;
92 void *address = (char*)sentry->address + offset;
93 void *range[2];
94 MAGIC_RANGE_SET_MIN(range, address);
95 MAGIC_RANGE_SET_MAX(range, (char*) address + type->size-1);
96 if(!MAGIC_ADDR_IS_IN_RANGE(selement->address, range)) {
97 return MAGIC_TYPE_WALK_SKIP_PATH;
98 }
99 if(address == sentry->address && type == sentry->type) {
100 magic_print_sentry_abs_name(sentry);
101 }
102 else {
103 short is_parent_array = parent_type->type_id == MAGIC_TYPE_ARRAY || parent_type->type_id == MAGIC_TYPE_VECTOR;
104 if(is_parent_array) {
105 _magic_printf("%s%d", MAGIC_SELEMENT_SEP, child_num);
106 }
107 else {
108 _magic_printf("%s%s", MAGIC_SELEMENT_SEP, parent_type->member_names[child_num]);
109 }
110 }
111 if(type->num_child_types == 0
112 || (address == selement->address && type == selement->type)) {
113 return MAGIC_TYPE_WALK_STOP;
114 }
115 return MAGIC_TYPE_WALK_CONTINUE;
116 }
117
118 /*===========================================================================*
119 * magic_selement_name_get_cb *
120 *===========================================================================*/
magic_selement_name_get_cb(const struct _magic_type * parent_type,const unsigned parent_offset,int child_num,const struct _magic_type * type,const unsigned offset,int depth,void * args_array)121 PUBLIC int magic_selement_name_get_cb(const struct _magic_type *parent_type,
122 const unsigned parent_offset, int child_num, const struct _magic_type *type,
123 const unsigned offset, int depth, void *args_array)
124 {
125 void **cb_args = (void **) args_array;
126
127 _magic_selement_t *selement = (_magic_selement_t*) cb_args[0];
128 char **buf = (char **) cb_args + 1;
129 int count, *buf_size = (int *) cb_args + 2;
130
131 short is_array = type->type_id == MAGIC_TYPE_ARRAY || type->type_id == MAGIC_TYPE_VECTOR;
132
133 struct _magic_sentry *sentry = selement->sentry;
134 void *address = (char *)sentry->address + offset;
135 void *range[2];
136 MAGIC_RANGE_SET_MIN(range, address);
137 MAGIC_RANGE_SET_MAX(range, (char *) address + type->size - 1);
138 if (!MAGIC_ADDR_IS_IN_RANGE(selement->address, range)) {
139 return MAGIC_TYPE_WALK_SKIP_PATH;
140 }
141
142 if (address == sentry->address && type == sentry->type) {
143 if (!(sentry->flags & MAGIC_STATE_DYNAMIC)) {
144 count = snprintf(*buf, *buf_size, "%s", sentry->name);
145 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
146 *buf += count;
147 *buf_size -= count;
148 } else {
149 struct _magic_dsentry *dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry);
150 assert(dsentry->parent_name && strcmp(dsentry->parent_name, ""));
151 assert(sentry->name && strcmp(sentry->name, ""));
152 count = snprintf(*buf, *buf_size, "%lu%s%s%s%s%s" MAGIC_ID_FORMAT,
153 (unsigned long)MAGIC_SENTRY_ID(sentry), MAGIC_DSENTRY_ABS_NAME_SEP,
154 dsentry->parent_name, MAGIC_DSENTRY_ABS_NAME_SEP, sentry->name,
155 MAGIC_DSENTRY_ABS_NAME_SEP, dsentry->site_id);
156 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
157 *buf += count;
158 *buf_size -= count;
159 }
160 } else {
161 short is_parent_array = parent_type->type_id == MAGIC_TYPE_ARRAY ||
162 parent_type->type_id == MAGIC_TYPE_VECTOR;
163 if (is_parent_array) {
164 count = snprintf(*buf, *buf_size, "%s%d",
165 MAGIC_SELEMENT_SEP, child_num);
166 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
167 *buf += count;
168 *buf_size -= count;
169 } else {
170 count = snprintf(*buf, *buf_size, "%s%s",
171 MAGIC_SELEMENT_SEP, parent_type->member_names[child_num]);
172 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
173 *buf += count;
174 *buf_size -= count;
175 }
176 }
177
178 if (type->num_child_types == 0
179 || (address == selement->address && type == selement->type)
180 || (is_array && address == selement->address && type == selement->parent_type)) {
181 return MAGIC_TYPE_WALK_STOP;
182 }
183
184 return MAGIC_TYPE_WALK_CONTINUE;
185 }
186
187 /*===========================================================================*
188 * magic_selement_print_value *
189 *===========================================================================*/
magic_selement_print_value(const _magic_selement_t * selement)190 PUBLIC void magic_selement_print_value(const _magic_selement_t *selement)
191 {
192 int type_id = selement->type->type_id;
193 unsigned size = selement->type->size;
194 double dvalue;
195 void *pvalue;
196 unsigned long uvalue;
197 long ivalue;
198 char vvalue;
199 switch(type_id) {
200 case MAGIC_TYPE_FLOAT:
201 dvalue = magic_selement_to_float(selement);
202 _magic_printf("float(%d):%g", size, dvalue);
203 _magic_printf("/%d", (long) dvalue);
204 break;
205
206 case MAGIC_TYPE_POINTER:
207 pvalue = magic_selement_to_ptr(selement);
208 _magic_printf("ptr:%08x", pvalue);
209 break;
210
211 case MAGIC_TYPE_INTEGER:
212 case MAGIC_TYPE_ENUM:
213 if(MAGIC_TYPE_FLAG(selement->type, MAGIC_TYPE_UNSIGNED)) {
214 uvalue = magic_selement_to_unsigned(selement);
215 _magic_printf("unsigned %s(%d):%u", type_id == MAGIC_TYPE_INTEGER ? "int" : "enum", size, uvalue);
216 }
217 else {
218 ivalue = magic_selement_to_int(selement);
219 _magic_printf("%s(%d):%d", type_id == MAGIC_TYPE_INTEGER ? "int" : "enum", size, ivalue);
220 }
221 break;
222
223 case MAGIC_TYPE_VOID:
224 vvalue = *((char*) selement->address);
225 _magic_printf("void(%d):%d", size, vvalue);
226 break;
227
228 default:
229 _magic_printf("???");
230 break;
231 }
232 }
233
234 /*===========================================================================*
235 * magic_selement_to_unsigned *
236 *===========================================================================*/
magic_selement_to_unsigned(const _magic_selement_t * selement)237 PUBLIC unsigned long magic_selement_to_unsigned(const _magic_selement_t *selement)
238 {
239 void *address = selement->address;
240 const struct _magic_type* type = selement->type;
241 unsigned long value = 0;
242 unsigned size = type->size;
243 assert(size > 0);
244 assert(type->type_id == MAGIC_TYPE_INTEGER
245 || type->type_id == MAGIC_TYPE_ENUM);
246
247 if(address == NULL)
248 return 0;
249
250 if(size == sizeof(unsigned char)) {
251 value = (unsigned long) *((unsigned char*) address);
252 }
253 else if(size == sizeof(unsigned short)) {
254 value = (unsigned long) *((unsigned short*) address);
255 }
256 #ifdef MAGIC_LONG_LONG_SUPPORTED
257 else if(size == sizeof(unsigned long long)) {
258 value = (unsigned long) *((unsigned long long*) address);
259 }
260 #endif
261 else {
262 assert(size == sizeof(unsigned long));
263 value = *((unsigned long*) address);
264 }
265
266 return value;
267 }
268
269 /*===========================================================================*
270 * magic_selement_to_int *
271 *===========================================================================*/
magic_selement_to_int(const _magic_selement_t * selement)272 PUBLIC long magic_selement_to_int(const _magic_selement_t *selement)
273 {
274 void *address = selement->address;
275 const struct _magic_type* type = selement->type;
276 long value = 0;
277 unsigned size = type->size;
278 assert(size > 0);
279 assert(type->type_id == MAGIC_TYPE_INTEGER
280 || type->type_id == MAGIC_TYPE_ENUM);
281
282 if(address == NULL)
283 return 0;
284
285 if(size == sizeof(char)) {
286 value = (long) *((char*) address);
287 }
288 else if(size == sizeof(short)) {
289 value = (long) *((short*) address);
290 }
291 #ifdef MAGIC_LONG_LONG_SUPPORTED
292 else if(size == sizeof(long long)) {
293 value = (long) *((long long*) address);
294 }
295 #endif
296 else {
297 assert(size == sizeof(long));
298 value = *((long*) address);
299 }
300
301 return value;
302 }
303
304 #ifdef MAGIC_LONG_LONG_SUPPORTED
305 /*===========================================================================*
306 * magic_selement_to_llu *
307 *===========================================================================*/
magic_selement_to_llu(const _magic_selement_t * selement)308 PUBLIC unsigned long long magic_selement_to_llu(const _magic_selement_t *selement)
309 {
310 void *address = selement->address;
311 const struct _magic_type* type = selement->type;
312 unsigned long long value;
313 unsigned size = type->size;
314
315 if(address == NULL)
316 return 0;
317
318 if (size == sizeof(unsigned long long))
319 value = *((unsigned long long*) address);
320 else
321 value = (unsigned long long) magic_selement_to_unsigned(selement);
322 return value;
323 }
324
325 /*===========================================================================*
326 * magic_selement_to_ll *
327 *===========================================================================*/
magic_selement_to_ll(const _magic_selement_t * selement)328 PUBLIC long long magic_selement_to_ll(const _magic_selement_t *selement)
329 {
330 void *address = selement->address;
331 const struct _magic_type* type = selement->type;
332 long long value;
333 unsigned size = type->size;
334
335 if(address == NULL)
336 return 0;
337
338 if (size == sizeof(long long))
339 value = *((long long*) address);
340 else
341 value = (long long) magic_selement_to_int(selement);
342 return value;
343 }
344 #endif
345
346 /*===========================================================================*
347 * magic_selement_to_float *
348 *===========================================================================*/
magic_selement_to_float(const _magic_selement_t * selement)349 PUBLIC double magic_selement_to_float(const _magic_selement_t *selement)
350 {
351 void *address = selement->address;
352 const struct _magic_type* type = selement->type;
353 double value = 0.0;
354 unsigned size = type->size;
355 assert(size > 0);
356 assert(type->type_id == MAGIC_TYPE_FLOAT);
357
358 if(address == NULL)
359 return 0;
360
361 if(size == sizeof(float)) {
362 value = (double) *((float*) address);
363 }
364 #ifdef MAGIC_LONG_DOUBLE_SUPPORTED
365 else if(size == sizeof(long double)) {
366 value = (double) *((long double*) address);
367 }
368 #endif
369 else {
370 assert(size == sizeof(double));
371 value = *((double*) address);
372 }
373
374 return value;
375 }
376
377 /*===========================================================================*
378 * magic_selement_to_ptr *
379 *===========================================================================*/
magic_selement_to_ptr(const _magic_selement_t * selement)380 PUBLIC void* magic_selement_to_ptr(const _magic_selement_t *selement)
381 {
382 void *address = selement->address;
383 const struct _magic_type* type = selement->type;
384 void* value = NULL;
385 assert(type->type_id == MAGIC_TYPE_POINTER);
386
387 if (!address)
388 return NULL;
389 value = *((void**) address);
390 return value;
391 }
392
393 /*===========================================================================*
394 * magic_selement_from_unsigned *
395 *===========================================================================*/
magic_selement_from_unsigned(const _magic_selement_t * selement,unsigned long value)396 PUBLIC void magic_selement_from_unsigned(const _magic_selement_t *selement, unsigned long value)
397 {
398 void *address = selement->address;
399 const struct _magic_type* type = selement->type;
400 unsigned size = type->size;
401 assert(size > 0);
402 assert(type->type_id == MAGIC_TYPE_INTEGER
403 || type->type_id == MAGIC_TYPE_ENUM);
404
405 /* Prevent a store to NULL. */
406 if(address == NULL)
407 return;
408
409 if(size == sizeof(unsigned char)) {
410 *((unsigned char*) address) = (unsigned char) value;
411 }
412 else if(size == sizeof(unsigned short)) {
413 *((unsigned short*) address) = (unsigned short) value;
414 }
415 #ifdef MAGIC_LONG_LONG_SUPPORTED
416 else if(size == sizeof(unsigned long long)) {
417 *((unsigned long long*) address) = (unsigned long long) value;
418 }
419 #endif
420 else {
421 assert(size == sizeof(unsigned long));
422 *((unsigned long*) address) = (unsigned long) value;
423 }
424 }
425
426 /*===========================================================================*
427 * magic_selement_from_int *
428 *===========================================================================*/
magic_selement_from_int(const _magic_selement_t * selement,long value)429 PUBLIC void magic_selement_from_int(const _magic_selement_t *selement, long value)
430 {
431 void *address = selement->address;
432 const struct _magic_type* type = selement->type;
433 unsigned size = type->size;
434 assert(size > 0);
435 assert(type->type_id == MAGIC_TYPE_INTEGER
436 || type->type_id == MAGIC_TYPE_ENUM);
437
438 /* Prevent a store to NULL. */
439 if(address == NULL)
440 return;
441
442 if(size == sizeof(char)) {
443 *((char*) address) = (char) value;
444 }
445 else if(size == sizeof(short)) {
446 *((short*) address) = (short) value;
447 }
448 #ifdef MAGIC_LONG_LONG_SUPPORTED
449 else if(size == sizeof(long long)) {
450 *((long long*) address) = (long long) value;
451 }
452 #endif
453 else {
454 assert(size == sizeof(long));
455 *((long*) address) = (long) value;
456 }
457 }
458
459 /*===========================================================================*
460 * magic_selement_from_float *
461 *===========================================================================*/
magic_selement_from_float(const _magic_selement_t * selement,double value)462 PUBLIC void magic_selement_from_float(const _magic_selement_t *selement, double value)
463 {
464 void *address = selement->address;
465 const struct _magic_type* type = selement->type;
466 unsigned size = type->size;
467 assert(size > 0);
468 assert(type->type_id == MAGIC_TYPE_FLOAT);
469
470 /* Prevent a store to NULL. */
471 if(address == NULL)
472 return;
473
474 if(size == sizeof(float)) {
475 *((float*) address) = (float) value;
476 }
477 #ifdef MAGIC_LONG_DOUBLE_SUPPORTED
478 else if(size == sizeof(long double)) {
479 *((long double*) address) = (long double) value;
480 }
481 #endif
482 else {
483 assert(size == sizeof(double));
484 *((double*) address) = (double) value;
485 }
486 }
487
488 /*===========================================================================*
489 * magic_selement_ptr_value_cast *
490 *===========================================================================*/
magic_selement_ptr_value_cast(const _magic_selement_t * src_selement,const _magic_selement_t * dst_selement,void * value_buffer)491 PUBLIC int magic_selement_ptr_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
492 {
493 int src_type_id = src_selement->type->type_id;
494 int dst_type_id = dst_selement->type->type_id;
495 unsigned src_size = src_selement->type->size;
496 unsigned dst_size = dst_selement->type->size;
497 void* src_value;
498 int r = 0;
499 assert(dst_size > 0);
500
501 if(dst_type_id != MAGIC_TYPE_POINTER) {
502 return EINVAL;
503 }
504 assert(dst_size == sizeof(void*));
505 if(src_size != sizeof(void*)) {
506 return EINVAL;
507 }
508 switch(src_type_id) {
509 case MAGIC_TYPE_POINTER:
510 return 0;
511 break;
512
513 case MAGIC_TYPE_INTEGER:
514 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
515 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, void*, &r, 0);
516 assert(r == 0);
517 }
518 else {
519 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, void*, &r, 0);
520 assert(r == 0);
521 }
522 break;
523
524 default:
525 return EINVAL;
526 break;
527 }
528
529 MAGIC_CHECKED_VALUE_DST_CAST(src_value, void*, value_buffer, void*, &r);
530 assert(r == 0);
531
532 return dst_size;
533 }
534
535 /*===========================================================================*
536 * magic_selement_unsigned_value_cast *
537 *===========================================================================*/
magic_selement_unsigned_value_cast(const _magic_selement_t * src_selement,const _magic_selement_t * dst_selement,void * value_buffer)538 PUBLIC int magic_selement_unsigned_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
539 {
540 int src_type_id = src_selement->type->type_id;
541 int dst_type_id = dst_selement->type->type_id;
542 int r = 0;
543 unsigned src_size = src_selement->type->size;
544 unsigned dst_size = dst_selement->type->size;
545 unsigned long src_value;
546 assert(dst_size > 0);
547
548 if(dst_type_id != MAGIC_TYPE_INTEGER && dst_type_id != MAGIC_TYPE_ENUM) {
549 return EINVAL;
550 }
551 switch(src_type_id) {
552 case MAGIC_TYPE_FLOAT:
553 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, unsigned long, &r, 1);
554 break;
555
556 case MAGIC_TYPE_POINTER:
557 if(dst_size != sizeof(void*)) {
558 return EINVAL;
559 }
560 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_ptr(src_selement), void*, src_value, unsigned long, &r, 0);
561 assert(r == 0);
562 break;
563
564 case MAGIC_TYPE_INTEGER:
565 case MAGIC_TYPE_ENUM:
566 if(src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
567 return 0;
568 }
569 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
570 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, unsigned long, &r, 0);
571 assert(r == 0);
572 }
573 else {
574 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, unsigned long, &r, 1);
575 }
576 break;
577
578 default:
579 return EINVAL;
580 break;
581 }
582
583 switch(dst_size) {
584 case sizeof(unsigned char):
585 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned char, &r);
586 break;
587
588 case sizeof(unsigned short):
589 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned short, &r);
590 break;
591
592 case sizeof(unsigned int):
593 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned int, &r);
594 break;
595
596 #ifdef MAGIC_LONG_LONG_SUPPORTED
597 case sizeof(unsigned long long):
598 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned long long, &r);
599 break;
600 #endif
601
602 default:
603 return EINVAL;
604 break;
605 }
606
607 if(r == 0) {
608 r = dst_size;
609 }
610
611 return r;
612 }
613
614 /*===========================================================================*
615 * magic_selement_int_value_cast *
616 *===========================================================================*/
magic_selement_int_value_cast(const _magic_selement_t * src_selement,const _magic_selement_t * dst_selement,void * value_buffer)617 PUBLIC int magic_selement_int_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
618 {
619 int src_type_id = src_selement->type->type_id;
620 int dst_type_id = dst_selement->type->type_id;
621 int r = 0;
622 unsigned src_size = src_selement->type->size;
623 unsigned dst_size = dst_selement->type->size;
624 long src_value;
625 assert(dst_size > 0);
626
627 if(dst_type_id != MAGIC_TYPE_INTEGER && dst_type_id != MAGIC_TYPE_ENUM) {
628 return EINVAL;
629 }
630
631 switch(src_type_id) {
632 case MAGIC_TYPE_FLOAT:
633 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, long, &r, 1);
634 break;
635
636 case MAGIC_TYPE_POINTER:
637 if(dst_size != sizeof(void*)) {
638 return EINVAL;
639 }
640 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_ptr(src_selement), void*, src_value, long, &r, 0);
641 assert(r == 0);
642 break;
643
644 case MAGIC_TYPE_INTEGER:
645 case MAGIC_TYPE_ENUM:
646 if(src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
647 return 0;
648 }
649 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
650 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, long, &r, 1);
651 }
652 else {
653 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, long, &r, 0);
654 assert(r == 0);
655 }
656 break;
657
658 default:
659 return EINVAL;
660 break;
661 }
662
663 switch(dst_size) {
664 case sizeof(char):
665 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, char, &r);
666 break;
667
668 case sizeof(short):
669 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, short, &r);
670 break;
671
672 case sizeof(int):
673 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, int, &r);
674 break;
675
676 #ifdef MAGIC_LONG_LONG_SUPPORTED
677 case sizeof(long long):
678 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, long long, &r);
679 break;
680 #endif
681
682 default:
683 return EINVAL;
684 break;
685 }
686
687 if(r == 0) {
688 r = dst_size;
689 }
690
691 return r;
692 }
693
694 /*===========================================================================*
695 * magic_selement_float_value_cast *
696 *===========================================================================*/
magic_selement_float_value_cast(const _magic_selement_t * src_selement,const _magic_selement_t * dst_selement,void * value_buffer)697 PUBLIC int magic_selement_float_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
698 {
699 int src_type_id = src_selement->type->type_id;
700 int dst_type_id = dst_selement->type->type_id;
701 int r = 0;
702 unsigned src_size = src_selement->type->size;
703 unsigned dst_size = dst_selement->type->size;
704 double src_value;
705 assert(dst_size > 0);
706
707 if(dst_type_id != MAGIC_TYPE_FLOAT) {
708 return EINVAL;
709 }
710 switch(src_type_id) {
711 case MAGIC_TYPE_FLOAT:
712 if(src_size == dst_size) {
713 return 0;
714 }
715 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, double, &r, 0);
716 assert(r == 0);
717 break;
718
719 case MAGIC_TYPE_INTEGER:
720 case MAGIC_TYPE_ENUM:
721 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
722 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, double, &r, 1);
723 }
724 else {
725 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, double, &r, 1);
726 }
727 break;
728
729 default:
730 return EINVAL;
731 break;
732 }
733
734
735 switch(dst_size) {
736 case sizeof(float):
737 MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, float, &r);
738 break;
739
740 case sizeof(double):
741 MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, double, &r);
742 break;
743
744 #ifdef MAGIC_LONG_DOUBLE_SUPPORTED
745 case sizeof(long double):
746 MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, long double, &r);
747 break;
748 #endif
749
750 default:
751 return EINVAL;
752 break;
753 }
754
755 if(r == 0) {
756 r = dst_size;
757 }
758
759 return r;
760 }
761
762 /*===========================================================================*
763 * magic_selement_value_cast *
764 *===========================================================================*/
magic_selement_value_cast(const _magic_selement_t * src_selement,const _magic_selement_t * dst_selement,void * value_buffer)765 PUBLIC int magic_selement_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
766 {
767 int r, src_type_id, dst_type_id;
768 size_t src_size, dst_size;
769 src_type_id = src_selement->type->type_id;
770 dst_type_id = dst_selement->type->type_id;
771 src_size = src_selement->type->size;
772 dst_size = dst_selement->type->size;
773 if(src_type_id == dst_type_id && src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
774 return 0;
775 }
776
777 /* No size change allowed in opaque value casts. */
778 if(src_type_id == MAGIC_TYPE_OPAQUE || dst_type_id == MAGIC_TYPE_OPAQUE) {
779 return src_size == dst_size ? 0 : EINVAL;
780 }
781
782 /* No size change allowed in void value casts. */
783 if(src_type_id == MAGIC_TYPE_VOID || dst_type_id == MAGIC_TYPE_VOID) {
784 return src_size == dst_size ? 0 : EINVAL;
785 }
786
787 switch(dst_type_id) {
788 case MAGIC_TYPE_POINTER:
789 /* Cast to pointer values. */
790 r = magic_selement_ptr_value_cast(src_selement, dst_selement, value_buffer);
791 break;
792
793 case MAGIC_TYPE_FLOAT:
794 /* Cast to float values. */
795 r = magic_selement_float_value_cast(src_selement, dst_selement, value_buffer);
796 break;
797
798 case MAGIC_TYPE_INTEGER:
799 case MAGIC_TYPE_ENUM:
800 if(MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
801 /* Cast to unsigned values. */
802 r = magic_selement_unsigned_value_cast(src_selement, dst_selement, value_buffer);
803 }
804 else {
805 /* Cast to integer values. */
806 r = magic_selement_int_value_cast(src_selement, dst_selement, value_buffer);
807 }
808 break;
809
810 default:
811 r = EINVAL;
812 break;
813 }
814 return r;
815 }
816
817 /*===========================================================================*
818 * magic_selement_get_parent *
819 *===========================================================================*/
magic_selement_get_parent(const _magic_selement_t * selement,_magic_selement_t * parent_selement)820 PUBLIC _magic_selement_t* magic_selement_get_parent(
821 const _magic_selement_t *selement, _magic_selement_t *parent_selement)
822 {
823 if(!selement->parent_type) {
824 return NULL;
825 }
826
827 parent_selement->sentry = selement->sentry;
828 parent_selement->parent_type = NULL;
829 parent_selement->child_num = 0;
830 parent_selement->type = selement->parent_type;
831 parent_selement->address = selement->parent_address;
832 parent_selement->num = 0;
833 assert(parent_selement->address >= parent_selement->sentry->address);
834
835 return parent_selement;
836 }
837
838 /*===========================================================================*
839 * magic_selement_fill_from_parent_info *
840 *===========================================================================*/
magic_selement_fill_from_parent_info(_magic_selement_t * selement,int walk_flags)841 PUBLIC void magic_selement_fill_from_parent_info(_magic_selement_t *selement,
842 int walk_flags)
843 {
844 unsigned offset;
845 magic_type_walk_step(selement->parent_type,
846 selement->child_num, &selement->type, &offset, walk_flags);
847 selement->address = (char*) selement->parent_address + offset;
848 }
849
850 /*===========================================================================*
851 * magic_selement_from_sentry *
852 *===========================================================================*/
magic_selement_from_sentry(struct _magic_sentry * sentry,_magic_selement_t * selement)853 PUBLIC _magic_selement_t* magic_selement_from_sentry(struct _magic_sentry *sentry,
854 _magic_selement_t *selement)
855 {
856 selement->sentry = sentry;
857 selement->parent_type = NULL;
858 selement->child_num = 0;
859 selement->type = sentry->type;
860 selement->address = sentry->address;
861 selement->num = 1;
862
863 return selement;
864 }
865
866 /*===========================================================================*
867 * magic_selement_from_relative_name *
868 *===========================================================================*/
magic_selement_from_relative_name(_magic_selement_t * parent_selement,_magic_selement_t * selement,char * name)869 PUBLIC _magic_selement_t* magic_selement_from_relative_name(
870 _magic_selement_t *parent_selement, _magic_selement_t *selement, char* name)
871 {
872 _magic_selement_t new_parent_selement;
873 const struct _magic_type* parent_type = parent_selement->type;
874 int parent_type_id = parent_type->type_id;
875 int walk_flags = 0;
876 int i, child_num = -1;
877 char *end;
878
879 if(!name || *name == '\0') {
880 return NULL;
881 }
882
883 if(parent_type_id == MAGIC_TYPE_UNION && (*name >= '0' && *name <= '9')) {
884 parent_type_id = MAGIC_TYPE_ARRAY;
885 walk_flags = MAGIC_TYPE_WALK_UNIONS_AS_VOID;
886 }
887
888 switch(parent_type_id) {
889 case MAGIC_TYPE_ARRAY:
890 case MAGIC_TYPE_VECTOR:
891 child_num = (int) strtol(name, &end, 10);
892 if(end == name || *end != '\0' || errno == ERANGE) {
893 return NULL;
894 }
895 break;
896
897 case MAGIC_TYPE_STRUCT:
898 case MAGIC_TYPE_UNION:
899 for(i=0; (unsigned int)i<parent_type->num_child_types;i++) {
900 if(!strcmp(parent_type->member_names[i], name)) {
901 child_num = i;
902 break;
903 }
904 }
905 if((unsigned int)i == parent_type->num_child_types) {
906 return NULL;
907 }
908 break;
909
910 case MAGIC_TYPE_POINTER:
911 i = magic_selement_recurse_ptr(parent_selement, selement, MAGIC_SELEMENT_MAX_PTR_RECURSIONS);
912 if(i <= 0 || i >= MAGIC_SELEMENT_MAX_PTR_RECURSIONS) {
913 return NULL;
914 }
915 new_parent_selement = *selement;
916 return magic_selement_from_relative_name(&new_parent_selement, selement, name);
917 break;
918
919 default:
920 return NULL;
921 break;
922 }
923
924 if(child_num != -1) {
925 selement->sentry = parent_selement->sentry;
926 selement->parent_type = parent_type;
927 selement->parent_address = parent_selement->address;
928 selement->child_num = child_num;
929 selement->num = parent_selement->num+1;
930 magic_selement_fill_from_parent_info(selement, walk_flags);
931 }
932
933 return selement;
934 }
935
936