Merge pull request #123 from zyantific/error-handling

Improve error handling
This commit is contained in:
Matt
2024-05-14 17:12:49 +03:00
committed by GitHub
41 changed files with 1338 additions and 707 deletions
+2
View File
@@ -67,6 +67,7 @@ endif()
# Target: zasm
set(zasm_SOURCES
"src/zasm/src/core/error.cpp"
"src/zasm/src/core/filestream.cpp"
"src/zasm/src/core/memorystream.cpp"
"src/zasm/src/decoder/decoder.cpp"
@@ -165,6 +166,7 @@ if(ZASM_BUILD_TESTS OR CMKR_ROOT_PROJECT) # tests
"src/tests/main.cpp"
"src/tests/tests/tests.assembler.cpp"
"src/tests/tests/tests.decoder.cpp"
"src/tests/tests/tests.error.cpp"
"src/tests/tests/tests.externals.cpp"
"src/tests/tests/tests.formatter.cpp"
"src/tests/tests/tests.imports.cpp"
+1 -1
View File
@@ -28,7 +28,7 @@ int main()
Serializer serializer{};
auto res = serializer.serialize(program, 0x00400000);
assert(res == Error::None);
assert(res == ErrorCode::None);
std::cout << examples::utils::getDisassemblyDump(serializer, program.getMode()) << "\n";
}
+1 -1
View File
@@ -34,7 +34,7 @@ int main()
Serializer serializer{};
auto res = serializer.serialize(program, 0x00400000);
assert(res == Error::None);
assert(res == ErrorCode::None);
std::cout << examples::utils::getDisassemblyDump(serializer, program.getMode()) << "\n";
}
+2 -2
View File
@@ -127,9 +127,9 @@ int main()
// Serialize program.
Serializer serializer;
if (auto err = serializer.serialize(program, reinterpret_cast<int64_t>(pCodePage)); err != zasm::Error::None)
if (auto err = serializer.serialize(program, reinterpret_cast<int64_t>(pCodePage)); err != zasm::ErrorCode::None)
{
std::cout << "Serialization failure: " << zasm::getErrorName(err) << "\n";
std::cout << "Serialization failure: " << err.getErrorName() << "\n";
return EXIT_FAILURE;
}
+1 -1
View File
@@ -84,7 +84,7 @@ namespace zasm::examples::utils
auto res = decoder.decode(sectBuf + sectOffset, sectLen - sectOffset, curAddress);
if (!res.hasValue())
{
std::cout << "Decoder Error: " << zasm::getErrorName(res.error()) << std::endl;
std::cout << "Decoder Error: " << res.error().getErrorName() << std::endl;
break;
}
+3 -3
View File
@@ -33,16 +33,16 @@ int main()
const auto decoderRes = decoder.decode(code.data() + bytesDecoded, code.size() - bytesDecoded, curAddress);
if (!decoderRes)
{
std::cout << "Failed to decode at " << std::hex << curAddress << ", " << getErrorName(decoderRes.error()) << "\n";
std::cout << "Failed to decode at " << std::hex << curAddress << ", " << decoderRes.error().getErrorName() << "\n";
return EXIT_FAILURE;
}
const auto& instrInfo = *decoderRes;
const auto instr = instrInfo.getInstruction();
if (auto res = assembler.emit(instr); res != zasm::Error::None)
if (auto res = assembler.emit(instr); res != zasm::ErrorCode::None)
{
std::cout << "Failed to emit instruction " << std::hex << curAddress << ", " << getErrorName(res) << "\n";
std::cout << "Failed to emit instruction " << std::hex << curAddress << ", " << res.getErrorName() << "\n";
}
bytesDecoded += instrInfo.getLength();
+1 -1
View File
@@ -51,7 +51,7 @@ int main()
Serializer serializer{};
auto res = serializer.serialize(program, 0x00400000);
assert(res == Error::None);
assert(res == ErrorCode::None);
std::cout << examples::utils::getDisassemblyDump(serializer, program.getMode()) << "\n";
}
+68 -34
View File
@@ -5,7 +5,7 @@
namespace zasm
{
enum class Error : std::uint32_t
enum class ErrorCode : std::uint32_t
{
None = 0,
// Generic.
@@ -28,47 +28,81 @@ namespace zasm
// Decoder.
InvalidInstruction,
OutOfBounds,
InstructionTooLong,
// Encoder.
ImpossibleInstruction,
AddressOutOfRange,
// Serialization.
EmptyState,
ImpossibleRelocation,
};
static constexpr const char* getErrorName(Error err) noexcept
/// <summary>
/// The Error class represents an error code and can have additionally a message attached.
/// If the object is constructed with an error message additional memory will be allocated.
/// If the object is constructed only with an error code there will be no extra allocation.
/// </summary>
class Error
{
#define ERROR_STRING(e) \
case e: \
return #e
std::uintptr_t _data{};
switch (err)
{
ERROR_STRING(Error::None);
ERROR_STRING(Error::InvalidMode);
ERROR_STRING(Error::NotInitialized);
ERROR_STRING(Error::InvalidOperation);
ERROR_STRING(Error::InvalidParameter);
ERROR_STRING(Error::FileNotFound);
ERROR_STRING(Error::AccessDenied);
ERROR_STRING(Error::OutOfMemory);
ERROR_STRING(Error::LabelNotFound);
ERROR_STRING(Error::UnresolvedLabel);
ERROR_STRING(Error::InvalidLabel);
ERROR_STRING(Error::LabelAlreadyBound);
ERROR_STRING(Error::SectionNotFound);
ERROR_STRING(Error::SectionAlreadyBound);
ERROR_STRING(Error::SignatureMismatch);
ERROR_STRING(Error::InvalidInstruction);
ERROR_STRING(Error::OutOfBounds);
ERROR_STRING(Error::ImpossibleInstruction);
ERROR_STRING(Error::EmptyState);
ERROR_STRING(Error::ImpossibleRelocation);
default:
assert(false);
break;
}
#undef ERROR_STRING
return nullptr;
}
public:
constexpr Error() noexcept = default;
Error(const Error& other);
Error(Error&& other) noexcept;
/// <summary>
/// Construct an Error object with the given error code.
/// </summary>
/// <param name="code">Error Code</param>
Error(ErrorCode code) noexcept;
/// <summary>
/// Construct an Error object with the given error code and an additional message.
/// The message will be copied so it is safe to pass a temporary string.
/// </summary>
/// <param name="code">Error Code</param>
/// <param name="message">Additional information</param>
Error(ErrorCode code, const char* message);
~Error() noexcept;
/// <summary>
/// Returns the assigned error code.
/// </summary>
/// <returns>Error code</returns>
ErrorCode getCode() const noexcept;
/// <summary>
/// Returns the error code name as a string.
/// The return value is never nullptr.
/// </summary>
/// <returns>Error name</returns>
const char* getErrorName() const noexcept;
/// <summary>
/// Get the error message if it was set. If the object was constructed without a message
/// this function will translate the error code into a generic message.
/// The return value is never nullptr.
/// </summary>
/// <returns>Error message</returns>
const char* getErrorMessage() const noexcept;
/// <summary>
/// Clears the error object which means that the error code will be set to ErrorCode::None.
/// If the object has an additional message it will be deallocated.
/// </summary>
void clear();
/// <summary>
/// Returns true if the error object is empty.
/// </summary>
bool empty() const noexcept;
bool operator==(ErrorCode code) const noexcept;
bool operator!=(ErrorCode code) const noexcept;
Error& operator=(Error&& other) noexcept;
Error& operator=(const Error& other) noexcept;
};
} // namespace zasm
+8 -3
View File
@@ -10,10 +10,15 @@ namespace zasm
// Internal wrapper type for unexpected.
template<typename T> struct Unexpected
{
const T failure;
T failure;
constexpr Unexpected(const T& val) noexcept
: failure{ val }
constexpr Unexpected(T&& arg) noexcept
: failure{ std::move(arg) }
{
}
constexpr Unexpected(const T& arg) noexcept
: failure{ arg }
{
}
};
+18 -18
View File
@@ -129,48 +129,48 @@ namespace zasm
const auto entryCount = static_cast<std::uint32_t>(_entries.size());
if (auto len = stream.write(&entryCount, sizeof(entryCount)); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
for (const auto& entry : _entries)
{
if (auto len = stream.write(entry.hash); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (auto len = stream.write(entry.offset); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (auto len = stream.write(entry.len); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (auto len = stream.write(entry.capacity); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (auto len = stream.write(entry.refCount); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
}
const auto dataSize = static_cast<std::uint32_t>(_data.size());
if (auto len = stream.write(dataSize); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (dataSize > 0)
{
if (auto len = stream.write(_data.data(), dataSize); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
}
return Error::None;
return ErrorCode::None;
}
Error load(IStream& stream)
@@ -180,7 +180,7 @@ namespace zasm
std::uint32_t entryCount{};
if (auto len = stream.read(&entryCount, sizeof(entryCount)); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
std::vector<Entry> loadedEntries;
@@ -189,30 +189,30 @@ namespace zasm
{
if (auto len = stream.read(entry.hash); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (auto len = stream.read(entry.offset); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (auto len = stream.read(entry.len); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (auto len = stream.read(entry.capacity); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (auto len = stream.read(entry.refCount); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
}
std::uint32_t dataSize{};
if (auto len = stream.read(&dataSize, sizeof(dataSize)); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
std::vector<char> loadedData;
@@ -221,14 +221,14 @@ namespace zasm
loadedData.resize(dataSize);
if (auto len = stream.read(loadedData.data(), dataSize); len == 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
}
_entries = std::move(loadedEntries);
_data = std::move(loadedData);
return Error::None;
return ErrorCode::None;
}
private:
+4
View File
@@ -18,6 +18,10 @@ namespace zasm
Result decode(const void* data, std::size_t len, std::uint64_t address) noexcept;
MachineMode getMode() const;
const Error& getLastError() const;
private:
ZydisDecoder _decoder{};
MachineMode _mode{};
+4 -4
View File
@@ -36,7 +36,7 @@ namespace zasm::formatter
/// </summary>
/// <param name="program">The program to print as text</param>
/// <param name="options">Format options</param>
std::string toString(Program& program, Options options = kDefaultOptions);
std::string toString(const Program& program, Options options = kDefaultOptions);
/// <summary>
/// Formats a single node and results the text.
@@ -44,7 +44,7 @@ namespace zasm::formatter
/// <param name="program">The program to print as text</param>
/// <param name="node">Formats only the specified node</param>
/// <param name="options">Format options</param>
std::string toString(Program& program, const Node* node, Options options = kDefaultOptions);
std::string toString(const Program& program, const Node* node, Options options = kDefaultOptions);
/// <summary>
/// Formats the specified range, 'to' is not inclusive.
@@ -53,7 +53,7 @@ namespace zasm::formatter
/// <param name="nodeFrom">First node</param>
/// <param name="nodeTo">Last node</param>
/// <param name="options">Format options</param>
std::string toString(Program& program, const Node* nodeFrom, const Node* nodeTo, Options options = kDefaultOptions);
std::string toString(const Program& program, const Node* nodeFrom, const Node* nodeTo, Options options = kDefaultOptions);
/// <summary>
/// Formats a single instruction and results the text.
@@ -61,7 +61,7 @@ namespace zasm::formatter
/// <param name="program">The program to print as text</param>
/// <param name="instr">Instruction to format</param>
/// <param name="options">Format options</param>
std::string toString(Program& program, const Instruction* instr, Options options = kDefaultOptions);
std::string toString(const Program& program, const Instruction* instr, Options options = kDefaultOptions);
/// <summary>
/// Formats a single instruction and results the text.
+4
View File
@@ -2082,6 +2082,10 @@ namespace zasm::x86
{
return emit(x86::Mnemonic::Jecxz, a);
}
inline Error jecxz(const Label& a)
{
return emit(x86::Mnemonic::Jecxz, a);
}
inline Error jknzd(const Mask& a, const Imm& b)
{
return emit(x86::Mnemonic::Jknzd, a, b);
+9 -9
View File
@@ -11,7 +11,7 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(label01.isValid(), true);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
}
TEST(AssemblerTests, TestDoubleBindLabel)
@@ -22,8 +22,8 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(label01.isValid(), true);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), Error::LabelAlreadyBound);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::LabelAlreadyBound);
}
TEST(AssemblerTests, TestBindInvalidLabel)
@@ -32,9 +32,9 @@ namespace zasm::tests
x86::Assembler assembler(program);
zasm::Label label01;
Label label01;
ASSERT_EQ(label01.isValid(), false);
ASSERT_EQ(assembler.bind(label01), Error::InvalidLabel);
ASSERT_EQ(assembler.bind(label01), ErrorCode::InvalidLabel);
}
TEST(AssemblerTests, TestEmitDirectMov)
@@ -43,7 +43,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.emit(x86::Mnemonic::Mov, x86::rax, Imm(01)), Error::None);
ASSERT_EQ(assembler.emit(x86::Mnemonic::Mov, x86::rax, Imm(01)), ErrorCode::None);
}
TEST(AssemblerTests, TestRemoveCursorNode)
@@ -52,11 +52,11 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.mov(x86::rax, x86::rax), Error::None);
ASSERT_EQ(assembler.mov(x86::rax, x86::rax), ErrorCode::None);
auto* nodeA = assembler.getCursor();
ASSERT_EQ(assembler.mov(x86::rdx, x86::rdx), Error::None);
ASSERT_EQ(assembler.mov(x86::rdx, x86::rdx), ErrorCode::None);
auto* nodeB = assembler.getCursor();
ASSERT_EQ(assembler.mov(x86::rbx, x86::rbx), Error::None);
ASSERT_EQ(assembler.mov(x86::rbx, x86::rbx), ErrorCode::None);
auto* nodeC = assembler.getCursor();
program.destroy(nodeC);
+4 -4
View File
@@ -22,10 +22,10 @@ namespace zasm::tests
ASSERT_EQ(decoded->getMnemonic(), x86::Mnemonic::Mov);
ASSERT_EQ(decoded->getOperandCount(), 2);
ASSERT_EQ(assembler.emit(decoded.value().getInstruction()), Error::None);
ASSERT_EQ(assembler.emit(decoded.value().getInstruction()), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
const std::array<uint8_t, 5> expected = {
0xB8, 0x01, 0x00, 0x00, 0x00,
@@ -60,10 +60,10 @@ namespace zasm::tests
ASSERT_EQ(decoded->getOperand<Mem>(0).getBase(), x86::rip);
ASSERT_EQ(decoded->getOperand<Mem>(0).getDisplacement(), 0x00007FF8833E0679);
ASSERT_EQ(assembler.emit(decoded.value().getInstruction()), Error::None);
ASSERT_EQ(assembler.emit(decoded.value().getInstruction()), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00007FF8833DF000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00007FF8833DF000), ErrorCode::None);
const std::array<uint8_t, 6> expected = {
0xFF, 0x15, 0x73, 0x16, 0x00, 0x00,
+191
View File
@@ -0,0 +1,191 @@
#include <chrono>
#include <gtest/gtest.h>
#include <zasm/core/errors.hpp>
namespace zasm::tests
{
TEST(ErrorTests, TestBasic)
{
Error error(ErrorCode::InvalidMode);
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
}
TEST(ErrorTests, TestExt)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
}
TEST(ErrorTests, TestExtClear)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
error.clear();
ASSERT_TRUE(error.empty());
ASSERT_EQ(error, ErrorCode::None);
}
TEST(ErrorTests, TestCopy1)
{
Error error(ErrorCode::InvalidMode);
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
Error error2(error);
ASSERT_EQ(error2, ErrorCode::InvalidMode);
ASSERT_EQ(error2.getCode(), ErrorCode::InvalidMode);
}
TEST(ErrorTests, TestCopy2)
{
Error error(ErrorCode::InvalidMode);
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
Error error2;
error2 = error;
ASSERT_EQ(error2, ErrorCode::InvalidMode);
ASSERT_EQ(error2.getCode(), ErrorCode::InvalidMode);
}
TEST(ErrorTests, TestCopyExt1)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
Error error2(error);
ASSERT_EQ(error2, ErrorCode::InvalidMode);
ASSERT_EQ(error2.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error2.getErrorMessage(), std::string("test message"));
}
TEST(ErrorTests, TestCopyExt2)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
Error error2;
error2 = error;
ASSERT_EQ(error2, ErrorCode::InvalidMode);
ASSERT_EQ(error2.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error2.getErrorMessage(), std::string("test message"));
}
TEST(ErrorTests, TestMoveExt1)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
Error error2(std::move(error));
ASSERT_EQ(error2, ErrorCode::InvalidMode);
ASSERT_EQ(error2.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error2.getErrorMessage(), std::string("test message"));
ASSERT_TRUE(error.empty());
}
TEST(ErrorTests, TestMoveExt2)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
Error error2;
error2 = std::move(error);
ASSERT_EQ(error2, ErrorCode::InvalidMode);
ASSERT_EQ(error2.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error2.getErrorMessage(), std::string("test message"));
ASSERT_TRUE(error.empty());
}
#if defined(_DEBUG) && 0
// Leak Tests.
// Disabled by default, this is a very crude way to test for memory leaks.
// The process runs for 5 seconds and creates/destroys Error objects in where we can observe
// if the memory usage is stable.
static constexpr auto kLeakTestDurationSecs = std::chrono::milliseconds(5000);
TEST(ErrorTests, TestLeak1)
{
auto start = std::chrono::high_resolution_clock::now();
while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start)
< kLeakTestDurationSecs)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
}
}
TEST(ErrorTests, TestLeak2)
{
auto start = std::chrono::high_resolution_clock::now();
while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start)
< kLeakTestDurationSecs)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
Error error2(std::move(error));
ASSERT_EQ(error2, ErrorCode::InvalidMode);
ASSERT_EQ(error2.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error2.getErrorMessage(), std::string("test message"));
}
}
TEST(ErrorTests, TestLeak3)
{
auto start = std::chrono::high_resolution_clock::now();
while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start)
< kLeakTestDurationSecs)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
Error error2;
error2 = std::move(error);
ASSERT_EQ(error2, ErrorCode::InvalidMode);
ASSERT_EQ(error2.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error2.getErrorMessage(), std::string("test message"));
}
}
TEST(ErrorTests, TestLeak4)
{
auto start = std::chrono::high_resolution_clock::now();
while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start)
< kLeakTestDurationSecs)
{
Error error(ErrorCode::InvalidMode, "test message");
ASSERT_EQ(error, ErrorCode::InvalidMode);
ASSERT_EQ(error.getCode(), ErrorCode::InvalidMode);
ASSERT_EQ(error.getErrorMessage(), std::string("test message"));
error.clear();
ASSERT_TRUE(error.empty());
ASSERT_EQ(error, ErrorCode::None);
}
}
#endif
} // namespace zasm::tests
+25 -25
View File
@@ -13,10 +13,10 @@ namespace zasm::tests
auto externalLabel = program.createExternalLabel("external");
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(x86::rip, externalLabel)), Error::None);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(x86::rip, externalLabel)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), ErrorCode::None);
const std::array<uint8_t, 7> expected = {
0x48, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00,
@@ -47,10 +47,10 @@ namespace zasm::tests
auto externalLabel = program.createExternalLabel("external");
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(externalLabel)), Error::None);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(externalLabel)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), ErrorCode::None);
const std::array<uint8_t, 8> expected = { 0x48, 0x8d, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -79,13 +79,13 @@ namespace zasm::tests
auto externalLabel = program.createExternalLabel("external");
auto labelData = assembler.createLabel("EmbeddedLabelPos");
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(x86::rip, labelData)), Error::None);
ASSERT_EQ(assembler.mov(x86::rdx, x86::qword_ptr(x86::rax)), Error::None);
ASSERT_EQ(assembler.bind(labelData), Error::None);
ASSERT_EQ(assembler.embedLabel(externalLabel), Error::None);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(x86::rip, labelData)), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::rdx, x86::qword_ptr(x86::rax)), ErrorCode::None);
ASSERT_EQ(assembler.bind(labelData), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(externalLabel), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), ErrorCode::None);
const std::array<uint8_t, 18> expected = {
0x48, 0x8D, 0x05, 0x03, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -116,13 +116,13 @@ namespace zasm::tests
auto externalLabel = program.createExternalLabel("external");
auto labelData = assembler.createLabel("EmbeddedLabelPos");
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(labelData)), Error::None);
ASSERT_EQ(assembler.mov(x86::rdx, x86::qword_ptr(x86::rax)), Error::None);
ASSERT_EQ(assembler.bind(labelData), Error::None);
ASSERT_EQ(assembler.embedLabel(externalLabel), Error::None);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(labelData)), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::rdx, x86::qword_ptr(x86::rax)), ErrorCode::None);
ASSERT_EQ(assembler.bind(labelData), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(externalLabel), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), ErrorCode::None);
const std::array<uint8_t, 19> expected = { 0x48, 0x8d, 0x04, 0x25, 0x0b, 0x00, 0x40, 0x00, 0x48, 0x8b,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -153,13 +153,13 @@ namespace zasm::tests
auto externalLabel = program.createExternalLabel("external");
auto labelData = assembler.createLabel("EmbeddedLabelPos");
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(labelData)), Error::None);
ASSERT_EQ(assembler.mov(x86::edx, x86::dword_ptr(x86::eax)), Error::None);
ASSERT_EQ(assembler.bind(labelData), Error::None);
ASSERT_EQ(assembler.embedLabel(externalLabel), Error::None);
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(labelData)), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::edx, x86::dword_ptr(x86::eax)), ErrorCode::None);
ASSERT_EQ(assembler.bind(labelData), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(externalLabel), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), ErrorCode::None);
const std::array<uint8_t, 12> expected = {
0x8D, 0x05, 0x08, 0x00, 0x40, 0x00, 0x8B, 0x10, 0x00, 0x00, 0x00, 0x00,
@@ -199,13 +199,13 @@ namespace zasm::tests
auto externalLabel = program.createExternalLabel("external");
auto labelData = assembler.createLabel("EmbeddedLabelPos");
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(labelData)), Error::None);
ASSERT_EQ(assembler.mov(x86::edx, x86::dword_ptr(x86::eax)), Error::None);
ASSERT_EQ(assembler.bind(labelData), Error::None);
ASSERT_EQ(assembler.embedLabel(externalLabel), Error::None);
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(labelData)), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::edx, x86::dword_ptr(x86::eax)), ErrorCode::None);
ASSERT_EQ(assembler.bind(labelData), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(externalLabel), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000400000), ErrorCode::None);
{
const std::array<uint8_t, 12> expected = {
@@ -238,7 +238,7 @@ namespace zasm::tests
ASSERT_EQ(relocInfo->offset, 8);
}
ASSERT_EQ(serializer.relocate(0x0000000000500000), Error::None);
ASSERT_EQ(serializer.relocate(0x0000000000500000), ErrorCode::None);
{
const std::array<uint8_t, 12> expected = {
+21 -21
View File
@@ -10,7 +10,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.mov(x86::eax, x86::edx), zasm::Error::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::edx), ErrorCode::None);
auto nodeStr = formatter::toString(program, program.getHead());
ASSERT_EQ(nodeStr, std::string("mov eax, edx"));
@@ -22,7 +22,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.lock().inc(x86::dword_ptr(x86::eax)), zasm::Error::None);
ASSERT_EQ(assembler.lock().inc(x86::dword_ptr(x86::eax)), ErrorCode::None);
auto nodeStr = formatter::toString(program, program.getHead());
ASSERT_EQ(nodeStr, std::string("lock inc dword ptr ds:[eax]"));
@@ -35,8 +35,8 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.lock().inc(x86::dword_ptr(label)), zasm::Error::None);
ASSERT_EQ(assembler.bind(label), zasm::Error::None);
ASSERT_EQ(assembler.lock().inc(x86::dword_ptr(label)), ErrorCode::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
auto nodeStr = formatter::toString(program, program.getHead());
ASSERT_EQ(nodeStr, std::string("lock inc dword ptr ds:[L0]"));
@@ -49,7 +49,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.mov(x86::eax, Imm(-1)), zasm::Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(-1)), ErrorCode::None);
auto nodeStr = formatter::toString(program, program.getHead());
ASSERT_EQ(nodeStr, std::string("mov eax, -1"));
@@ -62,7 +62,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.mov(x86::eax, Imm(0x12345678)), zasm::Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(0x12345678)), ErrorCode::None);
auto nodeStr = formatter::toString(program, program.getHead());
ASSERT_EQ(nodeStr, std::string("mov eax, 305419896"));
@@ -75,7 +75,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.mov(x86::eax, Imm(0x12345678)), zasm::Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(0x12345678)), ErrorCode::None);
auto nodeStr = formatter::toString(program, program.getHead(), formatter::Options::HexImmediates);
ASSERT_EQ(nodeStr, std::string("mov eax, 0x12345678"));
@@ -88,7 +88,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(x86::eax, 0x12345678)), zasm::Error::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(x86::eax, 0x12345678)), ErrorCode::None);
auto nodeStr = formatter::toString(program, program.getHead(), formatter::Options::HexOffsets);
ASSERT_EQ(nodeStr, std::string("mov eax, dword ptr ds:[eax+0x12345678]"));
@@ -101,7 +101,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(x86::eax, -0x12345678)), zasm::Error::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(x86::eax, -0x12345678)), ErrorCode::None);
auto nodeStr = formatter::toString(program, program.getHead(), formatter::Options::HexOffsets);
ASSERT_EQ(nodeStr, std::string("mov eax, dword ptr ds:[eax-0x12345678]"));
@@ -116,12 +116,12 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
auto label02 = assembler.createLabel();
ASSERT_EQ(assembler.jmp(label02), zasm::Error::None);
ASSERT_EQ(assembler.lock().inc(x86::dword_ptr(label01)), zasm::Error::None);
ASSERT_EQ(assembler.bind(label01), zasm::Error::None);
ASSERT_EQ(assembler.dd(0), zasm::Error::None);
ASSERT_EQ(assembler.bind(label02), zasm::Error::None);
ASSERT_EQ(assembler.nop(), zasm::Error::None);
ASSERT_EQ(assembler.jmp(label02), ErrorCode::None);
ASSERT_EQ(assembler.lock().inc(x86::dword_ptr(label01)), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.dd(0), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
auto nodeStr = formatter::toString(program);
ASSERT_EQ(nodeStr, std::string("jmp L1\nlock inc dword ptr ds:[L0]\nL0:\ndd 0x00000000\nL1:\nnop"));
@@ -136,12 +136,12 @@ namespace zasm::tests
auto label01 = assembler.createLabel("Label01");
auto label02 = assembler.createLabel("Label02");
ASSERT_EQ(assembler.jmp(label02), zasm::Error::None);
ASSERT_EQ(assembler.lock().inc(x86::dword_ptr(label01)), zasm::Error::None);
ASSERT_EQ(assembler.bind(label01), zasm::Error::None);
ASSERT_EQ(assembler.dd(0), zasm::Error::None);
ASSERT_EQ(assembler.bind(label02), zasm::Error::None);
ASSERT_EQ(assembler.nop(), zasm::Error::None);
ASSERT_EQ(assembler.jmp(label02), ErrorCode::None);
ASSERT_EQ(assembler.lock().inc(x86::dword_ptr(label01)), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.dd(0), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
auto nodeStr = formatter::toString(program);
ASSERT_EQ(nodeStr, std::string("jmp Label02\nlock inc dword ptr ds:[Label01]\nLabel01:\ndd 0x00000000\nLabel02:\nnop"));
+4 -4
View File
@@ -38,10 +38,10 @@ namespace zasm::tests
const auto labelImpExitProcess = program.getOrCreateImportLabel("kernel32.dll", "ExitProcess");
ASSERT_TRUE(labelImpExitProcess.isValid());
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(labelImpExitProcess)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(labelImpExitProcess)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 5> expected = {
0xA1, 0x00, 0x00, 0x00, 0x00,
@@ -79,10 +79,10 @@ namespace zasm::tests
const auto labelImpExitProcess = program.getOrCreateImportLabel("kernel32.dll", "ExitProcess");
ASSERT_TRUE(labelImpExitProcess.isValid());
ASSERT_EQ(assembler.mov(x86::rax, x86::qword_ptr(x86::rip, labelImpExitProcess)), Error::None);
ASSERT_EQ(assembler.mov(x86::rax, x86::qword_ptr(x86::rip, labelImpExitProcess)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 7> expected = {
0x48, 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00,
+6 -6
View File
@@ -16,13 +16,13 @@ namespace zasm::tests
.addOperand(x86::eax) //
.addOperand(zasm::Imm(1)); //
ASSERT_EQ(assembler.emit(instr), Error::None);
ASSERT_EQ(assembler.emit(instr), ErrorCode::None);
const auto* instrNode = assembler.getCursor();
ASSERT_NE(instrNode, nullptr);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
const std::array<uint8_t, 5> expected = {
0xB8, 0x01, 0x00, 0x00, 0x00,
@@ -43,7 +43,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
assembler.mov(x86::eax, zasm::Imm(2));
assembler.mov(x86::eax, Imm(2));
auto* instrNode = assembler.getCursor();
@@ -51,10 +51,10 @@ namespace zasm::tests
Instruction instr = assembler.getCursor()->get<Instruction>();
// Modify operand.
instr.setOperand(1, zasm::Imm(1));
instr.setOperand(1, Imm(1));
// Emit modified
ASSERT_EQ(assembler.emit(instr), Error::None);
ASSERT_EQ(assembler.emit(instr), ErrorCode::None);
// Remove original
program.destroy(instrNode);
@@ -63,7 +63,7 @@ namespace zasm::tests
ASSERT_NE(instrNode, nullptr);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
const std::array<uint8_t, 5> expected = {
0xB8, 0x01, 0x00, 0x00, 0x00,
+4 -4
View File
@@ -18,10 +18,10 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(instrTest.emitter(assembler), Error::None) << instrTest.operation;
ASSERT_EQ(instrTest.emitter(assembler), ErrorCode::None) << instrTest.operation;
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None) << instrTest.operation;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None) << instrTest.operation;
auto hexEncoded = hexEncode(serializer.getCode(), serializer.getCodeSize());
ASSERT_EQ(std::string(instrTest.instrBytes), hexEncoded) << instrTest.operation;
@@ -40,11 +40,11 @@ namespace zasm::tests
for (const auto& instrEntry : data::Instructions)
{
ASSERT_EQ(instrEntry.emitter(assembler), Error::None) << instrEntry.instrBytes << ", " << instrEntry.operation;
ASSERT_EQ(instrEntry.emitter(assembler), ErrorCode::None) << instrEntry.instrBytes << ", " << instrEntry.operation;
}
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const uint8_t* codeBuf = serializer.getCode();
size_t offset = 0;
@@ -17,7 +17,7 @@ namespace zasm::tests
Program program(MachineMode::AMD64);
x86::Assembler assembler(program);
ASSERT_EQ(instrTest.emitter(assembler), Error::None) << instrTest.operation;
ASSERT_EQ(instrTest.emitter(assembler), ErrorCode::None) << instrTest.operation;
const auto* node = assembler.getCursor();
ASSERT_NE(node, nullptr);
+54 -54
View File
@@ -11,7 +11,7 @@ namespace zasm::tests
for (int i = 0; i < 10; i++)
{
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), ErrorCode::None);
}
ASSERT_EQ(program.size(), 10);
@@ -31,7 +31,7 @@ namespace zasm::tests
for (int i = 0; i < 10; i++)
{
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), ErrorCode::None);
}
ASSERT_EQ(program.size(), 10);
@@ -51,7 +51,7 @@ namespace zasm::tests
for (int i = 0; i < 10; i++)
{
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), ErrorCode::None);
}
ASSERT_EQ(program.size(), 10);
@@ -68,7 +68,7 @@ namespace zasm::tests
{
ASSERT_NE(node, nullptr);
const auto& instr = node->get<zasm::Instruction>();
const auto& instr = node->get<Instruction>();
const auto& imm = instr.getOperand<1, Imm>();
ASSERT_EQ(imm.value<int>(), i);
@@ -87,7 +87,7 @@ namespace zasm::tests
for (int i = 0; i < 10; i++)
{
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), ErrorCode::None);
}
ASSERT_EQ(program.size(), 10);
@@ -104,7 +104,7 @@ namespace zasm::tests
{
ASSERT_NE(node, nullptr);
const auto& instr = node->get<zasm::Instruction>();
const auto& instr = node->get<Instruction>();
const auto& imm = instr.getOperand<1, Imm>();
ASSERT_EQ(imm.value<int>(), i);
@@ -121,7 +121,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.mov(x86::eax, Imm(0)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(0)), ErrorCode::None);
ASSERT_EQ(program.size(), 1);
ASSERT_EQ(program.getHead(), program.getTail());
@@ -136,7 +136,7 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.mov(x86::eax, Imm(0)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(0)), ErrorCode::None);
ASSERT_EQ(program.size(), 1);
ASSERT_EQ(program.getHead(), program.getTail());
@@ -154,7 +154,7 @@ namespace zasm::tests
Node* fifthNode = nullptr;
for (int i = 0; i < 10; i++)
{
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), ErrorCode::None);
if (i == 5)
fifthNode = assembler.getCursor();
}
@@ -170,7 +170,7 @@ namespace zasm::tests
{
ASSERT_NE(node, nullptr);
const auto& instr = node->get<zasm::Instruction>();
const auto& instr = node->get<Instruction>();
const auto& imm = instr.getOperand<1, Imm>();
ASSERT_EQ(imm.value<int>(), NumberOrder[i]);
@@ -190,7 +190,7 @@ namespace zasm::tests
Node* fifthNode = nullptr;
for (int i = 0; i < 10; i++)
{
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, Imm(i)), ErrorCode::None);
if (i == 5)
fifthNode = assembler.getCursor();
}
@@ -206,7 +206,7 @@ namespace zasm::tests
{
ASSERT_NE(node, nullptr);
const auto& instr = node->get<zasm::Instruction>();
const auto& instr = node->get<Instruction>();
const auto& imm = instr.getOperand<1, Imm>();
ASSERT_EQ(imm.value<int>(), NumberOrder[i]);
@@ -223,22 +223,22 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.mov(x86::eax, x86::ebx), zasm::Error::None);
ASSERT_EQ(assembler.xor_(x86::ebx, x86::edx), zasm::Error::None);
ASSERT_EQ(assembler.add(x86::eax, Imm(1)), zasm::Error::None);
ASSERT_EQ(assembler.not_(x86::eax), zasm::Error::None);
ASSERT_EQ(assembler.xor_(x86::eax, Imm(1)), zasm::Error::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::ebx), ErrorCode::None);
ASSERT_EQ(assembler.xor_(x86::ebx, x86::edx), ErrorCode::None);
ASSERT_EQ(assembler.add(x86::eax, Imm(1)), ErrorCode::None);
ASSERT_EQ(assembler.not_(x86::eax), ErrorCode::None);
ASSERT_EQ(assembler.xor_(x86::eax, Imm(1)), ErrorCode::None);
auto labelFoo = assembler.createLabel("foo");
ASSERT_EQ(labelFoo.getId(), zasm::Label::Id{ 0 });
ASSERT_EQ(labelFoo.getId(), Label::Id{ 0 });
ASSERT_EQ(labelFoo.isValid(), true);
ASSERT_EQ(assembler.bind(labelFoo), zasm::Error::None);
ASSERT_EQ(assembler.mov(x86::dword_ptr(x86::rip, labelFoo), x86::eax), zasm::Error::None);
ASSERT_EQ(assembler.bind(labelFoo), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::dword_ptr(x86::rip, labelFoo), x86::eax), ErrorCode::None);
ASSERT_EQ(program.size(), 7);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x400000), zasm::Error::None);
ASSERT_EQ(serializer.serialize(program, 0x400000), ErrorCode::None);
const std::array<uint8_t, 18> expected = {
0x89, 0xd8, 0x31, 0xd3, 0x83, 0xc0, 0x01, 0xf7, 0xd0, 0x83, 0xf0, 0x01, 0x89, 0x05, 0xfa, 0xff, 0xff, 0xff,
@@ -269,41 +269,41 @@ namespace zasm::tests
{
x86::Assembler assembler(program);
ASSERT_EQ(assembler.push(x86::rax), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::rcx), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::rdx), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::rbx), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::rbp), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::rsi), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::rdi), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::r8), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::r9), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::r10), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::r11), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::r12), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::r13), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::r14), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::r15), zasm::Error::None);
ASSERT_EQ(assembler.pushfq(), zasm::Error::None);
ASSERT_EQ(assembler.push(x86::rax), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::rcx), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::rdx), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::rbx), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::rbp), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::rsi), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::rdi), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::r8), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::r9), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::r10), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::r11), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::r12), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::r13), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::r14), ErrorCode::None);
ASSERT_EQ(assembler.push(x86::r15), ErrorCode::None);
ASSERT_EQ(assembler.pushfq(), ErrorCode::None);
ASSERT_EQ(assembler.popfq(), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::r15), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::r14), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::r13), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::r12), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::r11), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::r10), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::r9), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::r8), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::rdi), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::rsi), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::rbp), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::rbx), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::rdx), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::rcx), zasm::Error::None);
ASSERT_EQ(assembler.pop(x86::rax), zasm::Error::None);
ASSERT_EQ(assembler.popfq(), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::r15), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::r14), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::r13), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::r12), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::r11), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::r10), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::r9), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::r8), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::rdi), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::rsi), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::rbp), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::rbx), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::rdx), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::rcx), ErrorCode::None);
ASSERT_EQ(assembler.pop(x86::rax), ErrorCode::None);
ASSERT_EQ(serializer.serialize(program, address), zasm::Error::None);
ASSERT_EQ(serializer.serialize(program, address), ErrorCode::None);
address += 0x10;
ASSERT_NE(serializer.getCodeSize(), 0);
+36 -36
View File
@@ -11,10 +11,10 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(0)), Error::None);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(0)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 8> expected = {
0x48, 0x8D, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00,
@@ -42,10 +42,10 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(0)), Error::None);
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(0)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 6> expected = {
0x8D, 0x05, 0x00, 0x00, 0x00, 0x00,
@@ -74,11 +74,11 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, label), Error::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::eax, label), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 5> expected = {
0xb8, 0x00, 0x10, 0x40, 0x00,
@@ -107,11 +107,11 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.mov(x86::rax, label), Error::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::rax, label), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000401000000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000401000000), ErrorCode::None);
const std::array<uint8_t, 10> expected = {
0x48, 0xB8, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
@@ -140,11 +140,11 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(label)), Error::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(label)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 5> expected = {
0xA1, 0x00, 0x10, 0x40, 0x00,
@@ -173,12 +173,12 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(label)), Error::None);
ASSERT_EQ(assembler.embedLabel(label), Error::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(label)), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(label), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
{
const std::array<uint8_t, 9> expected = {
@@ -207,7 +207,7 @@ namespace zasm::tests
ASSERT_EQ(relocInfo02->offset, 5);
}
ASSERT_EQ(serializer.relocate(0x0000000000501000), Error::None);
ASSERT_EQ(serializer.relocate(0x0000000000501000), ErrorCode::None);
{
const std::array<uint8_t, 9> expected = {
@@ -244,12 +244,12 @@ namespace zasm::tests
x86::Assembler assembler(program);
auto label = assembler.createLabel();
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.mov(x86::rax, label), Error::None);
ASSERT_EQ(assembler.embedLabel(label), Error::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.mov(x86::rax, label), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(label), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000401000000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000401000000), ErrorCode::None);
{
const std::array<uint8_t, 18> expected = {
@@ -279,7 +279,7 @@ namespace zasm::tests
ASSERT_EQ(relocInfo02->offset, 10);
}
ASSERT_EQ(serializer.relocate(0x0000000501000000), Error::None);
ASSERT_EQ(serializer.relocate(0x0000000501000000), ErrorCode::None);
{
const std::array<uint8_t, 18> expected = {
@@ -323,25 +323,25 @@ namespace zasm::tests
auto labelC = a.createLabel();
ASSERT_EQ(labelC.isValid(), true);
ASSERT_EQ(a.section(".text"), Error::None);
ASSERT_EQ(a.section(".text"), ErrorCode::None);
{
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), Error::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), ErrorCode::None);
}
ASSERT_EQ(a.section(".data", Section::Attribs::Data), Error::None);
ASSERT_EQ(a.section(".data", Section::Attribs::Data), ErrorCode::None);
{
ASSERT_EQ(a.bind(labelA), Error::None);
ASSERT_EQ(a.dq(0x123456789), Error::None);
ASSERT_EQ(a.bind(labelB), Error::None);
ASSERT_EQ(a.dq(0x987654321), Error::None);
ASSERT_EQ(a.bind(labelC), Error::None);
ASSERT_EQ(a.dq(0xABCDEF123), Error::None);
ASSERT_EQ(a.bind(labelA), ErrorCode::None);
ASSERT_EQ(a.dq(0x123456789), ErrorCode::None);
ASSERT_EQ(a.bind(labelB), ErrorCode::None);
ASSERT_EQ(a.dq(0x987654321), ErrorCode::None);
ASSERT_EQ(a.bind(labelC), ErrorCode::None);
ASSERT_EQ(a.dq(0xABCDEF123), ErrorCode::None);
}
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
{
ASSERT_EQ(serializer.getSectionCount(), 2);
@@ -367,7 +367,7 @@ namespace zasm::tests
std::string("8967452301000000214365870900000023F1DEBC0A000000"));
}
ASSERT_EQ(serializer.relocate(0x00500000), Error::None);
ASSERT_EQ(serializer.relocate(0x00500000), ErrorCode::None);
{
ASSERT_EQ(serializer.getSectionCount(), 2);
+4 -4
View File
@@ -21,7 +21,7 @@ namespace zasm::tests
auto label = assembler.createLabel();
assembler.bind(label);
}
ASSERT_EQ(instrEntry.emitter(assembler), Error::None) << instrEntry.instrBytes << ", " << instrEntry.operation;
ASSERT_EQ(instrEntry.emitter(assembler), ErrorCode::None) << instrEntry.instrBytes << ", " << instrEntry.operation;
entries++;
}
}
@@ -89,7 +89,7 @@ namespace zasm::tests
// Save Program.
MemoryStream buf;
ASSERT_EQ(save(outputProgram, buf), Error::None);
ASSERT_EQ(save(outputProgram, buf), ErrorCode::None);
// Read the serialized data back into a separate program.
@@ -108,7 +108,7 @@ namespace zasm::tests
// Save Program.
const auto filePath = std::filesystem::temp_directory_path() / "saverestoretest.zasm";
ASSERT_EQ(save(outputProgram, filePath), Error::None);
ASSERT_EQ(save(outputProgram, filePath), ErrorCode::None);
// Read the serialized data back into a separate program.
auto inputProgram = load(filePath);
@@ -129,7 +129,7 @@ namespace zasm::tests
// Save Program.
MemoryStream buf;
ASSERT_EQ(save(outputProgram, buf), Error::None);
ASSERT_EQ(save(outputProgram, buf), ErrorCode::None);
// Read the serialized data back into a separate program.
buf.seek(0, SeekType::Begin);
+63 -63
View File
@@ -16,14 +16,14 @@ namespace zasm::tests
// .text by default.
{
ASSERT_EQ(a.jmp(labelA), Error::None);
ASSERT_EQ(a.nop(), Error::None);
ASSERT_EQ(a.bind(labelA), Error::None);
ASSERT_EQ(a.nop(), Error::None);
ASSERT_EQ(a.jmp(labelA), ErrorCode::None);
ASSERT_EQ(a.nop(), ErrorCode::None);
ASSERT_EQ(a.bind(labelA), ErrorCode::None);
ASSERT_EQ(a.nop(), ErrorCode::None);
}
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
ASSERT_EQ(serializer.getSectionCount(), 1);
@@ -48,25 +48,25 @@ namespace zasm::tests
auto labelC = a.createLabel();
ASSERT_EQ(labelC.isValid(), true);
ASSERT_EQ(a.section(".text"), Error::None);
ASSERT_EQ(a.section(".text"), ErrorCode::None);
{
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), Error::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), ErrorCode::None);
}
ASSERT_EQ(a.section(".data", Section::Attribs::Data), Error::None);
ASSERT_EQ(a.section(".data", Section::Attribs::Data), ErrorCode::None);
{
ASSERT_EQ(a.bind(labelA), Error::None);
ASSERT_EQ(a.dq(0x123456789), Error::None);
ASSERT_EQ(a.bind(labelB), Error::None);
ASSERT_EQ(a.dq(0x987654321), Error::None);
ASSERT_EQ(a.bind(labelC), Error::None);
ASSERT_EQ(a.dq(0xABCDEF123), Error::None);
ASSERT_EQ(a.bind(labelA), ErrorCode::None);
ASSERT_EQ(a.dq(0x123456789), ErrorCode::None);
ASSERT_EQ(a.bind(labelB), ErrorCode::None);
ASSERT_EQ(a.dq(0x987654321), ErrorCode::None);
ASSERT_EQ(a.bind(labelC), ErrorCode::None);
ASSERT_EQ(a.dq(0xABCDEF123), ErrorCode::None);
}
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
ASSERT_EQ(serializer.getSectionCount(), 2);
@@ -104,33 +104,33 @@ namespace zasm::tests
auto labelC = a.createLabel();
ASSERT_EQ(labelC.isValid(), true);
ASSERT_EQ(a.section(".text"), Error::None);
ASSERT_EQ(a.section(".text"), ErrorCode::None);
{
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), Error::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), ErrorCode::None);
}
// Identical name attrib align causes a merge.
ASSERT_EQ(a.section(".text"), Error::None);
ASSERT_EQ(a.section(".text"), ErrorCode::None);
{
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), Error::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), ErrorCode::None);
}
ASSERT_EQ(a.section(".data", Section::Attribs::Data), Error::None);
ASSERT_EQ(a.section(".data", Section::Attribs::Data), ErrorCode::None);
{
ASSERT_EQ(a.bind(labelA), Error::None);
ASSERT_EQ(a.dq(0x123456789), Error::None);
ASSERT_EQ(a.bind(labelB), Error::None);
ASSERT_EQ(a.dq(0x987654321), Error::None);
ASSERT_EQ(a.bind(labelC), Error::None);
ASSERT_EQ(a.dq(0xABCDEF123), Error::None);
ASSERT_EQ(a.bind(labelA), ErrorCode::None);
ASSERT_EQ(a.dq(0x123456789), ErrorCode::None);
ASSERT_EQ(a.bind(labelB), ErrorCode::None);
ASSERT_EQ(a.dq(0x987654321), ErrorCode::None);
ASSERT_EQ(a.bind(labelC), ErrorCode::None);
ASSERT_EQ(a.dq(0xABCDEF123), ErrorCode::None);
}
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
ASSERT_EQ(serializer.getSectionCount(), 2);
@@ -168,32 +168,32 @@ namespace zasm::tests
auto labelC = a.createLabel();
ASSERT_EQ(labelC.isValid(), true);
ASSERT_EQ(a.section(".text"), Error::None);
ASSERT_EQ(a.section(".text"), ErrorCode::None);
{
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), Error::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), ErrorCode::None);
}
ASSERT_EQ(a.section(".text", Section::Attribs::Exec), Error::None);
ASSERT_EQ(a.section(".text", Section::Attribs::Exec), ErrorCode::None);
{
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), Error::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rip, labelA)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rbx, x86::qword_ptr(x86::rip, labelB)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(x86::rip, labelC)), ErrorCode::None);
}
ASSERT_EQ(a.section(".data", Section::Attribs::Data), Error::None);
ASSERT_EQ(a.section(".data", Section::Attribs::Data), ErrorCode::None);
{
ASSERT_EQ(a.bind(labelA), Error::None);
ASSERT_EQ(a.dq(0x123456789), Error::None);
ASSERT_EQ(a.bind(labelB), Error::None);
ASSERT_EQ(a.dq(0x987654321), Error::None);
ASSERT_EQ(a.bind(labelC), Error::None);
ASSERT_EQ(a.dq(0xABCDEF123), Error::None);
ASSERT_EQ(a.bind(labelA), ErrorCode::None);
ASSERT_EQ(a.dq(0x123456789), ErrorCode::None);
ASSERT_EQ(a.bind(labelB), ErrorCode::None);
ASSERT_EQ(a.dq(0x987654321), ErrorCode::None);
ASSERT_EQ(a.bind(labelC), ErrorCode::None);
ASSERT_EQ(a.dq(0xABCDEF123), ErrorCode::None);
}
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
ASSERT_EQ(serializer.getSectionCount(), 3);
@@ -241,20 +241,20 @@ namespace zasm::tests
auto labelC = a.createLabel();
ASSERT_EQ(labelC.isValid(), true);
ASSERT_EQ(a.section(".text"), Error::None);
ASSERT_EQ(a.section(".text"), ErrorCode::None);
{
ASSERT_EQ(a.bind(labelA), Error::None);
ASSERT_EQ(a.jmp(labelB), Error::None);
ASSERT_EQ(a.bind(labelA), ErrorCode::None);
ASSERT_EQ(a.jmp(labelB), ErrorCode::None);
}
ASSERT_EQ(a.section(".text2", Section::Attribs::Code), Error::None);
ASSERT_EQ(a.section(".text2", Section::Attribs::Code), ErrorCode::None);
{
ASSERT_EQ(a.bind(labelB), Error::None);
ASSERT_EQ(a.jmp(labelA), Error::None);
ASSERT_EQ(a.bind(labelB), ErrorCode::None);
ASSERT_EQ(a.jmp(labelA), ErrorCode::None);
}
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
ASSERT_EQ(serializer.getSectionCount(), 2);
const auto* sectInfo01 = serializer.getSectionInfo(0);
@@ -287,20 +287,20 @@ namespace zasm::tests
auto labelC = a.createLabel();
ASSERT_EQ(labelC.isValid(), true);
ASSERT_EQ(a.section(".text"), Error::None);
ASSERT_EQ(a.section(".text"), ErrorCode::None);
{
ASSERT_EQ(a.bind(labelA), Error::None);
ASSERT_EQ(a.jz(labelB), Error::None);
ASSERT_EQ(a.bind(labelA), ErrorCode::None);
ASSERT_EQ(a.jz(labelB), ErrorCode::None);
}
ASSERT_EQ(a.section(".text2", Section::Attribs::Code), Error::None);
ASSERT_EQ(a.section(".text2", Section::Attribs::Code), ErrorCode::None);
{
ASSERT_EQ(a.bind(labelB), Error::None);
ASSERT_EQ(a.jz(labelA), Error::None);
ASSERT_EQ(a.bind(labelB), ErrorCode::None);
ASSERT_EQ(a.jz(labelA), ErrorCode::None);
}
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x00400000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x00400000), ErrorCode::None);
ASSERT_EQ(serializer.getSectionCount(), 2);
const auto* sectInfo01 = serializer.getSectionInfo(0);
+9 -9
View File
@@ -9,10 +9,10 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.mov(x86::rax, x86::qword_ptr(x86::fs, 0x30)), Error::None);
ASSERT_EQ(assembler.mov(x86::rax, x86::qword_ptr(x86::fs, 0x30)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 8> expected = {
0x64, 0x67, 0x48, 0xA1, 0x30, 0x00, 0x00, 0x00,
@@ -33,10 +33,10 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(x86::fs, 0x30)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(x86::fs, 0x30)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 5> expected = {
0x64, 0x67, 0xA1, 0x30, 0x00,
@@ -57,10 +57,10 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.mov(x86::rax, x86::qword_ptr(x86::gs, 0x30)), Error::None);
ASSERT_EQ(assembler.mov(x86::rax, x86::qword_ptr(x86::gs, 0x30)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 8> expected = {
0x65, 0x67, 0x48, 0xA1, 0x30, 0x00, 0x00, 0x00,
@@ -81,10 +81,10 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(x86::gs, 0x30)), Error::None);
ASSERT_EQ(assembler.mov(x86::eax, x86::dword_ptr(x86::gs, 0x30)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 5> expected = {
0x65, 0x67, 0xA1, 0x30, 0x00,
@@ -99,4 +99,4 @@ namespace zasm::tests
}
}
} // namespace zasm::tests
} // namespace zasm::tests
+301 -234
View File
@@ -10,10 +10,10 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(0)), Error::None);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(0)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 8> expected = {
0x48, 0x8D, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00,
@@ -34,10 +34,10 @@ namespace zasm::tests
x86::Assembler assembler(program);
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(0)), Error::None);
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(0)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 6> expected = {
0x8D, 0x05, 0x00, 0x00, 0x00, 0x00,
@@ -60,12 +60,12 @@ namespace zasm::tests
auto label = assembler.createLabel();
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(x86::rip, label)), Error::None);
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.dq(0x123C312F21329F31ULL), Error::None);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(x86::rip, label)), ErrorCode::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.dq(0x123C312F21329F31ULL), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 15> expected = {
0x48, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00, 0x31, 0x9F, 0x32, 0x21, 0x2F, 0x31, 0x3C, 0x12,
@@ -88,12 +88,12 @@ namespace zasm::tests
auto label = assembler.createLabel();
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(label)), Error::None);
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.dq(0x123C312F21329F31ULL), Error::None);
ASSERT_EQ(assembler.lea(x86::eax, x86::dword_ptr(label)), ErrorCode::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.dq(0x123C312F21329F31ULL), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 14> expected = { 0x8D, 0x05, 0x06, 0x10, 0x40, 0x00, 0x31,
0x9F, 0x32, 0x21, 0x2F, 0x31, 0x3C, 0x12 };
@@ -115,14 +115,14 @@ namespace zasm::tests
auto label = assembler.createLabel();
ASSERT_EQ(assembler.jmp(label), Error::None);
ASSERT_EQ(assembler.jmp(label), ErrorCode::None);
for (int i = 0; i < 124; i++)
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.int3(), Error::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.int3(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 127> expected = {
0xEB, 0x7C, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
@@ -151,15 +151,15 @@ namespace zasm::tests
auto label = assembler.createLabel();
ASSERT_EQ(assembler.jmp(label), Error::None);
ASSERT_EQ(assembler.jmp(label), ErrorCode::None);
for (int i = 0; i < 100; i++)
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 16), Error::None);
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.int3(), Error::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 16), ErrorCode::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.int3(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 113> expected = {
0xEB, 0x6E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
@@ -192,15 +192,15 @@ namespace zasm::tests
auto label = assembler.createLabel();
ASSERT_EQ(assembler.jmp(label), Error::None);
ASSERT_EQ(assembler.jmp(label), ErrorCode::None);
for (int i = 0; i < 124; i++)
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 32), Error::None);
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.int3(), Error::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 32), ErrorCode::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.int3(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 161> expected = {
0xE9, 0x9B, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
@@ -232,14 +232,14 @@ namespace zasm::tests
auto label = assembler.createLabel();
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.int3(), Error::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.int3(), ErrorCode::None);
for (int i = 0; i < 124; i++)
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.jmp(label), Error::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.jmp(label), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 127> expected = {
0xCC, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
@@ -268,14 +268,14 @@ namespace zasm::tests
auto label = assembler.createLabel();
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.int3(), Error::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.int3(), ErrorCode::None);
for (int i = 0; i < 124; i++)
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.jmp(label), Error::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.jmp(label), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 127> expected = {
0xCC, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
@@ -304,14 +304,14 @@ namespace zasm::tests
auto label = assembler.createLabel();
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.int3(), Error::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.int3(), ErrorCode::None);
for (int i = 0; i < 125; i++)
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.jmp(label), Error::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.jmp(label), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 131> expected = {
0xCC, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
@@ -340,14 +340,14 @@ namespace zasm::tests
auto label = assembler.createLabel();
ASSERT_EQ(assembler.bind(label), Error::None);
ASSERT_EQ(assembler.int3(), Error::None);
ASSERT_EQ(assembler.bind(label), ErrorCode::None);
ASSERT_EQ(assembler.int3(), ErrorCode::None);
for (int i = 0; i < 125; i++)
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.jmp(label), Error::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.jmp(label), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 131> expected = {
0xCC, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
@@ -376,12 +376,12 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(label01)), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.lea(x86::rax, x86::qword_ptr(label01)), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::UnresolvedLabel);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::UnresolvedLabel);
}
TEST(SerializationTests, UnBoundLabelRegression01)
@@ -406,67 +406,69 @@ namespace zasm::tests
Label labelImpExitProcess = program.getOrCreateImportLabel("kernel32.dll", "ExitProcess");
Label labelImpMessageBoxA = program.getOrCreateImportLabel("user32.dll", "MessageBoxA");
ASSERT_EQ(a.section(".text", Section::Attribs::Code | Section::Attribs::Exec | Section::Attribs::Read), Error::None);
ASSERT_EQ(a.bind(labelMain), Error::None);
ASSERT_EQ(a.sub(x86::rsp, Imm(0x28)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData01)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData01)), Error::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData02)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData02)), Error::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData03)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData03)), Error::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData04)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData04)), Error::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData05)), Error::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData05)), Error::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), Error::None);
ASSERT_EQ(a.xor_(x86::rcx, x86::rcx), Error::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelStrMessage)), Error::None);
ASSERT_EQ(a.lea(x86::r8, x86::qword_ptr(labelStrTitle)), Error::None);
ASSERT_EQ(a.mov(x86::r9, Imm(0)), Error::None);
ASSERT_EQ(a.call(x86::qword_ptr(labelImpMessageBoxA)), Error::None);
ASSERT_EQ(a.xor_(x86::rcx, x86::rcx), Error::None);
ASSERT_EQ(a.call(x86::qword_ptr(labelImpExitProcess)), Error::None);
ASSERT_EQ(a.add(x86::rsp, Imm(0x28)), Error::None);
ASSERT_EQ(a.ret(), Error::None);
ASSERT_EQ(
a.section(".text", Section::Attribs::Code | Section::Attribs::Exec | Section::Attribs::Read), ErrorCode::None);
ASSERT_EQ(a.bind(labelMain), ErrorCode::None);
ASSERT_EQ(a.sub(x86::rsp, Imm(0x28)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData01)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData01)), ErrorCode::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData02)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData02)), ErrorCode::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData03)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData03)), ErrorCode::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData04)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData04)), ErrorCode::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelRData05)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rax, x86::qword_ptr(x86::rdx)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelData05)), ErrorCode::None);
ASSERT_EQ(a.mov(x86::qword_ptr(x86::rdx), x86::rax), ErrorCode::None);
ASSERT_EQ(a.xor_(x86::rcx, x86::rcx), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rdx, x86::qword_ptr(labelStrMessage)), ErrorCode::None);
ASSERT_EQ(a.lea(x86::r8, x86::qword_ptr(labelStrTitle)), ErrorCode::None);
ASSERT_EQ(a.mov(x86::r9, Imm(0)), ErrorCode::None);
ASSERT_EQ(a.call(x86::qword_ptr(labelImpMessageBoxA)), ErrorCode::None);
ASSERT_EQ(a.xor_(x86::rcx, x86::rcx), ErrorCode::None);
ASSERT_EQ(a.call(x86::qword_ptr(labelImpExitProcess)), ErrorCode::None);
ASSERT_EQ(a.add(x86::rsp, Imm(0x28)), ErrorCode::None);
ASSERT_EQ(a.ret(), ErrorCode::None);
ASSERT_EQ(a.section(".data", Section::Attribs::Data | Section::Attribs::Read | Section::Attribs::Write), Error::None);
ASSERT_EQ(a.bind(labelData01), Error::None);
ASSERT_EQ(a.dq(01), Error::None);
ASSERT_EQ(a.bind(labelData02), Error::None);
ASSERT_EQ(a.dq(02), Error::None);
ASSERT_EQ(a.bind(labelData03), Error::None);
ASSERT_EQ(a.dq(03), Error::None);
ASSERT_EQ(a.bind(labelData04), Error::None);
ASSERT_EQ(a.dq(04), Error::None);
ASSERT_EQ(a.bind(labelData05), Error::None);
ASSERT_EQ(a.dq(05), Error::None);
ASSERT_EQ(
a.section(".data", Section::Attribs::Data | Section::Attribs::Read | Section::Attribs::Write), ErrorCode::None);
ASSERT_EQ(a.bind(labelData01), ErrorCode::None);
ASSERT_EQ(a.dq(01), ErrorCode::None);
ASSERT_EQ(a.bind(labelData02), ErrorCode::None);
ASSERT_EQ(a.dq(02), ErrorCode::None);
ASSERT_EQ(a.bind(labelData03), ErrorCode::None);
ASSERT_EQ(a.dq(03), ErrorCode::None);
ASSERT_EQ(a.bind(labelData04), ErrorCode::None);
ASSERT_EQ(a.dq(04), ErrorCode::None);
ASSERT_EQ(a.bind(labelData05), ErrorCode::None);
ASSERT_EQ(a.dq(05), ErrorCode::None);
ASSERT_EQ(a.section(".rdata", Section::Attribs::RData | Section::Attribs::Read), Error::None);
ASSERT_EQ(a.bind(labelStrMessage), Error::None);
ASSERT_EQ(a.embed("Hello World", 12), Error::None);
ASSERT_EQ(a.bind(labelRData01), Error::None);
ASSERT_EQ(a.dq(01), Error::None);
ASSERT_EQ(a.bind(labelRData02), Error::None);
ASSERT_EQ(a.dq(02), Error::None);
ASSERT_EQ(a.bind(labelRData03), Error::None);
ASSERT_EQ(a.dq(03), Error::None);
ASSERT_EQ(a.bind(labelRData04), Error::None);
ASSERT_EQ(a.dq(04), Error::None);
ASSERT_EQ(a.bind(labelRData05), Error::None);
ASSERT_EQ(a.dq(05), Error::None);
ASSERT_EQ(a.section(".rdata", Section::Attribs::RData | Section::Attribs::Read), ErrorCode::None);
ASSERT_EQ(a.bind(labelStrMessage), ErrorCode::None);
ASSERT_EQ(a.embed("Hello World", 12), ErrorCode::None);
ASSERT_EQ(a.bind(labelRData01), ErrorCode::None);
ASSERT_EQ(a.dq(01), ErrorCode::None);
ASSERT_EQ(a.bind(labelRData02), ErrorCode::None);
ASSERT_EQ(a.dq(02), ErrorCode::None);
ASSERT_EQ(a.bind(labelRData03), ErrorCode::None);
ASSERT_EQ(a.dq(03), ErrorCode::None);
ASSERT_EQ(a.bind(labelRData04), ErrorCode::None);
ASSERT_EQ(a.dq(04), ErrorCode::None);
ASSERT_EQ(a.bind(labelRData05), ErrorCode::None);
ASSERT_EQ(a.dq(05), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::UnresolvedLabel);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::UnresolvedLabel);
}
TEST(SerializationTests, EmbeddedLabelX64)
@@ -477,13 +479,13 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.embedLabel(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 10> expected = { 0x90, 0x90, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -504,13 +506,13 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.embedLabel(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 6> expected = { 0x90, 0x90, 0x00, 0x10, 0x40, 0x00 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -532,14 +534,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
auto label02 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label02), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.embedLabelRel(label02, label01, BitSize::_8), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.embedLabelRel(label02, label01, BitSize::_8), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 3> expected = { 0x90, 0x90, 0x01 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -561,14 +563,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
auto label02 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabelRel(label02, label01, BitSize::_8), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label02), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabelRel(label02, label01, BitSize::_8), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 3> expected = { 0x02, 0x90, 0x90 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -590,14 +592,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
auto label02 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabelRel(label01, label02, BitSize::_8), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label02), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabelRel(label01, label02, BitSize::_8), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 3> expected = { 0xFE, 0x90, 0x90 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -619,14 +621,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
auto label02 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabelRel(label02, label01, BitSize::_16), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label02), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabelRel(label02, label01, BitSize::_16), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 4> expected = { 0x03, 0x00, 0x90, 0x90 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -648,14 +650,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
auto label02 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabelRel(label01, label02, BitSize::_16), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label02), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabelRel(label01, label02, BitSize::_16), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 4> expected = { 0xFD, 0xFF, 0x90, 0x90 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -677,14 +679,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
auto label02 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabelRel(label02, label01, BitSize::_32), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label02), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabelRel(label02, label01, BitSize::_32), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 6> expected = { 0x05, 0x00, 0x00, 0x00, 0x90, 0x90 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -706,14 +708,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
auto label02 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabelRel(label01, label02, BitSize::_32), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label02), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabelRel(label01, label02, BitSize::_32), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 6> expected = { 0xFB, 0xFF, 0xFF, 0xFF, 0x90, 0x90 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -734,12 +736,12 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.db(0xCC, 16), Error::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabel(label01), Error::None);
ASSERT_EQ(assembler.db(0xCC, 16), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 24> expected = {
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
@@ -763,12 +765,12 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.dw(0x1234, 8), Error::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabel(label01), Error::None);
ASSERT_EQ(assembler.dw(0x1234, 8), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 24> expected = {
0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12,
@@ -792,12 +794,12 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.dd(0x12345678, 4), Error::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabel(label01), Error::None);
ASSERT_EQ(assembler.dd(0x12345678, 4), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 24> expected = {
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,
@@ -821,12 +823,12 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.dq(0x12345678AABBCCEE, 2), Error::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.embedLabel(label01), Error::None);
ASSERT_EQ(assembler.dq(0x12345678AABBCCEE, 2), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.embedLabel(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 24> expected = {
0xEE, 0xCC, 0xBB, 0xAA, 0x78, 0x56, 0x34, 0x12, 0xEE, 0xCC, 0xBB, 0xAA,
@@ -850,14 +852,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.db(0xCC, 4), Error::None);
ASSERT_EQ(assembler.db(0xCC, 4), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Data, 8), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Data, 8), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 8> expected = {
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
@@ -882,14 +884,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.db(0xCC, 4), Error::None);
ASSERT_EQ(assembler.db(0xCC, 4), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Data, 16), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Data, 16), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 16> expected = {
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
@@ -914,14 +916,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.db(0xCC, 4), Error::None);
ASSERT_EQ(assembler.db(0xCC, 4), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Data, 32), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Data, 32), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 32> expected = {
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
@@ -947,14 +949,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.inc(x86::eax), Error::None);
ASSERT_EQ(assembler.inc(x86::eax), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 8), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 8), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 8> expected = {
0xFF, 0xC0, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00,
@@ -979,14 +981,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.inc(x86::eax), Error::None);
ASSERT_EQ(assembler.inc(x86::eax), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 16), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 16), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 16> expected = {
0xFF, 0xC0, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00,
@@ -1011,14 +1013,14 @@ namespace zasm::tests
auto label01 = assembler.createLabel();
ASSERT_EQ(assembler.inc(x86::eax), Error::None);
ASSERT_EQ(assembler.inc(x86::eax), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 32), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 32), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 32> expected = {
0xFF, 0xC0, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00,
@@ -1038,12 +1040,12 @@ namespace zasm::tests
TEST(SerializationTests, SerializeDecodedSwapNodes)
{
zasm::Program program(zasm::MachineMode::I386);
std::vector<zasm::Node*> tails = {};
Program program(MachineMode::I386);
std::vector<Node*> tails = {};
{
zasm::x86::Assembler a(program);
zasm::Decoder decoder(zasm::MachineMode::I386);
x86::Assembler a(program);
Decoder decoder(MachineMode::I386);
const std::array<uint8_t, 12> raw_data = {
0xB8, 0x00, 0x10, 0x40, 0x00, // mov eax, [blabla]
@@ -1069,15 +1071,15 @@ namespace zasm::tests
auto bind_node = program.bindLabel(label);
program.moveBefore(tails[4], *bind_node);
tails[3]->getIf<zasm::Instruction>()->setOperand(0, label);
tails[3]->getIf<Instruction>()->setOperand(0, label);
zasm::x86::Assembler a(program);
x86::Assembler a(program);
a.setCursor(tails[4]);
a.xor_(zasm::x86::eax, zasm::x86::eax);
a.xor_(x86::eax, x86::eax);
zasm::Serializer serializer{};
Serializer serializer{};
auto r = serializer.serialize(program, 0x406000);
ASSERT_EQ(r, zasm::Error::None);
ASSERT_EQ(r, ErrorCode::None);
const std::array<std::uint8_t, 14> expected = { 0xB8, 0x00, 0x10, 0x40, 0x00, 0x83, 0xF8,
0x00, 0x90, 0xEB, 0x00, 0xC3, 0x31, 0xC0 };
@@ -1099,10 +1101,10 @@ namespace zasm::tests
auto reg = x86::rdx;
auto address = (uint64_t)0x0000000000401000;
ASSERT_EQ(assembler.mov(x86::Gp64(reg.getId()), x86::qword_ptr(x86::rip, (uintptr_t)address)), Error::None);
ASSERT_EQ(assembler.mov(x86::Gp64(reg.getId()), x86::qword_ptr(x86::rip, (uintptr_t)address)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<std::uint8_t, 7> expected = { 0x48, 0x8B, 0x15, 0xF9, 0xFF, 0xFF, 0xFF };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -1125,21 +1127,21 @@ namespace zasm::tests
auto label02 = assembler.createLabel();
auto label03 = assembler.createLabel();
ASSERT_EQ(assembler.bind(label03), Error::None);
ASSERT_EQ(assembler.jmp(label01), Error::None);
ASSERT_EQ(assembler.nop(), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 8), Error::None);
ASSERT_EQ(assembler.jmp(label02), Error::None);
ASSERT_EQ(assembler.bind(label01), Error::None);
ASSERT_EQ(assembler.int3(), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 10), Error::None);
ASSERT_EQ(assembler.bind(label02), Error::None);
ASSERT_EQ(assembler.int3(), Error::None);
ASSERT_EQ(assembler.jmp(label03), Error::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 10), Error::None);
ASSERT_EQ(assembler.bind(label03), ErrorCode::None);
ASSERT_EQ(assembler.jmp(label01), ErrorCode::None);
ASSERT_EQ(assembler.nop(), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 8), ErrorCode::None);
ASSERT_EQ(assembler.jmp(label02), ErrorCode::None);
ASSERT_EQ(assembler.bind(label01), ErrorCode::None);
ASSERT_EQ(assembler.int3(), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 10), ErrorCode::None);
ASSERT_EQ(assembler.bind(label02), ErrorCode::None);
ASSERT_EQ(assembler.int3(), ErrorCode::None);
ASSERT_EQ(assembler.jmp(label03), ErrorCode::None);
ASSERT_EQ(assembler.align(Align::Type::Code, 10), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x0000000000401000), ErrorCode::None);
const std::array<uint8_t, 30> expected = {
0xEB, 0x08, 0x90, 0x0F, 0x1F, 0x44, 0x00, 0x00, 0xEB, 0x0A, 0xCC, 0x0F, 0x1F, 0x84, 0x00,
@@ -1166,14 +1168,14 @@ namespace zasm::tests
x86::Assembler a(program);
auto label = a.createLabel();
ASSERT_EQ(a.push(x86::rbp), Error::None);
ASSERT_EQ(a.lea(x86::rbp, x86::qword_ptr(x86::rip, label)), Error::None);
ASSERT_EQ(a.xchg(x86::qword_ptr(x86::rsp), x86::rbp), Error::None);
ASSERT_EQ(a.ret(), Error::None);
ASSERT_EQ(a.bind(label), Error::None);
ASSERT_EQ(a.push(x86::rbp), ErrorCode::None);
ASSERT_EQ(a.lea(x86::rbp, x86::qword_ptr(x86::rip, label)), ErrorCode::None);
ASSERT_EQ(a.xchg(x86::qword_ptr(x86::rsp), x86::rbp), ErrorCode::None);
ASSERT_EQ(a.ret(), ErrorCode::None);
ASSERT_EQ(a.bind(label), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x140015000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x140015000), ErrorCode::None);
const std::array<uint8_t, 13> expected = {
0x55, 0x48, 0x8D, 0x2D, 0x05, 0x00, 0x00, 0x00, 0x48, 0x87, 0x2C, 0x24, 0xC3,
@@ -1195,10 +1197,10 @@ namespace zasm::tests
Program program(MachineMode::AMD64);
x86::Assembler a(program);
ASSERT_EQ(a.mov(x86::rax, x86::qword_ptr(x86::rax, x86::rbp)), Error::None);
ASSERT_EQ(a.mov(x86::rax, x86::qword_ptr(x86::rax, x86::rbp)), ErrorCode::None);
Serializer serializer;
ASSERT_EQ(serializer.serialize(program, 0x140015000), Error::None);
ASSERT_EQ(serializer.serialize(program, 0x140015000), ErrorCode::None);
const std::array<uint8_t, 4> expected = { 0x48, 0x8B, 0x04, 0x28 };
ASSERT_EQ(serializer.getCodeSize(), expected.size());
@@ -1211,4 +1213,69 @@ namespace zasm::tests
}
}
TEST(SerializationTests, TestSerializationErrorImpossibleInstruction)
{
Program program(MachineMode::AMD64);
x86::Assembler a(program);
ASSERT_EQ(a.and_(x86::rbp, Imm64(0x123456789ABCDF)), ErrorCode::None);
Serializer serializer;
auto res = serializer.serialize(program, 0x140015000);
ASSERT_EQ(res, ErrorCode::ImpossibleInstruction);
ASSERT_EQ(
res.getErrorMessage(),
std::string("Error at node \"and rbp, 0x123456789abcdf\" with id 0: Impossible instruction"));
}
TEST(SerializationTests, TestSerializationJecxzBad)
{
Program program(MachineMode::AMD64);
x86::Assembler a(program);
auto labelLoop = a.createLabel();
ASSERT_EQ(a.jecxz(labelLoop), ErrorCode::None);
ASSERT_EQ(a.dd(0, 256), ErrorCode::None);
ASSERT_EQ(a.bind(labelLoop), ErrorCode::None);
Serializer serializer;
auto res = serializer.serialize(program, 0x140015000);
ASSERT_EQ(res, ErrorCode::AddressOutOfRange);
ASSERT_EQ(res.getErrorMessage(), std::string("Error at node \"jecxz L0\" with id 0: Label out of range for operand 0"));
}
TEST(SerializationTests, TestSerializationJecxzGood)
{
Program program(MachineMode::AMD64);
x86::Assembler a(program);
auto labelLoop = a.createLabel();
ASSERT_EQ(a.jecxz(labelLoop), ErrorCode::None);
ASSERT_EQ(a.dd(0), ErrorCode::None);
ASSERT_EQ(a.bind(labelLoop), ErrorCode::None);
Serializer serializer;
auto res = serializer.serialize(program, 0x140015000);
ASSERT_EQ(res, ErrorCode::None);
}
TEST(SerializationTests, TestBadMemoryDisplacement)
{
Program program(MachineMode::AMD64);
x86::Assembler a(program);
ASSERT_EQ(a.mov(x86::rax, x86::qword_ptr(x86::rip, 0xF23456789)), ErrorCode::None);
Serializer serializer;
auto res = serializer.serialize(program, 0x140015000);
ASSERT_EQ(res, ErrorCode::AddressOutOfRange);
ASSERT_EQ(
res.getErrorMessage(),
std::string("Error at node \"mov rax, qword ptr ds:[rel 0xf23456789]\" with id 0: Displacement out of range for "
"operand 1"));
}
} // namespace zasm::tests
+1 -1
View File
@@ -44,6 +44,6 @@ namespace zasm::tests
std::ostream& operator<<(std::ostream& os, const Error& err)
{
return os << zasm::getErrorName(err);
return os << err.getErrorName();
}
}
+269
View File
@@ -0,0 +1,269 @@
#include <cassert>
#include <string>
#include <zasm/core/errors.hpp>
namespace zasm
{
static constexpr std::uint64_t kErrorExtBit = 0x8000000000000000ULL;
struct ErrorExt
{
ErrorCode code;
std::string message;
};
// TODO: This is not fully portable so we should check for systems where
// we have to use a different approach.
static ErrorExt* toErrorExt(std::uint64_t data) noexcept
{
assert((data & kErrorExtBit) != 0);
auto* ext = reinterpret_cast<ErrorExt*>(data & ~kErrorExtBit);
return ext;
}
static std::uint64_t toInternalErrorData(const ErrorExt* ext) noexcept
{
return static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(ext)) | kErrorExtBit;
}
static bool isExtError(std::uint64_t data) noexcept
{
return (data & kErrorExtBit) != 0;
}
Error::Error(const Error& other)
{
if (isExtError(other._data))
{
const auto* ext = toErrorExt(other._data);
auto* newExt = new ErrorExt(*ext);
_data = toInternalErrorData(newExt);
}
else
{
_data = other._data;
}
}
Error::Error(Error&& other) noexcept
{
_data = other._data;
other._data = 0;
}
Error::Error(ErrorCode code) noexcept
{
std::uint64_t data = static_cast<std::uint64_t>(code);
_data = data;
}
Error::Error(ErrorCode code, const char* message)
{
assert(message != nullptr);
auto* ext = new ErrorExt();
ext->code = code;
ext->message = message;
_data = toInternalErrorData(ext);
}
Error::~Error() noexcept
{
clear();
}
void Error::clear()
{
if (isExtError(_data))
{
const auto* ext = toErrorExt(_data);
delete ext;
}
_data = 0;
}
bool Error::empty() const noexcept
{
return _data == 0;
}
bool Error::operator==(ErrorCode code) const noexcept
{
return getCode() == code;
}
bool Error::operator!=(ErrorCode code) const noexcept
{
return !(*this == code);
}
Error& Error::operator=(Error&& other) noexcept
{
clear();
_data = other._data;
other._data = 0;
return *this;
}
Error& Error::operator=(const Error& other) noexcept
{
clear();
if (isExtError(other._data))
{
const auto* ext = toErrorExt(other._data);
auto* newExt = new ErrorExt(*ext);
_data = toInternalErrorData(newExt);
}
else
{
_data = other._data;
}
return *this;
}
static ErrorCode getErrorCode(std::uint64_t data) noexcept
{
if (data == 0)
{
return ErrorCode::None;
}
if (isExtError(data))
{
const auto* ext = toErrorExt(data);
return ext->code;
}
else
{
return static_cast<ErrorCode>(data);
}
}
ErrorCode Error::getCode() const noexcept
{
return getErrorCode(_data);
}
static constexpr const char* getErrorCodeName(ErrorCode err) noexcept
{
#define ERROR_STRING(e) \
case e: \
return #e
switch (err)
{
ERROR_STRING(ErrorCode::None);
ERROR_STRING(ErrorCode::InvalidMode);
ERROR_STRING(ErrorCode::NotInitialized);
ERROR_STRING(ErrorCode::InvalidOperation);
ERROR_STRING(ErrorCode::InvalidParameter);
ERROR_STRING(ErrorCode::FileNotFound);
ERROR_STRING(ErrorCode::AccessDenied);
ERROR_STRING(ErrorCode::OutOfMemory);
ERROR_STRING(ErrorCode::LabelNotFound);
ERROR_STRING(ErrorCode::UnresolvedLabel);
ERROR_STRING(ErrorCode::InvalidLabel);
ERROR_STRING(ErrorCode::LabelAlreadyBound);
ERROR_STRING(ErrorCode::SectionNotFound);
ERROR_STRING(ErrorCode::SectionAlreadyBound);
ERROR_STRING(ErrorCode::SignatureMismatch);
ERROR_STRING(ErrorCode::InvalidInstruction);
ERROR_STRING(ErrorCode::OutOfBounds);
ERROR_STRING(ErrorCode::ImpossibleInstruction);
ERROR_STRING(ErrorCode::EmptyState);
ERROR_STRING(ErrorCode::ImpossibleRelocation);
ERROR_STRING(ErrorCode::AddressOutOfRange);
ERROR_STRING(ErrorCode::InstructionTooLong);
ERROR_STRING(ErrorCode::ExternalLabelNotBindable);
default:
assert(false);
break;
}
#undef ERROR_STRING
return nullptr;
}
const char* Error::getErrorName() const noexcept
{
return getErrorCodeName(getCode());
}
static const char* getErrorCodeMessage(ErrorCode err) noexcept
{
// Give a default message for known error codes.
switch (err)
{
case ErrorCode::None:
return "No error";
case ErrorCode::InvalidMode:
return "Invalid mode";
case ErrorCode::NotInitialized:
return "Not initialized";
case ErrorCode::InvalidOperation:
return "Invalid operation";
case ErrorCode::InvalidParameter:
return "Invalid parameter";
case ErrorCode::FileNotFound:
return "File not found";
case ErrorCode::AccessDenied:
return "Access denied";
case ErrorCode::OutOfMemory:
return "Out of memory";
case ErrorCode::LabelNotFound:
return "Label not found";
case ErrorCode::UnresolvedLabel:
return "Unresolved label";
case ErrorCode::InvalidLabel:
return "Invalid label";
case ErrorCode::LabelAlreadyBound:
return "Label already bound";
case ErrorCode::SectionNotFound:
return "Section not found";
case ErrorCode::SectionAlreadyBound:
return "Section already bound";
case ErrorCode::SignatureMismatch:
return "Signature mismatch";
case ErrorCode::InvalidInstruction:
return "Invalid instruction";
case ErrorCode::OutOfBounds:
return "Out of bounds";
case ErrorCode::ImpossibleInstruction:
return "Impossible instruction";
case ErrorCode::EmptyState:
return "Empty state";
case ErrorCode::ImpossibleRelocation:
return "Impossible relocation";
case ErrorCode::ExternalLabelNotBindable:
return "External label can not be bound";
case ErrorCode::InstructionTooLong:
return "Instruction too long";
case ErrorCode::AddressOutOfRange:
return "Address out of range";
default:
break;
}
return "<invalid error code>";
}
const char* Error::getErrorMessage() const noexcept
{
if (isExtError(_data))
{
const auto* ext = toErrorExt(_data);
return ext->message.c_str();
}
else
{
return getErrorCodeMessage(getCode());
}
}
} // namespace zasm
+2 -2
View File
@@ -94,7 +94,7 @@ namespace zasm
#endif
if (fp == nullptr)
{
return Error::AccessDenied;
return ErrorCode::AccessDenied;
}
// Adjust the buffer size
@@ -108,7 +108,7 @@ namespace zasm
seek(0, SeekType::Begin);
_state->mode = mode;
return Error::None;
return ErrorCode::None;
}
bool FileStream::isOpen() const
+37 -6
View File
@@ -109,10 +109,19 @@ namespace zasm
break;
}
if (status != ZYAN_STATUS_SUCCESS)
switch (status)
{
// TODO: Translate proper error.
_status = Error::NotInitialized;
case ZYAN_STATUS_SUCCESS:
break;
case ZYAN_STATUS_INVALID_ARGUMENT:
_status = Error{ ErrorCode::InvalidParameter };
break;
case ZYAN_STATUS_INVALID_OPERATION:
_status = Error{ ErrorCode::InvalidOperation };
break;
default:
_status = Error{ ErrorCode::NotInitialized };
break;
}
}
@@ -158,7 +167,7 @@ namespace zasm
Decoder::Result Decoder::decode(const void* data, const std::size_t len, std::uint64_t address) noexcept
{
if (_status != Error::None)
if (_status != ErrorCode::None)
{
return zasm::makeUnexpected(_status);
}
@@ -169,8 +178,20 @@ namespace zasm
ZyanStatus status = ZydisDecoderDecodeFull(&_decoder, data, len, &instr, instrOps.data());
if (status != ZYAN_STATUS_SUCCESS)
{
// TODO: Translate proper error.
return zasm::makeUnexpected(Error::InvalidOperation);
switch (status)
{
case ZYDIS_STATUS_NO_MORE_DATA:
_status = Error{ ErrorCode::OutOfBounds };
break;
case ZYDIS_STATUS_INSTRUCTION_TOO_LONG:
_status = Error{ ErrorCode::InstructionTooLong };
break;
default:
_status = Error{ ErrorCode::InvalidInstruction };
break;
}
return zasm::makeUnexpected(_status);
}
InstructionDetail::CPUFlags flags{};
@@ -207,4 +228,14 @@ namespace zasm
return res;
}
MachineMode Decoder::getMode() const
{
return _mode;
}
const Error& Decoder::getLastError() const
{
return _status;
}
} // namespace zasm
+29 -15
View File
@@ -180,7 +180,8 @@ namespace zasm
}
}
assert(desiredBranchType != ZydisBranchType::ZYDIS_BRANCH_TYPE_NONE);
// If desiredBranchType is ZYDIS_BRANCH_TYPE_NONE it means we can not fit the address
// into the instruction, this is an error and should be handled by the caller.
return { res, desiredBranchType };
}
@@ -190,7 +191,7 @@ namespace zasm
dst.type = ZydisOperandType::ZYDIS_OPERAND_TYPE_REGISTER;
dst.reg.value = static_cast<ZydisRegister>(src.getId());
return Error::None;
return ErrorCode::None;
}
static int64_t getTemporaryRel(EncoderState& state) noexcept
@@ -236,11 +237,16 @@ namespace zasm
const auto targetAddress = labelVA.has_value() ? *labelVA : immValue;
const auto [addrRel, branchType] = processRelAddress(encodeInfo, ctx, targetAddress);
if (branchType == ZydisBranchType::ZYDIS_BRANCH_TYPE_NONE)
{
char msg[128];
std::snprintf(msg, sizeof(msg), "Label out of range for operand %zu", state.operandIndex);
return Error(ErrorCode::AddressOutOfRange, msg);
}
immValue = addrRel;
desiredBranchType = branchType;
assert(desiredBranchType != ZydisBranchType::ZYDIS_BRANCH_TYPE_NONE);
}
else
{
@@ -269,7 +275,7 @@ namespace zasm
dst.type = ZydisOperandType::ZYDIS_OPERAND_TYPE_IMMEDIATE;
dst.imm.s = immValue;
return Error::None;
return ErrorCode::None;
}
static Error buildOperand_(ZydisEncoderOperand& dst, EncoderState& state, const Imm& src)
@@ -298,7 +304,7 @@ namespace zasm
dst.type = ZydisOperandType::ZYDIS_OPERAND_TYPE_IMMEDIATE;
dst.imm.s = immValue;
return Error::None;
return ErrorCode::None;
}
static Error buildOperand_(ZydisEncoderOperand& dst, EncoderState& state, const Mem& src)
@@ -384,6 +390,13 @@ namespace zasm
if (isDisplacementValid)
{
displacement = displacement - (address + instrSize);
if (std::abs(displacement) > std::numeric_limits<std::int32_t>::max())
{
char msg[128];
std::snprintf(msg, sizeof(msg), "Displacement out of range for operand %zu", state.operandIndex);
return Error(ErrorCode::AddressOutOfRange, msg);
}
}
}
@@ -408,14 +421,14 @@ namespace zasm
state.req.prefixes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
}
return Error::None;
return ErrorCode::None;
}
static Error buildOperand_(
ZydisEncoderOperand& dst, [[maybe_unused]] EncoderState& state, [[maybe_unused]] const Operand::None& src) noexcept
{
dst.type = ZydisOperandType::ZYDIS_OPERAND_TYPE_UNUSED;
return Error::None;
return ErrorCode::None;
}
static Error buildOperand(ZydisEncoderOperand& dst, EncoderState& state, const Operand& src)
@@ -506,7 +519,7 @@ namespace zasm
{
if (!validateMachineMode(mode))
{
return Error::InvalidMode;
return ErrorCode::InvalidMode;
}
res.buffer.length = 0;
@@ -548,7 +561,7 @@ namespace zasm
{
auto& dstOp = req.operands[state.operandIndex]; // NOLINT
const auto& srcOp = operands[state.operandIndex]; // NOLINT
if (auto opStatus = buildOperand(dstOp, state, srcOp); opStatus != Error::None)
if (auto opStatus = buildOperand(dstOp, state, srcOp); opStatus != ErrorCode::None)
{
return opStatus;
}
@@ -564,7 +577,7 @@ namespace zasm
break;
case ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION:
default:
return Error::ImpossibleInstruction;
return ErrorCode::ImpossibleInstruction;
}
res.buffer.length = static_cast<std::uint8_t>(bufLen);
@@ -572,7 +585,7 @@ namespace zasm
res.relocData = state.relocData;
res.relocLabel = state.relocLabel;
return Error::None;
return ErrorCode::None;
}
Expected<EncoderResult, Error> encode(
@@ -580,7 +593,7 @@ namespace zasm
const Operand* operands)
{
EncoderResult res;
if (auto err = encode_(res, nullptr, mode, attribs, mnemonic, numOps, operands); err != Error::None)
if (auto err = encode_(res, nullptr, mode, attribs, mnemonic, numOps, operands); err != ErrorCode::None)
{
return makeUnexpected(err);
}
@@ -596,7 +609,8 @@ namespace zasm
// encode_ will set this to kHintRequiresSize in case a length is required for correct encoding.
ctx.instrSize = 0;
if (const auto encodeError = encode_(res, &ctx, mode, prefixes, mnemonic, numOps, operands); encodeError != Error::None)
if (const auto encodeError = encode_(res, &ctx, mode, prefixes, mnemonic, numOps, operands);
encodeError != ErrorCode::None)
{
return makeUnexpected(encodeError);
}
@@ -606,7 +620,7 @@ namespace zasm
// Encode with now known size, instruction size can change again in this call.
ctx.instrSize = res.buffer.length;
if (const auto encodeError = encode_(res, &ctx, mode, prefixes, mnemonic, numOps, operands);
encodeError != Error::None)
encodeError != ErrorCode::None)
{
return makeUnexpected(encodeError);
}
+10 -9
View File
@@ -23,7 +23,7 @@ namespace zasm::formatter
public:
static constexpr std::size_t kInlineCapacity = 64;
Program* program{};
const Program* program{};
Options options{};
union
@@ -41,7 +41,7 @@ namespace zasm::formatter
, options(opts)
{
}
constexpr Context(Program& prog, Options opts)
constexpr Context(const Program& prog, Options opts)
: program(&prog)
, options(opts)
{
@@ -337,11 +337,11 @@ namespace zasm::formatter
{
if (disp < 0)
{
ctx.format("0x%" PRIx64, -disp);
ctx.format("0x%02" PRIx64, -disp);
}
else
{
ctx.format("0x%" PRIx64, disp);
ctx.format("0x%02" PRIx64, disp);
}
}
else
@@ -488,7 +488,7 @@ namespace zasm::formatter
}
else
{
ctx.format(".section");
ctx.appendLiteral(".section");
}
}
@@ -548,7 +548,7 @@ namespace zasm::formatter
} // namespace detail
std::string toString(Program& program, const Node* node, Options options /*= kDefaultOptions*/)
std::string toString(const Program& program, const Node* node, Options options /*= kDefaultOptions*/)
{
if (node == nullptr)
{
@@ -562,12 +562,13 @@ namespace zasm::formatter
return { ctx.data(), ctx.size };
}
std::string toString(Program& program, Options options /*= {}*/)
std::string toString(const Program& program, Options options /*= {}*/)
{
return toString(program, program.getHead(), nullptr, options);
}
std::string toString(Program& program, const Node* nodeFrom, const Node* nodeTo, Options options /*= kDefaultOptions*/)
std::string toString(
const Program& program, const Node* nodeFrom, const Node* nodeTo, Options options /*= kDefaultOptions*/)
{
auto ctx = detail::Context(program, options);
@@ -587,7 +588,7 @@ namespace zasm::formatter
return { ctx.data(), ctx.size };
}
std::string toString(Program& program, const Instruction* instr, Options options /*= kDefaultOptions*/)
std::string toString(const Program& program, const Instruction* instr, Options options /*= kDefaultOptions*/)
{
if (instr == nullptr)
{
+1 -1
View File
@@ -49,7 +49,7 @@ namespace zasm
if (decoded.getVisibleOperandCount() != opCount)
{
return zasm::makeUnexpected(Error::InvalidOperation);
return zasm::makeUnexpected(Error{ ErrorCode::InvalidOperation });
}
// Replace the decoded operands with user specified operands.
+11 -11
View File
@@ -528,18 +528,18 @@ namespace zasm
const auto entryIdx = static_cast<std::size_t>(label.getId());
if (entryIdx >= _state->labels.size())
{
return makeUnexpected(Error::InvalidLabel);
return makeUnexpected(Error{ ErrorCode::InvalidLabel });
}
auto& entry = _state->labels[entryIdx];
if ((entry.flags & LabelFlags::External) != LabelFlags::None)
{
return makeUnexpected(Error::ExternalLabelNotBindable);
return makeUnexpected(Error{ ErrorCode::ExternalLabelNotBindable });
}
if (entry.node != nullptr)
{
return makeUnexpected(Error::LabelAlreadyBound);
return makeUnexpected(Error{ ErrorCode::LabelAlreadyBound });
}
auto* node = createNode_(*_state, label);
@@ -595,13 +595,13 @@ namespace zasm
{
if (!label.isValid())
{
return zasm::makeUnexpected(Error::InvalidLabel);
return zasm::makeUnexpected(Error{ ErrorCode::InvalidLabel });
}
const auto entryIdx = static_cast<std::size_t>(label.getId());
if (entryIdx >= _state->labels.size())
{
return makeUnexpected(Error::InvalidLabel);
return makeUnexpected(Error{ ErrorCode::InvalidLabel });
}
const auto& entry = _state->labels[entryIdx];
@@ -638,7 +638,7 @@ namespace zasm
const auto entryIdx = static_cast<std::size_t>(sectionId);
if (entryIdx >= prog.sections.size())
{
return makeUnexpected(Error::SectionNotFound);
return makeUnexpected(Error{ ErrorCode::SectionNotFound });
}
return &prog.sections[entryIdx];
}
@@ -654,7 +654,7 @@ namespace zasm
auto& entry = sectEntry.value();
if (entry->node != nullptr)
{
return makeUnexpected(Error::SectionAlreadyBound);
return makeUnexpected(Error{ ErrorCode::SectionAlreadyBound });
}
auto* node = createNode_(*_state, section);
@@ -679,7 +679,7 @@ namespace zasm
{
if (name == nullptr)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
auto sectEntry = getSectionData(*_state, section.getId());
@@ -697,7 +697,7 @@ namespace zasm
}
entry->nameId = _state->symbolNames.aquire(name);
return Error::None;
return ErrorCode::None;
}
std::int32_t Program::getSectionAlign(const Section& section) noexcept
@@ -716,7 +716,7 @@ namespace zasm
{
if (align <= 0)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
auto sectEntry = getSectionData(*_state, section.getId());
@@ -728,7 +728,7 @@ namespace zasm
auto* entry = sectEntry.value();
entry->align = align;
return Error::None;
return ErrorCode::None;
}
} // namespace zasm
+32 -32
View File
@@ -50,7 +50,7 @@ namespace zasm
std::vector<std::uint8_t> buf;
buf.resize(size);
if (auto err = helper.read(buf.data(), size); err != Error::None)
if (auto err = helper.read(buf.data(), size); err != ErrorCode::None)
{
return nullptr;
}
@@ -84,7 +84,7 @@ namespace zasm
template<> Error loadOperand_<Operand::None>(SaveRestore& helper, Operand&)
{
return Error::None;
return ErrorCode::None;
}
template<> Error loadOperand_<Reg>(SaveRestore& helper, Operand& op)
@@ -94,7 +94,7 @@ namespace zasm
op = Reg(regId);
return Error::None;
return ErrorCode::None;
}
template<> Error loadOperand_<Mem>(SaveRestore& helper, Operand& op)
@@ -117,7 +117,7 @@ namespace zasm
op = Mem(bitSize, Reg(regSeg), Label(labelId), Reg(regBase), Reg(regIdx), scale, disp);
return Error::None;
return ErrorCode::None;
}
template<> Error loadOperand_<Imm>(SaveRestore& helper, Operand& op)
@@ -127,7 +127,7 @@ namespace zasm
op = Imm(val);
return Error::None;
return ErrorCode::None;
}
template<> Error loadOperand_<Label>(SaveRestore& helper, Operand& op)
@@ -137,7 +137,7 @@ namespace zasm
op = Label(labelId);
return Error::None;
return ErrorCode::None;
}
template<> Node* loadNode_<Instruction>(SaveRestore& helper, Program& program)
@@ -162,31 +162,31 @@ namespace zasm
switch (opType)
{
case OperandType::None:
if (auto err = loadOperand_<Operand::None>(helper, op); err != Error::None)
if (auto err = loadOperand_<Operand::None>(helper, op); err != ErrorCode::None)
{
return nullptr;
}
break;
case OperandType::Register:
if (auto err = loadOperand_<Reg>(helper, op); err != Error::None)
if (auto err = loadOperand_<Reg>(helper, op); err != ErrorCode::None)
{
return nullptr;
}
break;
case OperandType::Memory:
if (auto err = loadOperand_<Mem>(helper, op); err != Error::None)
if (auto err = loadOperand_<Mem>(helper, op); err != ErrorCode::None)
{
return nullptr;
}
break;
case OperandType::Immediate:
if (auto err = loadOperand_<Imm>(helper, op); err != Error::None)
if (auto err = loadOperand_<Imm>(helper, op); err != ErrorCode::None)
{
return nullptr;
}
break;
case OperandType::Label:
if (auto err = loadOperand_<Label>(helper, op); err != Error::None)
if (auto err = loadOperand_<Label>(helper, op); err != ErrorCode::None)
{
return nullptr;
}
@@ -244,7 +244,7 @@ namespace zasm
if (node == nullptr)
{
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
auto* intl = static_cast<detail::Node*>(node);
@@ -253,7 +253,7 @@ namespace zasm
program.append(node);
return Error::None;
return ErrorCode::None;
}
static Error loadNodes(SaveRestore& helper, Program& program)
@@ -263,13 +263,13 @@ namespace zasm
helper >> nodeCount;
for (std::uint64_t i = 0; i < nodeCount; ++i)
{
if (auto err = loadNode(helper, program); err != Error::None)
if (auto err = loadNode(helper, program); err != ErrorCode::None)
{
return err;
}
}
return Error::None;
return ErrorCode::None;
}
static Error loadLabels(SaveRestore& helper, Program& program)
@@ -306,7 +306,7 @@ namespace zasm
labels.push_back(labelData);
}
return Error::None;
return ErrorCode::None;
}
static Error loadSections(SaveRestore& helper, Program& program)
@@ -343,7 +343,7 @@ namespace zasm
sections.push_back(sectData);
}
return Error::None;
return ErrorCode::None;
}
static Error loadSymbols(SaveRestore& helper, Program& program)
@@ -352,26 +352,26 @@ namespace zasm
auto& programState = program.getState();
auto& symbols = programState.symbolNames;
if (auto err = symbols.load(stream); err != Error::None)
if (auto err = symbols.load(stream); err != ErrorCode::None)
{
return err;
}
return Error::None;
return ErrorCode::None;
}
static Error loadProgram(SaveRestore& helper, Program& program)
{
std::uint32_t signature{};
if (auto err = helper.read(&signature, sizeof(signature)); err != Error::None)
if (auto err = helper.read(&signature, sizeof(signature)); err != ErrorCode::None)
{
return err;
}
if (signature != kZasmSignature)
{
return Error::SignatureMismatch;
return ErrorCode::SignatureMismatch;
}
MachineMode mode{};
@@ -382,22 +382,22 @@ namespace zasm
Node::Id nextNodeId{};
helper >> nextNodeId;
if (auto err = loadNodes(helper, program); err != Error::None)
if (auto err = loadNodes(helper, program); err != ErrorCode::None)
{
return err;
}
if (auto err = loadSections(helper, program); err != Error::None)
{
return err;
}
if (auto err = loadLabels(helper, program); err != Error::None)
if (auto err = loadSections(helper, program); err != ErrorCode::None)
{
return err;
}
if (auto err = loadSymbols(helper, program); err != Error::None)
if (auto err = loadLabels(helper, program); err != ErrorCode::None)
{
return err;
}
if (auto err = loadSymbols(helper, program); err != ErrorCode::None)
{
return err;
}
@@ -406,7 +406,7 @@ namespace zasm
auto& programState = program.getState();
programState.nextNodeId = nextNodeId;
return Error::None;
return ErrorCode::None;
}
zasm::Expected<Program, Error> load(IStream& stream)
@@ -416,7 +416,7 @@ namespace zasm
SaveRestore helper(stream, true);
Program program{};
if (auto err = loadProgram(helper, program); err != Error::None)
if (auto err = loadProgram(helper, program); err != ErrorCode::None)
{
return makeUnexpected(err);
}
@@ -434,7 +434,7 @@ namespace zasm
FileStream stream(inputFilePath, StreamMode::Read);
if (!stream.isOpen())
{
return makeUnexpected(Error::AccessDenied);
return makeUnexpected(Error{ ErrorCode::AccessDenied });
}
return load(stream);
+29 -29
View File
@@ -23,7 +23,7 @@ namespace zasm
{
helper << NodeType::Sentinel;
return Error::None;
return ErrorCode::None;
}
static Error saveNode_(SaveRestore& helper, const Program& program, const Label& data)
@@ -32,7 +32,7 @@ namespace zasm
helper << data.getId();
return Error::None;
return ErrorCode::None;
}
static Error saveNode_(SaveRestore& helper, const Program& program, const EmbeddedLabel& data)
@@ -43,7 +43,7 @@ namespace zasm
helper << data.getRelativeLabel().getId();
helper << data.getSize();
return Error::None;
return ErrorCode::None;
}
static Error saveNode_(SaveRestore& helper, const Program& program, const Data& data)
@@ -54,7 +54,7 @@ namespace zasm
helper << static_cast<std::uint64_t>(data.getRepeatCount());
helper.write(data.getData(), data.getSize());
return Error::None;
return ErrorCode::None;
}
static Error saveNode_(SaveRestore& helper, const Program& program, const Section& data)
@@ -63,7 +63,7 @@ namespace zasm
helper << data.getId();
return Error::None;
return ErrorCode::None;
}
static Error saveNode_(SaveRestore& helper, const Program& program, const Align& data)
@@ -73,14 +73,14 @@ namespace zasm
helper << data.getType();
helper << data.getAlign();
return Error::None;
return ErrorCode::None;
}
static Error saveOperand_(SaveRestore& helper, const Operand::None&)
{
helper << OperandType::None;
return Error::None;
return ErrorCode::None;
}
static Error saveOperand_(SaveRestore& helper, const Reg& data)
@@ -89,7 +89,7 @@ namespace zasm
helper << data.getId();
return Error::None;
return ErrorCode::None;
}
static Error saveOperand_(SaveRestore& helper, const Mem& data)
@@ -104,7 +104,7 @@ namespace zasm
helper << data.getDisplacement();
helper << data.getLabelId();
return Error::None;
return ErrorCode::None;
}
static Error saveOperand_(SaveRestore& helper, const Imm& data)
@@ -113,7 +113,7 @@ namespace zasm
helper << data.value<std::int64_t>();
return Error::None;
return ErrorCode::None;
}
static Error saveOperand_(SaveRestore& helper, const Label& data)
@@ -122,7 +122,7 @@ namespace zasm
helper << data.getId();
return Error::None;
return ErrorCode::None;
}
static Error saveOperand(SaveRestore& helper, const Operand& op)
@@ -140,13 +140,13 @@ namespace zasm
for (std::size_t i = 0; i < data.getOperandCount(); ++i)
{
const auto& op = data.getOperand(i);
if (auto err = saveOperand(helper, op); err != Error::None)
if (auto err = saveOperand(helper, op); err != ErrorCode::None)
{
return err;
}
}
return Error::None;
return ErrorCode::None;
}
static Error saveNode(SaveRestore& helper, const Program& program, const Node* node)
@@ -157,12 +157,12 @@ namespace zasm
helper << nodeInt->getUserDataU64();
auto err = nodeInt->visit([&](const auto& nodeData) { return saveNode_(helper, program, nodeData); });
if (err != Error::None)
if (err != ErrorCode::None)
{
return err;
}
return Error::None;
return ErrorCode::None;
}
static Error saveNodes(SaveRestore& helper, const Program& program)
@@ -174,14 +174,14 @@ namespace zasm
const auto* node = program.getHead();
while (node != nullptr)
{
if (auto err = saveNode(helper, program, node); err != Error::None)
if (auto err = saveNode(helper, program, node); err != ErrorCode::None)
{
return err;
}
node = node->getNext();
}
return Error::None;
return ErrorCode::None;
}
static Error saveLabels(SaveRestore& helper, const Program& program)
@@ -200,7 +200,7 @@ namespace zasm
helper << getNodeId(labelData.node);
}
return Error::None;
return ErrorCode::None;
}
static Error saveSections(SaveRestore& helper, const Program& program)
@@ -219,7 +219,7 @@ namespace zasm
helper << getNodeId(sectionData.node);
}
return Error::None;
return ErrorCode::None;
}
static Error saveSymbols(SaveRestore& helper, const Program& program)
@@ -228,12 +228,12 @@ namespace zasm
const auto& programState = program.getState();
const auto& symbols = programState.symbolNames;
if (auto err = symbols.save(stream); err != Error::None)
if (auto err = symbols.save(stream); err != ErrorCode::None)
{
return err;
}
return Error::None;
return ErrorCode::None;
}
static Error saveProgram(SaveRestore& helper, const Program& program)
@@ -246,27 +246,27 @@ namespace zasm
auto& programState = program.getState();
helper << programState.nextNodeId;
if (auto err = saveNodes(helper, program); err != Error::None)
if (auto err = saveNodes(helper, program); err != ErrorCode::None)
{
return err;
}
if (auto err = saveSections(helper, program); err != Error::None)
if (auto err = saveSections(helper, program); err != ErrorCode::None)
{
return err;
}
if (auto err = saveLabels(helper, program); err != Error::None)
if (auto err = saveLabels(helper, program); err != ErrorCode::None)
{
return err;
}
if (auto err = saveSymbols(helper, program); err != Error::None)
if (auto err = saveSymbols(helper, program); err != ErrorCode::None)
{
return err;
}
return Error::None;
return ErrorCode::None;
}
Error save(const Program& program, IStream& stream)
@@ -275,12 +275,12 @@ namespace zasm
{
SaveRestore helper(stream, false);
if (auto err = saveProgram(helper, program); err != Error::None)
if (auto err = saveProgram(helper, program); err != ErrorCode::None)
{
return err;
}
return Error::None;
return ErrorCode::None;
}
catch (Error err)
{
@@ -293,7 +293,7 @@ namespace zasm
FileStream fs(outputFilePath, StreamMode::Write);
if (!fs.isOpen())
{
return Error::AccessDenied;
return ErrorCode::AccessDenied;
}
return save(program, fs);
+17 -16
View File
@@ -33,26 +33,26 @@ namespace zasm
{
if (_isLoad)
{
return Error::InvalidOperation;
return ErrorCode::InvalidOperation;
}
_stream.write(src, length);
return Error::None;
return ErrorCode::None;
}
Error read(void* dst, size_t length)
{
if (!_isLoad || _stream.isEnd())
{
return Error::InvalidOperation;
return ErrorCode::InvalidOperation;
}
_stream.read(dst, length);
return Error::None;
return ErrorCode::None;
}
template<typename T> SaveRestore& operator<<(const T& value)
{
if (_isLoad)
throw Error::InvalidOperation;
throw Error{ ErrorCode::InvalidOperation };
using ValueType = std::decay_t<T>;
@@ -60,17 +60,18 @@ namespace zasm
if constexpr (kEnableVariableLengthEncoding && std::is_integral_v<ValueType>)
{
if (auto err = writeVariableInteger(value); err != Error::None)
if (auto err = writeVariableInteger(value); err != ErrorCode::None)
throw err;
}
else if constexpr (kEnableVariableLengthEncoding && std::is_enum_v<ValueType>)
{
if (auto err = writeVariableInteger(static_cast<std::underlying_type_t<ValueType>>(value)); err != Error::None)
if (auto err = writeVariableInteger(static_cast<std::underlying_type_t<ValueType>>(value));
err != ErrorCode::None)
throw err;
}
else
{
if (auto err = write(&value, sizeof(T)); err != Error::None)
if (auto err = write(&value, sizeof(T)); err != ErrorCode::None)
throw err;
}
@@ -80,7 +81,7 @@ namespace zasm
template<typename T> SaveRestore& operator>>(T& value)
{
if (!_isLoad)
throw Error::InvalidOperation;
throw ErrorCode::InvalidOperation;
using ValueType = std::decay_t<T>;
@@ -88,7 +89,7 @@ namespace zasm
if constexpr (kEnableVariableLengthEncoding && std::is_integral_v<ValueType>)
{
if (auto err = readVariableInteger(value); err != Error::None)
if (auto err = readVariableInteger(value); err != ErrorCode::None)
throw err;
}
else if constexpr (kEnableVariableLengthEncoding && std::is_enum_v<ValueType>)
@@ -96,14 +97,14 @@ namespace zasm
using T2 = std::underlying_type_t<ValueType>;
T2 tmp{};
if (auto err = readVariableInteger(tmp); err != Error::None)
if (auto err = readVariableInteger(tmp); err != ErrorCode::None)
throw err;
value = static_cast<T>(tmp);
}
else
{
if (auto err = read(static_cast<void*>(&value), sizeof(T)); err != Error::None)
if (auto err = read(static_cast<void*>(&value), sizeof(T)); err != ErrorCode::None)
throw err;
}
@@ -125,10 +126,10 @@ namespace zasm
}
tempBuffer[bytesUsed++] = static_cast<std::uint8_t>(tmp & 0x7F);
if (auto err = write(tempBuffer, bytesUsed); err != Error::None)
if (auto err = write(tempBuffer, bytesUsed); err != ErrorCode::None)
return err;
return Error::None;
return ErrorCode::None;
}
template<typename T> Error readVariableInteger(T& value)
@@ -137,7 +138,7 @@ namespace zasm
for (std::size_t i = 0;; i++)
{
std::uint8_t byte;
if (auto err = read(&byte, sizeof(byte)); err != Error::None)
if (auto err = read(&byte, sizeof(byte)); err != ErrorCode::None)
return err;
tmp |= (static_cast<T>(byte) & 0x7F) << (i * 7);
@@ -145,7 +146,7 @@ namespace zasm
break;
}
value = static_cast<T>(tmp);
return Error::None;
return ErrorCode::None;
}
};
+39 -31
View File
@@ -4,6 +4,7 @@
#include "../program/program.state.hpp"
#include "zasm/core/math.hpp"
#include "zasm/encoder/encoder.hpp"
#include "zasm/formatter/formatter.hpp"
#include <Zydis/Decoder.h>
#include <algorithm>
@@ -66,7 +67,7 @@ namespace zasm
nodeEntry.address = ctx.va;
ctx.nodeIndex++;
return Error::None;
return ErrorCode::None;
}
static constexpr auto kX86NopTable = std::array<std::array<std::uint8_t, 8>, 9>{ {
@@ -140,7 +141,7 @@ namespace zasm
ctx.va += alignSize;
ctx.offset += alignSize;
return Error::None;
return ErrorCode::None;
}
static Error serializeNode(const detail::ProgramState& prog, SerializeContext& state, const Instruction& instr)
@@ -157,7 +158,7 @@ namespace zasm
auto& nodeEntry = ctx.nodes[ctx.nodeIndex];
ctx.nodeIndex++;
if (nodeEntry.length != 0 && res->buffer.length != nodeEntry.length)
if (nodeEntry.length != 0 && res->buffer.length != nodeEntry.length)
{
ctx.needsExtraPass = true;
}
@@ -178,14 +179,14 @@ namespace zasm
auto& buffer = state.buffer;
buffer.insert(buffer.end(), std::begin(res->buffer.data), std::begin(res->buffer.data) + res->buffer.length);
return Error::None;
return ErrorCode::None;
}
static Error serializeNode(const detail::ProgramState& prog, SerializeContext& state, const Label& label)
{
if (!label.isValid())
{
return Error::InvalidLabel;
return ErrorCode::InvalidLabel;
}
auto& ctx = state.ctx;
@@ -200,14 +201,14 @@ namespace zasm
const auto labelIdx = static_cast<std::size_t>(label.getId());
if (labelIdx >= prog.labels.size())
{
return Error::LabelNotFound;
return ErrorCode::LabelNotFound;
}
auto& linkEntry = state.ctx.getOrCreateLabelLink(label.getId());
linkEntry.boundOffset = ctx.offset;
linkEntry.boundVA = ctx.va;
return Error::None;
return ErrorCode::None;
}
static bool isSameSection(const EncoderSection& lhs, const EncoderSection& rhs) noexcept
@@ -235,7 +236,7 @@ namespace zasm
const auto sectionIndex = static_cast<std::size_t>(section.getId());
if (sectionIndex >= prog.sections.size())
{
return Error::SectionNotFound;
return ErrorCode::SectionNotFound;
}
const auto& sectionData = prog.sections[sectionIndex];
@@ -269,7 +270,7 @@ namespace zasm
nodeEntry.offset = ctx.offset;
nodeEntry.address = ctx.va;
return Error::None;
return ErrorCode::None;
}
static Error serializeNode([[maybe_unused]] const detail::ProgramState& program, SerializeContext& state, const Data& data)
@@ -301,7 +302,7 @@ namespace zasm
std::copy_n(ptr, dataSize, std::back_inserter(buffer));
}
return Error::None;
return ErrorCode::None;
}
static Error serializeNode(const detail::ProgramState& program, SerializeContext& state, const EmbeddedLabel& data)
@@ -345,7 +346,7 @@ namespace zasm
{
if (!ctx.needsExtraPass && absValue >= std::numeric_limits<std::uint8_t>::max())
{
return Error::InvalidLabel;
return ErrorCode::InvalidLabel;
}
const auto rawValue = static_cast<std::int8_t>(labelAddr);
std::memcpy(tempBuf.data(), &rawValue, sizeof(rawValue));
@@ -355,7 +356,7 @@ namespace zasm
{
if (!ctx.needsExtraPass && absValue >= std::numeric_limits<std::uint16_t>::max())
{
return Error::InvalidLabel;
return ErrorCode::InvalidLabel;
}
const auto rawValue = static_cast<std::int16_t>(labelAddr);
std::memcpy(tempBuf.data(), &rawValue, sizeof(rawValue));
@@ -365,7 +366,7 @@ namespace zasm
{
if (!ctx.needsExtraPass && absValue >= std::numeric_limits<std::uint32_t>::max())
{
return Error::InvalidLabel;
return ErrorCode::InvalidLabel;
}
const auto rawValue = static_cast<std::int32_t>(labelAddr);
std::memcpy(tempBuf.data(), &rawValue, sizeof(rawValue));
@@ -379,7 +380,7 @@ namespace zasm
}
else
{
return Error::InvalidOperation;
return ErrorCode::InvalidOperation;
}
auto& nodeEntry = ctx.nodes[ctx.nodeIndex];
@@ -406,7 +407,7 @@ namespace zasm
auto& buffer = state.buffer;
buffer.insert(buffer.end(), std::begin(tempBuf), std::begin(tempBuf) + byteSize);
return Error::None;
return ErrorCode::None;
}
Serializer::Serializer()
@@ -476,7 +477,7 @@ namespace zasm
defaultSect.address = newBase;
defaultSect.nameId = programState.symbolNames.aquire(".text");
const auto serializePass = [&]() {
const auto serializePass = [&]() -> Error {
state.buffer.clear();
encoderCtx.needsExtraPass = false;
@@ -485,7 +486,6 @@ namespace zasm
encoderCtx.va = newBase;
encoderCtx.nodeIndex = 0;
encoderCtx.sectionIndex = 0;
// Setup default section.
encoderCtx.sections.clear();
@@ -494,9 +494,17 @@ namespace zasm
for (const auto* node = first; node != lastNode; node = node->getNext())
{
const auto status = node->visit([&](auto&& n) { return serializeNode(programState, state, n); });
if (status != Error::None)
if (status != ErrorCode::None)
{
return status;
const auto fmtOptions = formatter::Options::HexImmediates | formatter::Options::HexOffsets;
const auto nodeString = formatter::toString(program, node, fmtOptions);
char msg[256];
std::snprintf(
msg, sizeof(msg), "Error at node \"%s\" with id %u: %s", nodeString.c_str(),
static_cast<std::uint32_t>(node->getId()), status.getErrorMessage());
return Error(status.getCode(), msg);
}
}
@@ -504,11 +512,11 @@ namespace zasm
codeDiff = newSize - codeSize;
codeSize = newSize;
return Error::None;
return ErrorCode::None;
};
// Initial.
if (const auto status = serializePass(); status != Error::None)
if (const auto status = serializePass(); status != ErrorCode::None)
{
return status;
}
@@ -521,13 +529,13 @@ namespace zasm
std::begin(encoderCtx.labelLinks), std::end(encoderCtx.labelLinks), isUnresolvedLabel);
if (hasUnresolvedLinks)
{
return Error::UnresolvedLabel;
return ErrorCode::UnresolvedLabel;
}
// Second or more passes.
while (encoderCtx.needsExtraPass)
{
if (const auto status = serializePass(); status != Error::None)
if (const auto status = serializePass(); status != ErrorCode::None)
{
return status;
}
@@ -543,7 +551,7 @@ namespace zasm
const auto labelIdx = static_cast<std::size_t>(labelLink.id);
if (labelIdx >= programState.labels.size())
{
return Error::InvalidLabel;
return ErrorCode::InvalidLabel;
}
auto& labelEntry = _state->labels.emplace_back();
@@ -565,12 +573,12 @@ namespace zasm
decoderStatus = ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZydisStackWidth::ZYDIS_STACK_WIDTH_64);
break;
default:
return Error::InvalidParameter;
return ErrorCode::InvalidParameter;
}
if (decoderStatus != ZYAN_STATUS_SUCCESS)
{
// FIXME: Make this a better error.
return Error::InvalidMode;
return ErrorCode::InvalidMode;
}
_state->relocations.clear();
@@ -607,7 +615,7 @@ namespace zasm
if (decoderStatus != ZYAN_STATUS_SUCCESS)
{
// FIXME: Properly translate the error.
return Error::ImpossibleRelocation;
return ErrorCode::ImpossibleRelocation;
}
if (node.relocData == RelocationData::Immediate)
@@ -676,14 +684,14 @@ namespace zasm
_state->base = newBase;
return Error::None;
return ErrorCode::None;
}
Error Serializer::relocate(std::int64_t newBase)
{
if (_state->code.empty())
{
return Error::EmptyState;
return ErrorCode::EmptyState;
}
const auto oldBase = _state->base;
@@ -706,7 +714,7 @@ namespace zasm
if (newValue > std::numeric_limits<std::uint32_t>::max())
{
return Error::ImpossibleRelocation;
return ErrorCode::ImpossibleRelocation;
}
value = static_cast<std::uint32_t>(newValue);
@@ -761,7 +769,7 @@ namespace zasm
_state->externalRelocations = std::move(externalRelocs);
_state->base = newBase;
return Error::None;
return ErrorCode::None;
}
std::int64_t Serializer::getBase() const noexcept
+12 -12
View File
@@ -46,7 +46,7 @@ namespace zasm::x86
_cursor = _program.insertAfter(_cursor, labelNode.value());
return Error::None;
return ErrorCode::None;
}
Error Assembler::section(
@@ -62,7 +62,7 @@ namespace zasm::x86
_cursor = _program.insertAfter(_cursor, sectNode.value());
return Error::None;
return ErrorCode::None;
}
Error Assembler::db(std::uint8_t val, std::size_t repeatCount /*= 1*/)
@@ -72,7 +72,7 @@ namespace zasm::x86
auto* dataNode = _program.createNode(std::move(data));
_cursor = _program.insertAfter(_cursor, dataNode);
return Error::None;
return ErrorCode::None;
}
Error Assembler::dw(std::uint16_t val, std::size_t repeatCount /*= 1*/)
@@ -82,7 +82,7 @@ namespace zasm::x86
auto* dataNode = _program.createNode(std::move(data));
_cursor = _program.insertAfter(_cursor, dataNode);
return Error::None;
return ErrorCode::None;
}
Error Assembler::dd(std::uint32_t val, std::size_t repeatCount /*= 1*/)
@@ -92,7 +92,7 @@ namespace zasm::x86
auto* dataNode = _program.createNode(std::move(data));
_cursor = _program.insertAfter(_cursor, dataNode);
return Error::None;
return ErrorCode::None;
}
Error Assembler::dq(std::uint64_t val, std::size_t repeatCount /*= 1*/)
@@ -102,7 +102,7 @@ namespace zasm::x86
auto* dataNode = _program.createNode(std::move(data));
_cursor = _program.insertAfter(_cursor, dataNode);
return Error::None;
return ErrorCode::None;
}
Error Assembler::embed(const void* ptr, std::size_t len)
@@ -112,7 +112,7 @@ namespace zasm::x86
auto* dataNode = _program.createNode(std::move(data));
_cursor = _program.insertAfter(_cursor, dataNode);
return Error::None;
return ErrorCode::None;
}
Error Assembler::align(Align::Type type, std::uint32_t align)
@@ -122,7 +122,7 @@ namespace zasm::x86
auto* node = _program.createNode(std::move(data));
_cursor = _program.insertAfter(_cursor, node);
return Error::None;
return ErrorCode::None;
}
Error Assembler::emit(Instruction::Attribs attribs, Instruction::Mnemonic mnemonic, std::size_t numOps, const Operand* ops)
@@ -136,7 +136,7 @@ namespace zasm::x86
auto* node = _program.createNode(std::move(instr));
_cursor = _program.insertAfter(_cursor, node);
return Error::None;
return ErrorCode::None;
}
Error Assembler::emit(const Instruction& instr)
@@ -158,13 +158,13 @@ namespace zasm::x86
}
else
{
return Error::InvalidMode;
return ErrorCode::InvalidMode;
}
auto* node = _program.createNode(EmbeddedLabel(label, size));
_cursor = _program.insertAfter(_cursor, node);
return Error::None;
return ErrorCode::None;
}
Error Assembler::embedLabelRel(Label label, Label relativeTo, BitSize size)
@@ -172,7 +172,7 @@ namespace zasm::x86
auto* node = _program.createNode(EmbeddedLabel(label, relativeTo, size));
_cursor = _program.insertAfter(_cursor, node);
return Error::None;
return ErrorCode::None;
}
void Assembler::onNodeDetach(Node* node) noexcept