RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
dumper.h
1#ifndef DUMPER_H
2#define DUMPER_H
3
4#include <iostream>
5#include <iomanip>
6#include <set>
7#include <vector>
8#include "../common.h"
9#include "../unicode.h"
10#include "../linker/image.h"
11
12namespace Dumper
13{
14
15enum display_option
16{
17 _Image,
18 _Header,
19 _Symbol,
20 _Relocation,
21 _Import,
22 _Export,
23 _Control,
24 _String,
25 _Debug,
26 _Resource,
27 _Dynamic,
28 _Miscellaneous,
29 _Redundant,
30 _Generated,
31
33 Image = 1 << _Image,
35 Header = 1 << _Header,
37 Symbol = 1 << _Symbol,
39 Relocation = 1 << _Relocation,
41 Import = 1 << _Import,
43 Export = 1 << _Export,
45 Control = 1 << _Control,
47 String = 1 << _String,
49 Debug = 1 << _Debug,
51 Resource = 1 << _Resource,
53 Dynamic = 1 << _Dynamic,
55 Miscellaneous = 1 << _Miscellaneous,
57 Redundant = 1 << _Redundant,
59 Generated = 1 << _Generated,
60
61 None = 0,
62 All = Image | Header | Symbol | Relocation | Import | Export | Control | String | Debug | Resource | Dynamic | Miscellaneous | Redundant | Generated,
63};
64
65class Dumper;
66
68{
69public:
70 virtual ~Encoding() = default;
71
72 virtual char32_t GetChar(uint8_t const *& input, size_t& length) = 0;
73
74 char32_t operator[](uint8_t input)
75 {
76 uint8_t const * input_pointer = &input;
77 size_t length = 1;
78 return GetChar(input_pointer, length);
79 }
80};
81
83{
84public:
85 char32_t (* codepage)[256];
86
87 SingleByteEncoding() = delete;
88 SingleByteEncoding(const SingleByteEncoding& ) = delete;
89
90 SingleByteEncoding(char32_t (& codepage)[256])
91 : codepage(&codepage)
92 {
93 assert(this->codepage != nullptr);
94 }
95
96 char32_t GetChar(uint8_t const *& input, size_t& length) override;
97};
98
99// TODO: untested
100class UTF8Encoding : public Encoding
101{
102public:
104 {
105 }
106
107 char32_t GetChar(uint8_t const *& input, size_t& length) override;
108};
109
111{
112public:
113 ::EndianType endiantype;
114
115 UTF16Encoding(::EndianType endiantype)
116 : endiantype(endiantype)
117 {
118 }
119
120 char32_t GetChar(uint8_t const *& input, size_t& length) override;
121};
122
123// TODO: untested
125{
126public:
127 ::EndianType endiantype;
128
129 UTF32Encoding(::EndianType endiantype)
130 : endiantype(endiantype)
131 {
132 }
133
134 char32_t GetChar(uint8_t const *& input, size_t& length) override;
135};
136
137class Dumper;
139{
140public:
141 enum Formatting
142 {
143 Bold,
144 Underline,
145 };
146
147 std::string text;
148 std::map<size_t, std::map<Formatting, bool>> formatting;
149
150 RichText() = default;
151
152 RichText(std::string text)
153 : text(text)
154 {
155 }
156
157 template <typename ... Ts>
158 RichText(std::string text, Formatting format, Ts ... rest)
159 : RichText{text, rest...}
160 {
161 formatting[0][format] = true;
162 formatting[text.size()][format] = false;
163 }
164
165 RichText& operator +=(char c)
166 {
167 text += c;
168 return *this;
169 }
170
171 RichText& operator +=(std::string s)
172 {
173 text += s;
174 return *this;
175 }
176
177 RichText& operator +=(const RichText& other);
178 void Dump(Dumper& dump) const;
179
180 bool operator ==(const RichText& other) const
181 {
182 return text == other.text && formatting == other.formatting;
183 }
184};
185
186static inline RichText operator +(const RichText& first, const RichText& second)
187{
188 RichText result = first;
189 result += second;
190 return result;
191}
192
196template <typename ... Ts>
198{
199public:
200 virtual ~Display() { }
201
203 virtual bool IsMissing(std::tuple<Ts...>& values)
204 {
205 //return is_missing(values);
206 return values == std::tuple<Ts...>();
207 }
208
210 virtual void DisplayValue(Dumper& dump, std::tuple<Ts...> values) = 0;
211};
212
216class ChoiceDisplay : public Display<offset_t>
217{
218public:
222 std::map<offset_t, std::string> names;
226 std::string default_name;
227
239 std::shared_ptr<Display<offset_t>> secondary_display;
240
241 ChoiceDisplay(std::map<offset_t, std::string> names, std::string default_name, bool missing_on_value, offset_t missing_value, std::shared_ptr<Display<offset_t>> secondary_display)
243 {
244 }
245
254 static std::shared_ptr<ChoiceDisplay> Make(std::map<offset_t, std::string> names, std::string default_name = "unknown", std::shared_ptr<Display<offset_t>> secondary_display = nullptr)
255 {
256 return std::make_shared<ChoiceDisplay>(names, default_name, false, 0, secondary_display);
257 }
258
268 static std::shared_ptr<ChoiceDisplay> Make(std::map<offset_t, std::string> names, offset_t missing_value, std::string default_name = "unknown", std::shared_ptr<Display<offset_t>> secondary_display = nullptr)
269 {
270 return std::make_shared<ChoiceDisplay>(names, default_name, true, missing_value, secondary_display);
271 }
272
280 static std::shared_ptr<ChoiceDisplay> Make(std::map<offset_t, std::string> names, std::shared_ptr<Display<offset_t>> secondary_display)
281 {
282 return std::make_shared<ChoiceDisplay>(names, "unknown", false, 0, secondary_display);
283 }
284
293 static std::shared_ptr<ChoiceDisplay> Make(std::map<offset_t, std::string> names, offset_t missing_value, std::shared_ptr<Display<offset_t>> secondary_display)
294 {
295 return std::make_shared<ChoiceDisplay>(names, "unknown", true, missing_value, secondary_display);
296 }
297
305 static std::shared_ptr<ChoiceDisplay> Make(std::string on_true, std::string on_false)
306 {
307 std::map<offset_t, std::string> names;
308 /* TODO: alternative?
309 default_name = on_true;
310 names[0] = on_false;
311 */
312 names[0] = on_false;
313 names[1] = on_true;
314 return std::make_shared<ChoiceDisplay>(names, "", false, 0, nullptr);
315 }
316
323 static std::shared_ptr<ChoiceDisplay> Make(std::string on_true)
324 {
325 std::map<offset_t, std::string> names;
326 /* TODO: alternative?
327 default_name = on_true;
328 missing_on_value = true;
329 missing_value = 0;
330 */
331 names[1] = on_true;
332 return std::make_shared<ChoiceDisplay>(names, "unknown", false, 0, nullptr);
333 }
334
335 bool IsMissing(std::tuple<offset_t>& values) override;
336 void DisplayValue(Dumper& dump, std::tuple<offset_t> values) override;
337};
338
342class HexDisplay : public Display<offset_t>
343{
344public:
345 unsigned width;
346 HexDisplay(unsigned width)
347 : width(width)
348 {
349 }
350
357 static std::shared_ptr<HexDisplay> Make(unsigned width = 8)
358 {
359 return std::make_shared<HexDisplay>(width);
360 }
361
362 void DisplayValue(Dumper& dump, std::tuple<offset_t> values) override;
363};
364
368class DecDisplay : public Display<offset_t>
369{
370public:
371 std::string suffix;
372 bool enable_signed = false;
373 DecDisplay(std::string suffix, bool enable_signed)
374 : suffix(suffix), enable_signed(enable_signed)
375 {
376 }
377
384 static std::shared_ptr<DecDisplay> Make(bool enable_signed)
385 {
386 return std::make_shared<DecDisplay>("", enable_signed);
387 }
388
396 static std::shared_ptr<DecDisplay> Make(std::string suffix = "", bool enable_signed = false)
397 {
398 return std::make_shared<DecDisplay>(suffix, enable_signed);
399 }
400
401 void DisplayValue(Dumper& dump, std::tuple<offset_t> values) override;
402};
403
407class SegmentedDisplay : public Display<offset_t, offset_t>
408{
409public:
410 unsigned width;
411 SegmentedDisplay(unsigned width)
412 : width(width)
413 {
414 }
415
422 static std::shared_ptr<SegmentedDisplay> Make(unsigned width = 4)
423 {
424 return std::make_shared<SegmentedDisplay>(width);
425 }
426
427 void DisplayValue(Dumper& dump, std::tuple<offset_t, offset_t> values) override;
428};
429
433class VersionDisplay : public Display<offset_t, offset_t>
434{
435public:
436 std::string separator;
437 VersionDisplay(std::string separator)
438 : separator(separator)
439 {
440 }
441
448 static std::shared_ptr<VersionDisplay> Make(std::string separator = ".")
449 {
450 return std::make_shared<VersionDisplay>(separator);
451 }
452
453 void DisplayValue(Dumper& dump, std::tuple<offset_t, offset_t> values) override;
454};
455
459template <typename ... Ts>
460 class SectionedDisplay : public Display<offset_t, Ts...>
461{
462public:
463 std::string suffix;
464 std::shared_ptr<Display<Ts...>> offset_display;
465
466 SectionedDisplay(std::string suffix, std::shared_ptr<Display<Ts...>> offset_display)
467 : suffix(suffix), offset_display(offset_display)
468 {
469 }
470
477 static std::shared_ptr<SectionedDisplay> Make(std::shared_ptr<Display<Ts...>> offset_display)
478 {
479 return Make("", offset_display);
480 }
481
489 static std::shared_ptr<SectionedDisplay> Make(std::string suffix, std::shared_ptr<Display<Ts...>> offset_display)
490 {
491 return std::make_shared<SectionedDisplay>(suffix, offset_display);
492 }
493
494 void DisplayValue(Dumper& dump, std::tuple<offset_t, Ts...> values) override;
495};
496
500class BitFieldDisplay : public HexDisplay, public std::enable_shared_from_this<BitFieldDisplay>
501{
502public:
504 {
505 public:
506 unsigned offset, length;
507 std::shared_ptr<Display<offset_t>> display;
508 bool optional_field;
509 std::string label;
510
511 BitField(unsigned offset, unsigned length, std::shared_ptr<Display<offset_t>> display, bool optional_field, std::string label)
512 : offset(offset), length(length), display(display), optional_field(optional_field), label(label)
513 {
514 }
515
516 bool ShouldDisplay(std::tuple<offset_t>& values)
517 {
518 return !optional_field || !display->IsMissing(values);
519 }
520 };
521
522 std::map<unsigned, std::unique_ptr<BitField>> bitfields;
523
524 BitFieldDisplay(unsigned width)
525 : HexDisplay(width)
526 {
527 }
528
535 static std::shared_ptr<BitFieldDisplay> Make(unsigned width = 8)
536 {
537 return std::make_shared<BitFieldDisplay>(width);
538 }
539
540 std::shared_ptr<BitFieldDisplay> AddBitField(unsigned offset, unsigned length, std::shared_ptr<Display<offset_t>> display, bool optional_field)
541 {
542 bitfields[offset] = std::make_unique<BitField>(offset, length, display, optional_field, "");
543 return shared_from_this();
544 }
545
546 std::shared_ptr<BitFieldDisplay> AddBitField(unsigned offset, unsigned length, std::string label, std::shared_ptr<Display<offset_t>> display, bool optional_field = false)
547 {
548 bitfields[offset] = std::make_unique<BitField>(offset, length, display, optional_field, label);
549 return shared_from_this();
550 }
551
552 void DisplayValue(Dumper& dump, std::tuple<offset_t> values) override;
553};
554
560template <typename Clock>
561 class TimestampDisplay : public Display<::Timestamp<Clock>>
562{
563public:
564 typedef ::Timestamp<Clock> Timestamp;
565
566 static std::shared_ptr<TimestampDisplay> Make()
567 {
568 return std::make_shared<TimestampDisplay>();
569 }
570
571 bool IsMissing(std::tuple<Timestamp>& values) override
572 {
573 return Clock::to_ticks(std::get<0>(values)) == 0;
574 }
575
576 void DisplayValue(Dumper& dump, std::tuple<Timestamp> values) override;
577
578 using Display<Timestamp>::IsMissing;
579 bool IsMissing(std::tuple<offset_t>& values)
580 {
581 return std::get<0>(values) == 0;
582 }
583
584 using Display<Timestamp>::DisplayValue;
585 void DisplayValue(Dumper& dump, std::tuple<offset_t> values)
586 {
587 // convert the first value to the time corresponding to the specified number of ticks
588 DisplayValue(dump, std::make_tuple(Clock::to_time_stamp(std::get<0>(values))));
589 }
590};
591
595class BlobDisplay : public Display<std::vector<uint8_t>>
596{
597public:
601 offset_t width;
602
606 std::shared_ptr<Display<std::string>> secondary_display;
607
608 BlobDisplay(size_t width, std::shared_ptr<Display<std::string>> secondary_display = nullptr)
610 {
611 }
612
621 static std::shared_ptr<BlobDisplay> Make(size_t width, std::shared_ptr<Display<std::string>> secondary_display = nullptr)
622 {
623 return std::make_shared<BlobDisplay>(width, secondary_display);
624 }
625
626 bool IsMissing(std::tuple<std::vector<uint8_t>>& values) override;
627 void DisplayValue(Dumper& dump, std::tuple<std::vector<uint8_t>> values) override;
628
629 using Display<std::vector<uint8_t>>::IsMissing;
630 bool IsMissing(std::tuple<offset_t>& values);
631 using Display<std::vector<uint8_t>>::DisplayValue;
632 void DisplayValue(Dumper& dump, std::tuple<offset_t> values);
633};
634
638class StringDisplay : public Display<std::string>
639{
640public:
644 offset_t width;
645 std::string open_quote, close_quote;
646
647 StringDisplay(size_t width, std::string open_quote, std::string close_quote)
648 : width(width), open_quote(open_quote), close_quote(close_quote)
649 {
650 }
651
660 static std::shared_ptr<StringDisplay> Make(size_t width, std::string open_quote, std::string close_quote)
661 {
662 return std::make_shared<StringDisplay>(width, open_quote, close_quote);
663 }
664
672 static std::shared_ptr<StringDisplay> Make(size_t width, std::string quote = "")
673 {
674 return std::make_shared<StringDisplay>(width, quote, quote);
675 }
676
683 static std::shared_ptr<StringDisplay> Make(std::string quote = "")
684 {
685 return std::make_shared<StringDisplay>(-1, quote, quote);
686 }
687
688 bool IsMissing(std::tuple<std::string>& values) override;
689 void DisplayValue(Dumper& dump, std::tuple<std::string> values) override;
690
691 using Display<std::string>::IsMissing;
692 bool IsMissing(std::tuple<offset_t>& values);
693 using Display<std::string>::DisplayValue;
694 void DisplayValue(Dumper& dump, std::tuple<offset_t> values);
695};
696
700class RichTextDisplay : public Display<RichText>
701{
702public:
703 std::string open_quote, close_quote;
704
705 RichTextDisplay(std::string open_quote, std::string close_quote)
706 : open_quote(open_quote), close_quote(close_quote)
707 {
708 }
709
717 static std::shared_ptr<RichTextDisplay> Make(std::string open_quote, std::string close_quote)
718 {
719 return std::make_shared<RichTextDisplay>(open_quote, close_quote);
720 }
721
728 static std::shared_ptr<RichTextDisplay> Make(std::string quote = "")
729 {
730 return std::make_shared<RichTextDisplay>(quote, quote);
731 }
732
733 bool IsMissing(std::tuple<RichText>& values) override;
734 void DisplayValue(Dumper& dump, std::tuple<RichText> values) override;
735
736 using Display<RichText>::IsMissing;
737 bool IsMissing(std::tuple<offset_t>& values);
738 using Display<RichText>::DisplayValue;
739 void DisplayValue(Dumper& dump, std::tuple<offset_t> values);
740};
741
745class Field
746{
747public:
749 std::string label;
754
755 Field(std::string label, bool optional_field, bool internal)
757 {
758 }
759
760 virtual ~Field();
761
762 virtual bool ShouldDisplay() = 0;
763 virtual void DisplayValue(Dumper& dump) = 0;
764};
765
769template <typename ... Ts>
770 class FieldOf : public Field
771{
772public:
774 std::shared_ptr<Display<Ts...>> display;
775 std::tuple<Ts...> values;
776
777 FieldOf(std::string label, std::shared_ptr<Display<Ts...>> display, Ts... values, bool optional_field = false, bool internal = false)
778 : Field(label, optional_field, internal), display{display}, values{values...}
779 {
780 }
781
782 bool ShouldDisplay() override
783 {
784 return !internal && (!optional_field || !display->IsMissing(values));
785 }
786
787 void DisplayValue(Dumper& dump) override
788 {
789 display->DisplayValue(dump, values);
790 }
791};
792
797{
798public:
799 std::string name;
800
801 std::map<std::string, std::shared_ptr<Field>> field_names;
802 std::vector<std::shared_ptr<Field>> fields;
803
804 Container(std::string name = "")
805 : name(name)
806 {
807 }
808
809 virtual ~Container();
810
811 std::shared_ptr<Field> FindField(std::string name)
812 {
813 auto it = field_names.find(name);
814 if(it == field_names.end())
815 return nullptr;
816 return it->second;
817 }
818
819 template <typename T>
820 T GetField(std::string name, offset_t default_value = T())
821 {
822 auto it = field_names.find(name);
823 if(it == field_names.end())
824 return default_value;
825 if(auto field = std::dynamic_pointer_cast<FieldOf<T>>(it->second))
826 {
827 return std::get<0>(field->values);
828 }
829 return default_value;
830 }
831
832#if 0
833 offset_t GetField(std::string name, int index, offset_t default_value)
834 {
835 auto it = field_names.find(name);
836 if(it == field_names.end())
837 return default_value;
838 return it->second->values[index];
839 }
840#endif
841
842 void AddField(std::shared_ptr<Field> field)
843 {
844 fields.push_back(field);
845 field_names[field->label] = field;
846 }
847
848 void AddField(size_t index, std::shared_ptr<Field> field)
849 {
850 fields.insert(fields.begin() + index, field);
851 field_names[field->label] = field;
852 }
853
854 template <typename D, typename ... Ts>
855 void AddField(std::string label, std::shared_ptr<D> display, Ts... values)
856 {
857 AddField(std::make_shared<FieldOf<Ts...>>(label, display, values..., false, false));
858 }
859
860 template <typename D, typename ... Ts>
861 void AddOptionalField(std::string label, std::shared_ptr<D> display, Ts... values)
862 {
863 AddField(std::make_shared<FieldOf<Ts...>>(label, display, values..., true, false));
864 }
865
866 template <typename D, typename ... Ts>
867 void AddHiddenField(std::string label, std::shared_ptr<D> display, Ts... values)
868 {
869 AddField(std::make_shared<FieldOf<Ts...>>(label, display, values..., false, true));
870 }
871
872 template <typename D, typename ... Ts>
873 void InsertField(size_t index, std::string label, std::shared_ptr<D> display, Ts... values)
874 {
875 AddField(index, std::make_shared<FieldOf<Ts...>>(label, display, values..., false, false));
876 }
877
878 template <typename D, typename ... Ts>
879 void InsertOptionalField(size_t index, std::string label, std::shared_ptr<D> display, Ts... values)
880 {
881 AddField(index, std::make_shared<FieldOf<Ts...>>(label, display, values..., true, false));
882 }
883
884 template <typename D, typename ... Ts>
885 void InsertHiddenField(size_t index, std::string label, std::shared_ptr<D> display, Ts... values)
886 {
887 AddField(index, std::make_shared<FieldOf<Ts...>>(label, display, values..., false, true));
888 }
889
895 virtual void Display(Dumper& dump, int options);
896};
897
901class Region : public Container
902{
903public:
904 Region(std::string name, offset_t offset, offset_t length, unsigned display_width)
905 : Container(name)
906 {
907 AddField("Offset", HexDisplay::Make(display_width), offset);
908 AddField("Length", HexDisplay::Make(display_width), length);
909 }
910
911 static std::shared_ptr<Region> Make(std::string name, offset_t offset, offset_t length, unsigned display_width)
912 {
913 return std::make_shared<Region>(name, offset, length, display_width);
914 }
915
916// void Display(Dumper& dump, int options);
917};
918
922class Entry : public Container
923{
924public:
925 offset_t number;
926 offset_t offset;
927 unsigned display_width;
928
929 Entry(std::string name, offset_t number, offset_t offset = offset_t(-1), unsigned display_width = 8)
930 : Container(name), number(number), offset(offset), display_width(display_width)
931 {
932 }
933
934 void Display(Dumper& dump, int options) override;
935};
936
940class Block : public Region
941{
942public:
949
950 static SingleByteEncoding encoding_default;
951 static SingleByteEncoding encoding_cp437;
952 static SingleByteEncoding encoding_st;
953 static SingleByteEncoding encoding_iso8859_1;
954 static SingleByteEncoding encoding_windows1252;
955 static SingleByteEncoding encoding_macroman;
956 static UTF8Encoding encoding_utf8;
957 static UTF16Encoding encoding_utf16le;
958 static UTF16Encoding encoding_utf16be;
959 static UTF32Encoding encoding_utf32le;
960 static UTF32Encoding encoding_utf32be;
961
962 std::shared_ptr<Linker::Image> image;
963
964 std::set<offset_t> signal_starts;
965 std::set<offset_t> signal_ends;
966
973 void AddSignal(offset_t off, offset_t len)
974 {
975 offset_t end = off + len - 1;
976 signal_starts.insert(off);
977 signal_ends.insert(end);
978 }
979
980 Block(std::string name, offset_t offset, std::shared_ptr<Linker::Image> image, offset_t address, unsigned display_width,
981 unsigned offset_display_width = 8, unsigned address_display_width = -1u, unsigned position_display_width = -1u)
982 : Region(name, offset, image ? image->ImageSize() : 0, display_width),
987 image(image)
988 {
989 AddField("Address", HexDisplay::Make(display_width), address);
990 }
991
992 static std::shared_ptr<Block> Make(std::string name, offset_t offset, std::shared_ptr<Linker::Image> image, offset_t address, unsigned display_width,
993 unsigned offset_display_width = 8, unsigned address_display_width = -1u, unsigned position_display_width = -1u)
994 {
995 return std::make_shared<Block>(name, offset, image, address, display_width, offset_display_width, address_display_width, position_display_width);
996 }
997
998 void Display(Dumper& dump, int options) override;
999};
1000
1009{
1010public:
1011 std::ostream& out;
1012 bool use_ansi;
1013 int show_options = All;
1014 int hide_options = None;
1015
1016 SingleByteEncoding * encoding;
1017 Encoding * string_encoding;
1018
1019 Dumper(std::ostream& out)
1020 : out(out), use_ansi(true), encoding(nullptr), string_encoding(nullptr)
1021 {
1022 }
1023
1024 SingleByteEncoding * SetEncoding(SingleByteEncoding& encoding, bool force = false)
1025 {
1026 SingleByteEncoding * old_encoding = this->encoding;
1027 if(this->encoding == nullptr || force)
1028 {
1029 this->encoding = &encoding;
1030 }
1031 return old_encoding;
1032 }
1033
1034 Encoding * SetStringEncoding(Encoding& encoding)
1035 {
1036 Encoding * old_encoding = this->string_encoding;
1037 this->string_encoding = &encoding;
1038 return old_encoding;
1039 }
1040
1041 void SetTitle(std::string title)
1042 {
1043 out << "=== " << title << " ===" << std::endl;
1044 }
1045
1046// std::vector<Field> fields;
1047
1051 void PrintHex(offset_t value, unsigned width, std::string prefix = "0x")
1052 {
1053 out << prefix << std::hex << std::setw(width) << std::setfill('0') << value;
1054 }
1055
1056#if 0
1060 void PrintHex(offset_t value, unsigned width, bool prefixed)
1061 {
1062 PrintHex(value, width, prefixed ? "0x" : "");
1063 }
1064#endif
1065
1069 void PrintDec(offset_t value, std::string prefix = "#")
1070 {
1071 out << prefix << std::dec << value;
1072 }
1073
1077 void PrintDecSigned(relative_offset_t value, std::string prefix = "#")
1078 {
1079 out << prefix << std::dec << value;
1080 }
1081
1082#if 0
1086 void PrintDec(offset_t value, bool prefixed)
1087 {
1088 PrintDec(value, prefixed ? "#" : "");
1089 }
1090#endif
1091
1095 void PutChar(char32_t c)
1096 {
1097 /* TODO: this should depend on the current locale */
1098 const char32_t * input = &c;
1099 char * output = nullptr;
1100 size_t size;
1101 UTF32ToUTF8(input, output, 0, size);
1102 std::vector<char> buffer(size);
1103 output = buffer.data();
1104 UTF32ToUTF8(input, output, size, size);
1105 out << std::string(buffer.data(), buffer.size());
1106 }
1107
1108 void PutEncodedString(std::string encoded_string, bool terminate_at_null = false)
1109 {
1110 uint8_t const * input = reinterpret_cast<uint8_t *>(encoded_string.data());
1111 size_t length = encoded_string.size();
1112 char32_t c;
1113 while((c = (string_encoding ? string_encoding : encoding)->GetChar(input, length)) != char32_t(-1) || (terminate_at_null && c == U'\0'))
1114 {
1115 PutChar(c);
1116 }
1117 }
1118
1119 void PutEncodedString(offset_t width, std::string encoded_string, char32_t padding)
1120 {
1121 uint8_t const * input = reinterpret_cast<uint8_t *>(encoded_string.data());
1122 size_t length = encoded_string.size();
1123 char32_t c;
1124 while(width > 0 && (c = (string_encoding ? string_encoding : encoding)->GetChar(input, length)) != char32_t(-1))
1125 {
1126 PutChar(c);
1127 width --;
1128 }
1129 while(width > 0)
1130 {
1131 PutChar(padding);
1132 width --;
1133 }
1134 }
1135
1140 {
1141 if(use_ansi)
1142 out << "\33[1m";
1143 }
1144
1148 void EndBold()
1149 {
1150 if(use_ansi)
1151 out << "\33[22m";
1152 }
1153
1158 {
1159 if(use_ansi)
1160 out << "\33[4m";
1161 }
1162
1167 {
1168 if(use_ansi)
1169 out << "\33[m";
1170 }
1171};
1172
1173template <unsigned I, size_t ... Is, typename ... Ts>
1174 inline auto rest_(std::tuple<Ts...> elements, std::index_sequence<Is...> s)
1175{
1176 return std::make_tuple(std::get<I + Is>(elements)...);
1177}
1178
1179template <unsigned I, typename ... Ts>
1180 inline auto rest(std::tuple<Ts...> elements)
1181{
1182 return rest_<I>(elements, std::make_index_sequence<sizeof...(Ts) - I>());
1183}
1184
1185template <typename ... Ts>
1186 void SectionedDisplay<Ts...>::DisplayValue(Dumper& dump, std::tuple<offset_t, Ts...> values)
1187{
1188 dump.PrintDec(std::get<0>(values), "");
1189 dump.out << suffix << ':';
1190 offset_display->DisplayValue(dump, rest<1>(values));
1191}
1192
1193template <typename Clock>
1194 void TimestampDisplay<Clock>::DisplayValue(Dumper& dump, std::tuple<Timestamp> values)
1195{
1196 dump.out << Clock::to_iso_time(std::get<0>(values));
1197}
1198
1199}
1200
1201#endif /* DUMPER_H */
Definition dumper.h:504
A value that is separated into bitfields, typically bit flags.
Definition dumper.h:501
static std::shared_ptr< BitFieldDisplay > Make(unsigned width=8)
Create a bit field display.
Definition dumper.h:535
A display for a fixed length binary data field.
Definition dumper.h:596
std::shared_ptr< Display< std::string > > secondary_display
Alternative representation, appearing after the value.
Definition dumper.h:606
offset_t width
The width of the string field, exactly this many characters will be shown, unless it is offset_t(-1),...
Definition dumper.h:601
static std::shared_ptr< BlobDisplay > Make(size_t width, std::shared_ptr< Display< std::string > > secondary_display=nullptr)
Create a binary blob display.
Definition dumper.h:621
A region within a file that can be dumped, decompiled, and it may contain fixups.
Definition dumper.h:941
unsigned offset_display_width
Displaying in-file offsets.
Definition dumper.h:944
void AddSignal(offset_t off, offset_t len)
Add a relocation inside the image block.
Definition dumper.h:973
unsigned position_display_width
Displaying in-segment positions.
Definition dumper.h:946
void Display(Dumper &dump, int options) override
Passes information onto the dumper.
Definition dumper.cc:452
unsigned address_display_width
Displaying in-memory addresses.
Definition dumper.h:948
Represents an enumerated value, with named options.
Definition dumper.h:217
static std::shared_ptr< ChoiceDisplay > Make(std::map< offset_t, std::string > names, offset_t missing_value, std::string default_name="unknown", std::shared_ptr< Display< offset_t > > secondary_display=nullptr)
Create a choice display.
Definition dumper.h:268
std::map< offset_t, std::string > names
Maps values to names.
Definition dumper.h:222
std::shared_ptr< Display< offset_t > > secondary_display
Alternative representation, appearing in parentheses after the value.
Definition dumper.h:239
static std::shared_ptr< ChoiceDisplay > Make(std::string on_true)
Creates a boolean choice that is either present with name or not present at all.
Definition dumper.h:323
bool missing_on_value
If false, any value not listed in names is missing, otherwise only missing_value is missing.
Definition dumper.h:231
static std::shared_ptr< ChoiceDisplay > Make(std::string on_true, std::string on_false)
Creates a boolean choice.
Definition dumper.h:305
std::string default_name
Name for values not contained in names.
Definition dumper.h:226
static std::shared_ptr< ChoiceDisplay > Make(std::map< offset_t, std::string > names, offset_t missing_value, std::shared_ptr< Display< offset_t > > secondary_display)
Create a choice display.
Definition dumper.h:293
offset_t missing_value
The single missing value, only used for missing_on_value true.
Definition dumper.h:235
static std::shared_ptr< ChoiceDisplay > Make(std::map< offset_t, std::string > names, std::string default_name="unknown", std::shared_ptr< Display< offset_t > > secondary_display=nullptr)
Create a choice display.
Definition dumper.h:254
static std::shared_ptr< ChoiceDisplay > Make(std::map< offset_t, std::string > names, std::shared_ptr< Display< offset_t > > secondary_display)
Create a choice display.
Definition dumper.h:280
A record whose values should be displayed together, as a collection.
Definition dumper.h:797
Represents a field with a decimal display, usually indices into an array or similar,...
Definition dumper.h:369
static std::shared_ptr< DecDisplay > Make(bool enable_signed)
Creates a decimal display.
Definition dumper.h:384
static std::shared_ptr< DecDisplay > Make(std::string suffix="", bool enable_signed=false)
Creates a decimal display.
Definition dumper.h:396
This class represents an entry that can be displayed in a file dump.
Definition dumper.h:198
virtual bool IsMissing(std::tuple< Ts... > &values)
Returns true if the specified value is such that it should not be displayed.
Definition dumper.h:203
virtual void DisplayValue(Dumper &dump, std::tuple< Ts... > values)=0
Prints the value through the Dumper, different types of fields can be displayed in different ways.
An abstract interface that separates structure and presentation of the data inside a file.
Definition dumper.h:1009
void PrintDecSigned(relative_offset_t value, std::string prefix="#")
Displays a decimal value (default prefix is "#")
Definition dumper.h:1077
void BeginBold()
ANSI escape sequence to begin bold text.
Definition dumper.h:1139
void PrintHex(offset_t value, unsigned width, std::string prefix="0x")
Displays a hexadecimal value (default prefix is "0x")
Definition dumper.h:1051
void EndBold()
ANSI escape sequence to end terminate text.
Definition dumper.h:1148
void EndUnderline()
ANSI escape sequence to remove all formatting.
Definition dumper.h:1166
void PrintDec(offset_t value, std::string prefix="#")
Displays a decimal value (default prefix is "#")
Definition dumper.h:1069
void BeginUnderline()
ANSI escape sequence to add underline.
Definition dumper.h:1157
void PutChar(char32_t c)
Displays a Unicode character as a UTF-8 byte sequence.
Definition dumper.h:1095
Definition dumper.h:68
A brief record, such as a relocation or imported library.
Definition dumper.h:923
A typed representation of a named value within a structure.
Definition dumper.h:771
std::shared_ptr< Display< Ts... > > display
The method to show it in.
Definition dumper.h:774
A representation of a named value within a structure.
Definition dumper.h:746
std::string label
The name to be displayed.
Definition dumper.h:749
bool internal
The field should not be displayed, it is for internal use (alternatively, it can be displayed through...
Definition dumper.h:753
bool optional_field
If the field is optional, it will not be displayed for certain values.
Definition dumper.h:751
Represents a field with a hexadecimal display, typically bitfields, addresses, sizes,...
Definition dumper.h:343
static std::shared_ptr< HexDisplay > Make(unsigned width=8)
Creates a hexadecimal display.
Definition dumper.h:357
A record that represents a region within the file.
Definition dumper.h:902
A display for a fixed or variable length string field with formatting.
Definition dumper.h:701
static std::shared_ptr< RichTextDisplay > Make(std::string quote="")
Create a string display.
Definition dumper.h:728
static std::shared_ptr< RichTextDisplay > Make(std::string open_quote, std::string close_quote)
Create a string display.
Definition dumper.h:717
Definition dumper.h:139
A display with a prefix for a section.
Definition dumper.h:461
static std::shared_ptr< SectionedDisplay > Make(std::string suffix, std::shared_ptr< Display< Ts... > > offset_display)
Create a sectioned display of an unsigned decimal and a secondary value.
Definition dumper.h:489
static std::shared_ptr< SectionedDisplay > Make(std::shared_ptr< Display< Ts... > > offset_display)
Create a sectioned display of an unsigned decimal and a secondary value.
Definition dumper.h:477
A value displayed as a colon-separated pair, typically 8086 segmented addresses.
Definition dumper.h:408
static std::shared_ptr< SegmentedDisplay > Make(unsigned width=4)
Create a segmented display of two hexadecimal values.
Definition dumper.h:422
Definition dumper.h:83
A display for a fixed or variable length string field.
Definition dumper.h:639
offset_t width
The width of the string field, exactly this many characters will be shown, unless it is offset_t(-1),...
Definition dumper.h:644
static std::shared_ptr< StringDisplay > Make(size_t width, std::string quote="")
Create a string display.
Definition dumper.h:672
static std::shared_ptr< StringDisplay > Make(size_t width, std::string open_quote, std::string close_quote)
Create a string display.
Definition dumper.h:660
static std::shared_ptr< StringDisplay > Make(std::string quote="")
Create a string display.
Definition dumper.h:683
A value that holds a time point.
Definition dumper.h:562
Definition dumper.h:111
Definition dumper.h:125
Definition dumper.h:101
A value displayed as a separated pair, such as a version number.
Definition dumper.h:434
static std::shared_ptr< VersionDisplay > Make(std::string separator=".")
Create a version display of two unsigned decimal values.
Definition dumper.h:448