1 // Copyright (c) 2011 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.
5 #include "courgette/disassembler.h"
7 #include "base/logging.h"
8 #include "base/memory/ptr_util.h"
9 #include "courgette/assembly_program.h"
10 #include "courgette/encoded_program.h"
14 Disassembler::RvaVisitor_Abs32::RvaVisitor_Abs32(
15 const std::vector<RVA>& rva_locations,
16 const AddressTranslator& translator)
17 : VectorRvaVisitor<RVA>(rva_locations), translator_(translator) {
20 RVA Disassembler::RvaVisitor_Abs32::Get() const {
21 // For Abs32 targets, get target RVA from architecture-dependent functions.
22 return translator_.PointerToTargetRVA(translator_.RVAToPointer(*it_));
25 Disassembler::RvaVisitor_Rel32::RvaVisitor_Rel32(
26 const std::vector<RVA>& rva_locations,
27 const AddressTranslator& translator)
28 : VectorRvaVisitor<RVA>(rva_locations), translator_(translator) {
31 RVA Disassembler::RvaVisitor_Rel32::Get() const {
32 // For Rel32 targets, only handle 32-bit offsets.
33 return *it_ + 4 + Read32LittleEndian(translator_.RVAToPointer(*it_));
36 Disassembler::Disassembler(const uint8_t* start, size_t length)
37 : failure_reason_("uninitialized") {
40 end_ = start_ + length_;
43 Disassembler::~Disassembler() = default;
45 const uint8_t* Disassembler::FileOffsetToPointer(FileOffset file_offset) const {
46 CHECK_LE(file_offset, static_cast<FileOffset>(end_ - start_));
47 return start_ + file_offset;
50 const uint8_t* Disassembler::RVAToPointer(RVA rva) const {
51 FileOffset file_offset = RVAToFileOffset(rva);
52 if (file_offset == kNoFileOffset)
55 return FileOffsetToPointer(file_offset);
58 std::unique_ptr<AssemblyProgram> Disassembler::CreateProgram(bool annotate) {
59 if (!ok() || !ExtractAbs32Locations() || !ExtractRel32Locations())
62 std::unique_ptr<AssemblyProgram> program =
63 std::make_unique<AssemblyProgram>(kind(), image_base());
65 PrecomputeLabels(program.get());
66 RemoveUnusedRel32Locations(program.get());
67 program->DefaultAssignIndexes();
70 if (!program->AnnotateLabels(GetInstructionGenerator(program.get())))
77 Status Disassembler::DisassembleAndEncode(AssemblyProgram* program,
78 EncodedProgram* encoded) {
79 program->PrepareEncodedProgram(encoded);
80 return encoded->GenerateInstructions(program->kind(),
81 GetInstructionGenerator(program))
83 : C_DISASSEMBLY_FAILED;
86 bool Disassembler::Good() {
87 failure_reason_ = nullptr;
91 bool Disassembler::Bad(const char* reason) {
92 failure_reason_ = reason;
96 void Disassembler::PrecomputeLabels(AssemblyProgram* program) {
97 std::unique_ptr<RvaVisitor> abs32_visitor(CreateAbs32TargetRvaVisitor());
98 std::unique_ptr<RvaVisitor> rel32_visitor(CreateRel32TargetRvaVisitor());
99 program->PrecomputeLabels(abs32_visitor.get(), rel32_visitor.get());
102 void Disassembler::ReduceLength(size_t reduced_length) {
103 CHECK_LE(reduced_length, length_);
104 length_ = reduced_length;
105 end_ = start_ + length_;
108 } // namespace courgette