disassembler_ztf.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef COMPONENTS_ZUCCHINI_DISASSEMBLER_ZTF_H_
  5. #define COMPONENTS_ZUCCHINI_DISASSEMBLER_ZTF_H_
  6. #include <stdint.h>
  7. #include <stdlib.h>
  8. #include <memory>
  9. #include <string>
  10. #include <vector>
  11. #include "components/zucchini/disassembler.h"
  12. #include "components/zucchini/image_utils.h"
  13. #include "components/zucchini/type_ztf.h"
  14. #include "third_party/abseil-cpp/absl/types/optional.h"
  15. namespace zucchini {
  16. // Disassembler for text based files. This file format is supported for
  17. // debugging Zucchini and is not intended for production usage.
  18. //
  19. // A valid Zucchini Text Format (ZTF) file is specified as follows:
  20. //
  21. // Header:
  22. // The first four bytes must be - 'Z' 'T' 'x' 't'
  23. // Footer:
  24. // The last five bytes must be - 't' 'x' 'T' 'Z' '\n'
  25. // (note that terminating new line is required).
  26. // Content:
  27. // The content can be any sequence of printable ASCII characters and new line
  28. // (but not carriage return). This excludes the sequence that comprises the
  29. // Footer.
  30. // References:
  31. // A reference is either Absolute or Relative. All references must begin and
  32. // end with a pair of enclosing characters <open>, <close>. The options are:
  33. // - Angles: '<' and '>'
  34. // - Braces: '{' and '}'
  35. // - Brackets: '[' and ']'
  36. // - Parentheses: '(' and ')'
  37. //
  38. // A reference contains three items:
  39. // - A line number <line>
  40. // - A delimiter ',' <delimiter>
  41. // - A column number <col>
  42. // <line> and <col> may contain 1-3 digits and both must contain the same
  43. // number of digits. If a number is too short then it can be left-padded
  44. // with '0'.
  45. //
  46. // For Absolute references, <line> and <col> are 1-based (i.e. positive)
  47. // index of line and column numbers of a character in the ZTF. This follows
  48. // standard convention for text editors. Note that "\n" is considered to be
  49. // part of a preceding line.
  50. //
  51. // <open><line><delimiter><col><close>
  52. //
  53. // For Relative references, <line> and <col> are integer offsets deltas of the
  54. // target's (absolute) line and column relative to the line and column of the
  55. // reference's first byte (i.e. <open>). Relative references have <sign> ('+'
  56. // or '-') before <line> and <col>. For the special case of "0", "00", etc.,
  57. // <sign> must be "+".
  58. //
  59. // <open><sign><line><delimiter><sign><col><close>
  60. //
  61. // If a reference points outside the target either in writing or reading it is
  62. // considered invalid and ignored. Similarly if it overflows a line. i.e. if a
  63. // line is 10 characters long and a references targets character 11 of that
  64. // line it is rejected. Lines are delimited with '\n' which is counted toward
  65. // the line length.
  66. //
  67. // If a reference is to be written that would overwrite a '\n' character it is
  68. // ignored as this would break all other line values.
  69. enum : size_t { kMaxDigitCount = 3 };
  70. // Helper class for translating among offset_t, ztf::LineCol and
  71. // ztf::DeltaLineCol.
  72. class ZtfTranslator {
  73. public:
  74. ZtfTranslator();
  75. ZtfTranslator(const ZtfTranslator&) = delete;
  76. const ZtfTranslator& operator=(const ZtfTranslator&) = delete;
  77. ~ZtfTranslator();
  78. // Initializes |line_starts_| with the contents of |image|.
  79. bool Init(ConstBufferView image);
  80. // Checks if |lc| is a valid location in the file.
  81. bool IsValid(ztf::LineCol lc) const;
  82. // Checks if |dlc| relative to |offset| is a valid location in the file.
  83. bool IsValid(offset_t offset, ztf::DeltaLineCol dlc) const;
  84. // Returns the offset corresponding to |line_col| if it is valid. Otherwise
  85. // returns |kInvalidOffset|.
  86. offset_t LineColToOffset(ztf::LineCol line_col) const;
  87. // Returns the ztf::LineCol for an |offset| if it is valid. Otherwise returns
  88. // absl::nullopt.
  89. absl::optional<ztf::LineCol> OffsetToLineCol(offset_t offset) const;
  90. private:
  91. // Returns an iterator to the range containing |offset|. Which is represented
  92. // by the starting offset. The next element will contain the upper bound of
  93. // the range.
  94. std::vector<offset_t>::const_iterator SearchForRange(offset_t offset) const;
  95. // Returns the length of a 1-indexed line. The caller is expected to check
  96. // that the requested line exists.
  97. offset_t LineLength(uint16_t line) const;
  98. offset_t NumLines() const {
  99. return static_cast<offset_t>(line_starts_.size() - 1);
  100. }
  101. // |line_starts_| is a sorted list of each line's starting offset, along with
  102. // the image size as the sentinel; it looks like {0, ..., image.size}.
  103. std::vector<offset_t> line_starts_;
  104. };
  105. // Disassembler for Zucchini Text Format (ZTF).
  106. class DisassemblerZtf : public Disassembler {
  107. public:
  108. static constexpr uint16_t kVersion = 1;
  109. // Target Pools
  110. enum ReferencePool : uint8_t {
  111. kAngles, // <>
  112. kBraces, // {}
  113. kBrackets, // []
  114. kParentheses // ()
  115. };
  116. // Type breakdown. Should contain all permutations of ReferencePool, Abs|Rel
  117. // and the possible number of digits (1-3).
  118. enum ReferenceType : uint8_t {
  119. kAnglesAbs1,
  120. kAnglesAbs2,
  121. kAnglesAbs3,
  122. kAnglesRel1,
  123. kAnglesRel2,
  124. kAnglesRel3,
  125. kBracesAbs1,
  126. kBracesAbs2,
  127. kBracesAbs3,
  128. kBracesRel1,
  129. kBracesRel2,
  130. kBracesRel3,
  131. kBracketsAbs1,
  132. kBracketsAbs2,
  133. kBracketsAbs3,
  134. kBracketsRel1,
  135. kBracketsRel2,
  136. kBracketsRel3,
  137. kParenthesesAbs1,
  138. kParenthesesAbs2,
  139. kParenthesesAbs3,
  140. kParenthesesRel1,
  141. kParenthesesRel2,
  142. kParenthesesRel3,
  143. kNumTypes
  144. };
  145. DisassemblerZtf();
  146. DisassemblerZtf(const DisassemblerZtf&) = delete;
  147. const DisassemblerZtf& operator=(const DisassemblerZtf&) = delete;
  148. ~DisassemblerZtf() override;
  149. // Applies quick checks to determine if |image| *may* point to the start of a
  150. // ZTF file. Returns true on success.
  151. static bool QuickDetect(ConstBufferView image);
  152. // Disassembler:
  153. ExecutableType GetExeType() const override;
  154. std::string GetExeTypeString() const override;
  155. std::vector<ReferenceGroup> MakeReferenceGroups() const override;
  156. // Reference Readers, templated to allow configurable digit count and pool.
  157. template <uint8_t digits, ReferencePool pool>
  158. std::unique_ptr<ReferenceReader> MakeReadAbs(offset_t lo, offset_t hi);
  159. template <uint8_t digits, ReferencePool pool>
  160. std::unique_ptr<ReferenceReader> MakeReadRel(offset_t lo, offset_t hi);
  161. // Reference Writers, templated to allow configurable digit count and pool.
  162. template <uint8_t digits, ReferencePool pool>
  163. std::unique_ptr<ReferenceWriter> MakeWriteAbs(MutableBufferView image);
  164. template <uint8_t digits, ReferencePool pool>
  165. std::unique_ptr<ReferenceWriter> MakeWriteRel(MutableBufferView image);
  166. private:
  167. friend Disassembler;
  168. // Disassembler:
  169. bool Parse(ConstBufferView image) override;
  170. ZtfTranslator translator_;
  171. };
  172. } // namespace zucchini
  173. #endif // COMPONENTS_ZUCCHINI_DISASSEMBLER_ZTF_H_