Arion 1.0.2-alpha
A high-performance C++ framework for emulating executable binaries.
 
Loading...
Searching...
No Matches
struct_utils.hpp
Go to the documentation of this file.
1#ifndef ARION_STRUCT_UTILS_HPP
2#define ARION_STRUCT_UTILS_HPP
3
8#include <cstdint>
9#include <map>
10#include <memory>
11#include <sstream>
12#include <stack>
13#include <string>
14#include <vector>
15
17{
19using STRUCT_ID = uint64_t;
20
22inline std::map<arion::CPU_ARCH, uint8_t> ALIGN_BY_ARCH{
27};
28
30inline std::map<arion::CPU_ARCH, uint8_t> PTR_SZ_BY_ARCH{
35};
36
38inline std::map<arion::CPU_ARCH, uint16_t> ARCH_SZ{
43};
44
69
93
133
136{
137 private:
139 std::map<std::string, uint64_t> int_vals;
141 std::map<std::string, void *> arr_vals;
142
143 public:
148 {
149 for (auto arr_it : this->arr_vals)
150 free(arr_it.second);
151 }
153 void set_field(std::string name, uint64_t val)
154 {
155 this->int_vals[name] = val;
156 }
158 void set_field(std::string name, void *arr)
159 {
160 auto arr_it = this->arr_vals.find(name);
161 if (arr_it != this->arr_vals.end())
162 free(arr_it->second);
163 this->arr_vals[name] = arr;
164 }
166 bool has_int_field(std::string name)
167 {
168 auto int_it = this->int_vals.find(name);
169 return int_it != this->int_vals.end();
170 }
172 uint64_t get_int_field(std::string name)
173 {
174 auto int_it = this->int_vals.find(name);
175 if (int_it == this->int_vals.end())
177 return int_it->second;
178 }
180 bool has_arr_field(std::string name)
181 {
182 auto arr_it = this->arr_vals.find(name);
183 return arr_it != this->arr_vals.end();
184 }
186 void *get_arr_field(std::string name)
187 {
188 auto arr_it = this->arr_vals.find(name);
189 if (arr_it == this->arr_vals.end())
191 return arr_it->second;
192 }
193};
194
199template <typename T> class PolymorphicStructFactory
200{
201 private:
205 std::stack<STRUCT_ID> free_ids;
207 std::map<STRUCT_ID, std::unique_ptr<PolymorphicStruct>> curr_structs;
209 std::vector<POLYMORPHIC_STRUCT_FIELD> fields;
210
216 {
217 STRUCT_ID id;
218 if (!this->free_ids.empty())
219 {
220 id = this->free_ids.top();
221 this->free_ids.pop();
222 }
223 else
224 {
225 if (this->curr_id == ARION_MAX_U64)
227 id = this->curr_id++;
228 }
229 return id;
230 }
231
237 STRUCT_ID add_struct_entry(std::unique_ptr<PolymorphicStruct> struct_inst)
238 {
239 STRUCT_ID id = this->gen_next_id();
240 this->curr_structs[id] = std::move(struct_inst);
241 return id;
242 }
243
250 {
251 auto align_it = ALIGN_BY_ARCH.find(arch);
252 if (align_it == ALIGN_BY_ARCH.end())
254 return align_it->second;
255 }
256
263 {
264 auto ptr_sz_it = PTR_SZ_BY_ARCH.find(arch);
265 if (ptr_sz_it == PTR_SZ_BY_ARCH.end())
267 return ptr_sz_it->second;
268 }
269
276 {
277 auto arch_sz_it = ARCH_SZ.find(arch);
278 if (arch_sz_it == ARCH_SZ.end())
280 return arch_sz_it->second;
281 }
282
283 protected:
288 PolymorphicStructFactory(std::vector<POLYMORPHIC_STRUCT_FIELD> fields) : fields(std::move(fields)) {};
293 {
294 this->clear_structs();
295 }
296
299
300 public:
308 {
309 size_t struct_sz = 0;
310 uint8_t align = this->get_align(arch);
311 uint8_t ptr_sz = this->get_ptr_sz(arch);
312 uint16_t arch_sz = this->get_arch_sz(arch);
313 for (POLYMORPHIC_STRUCT_FIELD field : this->fields)
314 {
315 if (field.constraint.arch != arion::CPU_ARCH::UNKNOWN_ARCH && arch != field.constraint.arch)
316 continue;
317 if (field.constraint.arch_sz != 0 && arch_sz != field.constraint.arch_sz)
318 continue;
319
320 switch (field.type)
321 {
322 case V8: {
323 uint8_t val;
324 struct_sz += sizeof(uint8_t);
325 break;
326 }
327 case V16: {
328 if (struct_sz % sizeof(uint16_t))
329 struct_sz += sizeof(uint16_t) - (struct_sz % sizeof(uint16_t));
330 struct_sz += sizeof(uint16_t);
331 break;
332 }
333 case V32: {
334 if (struct_sz % sizeof(uint32_t))
335 struct_sz += sizeof(uint32_t) - (struct_sz % sizeof(uint32_t));
336 struct_sz += sizeof(uint32_t);
337 break;
338 }
339 case V64: {
340 if (struct_sz % sizeof(uint64_t))
341 struct_sz += sizeof(uint64_t) - (struct_sz % sizeof(uint64_t));
342 struct_sz += sizeof(uint64_t);
343 break;
344 }
345 case PTR_SZ: {
346 if (struct_sz % ptr_sz)
347 struct_sz += ptr_sz - (struct_sz % ptr_sz);
348 struct_sz += ptr_sz;
349 break;
350 }
351 case A8: {
352 size_t arr_sz = field.sz * sizeof(uint8_t);
353 struct_sz += arr_sz;
354 break;
355 }
356 case A16: {
357 if (struct_sz % sizeof(uint16_t))
358 struct_sz += sizeof(uint16_t) - (struct_sz % sizeof(uint16_t));
359 size_t arr_sz = field.sz * sizeof(uint16_t);
360 struct_sz += arr_sz;
361 break;
362 }
363 case A32: {
364 if (struct_sz % sizeof(uint32_t))
365 struct_sz += sizeof(uint32_t) - (struct_sz % sizeof(uint32_t));
366 size_t arr_sz = field.sz * sizeof(uint32_t);
367 struct_sz += arr_sz;
368 break;
369 }
370 case A64: {
371 if (struct_sz % sizeof(uint64_t))
372 struct_sz += sizeof(uint64_t) - (struct_sz % sizeof(uint64_t));
373 size_t arr_sz = field.sz * sizeof(uint64_t);
374 struct_sz += arr_sz;
375 break;
376 }
377 case PTR_ARR: {
378 if (struct_sz % ptr_sz)
379 struct_sz += ptr_sz - (struct_sz % ptr_sz);
380 size_t arr_sz = field.sz * ptr_sz;
381 struct_sz += arr_sz;
382 break;
383 }
384 default:
385 break;
386 }
387 }
388 if (struct_sz % align)
389 {
390 uint8_t align_sz = align - (struct_sz % align);
391 struct_sz += align_sz;
392 }
393 return struct_sz;
394 }
395
401 {
403 }
404
412 {
413 uint8_t align = this->get_align(arch);
414 uint8_t ptr_sz = this->get_ptr_sz(arch);
415 uint16_t arch_sz = this->get_arch_sz(arch);
416 std::unique_ptr<PolymorphicStruct> curr_struct = std::make_unique<PolymorphicStruct>();
417
418 off_t off = 0;
419 for (POLYMORPHIC_STRUCT_FIELD field : this->fields)
420 {
421 if (field.constraint.arch != arion::CPU_ARCH::UNKNOWN_ARCH && arch != field.constraint.arch)
422 continue;
423 if (field.constraint.arch_sz != 0 && arch_sz != field.constraint.arch_sz)
424 continue;
425
426 switch (field.type)
427 {
428 case V8: {
429 uint8_t val;
430 memcpy(&val, struct_inst + off, sizeof(uint8_t));
431 curr_struct->set_field(field.name, val);
432 off += sizeof(uint8_t);
433 break;
434 }
435 case V16: {
436 if (off % sizeof(uint16_t))
437 off += sizeof(uint16_t) - (off % sizeof(uint16_t));
438 uint16_t val;
439 memcpy(&val, struct_inst + off, sizeof(uint16_t));
440 curr_struct->set_field(field.name, val);
441 off += sizeof(uint16_t);
442 break;
443 }
444 case V32: {
445 if (off % sizeof(uint32_t))
446 off += sizeof(uint32_t) - (off % sizeof(uint32_t));
447 uint32_t val;
448 memcpy(&val, struct_inst + off, sizeof(uint32_t));
449 curr_struct->set_field(field.name, val);
450 off += sizeof(uint32_t);
451 break;
452 }
453 case V64: {
454 if (off % sizeof(uint64_t))
455 off += sizeof(uint64_t) - (off % sizeof(uint64_t));
456 uint64_t val;
457 memcpy(&val, struct_inst + off, sizeof(uint64_t));
458 curr_struct->set_field(field.name, val);
459 off += sizeof(uint64_t);
460 break;
461 }
462 case PTR_SZ: {
463 if (off % ptr_sz)
464 off += ptr_sz - (off % ptr_sz);
465 uint64_t val;
466 memcpy(&val, struct_inst + off, ptr_sz);
467 curr_struct->set_field(field.name, val);
468 off += ptr_sz;
469 break;
470 }
471 case A8: {
472 size_t arr_sz = field.sz * sizeof(uint8_t);
473 uint8_t *arr = (uint8_t *)malloc(arr_sz);
474 memcpy(arr, struct_inst + off, arr_sz);
475 curr_struct->set_field(field.name, arr);
476 off += arr_sz;
477 break;
478 }
479 case A16: {
480 if (off % sizeof(uint16_t))
481 off += sizeof(uint16_t) - (off % sizeof(uint16_t));
482 size_t arr_sz = field.sz * sizeof(uint16_t);
483 uint16_t *arr = (uint16_t *)malloc(arr_sz);
484 memcpy(arr, struct_inst + off, arr_sz);
485 curr_struct->set_field(field.name, arr);
486 off += arr_sz;
487 break;
488 }
489 case A32: {
490 if (off % sizeof(uint32_t))
491 off += sizeof(uint32_t) - (off % sizeof(uint32_t));
492 size_t arr_sz = field.sz * sizeof(uint32_t);
493 uint32_t *arr = (uint32_t *)malloc(arr_sz);
494 memcpy(arr, struct_inst + off, arr_sz);
495 curr_struct->set_field(field.name, arr);
496 off += arr_sz;
497 break;
498 }
499 case A64: {
500 if (off % sizeof(uint64_t))
501 off += sizeof(uint64_t) - (off % sizeof(uint64_t));
502 size_t arr_sz = field.sz * sizeof(uint64_t);
503 uint64_t *arr = (uint64_t *)malloc(arr_sz);
504 memcpy(arr, struct_inst + off, arr_sz);
505 curr_struct->set_field(field.name, arr);
506 off += arr_sz;
507 break;
508 }
509 case PTR_ARR: {
510 if (off % ptr_sz)
511 off += ptr_sz - (off % ptr_sz);
512 size_t arr_sz = field.sz * ptr_sz;
513 uint8_t *arr = (uint8_t *)malloc(arr_sz);
514 memcpy(arr, struct_inst + off, arr_sz);
515 curr_struct->set_field(field.name, arr);
516 off += arr_sz;
517 break;
518 }
519 default:
520 break;
521 }
522 }
523 STRUCT_ID id = this->add_struct_entry(std::move(curr_struct));
524 return id;
525 }
526
532 STRUCT_ID feed_host(T *struct_inst)
533 {
534 arion::BYTE *data = (arion::BYTE *)malloc(sizeof(T));
535 memcpy(data, struct_inst, sizeof(T));
536 STRUCT_ID id = this->feed(arion::get_host_cpu_arch(), data);
537 free(data);
538 return id;
539 }
540
548 arion::BYTE *build(STRUCT_ID id, arion::CPU_ARCH arch, size_t &struct_len)
549 {
550 auto struct_it = this->curr_structs.find(id);
551 if (struct_it == this->curr_structs.end())
553 std::unique_ptr<PolymorphicStruct> curr_struct = std::move(struct_it->second);
554
555 std::vector<arion::BYTE> data_vec;
556 uint8_t align = this->get_align(arch);
557 uint8_t ptr_sz = this->get_ptr_sz(arch);
558 uint16_t arch_sz = this->get_arch_sz(arch);
559
560 for (POLYMORPHIC_STRUCT_FIELD field : this->fields)
561 {
562 if (field.constraint.arch != arion::CPU_ARCH::UNKNOWN_ARCH && arch != field.constraint.arch)
563 continue;
564 if (field.constraint.arch_sz != 0 && arch_sz != field.constraint.arch_sz)
565 continue;
566
567 switch (field.type)
568 {
569 case V8: {
570 uint8_t val = 0;
571 if (curr_struct->has_int_field(field.name))
572 val = curr_struct->get_int_field(field.name);
573 data_vec.push_back(val);
574 break;
575 }
576 case V16: {
577 if (data_vec.size() % sizeof(uint16_t))
578 {
579 uint8_t align_sz = sizeof(uint16_t) - (data_vec.size() % sizeof(uint16_t));
580 data_vec.insert(data_vec.end(), align_sz, 0);
581 }
582 uint16_t val = 0;
583 if (curr_struct->has_int_field(field.name))
584 val = curr_struct->get_int_field(field.name);
585 data_vec.insert(data_vec.end(), (uint8_t *)&val, (uint8_t *)&val + sizeof(uint16_t));
586 break;
587 }
588 case V32: {
589 if (data_vec.size() % sizeof(uint32_t))
590 {
591 uint8_t align_sz = sizeof(uint32_t) - (data_vec.size() % sizeof(uint32_t));
592 data_vec.insert(data_vec.end(), align_sz, 0);
593 }
594 uint32_t val = 0;
595 if (curr_struct->has_int_field(field.name))
596 val = curr_struct->get_int_field(field.name);
597 data_vec.insert(data_vec.end(), (uint8_t *)&val, (uint8_t *)&val + sizeof(uint32_t));
598 break;
599 }
600 case V64: {
601 if (data_vec.size() % sizeof(uint64_t))
602 {
603 uint8_t align_sz = sizeof(uint64_t) - (data_vec.size() % sizeof(uint64_t));
604 data_vec.insert(data_vec.end(), align_sz, 0);
605 }
606 uint64_t val = 0;
607 if (curr_struct->has_int_field(field.name))
608 val = curr_struct->get_int_field(field.name);
609 data_vec.insert(data_vec.end(), (uint8_t *)&val, (uint8_t *)&val + sizeof(uint64_t));
610 break;
611 }
612 case PTR_SZ: {
613 if (data_vec.size() % ptr_sz)
614 {
615 uint8_t align_sz = ptr_sz - (data_vec.size() % ptr_sz);
616 data_vec.insert(data_vec.end(), align_sz, 0);
617 }
618 uint64_t val = 0;
619 if (curr_struct->has_int_field(field.name))
620 val = curr_struct->get_int_field(field.name);
621 data_vec.insert(data_vec.end(), (uint8_t *)&val, (uint8_t *)&val + ptr_sz);
622 break;
623 }
624 case A8: {
625 size_t arr_sz = field.sz * sizeof(uint8_t);
626 bool has_field = curr_struct->has_arr_field(field.name);
627 uint8_t *arr;
628 if (has_field)
629 arr = (uint8_t *)curr_struct->get_arr_field(field.name);
630 else
631 arr = (uint8_t *)malloc(arr_sz);
632 data_vec.insert(data_vec.end(), arr, arr + arr_sz);
633 if (!has_field)
634 free(arr);
635 break;
636 }
637 case A16: {
638 if (data_vec.size() % sizeof(uint16_t))
639 {
640 uint8_t align_sz = sizeof(uint16_t) - (data_vec.size() % sizeof(uint16_t));
641 data_vec.insert(data_vec.end(), align_sz, 0);
642 }
643 size_t arr_sz = field.sz * sizeof(uint16_t);
644 bool has_field = curr_struct->has_arr_field(field.name);
645 uint16_t *arr;
646 if (has_field)
647 arr = (uint16_t *)curr_struct->get_arr_field(field.name);
648 else
649 arr = (uint16_t *)malloc(arr_sz);
650 data_vec.insert(data_vec.end(), (uint8_t *)arr, (uint8_t *)arr + arr_sz);
651 if (!has_field)
652 free(arr);
653 break;
654 }
655 case A32: {
656 if (data_vec.size() % sizeof(uint32_t))
657 {
658 uint8_t align_sz = sizeof(uint32_t) - (data_vec.size() % sizeof(uint32_t));
659 data_vec.insert(data_vec.end(), align_sz, 0);
660 }
661 size_t arr_sz = field.sz * sizeof(uint32_t);
662 bool has_field = curr_struct->has_arr_field(field.name);
663 uint32_t *arr;
664 if (has_field)
665 arr = (uint32_t *)curr_struct->get_arr_field(field.name);
666 else
667 arr = (uint32_t *)malloc(arr_sz);
668 data_vec.insert(data_vec.end(), (uint8_t *)arr, (uint8_t *)arr + arr_sz);
669 if (!has_field)
670 free(arr);
671 break;
672 }
673 case A64: {
674 if (data_vec.size() % sizeof(uint64_t))
675 {
676 uint8_t align_sz = sizeof(uint64_t) - (data_vec.size() % sizeof(uint64_t));
677 data_vec.insert(data_vec.end(), align_sz, 0);
678 }
679 size_t arr_sz = field.sz * sizeof(uint64_t);
680 bool has_field = curr_struct->has_arr_field(field.name);
681 uint64_t *arr;
682 if (has_field)
683 arr = (uint64_t *)curr_struct->get_arr_field(field.name);
684 else
685 arr = (uint64_t *)malloc(arr_sz);
686 data_vec.insert(data_vec.end(), (uint8_t *)arr, (uint8_t *)arr + arr_sz);
687 if (!has_field)
688 free(arr);
689 break;
690 }
691 case PTR_ARR: {
692 if (data_vec.size() % ptr_sz)
693 {
694 uint8_t align_sz = ptr_sz - (data_vec.size() % ptr_sz);
695 data_vec.insert(data_vec.end(), align_sz, 0);
696 }
697 size_t arr_sz = field.sz * ptr_sz;
698 bool has_field = curr_struct->has_arr_field(field.name);
699 uint8_t *arr;
700 if (has_field)
701 arr = (uint8_t *)curr_struct->get_arr_field(field.name);
702 else
703 arr = (uint8_t *)malloc(arr_sz);
704 data_vec.insert(data_vec.end(), (uint8_t *)arr, (uint8_t *)arr + arr_sz);
705 if (!has_field)
706 free(arr);
707 break;
708 }
709 default:
710 break;
711 }
712 }
713
714 if (data_vec.size() % align)
715 {
716 uint8_t align_sz = align - (data_vec.size() % align);
717 data_vec.insert(data_vec.end(), align_sz, 0);
718 }
719 struct_len = data_vec.size();
720 arion::BYTE *data = (arion::BYTE *)malloc(struct_len);
721 memcpy(data, data_vec.data(), struct_len);
722 this->curr_structs[id] = std::move(curr_struct);
723 return data;
724 }
725
732 {
733 size_t data_len;
734 arion::BYTE *data = this->build(id, arion::get_host_cpu_arch(), data_len);
735 T *struct_inst = (T *)malloc(sizeof(T));
736 size_t min_sz = std::min(sizeof(T), data_len);
737 memcpy(struct_inst, data, min_sz);
738 free(data);
739 return struct_inst;
740 }
741
749 std::string to_string(STRUCT_ID id, std::shared_ptr<arion::Arion> arion, arion::CPU_ARCH arch)
750 {
751 auto struct_it = this->curr_structs.find(id);
752 if (struct_it == this->curr_structs.end())
754 std::unique_ptr<PolymorphicStruct> curr_struct = std::move(struct_it->second);
755
756 uint8_t align = this->get_align(arch);
757 uint8_t ptr_sz = this->get_ptr_sz(arch);
758 uint16_t arch_sz = this->get_arch_sz(arch);
759
760 std::stringstream ss;
761 ss << "{";
762
763 for (POLYMORPHIC_STRUCT_FIELD field : this->fields)
764 {
765 if (field.constraint.arch != arion::CPU_ARCH::UNKNOWN_ARCH && arch != field.constraint.arch)
766 continue;
767 if (field.constraint.arch_sz != 0 && arch_sz != field.constraint.arch_sz)
768 continue;
769
770 if (ss.str().size() > 1)
771 ss << ", ";
772 ss << field.name << "=";
773 switch (field.type)
774 {
775 case V8:
776 case V16:
777 case V32:
778 case V64:
779 case PTR_SZ: {
780 uint64_t val = 0;
781 if (curr_struct->has_int_field(field.name))
782 val = curr_struct->get_int_field(field.name);
783 ss << field.arion_type->str(arion, val);
784 break;
785 }
786 case A8: {
787 ss << "{";
788 if (curr_struct->has_arr_field(field.name))
789 {
790 uint8_t *arr = (uint8_t *)curr_struct->get_arr_field(field.name);
791 for (size_t arr_i = 0; arr_i < field.sz; arr_i++)
792 {
793 ss << field.arion_type->str(arion, arr[arr_i]);
794 if (arr_i < field.sz - 1)
795 ss << ", ";
796 }
797 }
798 ss << "}";
799 break;
800 }
801 case A16: {
802 ss << "{";
803 if (curr_struct->has_arr_field(field.name))
804 {
805 uint16_t *arr = (uint16_t *)curr_struct->get_arr_field(field.name);
806 for (size_t arr_i = 0; arr_i < field.sz; arr_i++)
807 {
808 ss << field.arion_type->str(arion, arr[arr_i]);
809 if (arr_i < field.sz - 1)
810 ss << ", ";
811 }
812 }
813 ss << "}";
814 break;
815 }
816 case A32: {
817 ss << "{";
818 if (curr_struct->has_arr_field(field.name))
819 {
820 uint32_t *arr = (uint32_t *)curr_struct->get_arr_field(field.name);
821 for (size_t arr_i = 0; arr_i < field.sz; arr_i++)
822 {
823 ss << field.arion_type->str(arion, arr[arr_i]);
824 if (arr_i < field.sz - 1)
825 ss << ", ";
826 }
827 }
828 ss << "}";
829 break;
830 }
831 case A64: {
832 ss << "{";
833 if (curr_struct->has_arr_field(field.name))
834 {
835 uint64_t *arr = (uint64_t *)curr_struct->get_arr_field(field.name);
836 for (size_t arr_i = 0; arr_i < field.sz; arr_i++)
837 {
838 ss << field.arion_type->str(arion, arr[arr_i]);
839 if (arr_i < field.sz - 1)
840 ss << ", ";
841 }
842 }
843 ss << "}";
844 break;
845 }
846 case PTR_ARR: {
847 ss << "{";
848 if (curr_struct->has_arr_field(field.name))
849 {
850 void *arr = curr_struct->get_arr_field(field.name);
851 for (size_t arr_i = 0; arr_i < field.sz; arr_i++)
852 {
853 uint64_t val = 0;
854 memcpy(&val, (void *)((uint64_t)arr + arr_i * ptr_sz), ptr_sz);
855 ss << field.arion_type->str(arion, val);
856 if (arr_i < field.sz - 1)
857 ss << ", ";
858 }
859 }
860 ss << "}";
861 break;
862 }
863 default:
864 ss << "UNK_FIELD";
865 break;
866 }
867 }
868
869 ss << "}";
870
871 // Move the unique_ptr back into the map
872 this->curr_structs[id] = std::move(curr_struct);
873 return ss.str();
874 }
875
881 {
882 auto struct_it = this->curr_structs.find(id);
883 if (struct_it == this->curr_structs.end())
885
886 this->curr_structs.erase(id);
887 if (this->curr_structs.size())
888 this->free_ids.push(id);
889 else
890 {
891 this->free_ids = std::stack<STRUCT_ID>();
892 this->curr_id = 1;
893 }
894 }
895
900 {
901 std::vector<STRUCT_ID> struct_ids; // need to clone keys to prevent concurrency editing
902 for (const auto &struct_pair : this->curr_structs)
903 struct_ids.push_back(struct_pair.first);
904 for (STRUCT_ID struct_id : struct_ids)
905 this->release_struct(struct_id);
906 }
907};
908
911{
912 protected:
916 virtual ~AbsArionStructType() = default;
923 bool arion_is_mapped(std::shared_ptr<arion::Arion> arion, arion::ADDR addr);
929 arion::CPU_ARCH arion_curr_arch(std::shared_ptr<arion::Arion> arion);
937 std::vector<arion::BYTE> arion_read_mem(std::shared_ptr<arion::Arion> arion, arion::ADDR addr, size_t sz);
938};
939
945template <typename T> class ArionStructType : public arion_type::KernelType, public AbsArionStructType
946{
947 private:
949 std::shared_ptr<arion_poly_struct::PolymorphicStructFactory<T>> factory;
950
951 protected:
959
960 public:
968 std::string str(std::shared_ptr<arion::Arion> arion, uint64_t val) override
969 {
970 if (!val || !this->arion_is_mapped(arion, val))
971 return arion::int_to_hex<uint64_t>(val);
972 arion::CPU_ARCH arch = this->arion_curr_arch(arion);
973 size_t struct_sz = this->factory->get_struct_sz(arch);
974 arion::BYTE *struct_buf = (arion::BYTE *)malloc(struct_sz);
975 std::vector<arion::BYTE> struct_data = this->arion_read_mem(arion, val, struct_sz);
976 memcpy(struct_buf, struct_data.data(), struct_sz);
977 arion_poly_struct::STRUCT_ID struct_id = this->factory->feed(arch, struct_buf);
978 std::string struct_str = this->factory->to_string(struct_id, arion, arch);
979 free(struct_buf);
980 this->factory->release_struct(struct_id);
981 return struct_str;
982 }
983};
984
988{
989 private:
997 virtual std::shared_ptr<arion_poly_struct::AbsArionStructType> process(std::shared_ptr<arion::Arion> arion,
998 uint64_t val) = 0;
999
1000 protected:
1005 ArionVariableStructType(std::string name) : arion_type::KernelType(name, arion::LOG_COLOR::BLUE) {};
1006
1007 public:
1015 std::string str(std::shared_ptr<arion::Arion> arion, uint64_t val) override
1016 {
1017 std::shared_ptr<AbsArionStructType> struct_type = this->process(arion, val);
1018 if (!struct_type)
1019 return arion_type::INT_TYPE->str(arion, val);
1020 std::shared_ptr<arion_type::KernelType> type = std::dynamic_pointer_cast<arion_type::KernelType>(struct_type);
1021 if (!type)
1022 return arion_type::INT_TYPE->str(arion, val);
1023 return type->str(arion, val);
1024 }
1025};
1026
1027} // namespace arion_poly_struct
1028
1029#endif // ARION_STRUCT_UTILS_HPP
Thrown when attempting to access a field in a structure that does not exist.
Definition global_excepts.hpp:564
Thrown when there are too many active structures.
Definition global_excepts.hpp:576
Thrown when the CPU architecture is not supported.
Definition global_excepts.hpp:348
Thrown when an invalid struct id is specified.
Definition global_excepts.hpp:586
Abstract base class providing common utilities for structure types that interact with emulated memory...
Definition struct_utils.hpp:911
arion::CPU_ARCH arion_curr_arch(std::shared_ptr< arion::Arion > arion)
std::vector< arion::BYTE > arion_read_mem(std::shared_ptr< arion::Arion > arion, arion::ADDR addr, size_t sz)
bool arion_is_mapped(std::shared_ptr< arion::Arion > arion, arion::ADDR addr)
Definition struct_utils.hpp:946
ArionStructType(std::string name, std::shared_ptr< arion_poly_struct::PolymorphicStructFactory< T > > factory)
Definition struct_utils.hpp:957
std::shared_ptr< arion_poly_struct::PolymorphicStructFactory< T > > factory
The factory responsible for handling the polymorphic nature of the structure.
Definition struct_utils.hpp:949
std::string str(std::shared_ptr< arion::Arion > arion, uint64_t val) override
Definition struct_utils.hpp:968
Definition struct_utils.hpp:988
std::string str(std::shared_ptr< arion::Arion > arion, uint64_t val) override
Definition struct_utils.hpp:1015
ArionVariableStructType(std::string name)
Definition struct_utils.hpp:1005
virtual std::shared_ptr< arion_poly_struct::AbsArionStructType > process(std::shared_ptr< arion::Arion > arion, uint64_t val)=0
Definition struct_utils.hpp:200
STRUCT_ID feed_host(T *struct_inst)
Definition struct_utils.hpp:532
std::map< STRUCT_ID, std::unique_ptr< PolymorphicStruct > > curr_structs
Map of currently allocated polymorphic structure instances.
Definition struct_utils.hpp:207
STRUCT_ID curr_id
Counter for generating unique structure IDs.
Definition struct_utils.hpp:203
STRUCT_ID add_struct_entry(std::unique_ptr< PolymorphicStruct > struct_inst)
Definition struct_utils.hpp:237
uint8_t get_align(arion::CPU_ARCH arch)
Definition struct_utils.hpp:249
T * build_host(STRUCT_ID id)
Definition struct_utils.hpp:731
void release_struct(STRUCT_ID id)
Definition struct_utils.hpp:880
PolymorphicStructFactory(std::vector< POLYMORPHIC_STRUCT_FIELD > fields)
Definition struct_utils.hpp:288
std::string to_string(STRUCT_ID id, std::shared_ptr< arion::Arion > arion, arion::CPU_ARCH arch)
Definition struct_utils.hpp:749
size_t get_struct_sz(arion::CPU_ARCH arch)
Definition struct_utils.hpp:307
std::vector< POLYMORPHIC_STRUCT_FIELD > fields
Definition of all potential fields in the polymorphic structure.
Definition struct_utils.hpp:209
size_t get_host_struct_sz()
Definition struct_utils.hpp:400
std::stack< STRUCT_ID > free_ids
Stack of released IDs for reuse.
Definition struct_utils.hpp:205
arion::BYTE * build(STRUCT_ID id, arion::CPU_ARCH arch, size_t &struct_len)
Definition struct_utils.hpp:548
~PolymorphicStructFactory()
Definition struct_utils.hpp:292
uint8_t get_ptr_sz(arion::CPU_ARCH arch)
Definition struct_utils.hpp:262
void clear_structs()
Definition struct_utils.hpp:899
uint16_t get_arch_sz(arion::CPU_ARCH arch)
Definition struct_utils.hpp:275
STRUCT_ID feed(arion::CPU_ARCH arch, arion::BYTE *struct_inst)
Definition struct_utils.hpp:411
STRUCT_ID gen_next_id()
Definition struct_utils.hpp:215
Represents a single instance of a polymorphic structure, storing its field values dynamically.
Definition struct_utils.hpp:136
~PolymorphicStruct()
Definition struct_utils.hpp:147
uint64_t get_int_field(std::string name)
Retrieves the value of a named integer field.
Definition struct_utils.hpp:172
void set_field(std::string name, uint64_t val)
Sets an integer/primitive field value.
Definition struct_utils.hpp:153
void set_field(std::string name, void *arr)
Sets an array field value (takes ownership of the pointer).
Definition struct_utils.hpp:158
std::map< std::string, uint64_t > int_vals
Map storing integer/primitive field values by name.
Definition struct_utils.hpp:139
std::map< std::string, void * > arr_vals
Map storing pointers to dynamically allocated array field values by name.
Definition struct_utils.hpp:141
void * get_arr_field(std::string name)
Retrieves the pointer to a named array field.
Definition struct_utils.hpp:186
bool has_arr_field(std::string name)
Checks if a named array field exists.
Definition struct_utils.hpp:180
bool has_int_field(std::string name)
Checks if a named integer field exists.
Definition struct_utils.hpp:166
Abstract base class for all kernel-related data types used for visualization/logging.
Definition type_utils.hpp:27
std::string name
Display name of the data type (e.g., "File descriptor").
Definition type_utils.hpp:30
KernelType(std::string name, arion::LOG_COLOR color=arion::LOG_COLOR::DEFAULT)
Definition type_utils.hpp:40
#define ARION_MAX_U64
Maximum number for an unsigned 64-bit integer.
Definition global_defs.hpp:27
Definition struct_utils.hpp:17
std::map< arion::CPU_ARCH, uint16_t > ARCH_SZ
Map defining the architecture size (in bits) based on the CPU architecture.
Definition struct_utils.hpp:38
std::map< arion::CPU_ARCH, uint8_t > PTR_SZ_BY_ARCH
Map defining the size of a pointer (in bytes) based on the CPU architecture.
Definition struct_utils.hpp:30
POLYMORPHIC_STRUCT_FIELD_TYPE
Enumeration for specifying the size and type of a polymorphic structure field.
Definition struct_utils.hpp:47
@ A32
32-bit array type.
Definition struct_utils.hpp:63
@ A8
8-bit array type.
Definition struct_utils.hpp:59
@ PTR_ARR
Pointer size array type (array of pointers).
Definition struct_utils.hpp:67
@ A64
64-bit array type.
Definition struct_utils.hpp:65
@ V32
32-bit integer type.
Definition struct_utils.hpp:53
@ V64
64-bit integer type.
Definition struct_utils.hpp:55
@ V8
8-bit integer type.
Definition struct_utils.hpp:49
@ PTR_SZ
Pointer size type (size determined by architecture).
Definition struct_utils.hpp:57
@ V16
16-bit integer type.
Definition struct_utils.hpp:51
@ A16
16-bit array type.
Definition struct_utils.hpp:61
uint64_t STRUCT_ID
Type definition for a unique ID assigned to a managed polymorphic struct instance.
Definition struct_utils.hpp:19
std::map< arion::CPU_ARCH, uint8_t > ALIGN_BY_ARCH
Map defining the required memory alignment (in bytes) based on the CPU architecture.
Definition struct_utils.hpp:22
Definition type_utils.hpp:23
std::shared_ptr< IntType > INT_TYPE
Shared pointer to the singleton instance of IntType.
Definition arch_x86-64.hpp:11
uint64_t ADDR
Identifies a memory address.
Definition global_defs.hpp:36
CPU_ARCH get_host_cpu_arch()
Definition host_utils.hpp:17
CPU_ARCH
Identifies a CPU architecture.
Definition global_defs.hpp:128
@ X8664_ARCH
The x86-64 CPU architecture.
Definition global_defs.hpp:134
@ UNKNOWN_ARCH
Unknown CPU architecture.
Definition global_defs.hpp:130
@ X86_ARCH
The x86 CPU architecture.
Definition global_defs.hpp:132
@ ARM64_ARCH
The ARM64 CPU architecture.
Definition global_defs.hpp:138
@ ARM_ARCH
The ARM CPU architecture.
Definition global_defs.hpp:136
uint8_t BYTE
Identifies an 8-bit integer.
Definition global_defs.hpp:40
Structure defining an architecture constraint for a field in a polymorphic struct.
Definition struct_utils.hpp:72
uint16_t arch_sz
The specific architecture bit size required (e.g., 32 or 64 bit).
Definition struct_utils.hpp:76
POLYMORPHIC_STRUCT_CONSTRAINT()
Definition struct_utils.hpp:81
arion::CPU_ARCH arch
The specific architecture required for the field to be present/used.
Definition struct_utils.hpp:74
POLYMORPHIC_STRUCT_CONSTRAINT(uint16_t arch_sz)
Definition struct_utils.hpp:91
POLYMORPHIC_STRUCT_CONSTRAINT(arion::CPU_ARCH arch)
Definition struct_utils.hpp:86
Structure defining a field within a polymorphic struct, including its constraints and type metadata.
Definition struct_utils.hpp:96
POLYMORPHIC_STRUCT_CONSTRAINT constraint
Constraints dictating when this field is active.
Definition struct_utils.hpp:98
size_t sz
Size of the array (if an array type, otherwise 0).
Definition struct_utils.hpp:106
POLYMORPHIC_STRUCT_FIELD(POLYMORPHIC_STRUCT_CONSTRAINT constraint, POLYMORPHIC_STRUCT_FIELD_TYPE type, std::shared_ptr< arion_type::KernelType > arion_type, std::string name)
Definition struct_utils.hpp:117
POLYMORPHIC_STRUCT_FIELD(POLYMORPHIC_STRUCT_FIELD_TYPE type, std::shared_ptr< arion_type::KernelType > arion_type, std::string name)
Definition struct_utils.hpp:129
std::shared_ptr< arion_type::KernelType > arion_type
The Arion type object used for displaying/interpreting the field value.
Definition struct_utils.hpp:102
POLYMORPHIC_STRUCT_FIELD_TYPE type
The type and size of the field.
Definition struct_utils.hpp:100
POLYMORPHIC_STRUCT_FIELD(POLYMORPHIC_STRUCT_CONSTRAINT constraint, POLYMORPHIC_STRUCT_FIELD_TYPE type, std::shared_ptr< arion_type::KernelType > arion_type, std::string name, size_t sz)
Definition struct_utils.hpp:111
std::string name
The name of the field within the structure.
Definition struct_utils.hpp:104
POLYMORPHIC_STRUCT_FIELD(POLYMORPHIC_STRUCT_FIELD_TYPE type, std::shared_ptr< arion_type::KernelType > arion_type, std::string name, size_t sz)
Definition struct_utils.hpp:123