Repository navigation
Expand file tree
/
Copy pathexample.cpp
More file actions
136 lines (120 loc) · 5.78 KB
/
Copy pathexample.cpp
File metadata and controls
136 lines (120 loc) · 5.78 KB
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <cassert>
#include <iostream>
#include "nyxstone.h"
using namespace nyxstone;
int main(int /*argc*/, char** /*argv*/)
{
// Create the nyxstone instance:
auto nyxstone { NyxstoneBuilder("x86_64").build().value() };
// Assemble to bytes
std::vector<uint8_t> bytes {
nyxstone->assemble(/*assembly=*/"mov rax, rbx", /*address=*/0x1000, /* labels= */ {}).value()
};
{
const std::vector<uint8_t> expected { 0x48, 0x89, 0xd8 };
assert(bytes == expected);
}
// Assemble with additional information
std::vector<Nyxstone::Instruction> instrs { nyxstone
->assemble_to_instructions(
/*assembly=*/"mov rax, rbx", /*address=*/0x1000,
/*labels=*/ {})
.value() };
{
const std::vector<Nyxstone::Instruction> expected { Nyxstone::Instruction { /*address=*/0x1000,
/*assembly=*/"mov rax, rbx",
/*bytes=*/ { 0x48, 0x89, 0xd8 } } };
assert(instrs == expected);
}
// Assemble with inline label
instrs = nyxstone->assemble_to_instructions("je .label; nop; .label:", 0x1000, {}).value();
{
const std::vector<Nyxstone::Instruction> expected {
Nyxstone::Instruction { /*address=*/0x1000, /*assembly=*/"je .label", /*bytes=*/ { 0x74, 0x01 } },
Nyxstone::Instruction { /*address=*/0x1002, /*assembly=*/"nop", /*bytes=*/ { 0x90 } },
};
assert(instrs == expected);
}
// Assemble with external label
bytes = nyxstone->assemble("jmp .label", 0x1000, { Nyxstone::LabelDefinition { ".label", 0x100 } }).value();
{
const std::vector<uint8_t> expected { 0xe9, 0xfb, 0xf0, 0xff, 0xff };
assert(bytes == expected);
}
// Leave a reference to an external symbol to the linker and get its relocation
const Nyxstone::AssemblyResult result { nyxstone
->assemble_to_instructions_with_relocations(
/*assembly=*/"call ext", /*address=*/0x1000, /*labels=*/ {},
/*externs=*/ { "ext" })
.value() };
{
// x86_64 ELF uses RELA, so the relocation `R_X86_64_PLT32` (4) carries the addend and the field is 0
const std::vector<Nyxstone::Instruction> expected_instructions { Nyxstone::Instruction {
/*address=*/0x1000, /*assembly=*/"call ext", /*bytes=*/ { 0xe8, 0x00, 0x00, 0x00, 0x00 } } };
const std::vector<Nyxstone::Relocation> expected_relocations { Nyxstone::Relocation {
/*address=*/0x1001, /*type=*/4, /*symbol=*/"ext", /*has_addend=*/true, /*addend=*/-4 } };
assert(result.instructions == expected_instructions);
assert(result.relocations == expected_relocations);
}
// Disassemble some bytes
const std::vector<uint8_t> two_instruction_bytes
= { 0x48, 0x31, 0xc0, 0x66, 0x83, 0xc4, 0x08 }; // xor rax, rax; add sp, 8
std::string disassembly = nyxstone
->disassemble(
/*bytes=*/two_instruction_bytes,
/*address=*/0x1000,
/*count=*/0 // Disassemble all instructions
)
.value();
assert(disassembly
== "xor rax, rax\n"
"add sp, 8\n");
// Disassemble only one instruction of the bytes
disassembly = nyxstone
->disassemble(
/*bytes=*/two_instruction_bytes,
/*address=*/0x1000,
/*count=*/1 // Disassemble only one instruction
)
.value();
assert(disassembly == "xor rax, rax\n");
// Disassemble with additional information
instrs = nyxstone
->disassemble_to_instructions(
/*bytes=*/ { 0x48, 0x31, 0xc0, 0x66, 0x83, 0xc4, 0x08 },
/*address=*/0x1000,
/*count=*/0 // Disassemble all instructions
)
.value();
{
const std::vector<Nyxstone::Instruction> expected {
Nyxstone::Instruction { /*address=*/0x1000, /*assembly=*/"xor rax, rax", /*bytes=*/ { 0x48, 0x31, 0xc0 } },
Nyxstone::Instruction {
/*address=*/0x1003, /*assembly=*/"add sp, 8", /*bytes=*/ { 0x66, 0x83, 0xc4, 0x08 } },
};
assert(instrs == expected);
}
// Configure nyxstone to your liking:
nyxstone = std::move(
NyxstoneBuilder("thumbv8")
.with_cpu("cortex-m7")
.with_immediate_style(NyxstoneBuilder::IntegerBase::HexPrefix) // Change the printing style of immediates
.with_features("+mve.fp,+fp16") // Enable additional cpu features, here floating point instructions
.build()
.value());
// This fp instruction can be assembled via the new nyxstone instance
bytes = nyxstone->assemble("vadd.f16 s0, s1", 0x1000, {}).value();
{
const std::vector<uint8_t> expected { 0x30, 0xee, 0x20, 0x09 };
assert(bytes == expected);
}
// And the disassembly immediates are printed in hexadecimal style with a 0x-prefix
instrs = nyxstone->assemble_to_instructions("mov r0, #16", 0x1000, {}).value();
{
const std::vector<Nyxstone::Instruction> expected { Nyxstone::Instruction { /*address=*/0x1000,
/*assembly=*/"mov.w r0, #0x10",
/*bytes=*/ { 0x4f, 0xf0, 0x10, 0x00 } } };
assert(instrs == expected);
}
return 0;
}