• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 
5 #ifndef COMPONENTS_ZUCCHINI_DISASSEMBLER_H_
6 #define COMPONENTS_ZUCCHINI_DISASSEMBLER_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 #include "components/zucchini/buffer_view.h"
15 #include "components/zucchini/image_utils.h"
16 
17 namespace zucchini {
18 
19 // A vacuous ReferenceReader that produces no references.
20 class EmptyReferenceReader : public ReferenceReader {
21  public:
22   absl::optional<Reference> GetNext() override;
23 };
24 
25 // A vacuous EmptyReferenceWriter that does not write.
26 class EmptyReferenceWriter : public ReferenceWriter {
27  public:
28   void PutNext(Reference reference) override;
29 };
30 
31 // Disassembler needs to be declared before ReferenceGroup because the latter
32 // contains member pointers based on the former, and we use a compiler flag,
33 // -fcomplete-member-pointers, which enforces that member pointer base types are
34 // complete. This flag helps prevent us from running into problems in the
35 // Microsoft C++ ABI (see https://crbug.com/847724).
36 
37 class ReferenceGroup;
38 
39 // A Disassembler is used to encapsulate architecture specific operations, to:
40 // - Describe types of references found in the architecture using traits.
41 // - Extract references contained in an image file.
42 // - Correct target for some references.
43 class Disassembler {
44  public:
45   // Attempts to parse |image| and create an architecture-specifc Disassembler,
46   // as determined by DIS, which is inherited from Disassembler. Returns an
47   // instance of DIS if successful, and null otherwise.
48   template <class DIS>
Make(ConstBufferView image)49   static std::unique_ptr<DIS> Make(ConstBufferView image) {
50     auto disasm = std::make_unique<DIS>();
51     if (!disasm->Parse(image))
52       return nullptr;
53     return disasm;
54   }
55 
56   Disassembler(const Disassembler&) = delete;
57   const Disassembler& operator=(const Disassembler&) = delete;
58   virtual ~Disassembler();
59 
60   // Returns the type of executable handled by the Disassembler.
61   virtual ExecutableType GetExeType() const = 0;
62 
63   // Returns a more detailed description of the executable type.
64   virtual std::string GetExeTypeString() const = 0;
65 
66   // Creates and returns a vector that contains all groups of references.
67   // Groups must be aggregated by pool.
68   virtual std::vector<ReferenceGroup> MakeReferenceGroups() const = 0;
69 
image()70   ConstBufferView image() const { return image_; }
size()71   size_t size() const { return image_.size(); }
72 
num_equivalence_iterations()73   int num_equivalence_iterations() const { return num_equivalence_iterations_; }
74 
75  protected:
76   explicit Disassembler(int num_equivalence_iterations);
77 
78   // Parses |image| and initializes internal states. Returns true on success.
79   // This must be called once and before any other operation.
80   virtual bool Parse(ConstBufferView image) = 0;
81 
82   // Raw image data. After Parse(), a Disassembler should shrink this to contain
83   // only the portion containing the executable file it recognizes.
84   ConstBufferView image_;
85 
86   // The number of iterations to run for equivalence map generation. This should
87   // roughly be the max length of reference indirection chains.
88   int num_equivalence_iterations_;
89 };
90 
91 // A ReferenceGroup is associated with a specific |type| and has convenience
92 // methods to obtain readers and writers for that type. A ReferenceGroup does
93 // not store references; it is a lightweight class that communicates with the
94 // disassembler to operate on them.
95 class ReferenceGroup {
96  public:
97   // Member function pointer used to obtain a ReferenceReader.
98   using ReaderFactory = std::unique_ptr<ReferenceReader> (
99       Disassembler::*)(offset_t lower, offset_t upper);
100 
101   // Member function pointer used to obtain a ReferenceWriter.
102   using WriterFactory = std::unique_ptr<ReferenceWriter> (Disassembler::*)(
103       MutableBufferView image);
104 
105   // RefinedGeneratorFactory and RefinedReceptorFactory don't have to be
106   // identical to GeneratorFactory and ReceptorFactory, but they must be
107   // convertible. As a result, they can be pointer to member function of a
108   // derived Disassembler.
109   template <class RefinedReaderFactory, class RefinedWriterFactory>
ReferenceGroup(ReferenceTypeTraits traits,RefinedReaderFactory reader_factory,RefinedWriterFactory writer_factory)110   ReferenceGroup(ReferenceTypeTraits traits,
111                  RefinedReaderFactory reader_factory,
112                  RefinedWriterFactory writer_factory)
113       : traits_(traits),
114         reader_factory_(static_cast<ReaderFactory>(reader_factory)),
115         writer_factory_(static_cast<WriterFactory>(writer_factory)) {}
116 
117   // Returns a reader for all references in the binary.
118   // Invalidates any other writer or reader previously obtained for |disasm|.
119   std::unique_ptr<ReferenceReader> GetReader(Disassembler* disasm) const;
120 
121   // Returns a reader for references whose bytes are entirely contained in
122   // |[lower, upper)|.
123   // Invalidates any other writer or reader previously obtained for |disasm|.
124   std::unique_ptr<ReferenceReader> GetReader(offset_t lower,
125                                              offset_t upper,
126                                              Disassembler* disasm) const;
127 
128   // Returns a writer for references in |image|, assuming that |image| was the
129   // same one initially parsed by |disasm|.
130   // Invalidates any other writer or reader previously obtained for |disasm|.
131   std::unique_ptr<ReferenceWriter> GetWriter(MutableBufferView image,
132                                              Disassembler* disasm) const;
133 
134   // Returns traits describing the reference type.
traits()135   const ReferenceTypeTraits& traits() const { return traits_; }
136 
137   // Shorthand for traits().width.
width()138   offset_t width() const { return traits().width; }
139 
140   // Shorthand for traits().type_tag.
type_tag()141   TypeTag type_tag() const { return traits().type_tag; }
142 
143   // Shorthand for traits().pool_tag.
pool_tag()144   PoolTag pool_tag() const { return traits().pool_tag; }
145 
146  private:
147   ReferenceTypeTraits traits_;
148   ReaderFactory reader_factory_ = nullptr;
149   WriterFactory writer_factory_ = nullptr;
150 };
151 
152 }  // namespace zucchini
153 
154 #endif  // COMPONENTS_ZUCCHINI_DISASSEMBLER_H_
155