| // Copyright 2011 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "courgette/disassembler.h" |
| |
| #include "base/check_op.h" |
| #include "base/memory/ptr_util.h" |
| #include "courgette/assembly_program.h" |
| #include "courgette/encoded_program.h" |
| |
| namespace courgette { |
| |
| Disassembler::RvaVisitor_Abs32::RvaVisitor_Abs32( |
| const std::vector<RVA>& rva_locations, |
| const AddressTranslator& translator) |
| : VectorRvaVisitor<RVA>(rva_locations), translator_(translator) { |
| } |
| |
| RVA Disassembler::RvaVisitor_Abs32::Get() const { |
| // For Abs32 targets, get target RVA from architecture-dependent functions. |
| return translator_->PointerToTargetRVA(translator_->RVAToPointer(*it_)); |
| } |
| |
| Disassembler::RvaVisitor_Rel32::RvaVisitor_Rel32( |
| const std::vector<RVA>& rva_locations, |
| const AddressTranslator& translator) |
| : VectorRvaVisitor<RVA>(rva_locations), translator_(translator) { |
| } |
| |
| RVA Disassembler::RvaVisitor_Rel32::Get() const { |
| // For Rel32 targets, only handle 32-bit offsets. |
| return *it_ + 4 + Read32LittleEndian(translator_->RVAToPointer(*it_)); |
| } |
| |
| Disassembler::Disassembler(const uint8_t* start, size_t length) |
| : failure_reason_("uninitialized") { |
| start_ = start; |
| length_ = length; |
| end_ = start_ + length_; |
| } |
| |
| Disassembler::~Disassembler() = default; |
| |
| const uint8_t* Disassembler::FileOffsetToPointer(FileOffset file_offset) const { |
| CHECK_LE(file_offset, static_cast<FileOffset>(end_ - start_)); |
| return start_ + file_offset; |
| } |
| |
| const uint8_t* Disassembler::RVAToPointer(RVA rva) const { |
| FileOffset file_offset = RVAToFileOffset(rva); |
| if (file_offset == kNoFileOffset) |
| return nullptr; |
| |
| return FileOffsetToPointer(file_offset); |
| } |
| |
| std::unique_ptr<AssemblyProgram> Disassembler::CreateProgram(bool annotate) { |
| if (!ok() || !ExtractAbs32Locations() || !ExtractRel32Locations()) |
| return nullptr; |
| |
| std::unique_ptr<AssemblyProgram> program = |
| std::make_unique<AssemblyProgram>(kind(), image_base()); |
| |
| PrecomputeLabels(program.get()); |
| RemoveUnusedRel32Locations(program.get()); |
| program->DefaultAssignIndexes(); |
| |
| if (annotate) { |
| if (!program->AnnotateLabels(GetInstructionGenerator(program.get()))) |
| return nullptr; |
| } |
| |
| return program; |
| } |
| |
| Status Disassembler::DisassembleAndEncode(AssemblyProgram* program, |
| EncodedProgram* encoded) { |
| program->PrepareEncodedProgram(encoded); |
| return encoded->GenerateInstructions(program->kind(), |
| GetInstructionGenerator(program)) |
| ? C_OK |
| : C_DISASSEMBLY_FAILED; |
| } |
| |
| bool Disassembler::Good() { |
| failure_reason_ = nullptr; |
| return true; |
| } |
| |
| bool Disassembler::Bad(const char* reason) { |
| failure_reason_ = reason; |
| return false; |
| } |
| |
| void Disassembler::PrecomputeLabels(AssemblyProgram* program) { |
| std::unique_ptr<RvaVisitor> abs32_visitor(CreateAbs32TargetRvaVisitor()); |
| std::unique_ptr<RvaVisitor> rel32_visitor(CreateRel32TargetRvaVisitor()); |
| program->PrecomputeLabels(abs32_visitor.get(), rel32_visitor.get()); |
| } |
| |
| void Disassembler::ReduceLength(size_t reduced_length) { |
| CHECK_LE(reduced_length, length_); |
| length_ = reduced_length; |
| end_ = start_ + length_; |
| } |
| |
| } // namespace courgette |