-
Notifications
You must be signed in to change notification settings - Fork 0
/
disassembler.cc
108 lines (85 loc) · 3.23 KB
/
disassembler.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// 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 =
base::MakeUnique<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