blob: 96cbada8fbac5f4b634974d668c0cea52a9cfb92 [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// 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/logging.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