From 742d6eb0f64733a37861af7cb5303667bae13bef Mon Sep 17 00:00:00 2001 From: stuxnot <41650734+Stuxnot@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:30:32 +0200 Subject: [PATCH 1/8] Adds emproof namespace --- bindings/python/pynyxstone.cpp | 5 ++++- bindings/rust/src/nyxstone_ffi.cpp | 2 ++ bindings/rust/src/nyxstone_ffi.hpp | 4 ++-- examples/nyxstone-cli.cpp | 3 +++ examples/sample.cpp | 3 +++ include/nyxstone.h | 2 ++ src/ELFStreamerWrapper.cpp | 2 ++ src/ELFStreamerWrapper.h | 2 ++ src/ObjectWriterWrapper.cpp | 2 ++ src/ObjectWriterWrapper.h | 2 ++ src/nyxstone.cpp | 2 ++ 11 files changed, 26 insertions(+), 3 deletions(-) diff --git a/bindings/python/pynyxstone.cpp b/bindings/python/pynyxstone.cpp index 11482a2..94df25d 100644 --- a/bindings/python/pynyxstone.cpp +++ b/bindings/python/pynyxstone.cpp @@ -1,13 +1,16 @@ #include #include -#include #include +#include #include namespace py = pybind11; +using emproof::Nyxstone; +using emproof::NyxstoneBuilder; + std::vector assemble_to_bytes( Nyxstone& nyxstone, std::string assembly, diff --git a/bindings/rust/src/nyxstone_ffi.cpp b/bindings/rust/src/nyxstone_ffi.cpp index 5e60c94..0457a97 100644 --- a/bindings/rust/src/nyxstone_ffi.cpp +++ b/bindings/rust/src/nyxstone_ffi.cpp @@ -1,5 +1,7 @@ #include "nyxstone_ffi.hpp" +using namespace emproof; + struct LabelDefinition final { rust::str name {}; uint64_t address = 0; diff --git a/bindings/rust/src/nyxstone_ffi.hpp b/bindings/rust/src/nyxstone_ffi.hpp index 3da60ff..64db8f2 100644 --- a/bindings/rust/src/nyxstone_ffi.hpp +++ b/bindings/rust/src/nyxstone_ffi.hpp @@ -17,14 +17,14 @@ enum class IntegerBase : uint8_t; // See class and function documentation in Nyxstone.h for further info. class NyxstoneFFI { // Internal Nyxstone instance - std::unique_ptr nyxstone; + std::unique_ptr nyxstone; public: /** * @brief Constructor for NyxstoneFFI. * @param nyxstone Unique_ptr holding the Nyxstone instance. */ - explicit NyxstoneFFI(std::unique_ptr&& nyxstone) : nyxstone(std::move(nyxstone)) {} + explicit NyxstoneFFI(std::unique_ptr&& nyxstone) : nyxstone(std::move(nyxstone)) {} ~NyxstoneFFI() = default; NyxstoneFFI(const NyxstoneFFI& other) = delete; diff --git a/examples/nyxstone-cli.cpp b/examples/nyxstone-cli.cpp index 831c72a..0702ba1 100644 --- a/examples/nyxstone-cli.cpp +++ b/examples/nyxstone-cli.cpp @@ -12,6 +12,9 @@ namespace po = boost::program_options; +using emproof::Nyxstone; +using emproof::NyxstoneBuilder; + enum class Architecture; std::optional arch_parse_from_string(const std::string& arch); void print_bytes(const std::vector& bytes); diff --git a/examples/sample.cpp b/examples/sample.cpp index 422a83b..d31bb3c 100644 --- a/examples/sample.cpp +++ b/examples/sample.cpp @@ -3,6 +3,9 @@ #include #include +using emproof::Nyxstone; +using emproof::NyxstoneBuilder; + int main(int /* argc */, char** /* argv */) { try { auto nyxstone_x86_64 = NyxstoneBuilder().with_triple("x86_64-linux-gnu").build(); diff --git a/include/nyxstone.h b/include/nyxstone.h index 403da03..561d513 100644 --- a/include/nyxstone.h +++ b/include/nyxstone.h @@ -10,6 +10,7 @@ #include #pragma GCC diagnostic pop +namespace emproof { /// Nyxstone class for assembling and disassembling for a given architecture. class Nyxstone { /// The LLVM triple @@ -248,3 +249,4 @@ class NyxstoneBuilder { /// Detects all ARM Thumb architectures. LLVM doesn't seem to have a short way to check this. bool is_ArmT16_or_ArmT32(const llvm::Triple& triple); +} // namespace emproof diff --git a/src/ELFStreamerWrapper.cpp b/src/ELFStreamerWrapper.cpp index f6f8f00..da04b47 100644 --- a/src/ELFStreamerWrapper.cpp +++ b/src/ELFStreamerWrapper.cpp @@ -27,6 +27,7 @@ using namespace llvm; +namespace emproof { void ELFStreamerWrapper::emitInstruction(const MCInst& Inst, const MCSubtargetInfo& STI) { MCELFStreamer::emitInstruction(Inst, STI); @@ -133,3 +134,4 @@ std::unique_ptr ELFStreamerWrapper::createELFStreamerWrapper( } return streamer; } +} // namespace emproof diff --git a/src/ELFStreamerWrapper.h b/src/ELFStreamerWrapper.h index 208dda4..646cd72 100644 --- a/src/ELFStreamerWrapper.h +++ b/src/ELFStreamerWrapper.h @@ -10,6 +10,7 @@ #include #pragma GCC diagnostic pop +namespace emproof { /// This class derives from LLVM's MCELFStreamer, which enables us to receive /// information during assembly such as preliminary instruction size and bytes /// before relaxation and fixups (via method 'emitInstruction()'). @@ -69,3 +70,4 @@ class ELFStreamerWrapper: public llvm::MCELFStreamer { /// @brief Calls `MCELFStreamer::emitInstruction` and records instruction details. void emitInstruction(const llvm::MCInst& Inst, const llvm::MCSubtargetInfo& STI) override; }; +} // namespace emproof diff --git a/src/ObjectWriterWrapper.cpp b/src/ObjectWriterWrapper.cpp index a4b3e30..f548478 100644 --- a/src/ObjectWriterWrapper.cpp +++ b/src/ObjectWriterWrapper.cpp @@ -31,6 +31,7 @@ using namespace llvm; +namespace emproof { /// Performs a value alignment to a specific value. /// /// @param[in] value - Value to align. @@ -301,3 +302,4 @@ std::unique_ptr ObjectWriterWrapper::createObjectWriterWrapper( extended_error, instructions); } +} // namespace emproof diff --git a/src/ObjectWriterWrapper.h b/src/ObjectWriterWrapper.h index 4320281..c71dcb8 100644 --- a/src/ObjectWriterWrapper.h +++ b/src/ObjectWriterWrapper.h @@ -20,6 +20,7 @@ #include #pragma GCC diagnostic pop +namespace emproof { /// This class derives from LLVM's MCObjectWriter, which enables us to include /// user-define symbols/labels into the internal address resolution process /// (via 'executePostLayoutBinding()'). @@ -104,3 +105,4 @@ class ObjectWriterWrapper: public llvm::MCObjectWriter { /// @brief Write object to the stream and update the bytes of the instruction details. uint64_t writeObject(llvm::MCAssembler& Asm, const llvm::MCAsmLayout& Layout) override; }; +} // namespace emproof diff --git a/src/nyxstone.cpp b/src/nyxstone.cpp index 9922a9e..ff9b849 100644 --- a/src/nyxstone.cpp +++ b/src/nyxstone.cpp @@ -24,6 +24,7 @@ using namespace llvm; +namespace emproof { NyxstoneBuilder& NyxstoneBuilder::with_triple(std::string&& triple) noexcept { m_triple = std::move(triple); return *this; @@ -485,3 +486,4 @@ bool is_ArmT16_or_ArmT32(const llvm::Triple& triple) { || triple.getSubArch() == Triple::SubArchType::ARMSubArch_v8m_mainline || triple.getSubArch() == Triple::SubArchType::ARMSubArch_v8_1m_mainline); } +} // namespace emproof From 997ac4a9f3af93931c4faa34037eacd8637c06f3 Mon Sep 17 00:00:00 2001 From: stuxnot <41650734+Stuxnot@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:30:56 +0200 Subject: [PATCH 2/8] Removes std::endl --- examples/sample.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/sample.cpp b/examples/sample.cpp index d31bb3c..14f0937 100644 --- a/examples/sample.cpp +++ b/examples/sample.cpp @@ -16,7 +16,7 @@ int main(int /* argc */, char** /* argv */) { std::vector instructions; std::string disassembly; - std::cout << "assemble_to_bytes:" << std::endl; + std::cout << "assemble_to_bytes:\n"; std::cout << "\tmov rax, rax : [ "; nyxstone_x86_64->assemble_to_bytes("mov rax, rax", 0x1000, labels, bytes); std::cout << std::hex; @@ -24,7 +24,7 @@ int main(int /* argc */, char** /* argv */) { std::cout << std::setfill('0') << std::setw(2) << static_cast(byte) << " "; } std::cout << std::dec; - std::cout << "] - expected [ 48 89 c0 ]" << std::endl; + std::cout << "] - expected [ 48 89 c0 ]\n"; std::cout << "\tbne .label : [ "; nyxstone_armv8m->assemble_to_bytes("bne .label", 0x1000, labels, bytes); @@ -34,7 +34,7 @@ int main(int /* argc */, char** /* argv */) { std::cout << std::setfill('0') << std::setw(2) << static_cast(byte) << " "; } std::cout << std::dec; - std::cout << "] - expected [ 06 d1 ]" << std::endl; + std::cout << "] - expected [ 06 d1 ]\n"; std::cout << std::endl << "assemble_to_instructions:" << std::endl; std::cout << "\tmov rax, rax : [ "; @@ -46,7 +46,7 @@ int main(int /* argc */, char** /* argv */) { } std::cout << std::dec; } - std::cout << "] - expected [ 48 89 c0 ]" << std::endl; + std::cout << "] - expected [ 48 89 c0 ]\n"; std::cout << "\tbne .label : [ "; nyxstone_armv8m->assemble_to_instructions("bne .label", 0x1000, labels, instructions); @@ -57,23 +57,23 @@ int main(int /* argc */, char** /* argv */) { } std::cout << std::dec; } - std::cout << "] - expected [ 06 d1 ]" << std::endl; + std::cout << "] - expected [ 06 d1 ]\n"; std::cout << std::endl << "disassemble_to_text:" << std::endl; std::cout << "\t48 89 c0 : [ "; nyxstone_x86_64->disassemble_to_text({0x48, 0x89, 0xc0}, 0x1000, 0, disassembly); disassembly.erase(disassembly.find_last_not_of(" \t\n\r") + 1); std::cout << disassembly; - std::cout << " ] - expected [ mov rax, rax ]" << std::endl; + std::cout << " ] - expected [ mov rax, rax ]\n"; std::cout << "\t06 d1 : [ "; nyxstone_armv8m->disassemble_to_text({0x06, 0xd1}, 0x1000, 0, disassembly); disassembly.erase(disassembly.find_last_not_of(" \t\n\r") + 1); std::cout << disassembly; - std::cout << " ] - expected [ bne #12 ]" << std::endl; + std::cout << " ] - expected [ bne #12 ]\n"; } catch (const std::exception& e) { - std::cout << "An error occured: " << e.what() << std::endl; + std::cout << "An error occured: " << e.what() << "\n"; return 1; } From 4c1dd66e6b31ac8c592812fe754e39c2fda55bc2 Mon Sep 17 00:00:00 2001 From: stuxnot <41650734+Stuxnot@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:31:23 +0200 Subject: [PATCH 3/8] Changes order of private and public nyxstone members For better readibility, this commit moves the private members of nyxstone below the public member functions. It furthermore removes the unnecessary members cpu and features, which the nyxstone class does not need. --- include/nyxstone.h | 35 ++++++++++++++--------------------- src/nyxstone.cpp | 2 -- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/include/nyxstone.h b/include/nyxstone.h index 561d513..d270650 100644 --- a/include/nyxstone.h +++ b/include/nyxstone.h @@ -13,23 +13,6 @@ namespace emproof { /// Nyxstone class for assembling and disassembling for a given architecture. class Nyxstone { - /// The LLVM triple - llvm::Triple triple; - /// Specific cpu to use (can be empty). - std::string m_cpu; - /// Additional features to en-/disable (can be emtpy). - std::string m_features; - - const llvm::Target& target; - - llvm::MCTargetOptions target_options; - - std::unique_ptr register_info; - std::unique_ptr assembler_info; - std::unique_ptr instruction_info; - std::unique_ptr subtarget_info; - std::unique_ptr instruction_printer; - public: /// Custom exception class used throughout nyxstone to pass any kind of String describing an error upwards. class Exception final: public std::exception { @@ -95,8 +78,6 @@ class Nyxstone { /// @param instruction_printer Instruction printer for the given architecture. Nyxstone( llvm::Triple&& triple, - std::string&& cpu, - std::string&& features, const llvm::Target& target, llvm::MCTargetOptions&& target_options, std::unique_ptr&& register_info, @@ -105,8 +86,6 @@ class Nyxstone { std::unique_ptr&& subtarget_info, std::unique_ptr&& instruction_printer) noexcept : triple(std::move(triple)), - m_cpu(std::move(cpu)), - m_features(std::move(features)), target(target), target_options(std::move(target_options)), register_info(std::move(register_info)), @@ -184,6 +163,20 @@ class Nyxstone { size_t count, std::string* disassembly, std::vector* instructions) const; + + /// The LLVM triple + llvm::Triple triple; + + // Target is a static object, thus it is safe to take its const reference. + const llvm::Target& target; + + llvm::MCTargetOptions target_options; + + std::unique_ptr register_info; + std::unique_ptr assembler_info; + std::unique_ptr instruction_info; + std::unique_ptr subtarget_info; + std::unique_ptr instruction_printer; }; /** diff --git a/src/nyxstone.cpp b/src/nyxstone.cpp index ff9b849..77cabb2 100644 --- a/src/nyxstone.cpp +++ b/src/nyxstone.cpp @@ -126,8 +126,6 @@ std::unique_ptr NyxstoneBuilder::build() { return std::make_unique( std::move(triple), - std::move(m_cpu), - std::move(m_features), // target is a static object, thus it is safe to take its reference here: *target, std::move(target_options), From 3b060e90d8a7268441d19288f85b38339dd7190c Mon Sep 17 00:00:00 2001 From: stuxnot <41650734+Stuxnot@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:33:14 +0200 Subject: [PATCH 4/8] Explains uint8_t for IntegerBase --- include/nyxstone.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/nyxstone.h b/include/nyxstone.h index d270650..0dc138b 100644 --- a/include/nyxstone.h +++ b/include/nyxstone.h @@ -185,6 +185,7 @@ class Nyxstone { class NyxstoneBuilder { public: /// @brief Configuration options for the immediate representation in disassembly. + // This is a uint8_t for better interoperability with rust. enum class IntegerBase : uint8_t { /// Immediates are represented in decimal format. Dec = 0, From 494b1013e5a01a0b881f232429857f67d1ede833 Mon Sep 17 00:00:00 2001 From: stuxnot <41650734+Stuxnot@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:35:29 +0200 Subject: [PATCH 5/8] Moves bkpt prepend/remove to functions Creates functions for bkpt prepension and removal, so that the `assemble_impl` is easier to understand. --- src/nyxstone.cpp | 71 ++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/src/nyxstone.cpp b/src/nyxstone.cpp index 77cabb2..06f5385 100644 --- a/src/nyxstone.cpp +++ b/src/nyxstone.cpp @@ -184,7 +184,46 @@ void Nyxstone::disassemble_to_instructions( disassemble_impl(bytes, address, count, nullptr, &instructions); } -// NOLINTNEXTLINE (readability-function-cognitive-complexity) +namespace { +const char* const PREPENDED_ASSEMBLY {"bkpt #0x42\n"}; +constexpr std::array PREPENDED_BYTES {0x42, 0xbe}; + +std::string prepend_bkpt(std::string&& assembly, bool needs_prepend) { + if (needs_prepend) { + assembly.insert(0, PREPENDED_ASSEMBLY); + } + + return assembly; +} + +SmallVector +remove_bkpt(SmallVector&& bytes, std::vector* instructions, bool has_prepend) { + // If bkpt got prepended for alignment reasons, remove it from instructions and bytes + if (has_prepend) { + if (instructions != nullptr) { + const auto& first_instr_bytes = instructions->front().bytes; + const bool has_prepended_bytes = !instructions->empty() && first_instr_bytes.size() == 2 + && std::equal(begin(first_instr_bytes), end(first_instr_bytes), begin(PREPENDED_BYTES)); + if (!has_prepended_bytes) { + throw Nyxstone::Exception("Did not find prepended bkpt at first instruction."); + } + instructions->erase(instructions->begin()); + } + + if (bytes.size() < 2 || memcmp(PREPENDED_BYTES.data(), bytes.data(), 2) != 0) { + std::ostringstream error_stream; + error_stream << "Did not find prepended bkpt at first two bytes."; + error_stream << " Found bytes 0x" << std::hex << static_cast(bytes[0]) << " 0x" + << static_cast(bytes[1]); + throw Nyxstone::Exception(error_stream.str()); + } + bytes.erase(bytes.begin(), bytes.begin() + 2); + } + + return std::move(bytes); +} +} // namespace + void Nyxstone::assemble_impl( const std::string& assembly, uint64_t address, @@ -208,14 +247,8 @@ void Nyxstone::assemble_impl( // // tl;dr // For Thumb prepend 2 byte in assembly if `(address % 4) == 2` to get correct alignment behavior. - auto input_assembly = assembly; - const bool prepend_bkpt = is_ArmT16_or_ArmT32(triple) && address % 4 == 2; - uint64_t compensate_prepended_bkpt = 0; - std::vector prepend_bkpt_bytes = {0x42, 0xbe}; - if (prepend_bkpt) { - input_assembly.insert(0, "bkpt #0x42\n"); - compensate_prepended_bkpt = 2; - } + const bool needs_prepend {is_ArmT16_or_ArmT32(triple) && address % 4 == 2}; + const std::string input_assembly {prepend_bkpt(std::move(std::string {assembly}), needs_prepend)}; // Add input assembly text llvm::SourceMgr source_manager; @@ -326,6 +359,7 @@ void Nyxstone::assemble_impl( } // Inject user-defined labels + const uint64_t compensate_prepended_bkpt = (needs_prepend) ? PREPENDED_BYTES.size() : 0u; for (const auto& label : labels) { auto* inj_symbol = context.getOrCreateSymbol(label.name); inj_symbol->setOffset(label.address - address + compensate_prepended_bkpt); @@ -343,24 +377,7 @@ void Nyxstone::assemble_impl( throw Nyxstone::Exception(error_stream.str()); } - // If bkpt got prepended for alignment reasons, remove it from instructions and bytes - if (prepend_bkpt) { - if (instructions != nullptr) { - if (instructions->empty() || instructions->front().bytes != prepend_bkpt_bytes) { - throw Nyxstone::Exception("Did not find prepended bkpt at first instruction."); - } - instructions->erase(instructions->begin()); - } - - if (output_bytes.size() < 2 || memcmp(prepend_bkpt_bytes.data(), output_bytes.data(), 2) != 0) { - std::ostringstream error_stream; - error_stream << "Did not find prepended bkpt at first two bytes."; - error_stream << " Found bytes 0x" << std::hex << static_cast(output_bytes[0]) << " 0x" - << static_cast(output_bytes[1]); - throw Nyxstone::Exception(error_stream.str()); - } - output_bytes.erase(output_bytes.begin(), output_bytes.begin() + 2); - } + output_bytes = std::move(remove_bkpt(std::move(output_bytes), instructions, needs_prepend)); // Assign addresses if instruction details requested if (instructions != nullptr) { From e6e35e84e9cb1f6bd14983e269d2ce0142ca20e6 Mon Sep 17 00:00:00 2001 From: stuxnot <41650734+Stuxnot@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:58:13 +0200 Subject: [PATCH 6/8] Use WebKit clang-format style --- .clang-format | 69 +---- bindings/python/pynyxstone.cpp | 47 +-- bindings/rust/src/nyxstone_ffi.cpp | 48 ++- bindings/rust/src/nyxstone_ffi.hpp | 29 +- examples/nyxstone-cli.cpp | 13 +- examples/sample.cpp | 9 +- include/nyxstone.h | 118 ++++---- src/ELFStreamerWrapper.cpp | 56 ++-- src/ELFStreamerWrapper.h | 38 +-- src/ObjectWriterWrapper.cpp | 77 +++-- src/ObjectWriterWrapper.h | 47 ++- .../AArch64/MCTargetDesc/AArch64FixupKinds.h | 96 +++--- .../AArch64/MCTargetDesc/AArch64MCExpr.h | 44 ++- src/Target/ARM/MCTargetDesc/ARMFixupKinds.h | 212 +++++++------- src/nyxstone.cpp | 276 ++++++++---------- 15 files changed, 513 insertions(+), 666 deletions(-) diff --git a/.clang-format b/.clang-format index c3fc3e5..b8e589f 100644 --- a/.clang-format +++ b/.clang-format @@ -1,67 +1,4 @@ -AccessModifierOffset: -2 -AlignAfterOpenBracket: AlwaysBreak -AlignConsecutiveMacros: false -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlines: Right -AlignOperands: false -AlignTrailingComments: false -AllowAllArgumentsOnNextLine: false -AllowAllConstructorInitializersOnNextLine: false -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: true -AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: false -BinPackParameters: false -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Attach -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: AfterColon -BreakInheritanceList: AfterColon -BreakStringLiterals: false -ColumnLimit: 120 -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: true -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -FixNamespaceComments: true -IncludeBlocks: Regroup -IndentCaseLabels: true -IndentPPDirectives: BeforeHash +BasedOnStyle: WebKit IndentWidth: 4 -IndentWrappedFunctionNames: false -KeepEmptyLinesAtTheStartOfBlocks: false -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -PointerAlignment: Left -ReflowComments: false -SortIncludes: false -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: true -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: false -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 2 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Latest -TabWidth: 4 -UseTab: Never \ No newline at end of file +UseTab: Never +ColumnLimit: 120 \ No newline at end of file diff --git a/bindings/python/pynyxstone.cpp b/bindings/python/pynyxstone.cpp index 94df25d..3fb9f1c 100644 --- a/bindings/python/pynyxstone.cpp +++ b/bindings/python/pynyxstone.cpp @@ -12,39 +12,38 @@ using emproof::Nyxstone; using emproof::NyxstoneBuilder; std::vector assemble_to_bytes( - Nyxstone& nyxstone, - std::string assembly, - uint64_t address, - std::vector labels) { + Nyxstone& nyxstone, std::string assembly, uint64_t address, std::vector labels) +{ std::vector bytes; nyxstone.assemble_to_bytes(assembly, address, labels, bytes); return bytes; } std::vector assemble_to_instructions( - Nyxstone& nyxstone, - std::string assembly, - uint64_t address, - std::vector labels) { + Nyxstone& nyxstone, std::string assembly, uint64_t address, std::vector labels) +{ std::vector instructions; nyxstone.assemble_to_instructions(assembly, address, labels, instructions); return instructions; } -std::string disassemble_to_text(Nyxstone& nyxstone, std::vector bytes, uint64_t address, uint64_t count) { +std::string disassemble_to_text(Nyxstone& nyxstone, std::vector bytes, uint64_t address, uint64_t count) +{ std::string assembly; nyxstone.disassemble_to_text(bytes, address, count, assembly); return assembly; } -std::vector -disassemble_to_instructions(Nyxstone& nyxstone, std::vector bytes, uint64_t address, uint64_t count) { +std::vector disassemble_to_instructions( + Nyxstone& nyxstone, std::vector bytes, uint64_t address, uint64_t count) +{ std::vector instructions; nyxstone.disassemble_to_instructions(bytes, address, count, instructions); return instructions; } -PYBIND11_MODULE(nyxstone, m) { +PYBIND11_MODULE(nyxstone, m) +{ m.doc() = "pybind11 plugin for nyxstone"; py::class_(m, "LabelDefinition") @@ -53,16 +52,12 @@ PYBIND11_MODULE(nyxstone, m) { .def_readwrite("address", &Nyxstone::LabelDefinition::address); py::class_(m, "Instruction") - .def( - py::init>(), - py::arg("address"), - py::arg("assembly"), + .def(py::init>(), py::arg("address"), py::arg("assembly"), py::arg("bytes")) .def_readwrite("address", &Nyxstone::Instruction::address) .def_readwrite("bytes", &Nyxstone::Instruction::bytes) .def_readwrite("assembly", &Nyxstone::Instruction::assembly) - .def( - "__eq__", + .def("__eq__", [](const Nyxstone::Instruction& self, const Nyxstone::Instruction& other) { return self.address == other.address && self.assembly == other.assembly && self.bytes == other.bytes; }) @@ -88,25 +83,15 @@ PYBIND11_MODULE(nyxstone, m) { .def("with_triple", &NyxstoneBuilder::with_triple, "Specify the llvm target triple") .def("with_features", &NyxstoneBuilder::with_features, "Specify the llvm features to be en- or disabled") .def("with_cpu", &NyxstoneBuilder::with_cpu, "Specify the cpu to use") - .def( - "with_immediate_style", - &NyxstoneBuilder::with_immediate_style, + .def("with_immediate_style", &NyxstoneBuilder::with_immediate_style, "Specify the style in which immediates are printed") .def("build", &NyxstoneBuilder::build, "Build the Nyxstone instance"); py::class_(m, "Nyxstone") .def("assemble_to_bytes", &assemble_to_bytes, py::arg("assembly"), py::arg("address"), py::arg("labels")) - .def( - "assemble_to_instructions", - &assemble_to_instructions, - py::arg("assembly"), - py::arg("address"), + .def("assemble_to_instructions", &assemble_to_instructions, py::arg("assembly"), py::arg("address"), py::arg("labels")) - .def( - "disassemble_to_instructions", - &disassemble_to_instructions, - py::arg("bytes"), - py::arg("address"), + .def("disassemble_to_instructions", &disassemble_to_instructions, py::arg("bytes"), py::arg("address"), py::arg("count")) .def("disassemble_to_text", &disassemble_to_text, py::arg("bytes"), py::arg("address"), py::arg("count")); } diff --git a/bindings/rust/src/nyxstone_ffi.cpp b/bindings/rust/src/nyxstone_ffi.cpp index 0457a97..dade3b5 100644 --- a/bindings/rust/src/nyxstone_ffi.cpp +++ b/bindings/rust/src/nyxstone_ffi.cpp @@ -14,17 +14,16 @@ struct Instruction final { }; rust::Vec NyxstoneFFI::assemble_to_bytes( - const rust::str assembly, - uint64_t address, - const rust::Slice labels) const { + const rust::str assembly, uint64_t address, const rust::Slice labels) const +{ std::vector cpp_labels {}; cpp_labels.reserve(labels.size()); std::transform(std::begin(labels), std::end(labels), std::back_inserter(cpp_labels), [](const auto& label) { - return Nyxstone::LabelDefinition {std::string(label.name), label.address}; + return Nyxstone::LabelDefinition { std::string(label.name), label.address }; }); std::vector cpp_bytes {}; - nyxstone->assemble_to_bytes(std::string {assembly}, address, cpp_labels, cpp_bytes); + nyxstone->assemble_to_bytes(std::string { assembly }, address, cpp_labels, cpp_bytes); rust::Vec bytes; bytes.reserve(cpp_bytes.size()); @@ -34,17 +33,16 @@ rust::Vec NyxstoneFFI::assemble_to_bytes( } rust::Vec NyxstoneFFI::assemble_to_instructions( - const rust::str assembly, - uint64_t address, - const rust::Slice labels) const { + const rust::str assembly, uint64_t address, const rust::Slice labels) const +{ std::vector cpp_labels; cpp_labels.reserve(labels.size()); std::transform(std::begin(labels), std::end(labels), std::back_inserter(cpp_labels), [](const auto& label) { - return Nyxstone::LabelDefinition {std::string(label.name), label.address}; + return Nyxstone::LabelDefinition { std::string(label.name), label.address }; }); std::vector cpp_instructions {}; - nyxstone->assemble_to_instructions(std::string {assembly}, address, cpp_labels, cpp_instructions); + nyxstone->assemble_to_instructions(std::string { assembly }, address, cpp_labels, cpp_instructions); rust::Vec instructions {}; instructions.reserve(cpp_instructions.size()); @@ -52,14 +50,15 @@ rust::Vec NyxstoneFFI::assemble_to_instructions( rust::Vec bytes; bytes.reserve(cpp_insn.bytes.size()); std::copy(cpp_insn.bytes.begin(), cpp_insn.bytes.end(), std::back_inserter(bytes)); - instructions.push_back({cpp_insn.address, rust::String(cpp_insn.assembly), bytes}); + instructions.push_back({ cpp_insn.address, rust::String(cpp_insn.assembly), bytes }); } return instructions; } -rust::String -NyxstoneFFI::disassemble_to_text(const rust::Slice bytes, uint64_t address, size_t count) const { +rust::String NyxstoneFFI::disassemble_to_text( + const rust::Slice bytes, uint64_t address, size_t count) const +{ std::vector cpp_bytes; cpp_bytes.reserve(bytes.size()); std::copy(bytes.begin(), bytes.end(), std::back_inserter(cpp_bytes)); @@ -67,11 +66,12 @@ NyxstoneFFI::disassemble_to_text(const rust::Slice bytes, uint64_ nyxstone->disassemble_to_text(cpp_bytes, address, count, cpp_disassembly); - return {cpp_disassembly}; + return { cpp_disassembly }; } -rust::Vec -NyxstoneFFI::disassemble_to_instructions(const rust::Slice bytes, uint64_t address, size_t count) const { +rust::Vec NyxstoneFFI::disassemble_to_instructions( + const rust::Slice bytes, uint64_t address, size_t count) const +{ std::vector cpp_bytes {}; cpp_bytes.reserve(bytes.size()); std::copy(bytes.begin(), bytes.end(), std::back_inserter(cpp_bytes)); @@ -85,23 +85,21 @@ NyxstoneFFI::disassemble_to_instructions(const rust::Slice bytes, rust::Vec insn_bytes; insn_bytes.reserve(cpp_insn.bytes.size()); std::copy(cpp_insn.bytes.begin(), cpp_insn.bytes.end(), std::back_inserter(insn_bytes)); - instructions.push_back({cpp_insn.address, rust::String(cpp_insn.assembly), std::move(insn_bytes)}); + instructions.push_back({ cpp_insn.address, rust::String(cpp_insn.assembly), std::move(insn_bytes) }); } return instructions; } -std::unique_ptr create_nyxstone_ffi( // cppcheck-suppress unusedFunction - const rust::str triple_name, - const rust::str cpu, - const rust::str features, - const IntegerBase imm_style) { +std::unique_ptr create_nyxstone_ffi( // cppcheck-suppress unusedFunction + const rust::str triple_name, const rust::str cpu, const rust::str features, const IntegerBase imm_style) +{ NyxstoneBuilder::IntegerBase style = static_cast(static_cast(imm_style)); return std::make_unique(NyxstoneBuilder() - .with_triple(std::string {triple_name}) - .with_cpu(std::string {cpu}) - .with_features(std::string {features}) + .with_triple(std::string { triple_name }) + .with_cpu(std::string { cpu }) + .with_features(std::string { features }) .with_immediate_style(style) .build()); } diff --git a/bindings/rust/src/nyxstone_ffi.hpp b/bindings/rust/src/nyxstone_ffi.hpp index 64db8f2..0317740 100644 --- a/bindings/rust/src/nyxstone_ffi.hpp +++ b/bindings/rust/src/nyxstone_ffi.hpp @@ -19,27 +19,30 @@ class NyxstoneFFI { // Internal Nyxstone instance std::unique_ptr nyxstone; - public: +public: /** - * @brief Constructor for NyxstoneFFI. - * @param nyxstone Unique_ptr holding the Nyxstone instance. - */ - explicit NyxstoneFFI(std::unique_ptr&& nyxstone) : nyxstone(std::move(nyxstone)) {} + * @brief Constructor for NyxstoneFFI. + * @param nyxstone Unique_ptr holding the Nyxstone instance. + */ + explicit NyxstoneFFI(std::unique_ptr&& nyxstone) + : nyxstone(std::move(nyxstone)) + { + } ~NyxstoneFFI() = default; NyxstoneFFI(const NyxstoneFFI& other) = delete; NyxstoneFFI(NyxstoneFFI&& other) = delete; - rust::Vec - assemble_to_bytes(rust::str assembly, uint64_t address, rust::Slice labels) const; + rust::Vec assemble_to_bytes( + rust::str assembly, uint64_t address, rust::Slice labels) const; - rust::Vec - assemble_to_instructions(rust::str assembly, uint64_t address, rust::Slice labels) const; + rust::Vec assemble_to_instructions( + rust::str assembly, uint64_t address, rust::Slice labels) const; rust::String disassemble_to_text(rust::Slice bytes, uint64_t address, size_t count) const; - rust::Vec - disassemble_to_instructions(rust::Slice bytes, uint64_t address, size_t count) const; + rust::Vec disassemble_to_instructions( + rust::Slice bytes, uint64_t address, size_t count) const; }; /// @brief Creates a NyxstoneFFI instance for the specified triple with the specified CPU and features. @@ -48,5 +51,5 @@ class NyxstoneFFI { /// @param cpu The cpu to be used. /// @param features Llvm features string. /// @param imm_style The integer representation for immediates. -std::unique_ptr -create_nyxstone_ffi(rust::str triple_name, rust::str cpu, rust::str features, IntegerBase imm_style); +std::unique_ptr create_nyxstone_ffi( + rust::str triple_name, rust::str cpu, rust::str features, IntegerBase imm_style); diff --git a/examples/nyxstone-cli.cpp b/examples/nyxstone-cli.cpp index 0702ba1..133561f 100644 --- a/examples/nyxstone-cli.cpp +++ b/examples/nyxstone-cli.cpp @@ -21,7 +21,8 @@ void print_bytes(const std::vector& bytes); std::string arch_to_llvm_string(Architecture arch); std::optional> parse_labels(std::string labelstr); -int main(int argc, char** argv) { +int main(int argc, char** argv) +{ // clang-format off po::options_description desc("Allowed options"); desc.add_options() @@ -93,7 +94,7 @@ int main(int argc, char** argv) { labels = maybe_labels.value(); } - std::unique_ptr nyxstone {nullptr}; + std::unique_ptr nyxstone { nullptr }; try { nyxstone = std::move(NyxstoneBuilder().with_triple(std::move(arch)).build()); } catch (const std::exception& e) { @@ -151,7 +152,8 @@ int main(int argc, char** argv) { return 0; } -void print_bytes(const std::vector& bytes) { +void print_bytes(const std::vector& bytes) +{ std::cout << std::hex << "[ "; for (const auto& byte : bytes) { std::cout << std::setfill('0') << std::setw(2) << static_cast(byte) << " "; @@ -159,7 +161,8 @@ void print_bytes(const std::vector& bytes) { std::cout << std::dec << "]"; } -std::optional> parse_labels(std::string labelstr) { +std::optional> parse_labels(std::string labelstr) +{ auto delim = ','; std::vector labels; @@ -190,7 +193,7 @@ std::optional> parse_labels(std::string l return {}; } - labels.push_back(Nyxstone::LabelDefinition {name, value}); + labels.push_back(Nyxstone::LabelDefinition { name, value }); labelstr.erase(0, delim_pos == std::string::npos ? delim_pos : delim_pos + 1); } diff --git a/examples/sample.cpp b/examples/sample.cpp index 14f0937..5af1c40 100644 --- a/examples/sample.cpp +++ b/examples/sample.cpp @@ -6,12 +6,13 @@ using emproof::Nyxstone; using emproof::NyxstoneBuilder; -int main(int /* argc */, char** /* argv */) { +int main(int /* argc */, char** /* argv */) +{ try { auto nyxstone_x86_64 = NyxstoneBuilder().with_triple("x86_64-linux-gnu").build(); auto nyxstone_armv8m = NyxstoneBuilder().with_triple("armv8m.main-none-eabi").build(); - const std::vector labels {{".label", 0x1010}}; + const std::vector labels { { ".label", 0x1010 } }; std::vector bytes; std::vector instructions; std::string disassembly; @@ -61,13 +62,13 @@ int main(int /* argc */, char** /* argv */) { std::cout << std::endl << "disassemble_to_text:" << std::endl; std::cout << "\t48 89 c0 : [ "; - nyxstone_x86_64->disassemble_to_text({0x48, 0x89, 0xc0}, 0x1000, 0, disassembly); + nyxstone_x86_64->disassemble_to_text({ 0x48, 0x89, 0xc0 }, 0x1000, 0, disassembly); disassembly.erase(disassembly.find_last_not_of(" \t\n\r") + 1); std::cout << disassembly; std::cout << " ] - expected [ mov rax, rax ]\n"; std::cout << "\t06 d1 : [ "; - nyxstone_armv8m->disassemble_to_text({0x06, 0xd1}, 0x1000, 0, disassembly); + nyxstone_armv8m->disassemble_to_text({ 0x06, 0xd1 }, 0x1000, 0, disassembly); disassembly.erase(disassembly.find_last_not_of(" \t\n\r") + 1); std::cout << disassembly; std::cout << " ] - expected [ bne #12 ]\n"; diff --git a/include/nyxstone.h b/include/nyxstone.h index 0dc138b..decf317 100644 --- a/include/nyxstone.h +++ b/include/nyxstone.h @@ -13,34 +13,49 @@ namespace emproof { /// Nyxstone class for assembling and disassembling for a given architecture. class Nyxstone { - public: +public: /// Custom exception class used throughout nyxstone to pass any kind of String describing an error upwards. - class Exception final: public std::exception { - public: - [[nodiscard]] const char* what() const noexcept override { - return inner.c_str(); - } + class Exception final : public std::exception { + public: + [[nodiscard]] const char* what() const noexcept override { return inner.c_str(); } - Exception(const Exception& error) noexcept : inner(error.inner) {} - Exception(Exception&& error) noexcept : inner(std::move(error.inner)) {} - explicit Exception(const char* desc) noexcept : inner(desc) {} - explicit Exception(std::string&& desc) noexcept : inner(desc) {} - explicit Exception(const llvm::StringRef& desc) noexcept : inner(desc.str()) {} + Exception(const Exception& error) noexcept + : inner(error.inner) + { + } + Exception(Exception&& error) noexcept + : inner(std::move(error.inner)) + { + } + explicit Exception(const char* desc) noexcept + : inner(desc) + { + } + explicit Exception(std::string&& desc) noexcept + : inner(desc) + { + } + explicit Exception(const llvm::StringRef& desc) noexcept + : inner(desc.str()) + { + } ~Exception() override = default; - Exception& operator=(const Exception& error) noexcept { + Exception& operator=(const Exception& error) noexcept + { if (this != &error) { this->inner = error.inner; } return *this; } - Exception& operator=(Exception&& error) noexcept { + Exception& operator=(Exception&& error) noexcept + { this->inner = std::move(error.inner); return *this; } - private: + private: std::string inner; }; @@ -76,23 +91,20 @@ class Nyxstone { /// @param instruction_info Instruction information for the given triple. /// @param subtarget_info Information about the subtarget, created with @p cpu and @p features. /// @param instruction_printer Instruction printer for the given architecture. - Nyxstone( - llvm::Triple&& triple, - const llvm::Target& target, - llvm::MCTargetOptions&& target_options, - std::unique_ptr&& register_info, - std::unique_ptr&& assembler_info, - std::unique_ptr&& instruction_info, - std::unique_ptr&& subtarget_info, - std::unique_ptr&& instruction_printer) noexcept : - triple(std::move(triple)), - target(target), - target_options(std::move(target_options)), - register_info(std::move(register_info)), - assembler_info(std::move(assembler_info)), - instruction_info(std::move(instruction_info)), - subtarget_info(std::move(subtarget_info)), - instruction_printer(std::move(instruction_printer)) {} + Nyxstone(llvm::Triple&& triple, const llvm::Target& target, llvm::MCTargetOptions&& target_options, + std::unique_ptr&& register_info, std::unique_ptr&& assembler_info, + std::unique_ptr&& instruction_info, std::unique_ptr&& subtarget_info, + std::unique_ptr&& instruction_printer) noexcept + : triple(std::move(triple)) + , target(target) + , target_options(std::move(target_options)) + , register_info(std::move(register_info)) + , assembler_info(std::move(assembler_info)) + , instruction_info(std::move(instruction_info)) + , subtarget_info(std::move(subtarget_info)) + , instruction_printer(std::move(instruction_printer)) + { + } /// @brief Translates assembly instructions at given start address to bytes. /// @@ -103,10 +115,7 @@ class Nyxstone { /// @param address The absolute address of the first instruction. /// @param labels Label definitions, should hold all external labels used in the @p assembly. /// @param bytes The assembled byte code (Note: the vector is reset before writing to it). - void assemble_to_bytes( - const std::string& assembly, - uint64_t address, - const std::vector& labels, + void assemble_to_bytes(const std::string& assembly, uint64_t address, const std::vector& labels, std::vector& bytes) const; /// @brief Translates assembly instructions at given start address to instruction details containing bytes. @@ -118,11 +127,8 @@ class Nyxstone { /// @param address The absolute address of the first instruction. /// @param labels Label definitions, should hold all external labels used in the @p assembly. /// @param instructions Holds the instruction details of the assembled @p assembly. - void assemble_to_instructions( - const std::string& assembly, - uint64_t address, - const std::vector& labels, - std::vector& instructions) const; + void assemble_to_instructions(const std::string& assembly, uint64_t address, + const std::vector& labels, std::vector& instructions) const; /// @brief Translates bytes to disassembly text at given start address. /// @@ -130,9 +136,8 @@ class Nyxstone { /// @param address The absolute address of the byte code. /// @param count The number of instructions which should be disassembled, 0 means all. /// @param disassembly Disassembly output. - void - disassemble_to_text(const std::vector& bytes, uint64_t address, size_t count, std::string& disassembly) - const; + void disassemble_to_text( + const std::vector& bytes, uint64_t address, size_t count, std::string& disassembly) const; /// @brief Translates bytes to instruction details containing disassembly text at given start address. /// @@ -140,28 +145,17 @@ class Nyxstone { /// @param address The absolute address of the byte code. /// @param count The number of instructions which should be disassembled, 0 means all. /// @param instructions Holds the instruction details after disassembling. - void disassemble_to_instructions( - const std::vector& bytes, - uint64_t address, - size_t count, + void disassemble_to_instructions(const std::vector& bytes, uint64_t address, size_t count, std::vector& instructions) const; - private: +private: // Uses LLVM to assemble instructions. // Utilizes some custom overloads to import user-supplied label definitions and extract instruction details. - void assemble_impl( - const std::string& assembly, - uint64_t address, - const std::vector& labels, - std::vector& bytes, - std::vector* instructions) const; + void assemble_impl(const std::string& assembly, uint64_t address, const std::vector& labels, + std::vector& bytes, std::vector* instructions) const; // Uses LLVM to disassemble instructions. - void disassemble_impl( - const std::vector& bytes, - uint64_t address, - size_t count, - std::string* disassembly, + void disassemble_impl(const std::vector& bytes, uint64_t address, size_t count, std::string* disassembly, std::vector* instructions) const; /// The LLVM triple @@ -183,7 +177,7 @@ class Nyxstone { * @brief Builder for Nyxstone instances. **/ class NyxstoneBuilder { - public: +public: /// @brief Configuration options for the immediate representation in disassembly. // This is a uint8_t for better interoperability with rust. enum class IntegerBase : uint8_t { @@ -195,7 +189,7 @@ class NyxstoneBuilder { HexSuffix = 2, }; - private: +private: ///@brief The llvm target triple. std::string m_triple; /// @brief Specific CPU for LLVM, default is empty. @@ -205,7 +199,7 @@ class NyxstoneBuilder { /// @brief In which style immediates should be represented in disassembly. IntegerBase m_imm_style = IntegerBase::Dec; - public: +public: NyxstoneBuilder() = default; NyxstoneBuilder(const NyxstoneBuilder&) = default; NyxstoneBuilder(NyxstoneBuilder&&) = default; diff --git a/src/ELFStreamerWrapper.cpp b/src/ELFStreamerWrapper.cpp index da04b47..75b9488 100644 --- a/src/ELFStreamerWrapper.cpp +++ b/src/ELFStreamerWrapper.cpp @@ -28,7 +28,8 @@ using namespace llvm; namespace emproof { -void ELFStreamerWrapper::emitInstruction(const MCInst& Inst, const MCSubtargetInfo& STI) { +void ELFStreamerWrapper::emitInstruction(const MCInst& Inst, const MCSubtargetInfo& STI) +{ MCELFStreamer::emitInstruction(Inst, STI); // Only record instruction details if requested @@ -50,10 +51,7 @@ void ELFStreamerWrapper::emitInstruction(const MCInst& Inst, const MCSubtargetIn } // Get length of already recorded instructions - const size_t insn_byte_length = std::accumulate( - instructions->begin(), - instructions->end(), - static_cast(0), + const size_t insn_byte_length = std::accumulate(instructions->begin(), instructions->end(), static_cast(0), [](size_t acc, const Nyxstone::Instruction& insn) { return acc + insn.bytes.size(); }); // Iterate fragments @@ -62,18 +60,18 @@ void ELFStreamerWrapper::emitInstruction(const MCInst& Inst, const MCSubtargetIn // Get Content MutableArrayRef contents; switch (fragment.getKind()) { - default: - continue; - case MCFragment::FT_Data: { - auto& data_fragment = cast(fragment); - contents = data_fragment.getContents(); - break; - } - case MCFragment::FT_Relaxable: { - auto& relaxable_fragment = cast(fragment); - contents = relaxable_fragment.getContents(); - break; - } + default: + continue; + case MCFragment::FT_Data: { + auto& data_fragment = cast(fragment); + contents = data_fragment.getContents(); + break; + } + case MCFragment::FT_Relaxable: { + auto& relaxable_fragment = cast(fragment); + contents = relaxable_fragment.getContents(); + break; + } } frag_byte_length += contents.size(); @@ -111,23 +109,13 @@ void ELFStreamerWrapper::emitInstruction(const MCInst& Inst, const MCSubtargetIn } } -std::unique_ptr ELFStreamerWrapper::createELFStreamerWrapper( - MCContext& context, - std::unique_ptr&& assembler_backend, - std::unique_ptr&& object_writer, - std::unique_ptr&& code_emitter, - bool RelaxAll, - std::vector* instructions, - std::string& extended_error, - MCInstPrinter& instruction_printer) { - auto streamer = std::make_unique( - context, - std::move(assembler_backend), - std::move(object_writer), - std::move(code_emitter), - instructions, - extended_error, - instruction_printer); +std::unique_ptr ELFStreamerWrapper::createELFStreamerWrapper(MCContext& context, + std::unique_ptr&& assembler_backend, std::unique_ptr&& object_writer, + std::unique_ptr&& code_emitter, bool RelaxAll, std::vector* instructions, + std::string& extended_error, MCInstPrinter& instruction_printer) +{ + auto streamer = std::make_unique(context, std::move(assembler_backend), + std::move(object_writer), std::move(code_emitter), instructions, extended_error, instruction_printer); if (RelaxAll) { streamer->getAssembler().setRelaxAll(true); diff --git a/src/ELFStreamerWrapper.h b/src/ELFStreamerWrapper.h index 646cd72..6f651fa 100644 --- a/src/ELFStreamerWrapper.h +++ b/src/ELFStreamerWrapper.h @@ -14,7 +14,7 @@ namespace emproof { /// This class derives from LLVM's MCELFStreamer, which enables us to receive /// information during assembly such as preliminary instruction size and bytes /// before relaxation and fixups (via method 'emitInstruction()'). -class ELFStreamerWrapper: public llvm::MCELFStreamer { +class ELFStreamerWrapper : public llvm::MCELFStreamer { // Sink to record instruction details std::vector* instructions; @@ -24,7 +24,7 @@ class ELFStreamerWrapper: public llvm::MCELFStreamer { // Instruction printer llvm::MCInstPrinter& instruction_printer; - public: +public: /// @brief ELFStreamerWrapper constructor /// @param context The MCContext used for reporting errors. /// @param assembler_backend Backend for the wrapped MCELFStreamer. @@ -34,18 +34,16 @@ class ELFStreamerWrapper: public llvm::MCELFStreamer { /// @param instructions Vector to store instruction information. /// @param extended_error Reference to nyxstone error string. /// @param instruction_printer Instruction printer used to generate the instruction assembly. - ELFStreamerWrapper( - llvm::MCContext& context, - std::unique_ptr&& assembler_backend, - std::unique_ptr&& object_writer, - std::unique_ptr&& code_emitter, - std::vector* instructions, - std::string& extended_error, - llvm::MCInstPrinter& instruction_printer) : - llvm::MCELFStreamer(context, std::move(assembler_backend), std::move(object_writer), std::move(code_emitter)), - instructions(instructions), - extended_error(extended_error), - instruction_printer(instruction_printer) {} + ELFStreamerWrapper(llvm::MCContext& context, std::unique_ptr&& assembler_backend, + std::unique_ptr&& object_writer, std::unique_ptr&& code_emitter, + std::vector* instructions, std::string& extended_error, + llvm::MCInstPrinter& instruction_printer) + : llvm::MCELFStreamer(context, std::move(assembler_backend), std::move(object_writer), std::move(code_emitter)) + , instructions(instructions) + , extended_error(extended_error) + , instruction_printer(instruction_printer) + { + } /// @brief Creates a UniquePtr holding the ELFStreamerWrapper. /// @param context The MCContext used for reporting errors. @@ -57,14 +55,10 @@ class ELFStreamerWrapper: public llvm::MCELFStreamer { /// @param extended_error Reference to nyxstone error string. /// @param instruction_printer Instruction printer used to generate the instruction assembly. /// @return unique_ptr holding the ELFStreamerWrapper - static std::unique_ptr createELFStreamerWrapper( - llvm::MCContext& context, - std::unique_ptr&& assembler_backend, - std::unique_ptr&& object_writer, - std::unique_ptr&& code_emitter, - bool RelaxAll, - std::vector* instructions, - std::string& extended_error, + static std::unique_ptr createELFStreamerWrapper(llvm::MCContext& context, + std::unique_ptr&& assembler_backend, std::unique_ptr&& object_writer, + std::unique_ptr&& code_emitter, bool RelaxAll, + std::vector* instructions, std::string& extended_error, llvm::MCInstPrinter& instruction_printer); /// @brief Calls `MCELFStreamer::emitInstruction` and records instruction details. diff --git a/src/ObjectWriterWrapper.cpp b/src/ObjectWriterWrapper.cpp index f548478..3a155fd 100644 --- a/src/ObjectWriterWrapper.cpp +++ b/src/ObjectWriterWrapper.cpp @@ -37,7 +37,8 @@ namespace emproof { /// @param[in] value - Value to align. /// @param[in] alignment - Alignment to align the value. /// @returns Aligned value. -uint64_t alignUp(uint64_t value, uint64_t alignment) { +uint64_t alignUp(uint64_t value, uint64_t alignment) +{ auto remainder = value % alignment; return (remainder > 0) ? value + (alignment - remainder) : value; } @@ -47,7 +48,8 @@ uint64_t alignUp(uint64_t value, uint64_t alignment) { /// @param fixup The fixup to be validated. /// @param Layout The ASM Layout after fixups have been applied. /// @param context The MCContext used to report errors. -void validate_arm_thumb(const MCFixup& fixup, const MCAsmLayout& Layout, MCContext& context) { +void validate_arm_thumb(const MCFixup& fixup, const MCAsmLayout& Layout, MCContext& context) +{ // For all instructions we are checking here, we need to make sure that the fixup is a SymbolRef. // If it is not, we do not need to check the instruction. const bool fixup_is_symbolref = fixup.getValue() != nullptr && fixup.getValue()->getKind() == MCExpr::SymbolRef; @@ -69,7 +71,7 @@ void validate_arm_thumb(const MCFixup& fixup, const MCAsmLayout& Layout, MCConte // Check for out-of-bounds ARM Thumb2 `ADR` instruction if (fixup.getTargetKind() == ARM::fixup_t2_adr_pcrel_12) { auto offset = static_cast(cast(fixup.getValue())->getSymbol().getOffset()); - offset -= 4; // Source address is (PC + 4) + offset -= 4; // Source address is (PC + 4) // Check min/max bounds of instruction encoding // Symmetric bounds as `addw` and `subw` are used internally @@ -96,7 +98,7 @@ void validate_arm_thumb(const MCFixup& fixup, const MCAsmLayout& Layout, MCConte auto& symbol = cast(fixup.getValue())->getSymbol(); auto address = Layout.getFragmentOffset(symbol.getFragment()) + symbol.getOffset(); - auto offset = static_cast(symbol.getOffset()) - 4; // Source address is (PC + 4) + auto offset = static_cast(symbol.getOffset()) - 4; // Source address is (PC + 4) // Since llvm only wrongly assembles for offsets which differ from the allowed value for delta < 4 // it is enough to check that the offset is validly aligned to 4. For better error reporting, @@ -117,7 +119,8 @@ void validate_arm_thumb(const MCFixup& fixup, const MCAsmLayout& Layout, MCConte /// @param fixup The fixup to be validated. /// @param Layout The ASM Layout after fixups have been applied. /// @param context The MCContext used to report errors. -void validate_aarch64(const MCFixup& fixup, [[maybe_unused]] const MCAsmLayout& Layout, MCContext& context) { +void validate_aarch64(const MCFixup& fixup, [[maybe_unused]] const MCAsmLayout& Layout, MCContext& context) +{ // Check for out-of-bounds AArch64 `ADR` instruction if (context.getTargetTriple().isAArch64() && fixup.getTargetKind() == AArch64::fixup_aarch64_pcrel_adr_imm21 && fixup.getValue() != nullptr && fixup.getValue()->getKind() == MCExpr::Target @@ -134,20 +137,21 @@ void validate_aarch64(const MCFixup& fixup, [[maybe_unused]] const MCAsmLayout& } } -void ObjectWriterWrapper::validate_fixups(const MCFragment& fragment, const MCAsmLayout& Layout) { +void ObjectWriterWrapper::validate_fixups(const MCFragment& fragment, const MCAsmLayout& Layout) +{ // Get fixups const SmallVectorImpl* fixups = nullptr; switch (fragment.getKind()) { - default: - return; - case MCFragment::FT_Data: { - fixups = &cast(fragment).getFixups(); - break; - } - case MCFragment::FT_Relaxable: { - fixups = &cast(fragment).getFixups(); - break; - } + default: + return; + case MCFragment::FT_Data: { + fixups = &cast(fragment).getFixups(); + break; + } + case MCFragment::FT_Relaxable: { + fixups = &cast(fragment).getFixups(); + break; + } } // Iterate fixups @@ -164,17 +168,14 @@ void ObjectWriterWrapper::validate_fixups(const MCFragment& fragment, const MCAs } } -void ObjectWriterWrapper::executePostLayoutBinding(llvm::MCAssembler& Asm, const llvm::MCAsmLayout& Layout) { +void ObjectWriterWrapper::executePostLayoutBinding(llvm::MCAssembler& Asm, const llvm::MCAsmLayout& Layout) +{ inner_object_writer->executePostLayoutBinding(Asm, Layout); } -void ObjectWriterWrapper::recordRelocation( - MCAssembler& Asm, - const MCAsmLayout& Layout, - const MCFragment* Fragment, - const MCFixup& Fixup, - MCValue Target, - uint64_t& FixedValue) { +void ObjectWriterWrapper::recordRelocation(MCAssembler& Asm, const MCAsmLayout& Layout, const MCFragment* Fragment, + const MCFixup& Fixup, MCValue Target, uint64_t& FixedValue) +{ inner_object_writer->recordRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); // LLVM performs relocation for the AArch64 instruction `adrp` during the linking step. @@ -196,12 +197,12 @@ void ObjectWriterWrapper::recordRelocation( } } -uint64_t ObjectWriterWrapper::writeObject(MCAssembler& Asm, const MCAsmLayout& Layout) { +uint64_t ObjectWriterWrapper::writeObject(MCAssembler& Asm, const MCAsmLayout& Layout) +{ // Get .text section const auto& sections = Layout.getSectionOrder(); - const MCSection* const* text_section_it = std::find_if(std::begin(sections), std::end(sections), [](auto section) { - return section->getName().str() == ".text"; - }); + const MCSection* const* text_section_it = std::find_if( + std::begin(sections), std::end(sections), [](auto section) { return section->getName().str() == ".text"; }); if (text_section_it == sections.end()) { extended_error += "[writeObject] Object has no .text section."; @@ -240,9 +241,7 @@ uint64_t ObjectWriterWrapper::writeObject(MCAssembler& Asm, const MCAsmLayout& L // Update instruction bytes insn_bytes.clear(); insn_bytes.reserve(insn_len); - std::copy( - contents.begin() + frag_pos, - contents.begin() + frag_pos + insn_len, + std::copy(contents.begin() + frag_pos, contents.begin() + frag_pos + insn_len, std::back_inserter(insn_bytes)); // Prepare next iteration @@ -288,18 +287,10 @@ uint64_t ObjectWriterWrapper::writeObject(MCAssembler& Asm, const MCAsmLayout& L } std::unique_ptr ObjectWriterWrapper::createObjectWriterWrapper( - std::unique_ptr&& object_writer, - raw_pwrite_stream& stream, - MCContext& context, - bool write_text_section_only, - std::string& extended_error, - std::vector* instructions) { + std::unique_ptr&& object_writer, raw_pwrite_stream& stream, MCContext& context, + bool write_text_section_only, std::string& extended_error, std::vector* instructions) +{ return std::make_unique( - std::move(object_writer), - stream, - context, - write_text_section_only, - extended_error, - instructions); + std::move(object_writer), stream, context, write_text_section_only, extended_error, instructions); } } // namespace emproof diff --git a/src/ObjectWriterWrapper.h b/src/ObjectWriterWrapper.h index c71dcb8..218f782 100644 --- a/src/ObjectWriterWrapper.h +++ b/src/ObjectWriterWrapper.h @@ -28,7 +28,7 @@ namespace emproof { /// This class also enables us to limit the final output byte stream to the /// relevant bytes (as opposed to the whole ELF object file) and grab final /// instruction bytes (after relaxation and fixups) (via 'writeObject()'). -class ObjectWriterWrapper: public llvm::MCObjectWriter { +class ObjectWriterWrapper : public llvm::MCObjectWriter { // Wrapped MCObjectWriter, f. i., ELFSingleObjectWriter std::unique_ptr inner_object_writer; @@ -56,51 +56,42 @@ class ObjectWriterWrapper: public llvm::MCObjectWriter { /// @param Layout The ASM Layout after fixups have been applied. void validate_fixups(const llvm::MCFragment& fragment, const llvm::MCAsmLayout& Layout); - public: +public: /// @brief Creates an ObjectWriterWrapper. /// /// The ObjectWriterWrapper is created using the wrapped MCObjectWriter, some additional llvm classes /// used for querying additional information from LLVM, and a (nullable) pointer to the instruction information. /// /// @param object_writer The object writer object to wrap, must implement the function used by this class. - /// @param stream Stream (used for the @p object_writer) to write the .text section to if requested via @p write_text_section_only. + /// @param stream Stream (used for the @p object_writer) to write the .text section to if requested via @p + /// write_text_section_only. /// @param write_text_section_only If only the .text section should be written to @p stream. /// @param extended_error Accumulation for llvm errors, since Exceptions might not be supported by the linked LLVM. /// @param instructions Instruction information for which the bytes should be corrected. - ObjectWriterWrapper( - std::unique_ptr&& object_writer, - llvm::raw_pwrite_stream& stream, - llvm::MCContext& context, - bool write_text_section_only, - std::string& extended_error, - std::vector* instructions) : - inner_object_writer(std::move(object_writer)), - stream(stream), - context(context), - write_text_section_only(write_text_section_only), - extended_error(extended_error), - instructions(instructions) {} + ObjectWriterWrapper(std::unique_ptr&& object_writer, llvm::raw_pwrite_stream& stream, + llvm::MCContext& context, bool write_text_section_only, std::string& extended_error, + std::vector* instructions) + : inner_object_writer(std::move(object_writer)) + , stream(stream) + , context(context) + , write_text_section_only(write_text_section_only) + , extended_error(extended_error) + , instructions(instructions) + { + } /// @brief Creates a UniquePtr holding the the ObjectWriterWrapper static std::unique_ptr createObjectWriterWrapper( - std::unique_ptr&& object_writer, - llvm::raw_pwrite_stream& stream, - llvm::MCContext& context, - bool write_text_section_only, - std::string& extended_error, + std::unique_ptr&& object_writer, llvm::raw_pwrite_stream& stream, + llvm::MCContext& context, bool write_text_section_only, std::string& extended_error, std::vector* instructions); /// @brief Simple function wrapper calling the wrapped object wrapper function directly. void executePostLayoutBinding(llvm::MCAssembler& Asm, const llvm::MCAsmLayout& Layout) override; /// @brief Performs relocations via the wrapped object wrapper as well as custom relocations. - void recordRelocation( - llvm::MCAssembler& Asm, - const llvm::MCAsmLayout& Layout, - const llvm::MCFragment* Fragment, - const llvm::MCFixup& Fixup, - llvm::MCValue Target, - uint64_t& FixedValue) override; + void recordRelocation(llvm::MCAssembler& Asm, const llvm::MCAsmLayout& Layout, const llvm::MCFragment* Fragment, + const llvm::MCFixup& Fixup, llvm::MCValue Target, uint64_t& FixedValue) override; /// @brief Write object to the stream and update the bytes of the instruction details. uint64_t writeObject(llvm::MCAssembler& Asm, const llvm::MCAsmLayout& Layout) override; diff --git a/src/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h b/src/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h index 83ee094..f90d7d5 100644 --- a/src/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h +++ b/src/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h @@ -17,53 +17,53 @@ namespace llvm { namespace AArch64 { -enum Fixups { - // A 21-bit pc-relative immediate inserted into an ADR instruction. - fixup_aarch64_pcrel_adr_imm21 = FirstTargetFixupKind, - - // A 21-bit pc-relative immediate inserted into an ADRP instruction. - fixup_aarch64_pcrel_adrp_imm21, - - // 12-bit fixup for add/sub instructions. No alignment adjustment. All value - // bits are encoded. - fixup_aarch64_add_imm12, - - // unsigned 12-bit fixups for load and store instructions. - fixup_aarch64_ldst_imm12_scale1, - fixup_aarch64_ldst_imm12_scale2, - fixup_aarch64_ldst_imm12_scale4, - fixup_aarch64_ldst_imm12_scale8, - fixup_aarch64_ldst_imm12_scale16, - - // The high 19 bits of a 21-bit pc-relative immediate. Same encoding as - // fixup_aarch64_pcrel_adrhi, except this is used by pc-relative loads and - // generates relocations directly when necessary. - fixup_aarch64_ldr_pcrel_imm19, - - // FIXME: comment - fixup_aarch64_movw, - - // The high 14 bits of a 21-bit pc-relative immediate. - fixup_aarch64_pcrel_branch14, - - // The high 19 bits of a 21-bit pc-relative immediate. Same encoding as - // fixup_aarch64_pcrel_adrhi, except this is use by b.cc and generates - // relocations directly when necessary. - fixup_aarch64_pcrel_branch19, - - // The high 26 bits of a 28-bit pc-relative immediate. - fixup_aarch64_pcrel_branch26, - - // The high 26 bits of a 28-bit pc-relative immediate. Distinguished from - // branch26 only on ELF. - fixup_aarch64_pcrel_call26, - - // Marker - LastTargetFixupKind, - NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind -}; - -} // end namespace AArch64 -} // end namespace llvm + enum Fixups { + // A 21-bit pc-relative immediate inserted into an ADR instruction. + fixup_aarch64_pcrel_adr_imm21 = FirstTargetFixupKind, + + // A 21-bit pc-relative immediate inserted into an ADRP instruction. + fixup_aarch64_pcrel_adrp_imm21, + + // 12-bit fixup for add/sub instructions. No alignment adjustment. All value + // bits are encoded. + fixup_aarch64_add_imm12, + + // unsigned 12-bit fixups for load and store instructions. + fixup_aarch64_ldst_imm12_scale1, + fixup_aarch64_ldst_imm12_scale2, + fixup_aarch64_ldst_imm12_scale4, + fixup_aarch64_ldst_imm12_scale8, + fixup_aarch64_ldst_imm12_scale16, + + // The high 19 bits of a 21-bit pc-relative immediate. Same encoding as + // fixup_aarch64_pcrel_adrhi, except this is used by pc-relative loads and + // generates relocations directly when necessary. + fixup_aarch64_ldr_pcrel_imm19, + + // FIXME: comment + fixup_aarch64_movw, + + // The high 14 bits of a 21-bit pc-relative immediate. + fixup_aarch64_pcrel_branch14, + + // The high 19 bits of a 21-bit pc-relative immediate. Same encoding as + // fixup_aarch64_pcrel_adrhi, except this is use by b.cc and generates + // relocations directly when necessary. + fixup_aarch64_pcrel_branch19, + + // The high 26 bits of a 28-bit pc-relative immediate. + fixup_aarch64_pcrel_branch26, + + // The high 26 bits of a 28-bit pc-relative immediate. Distinguished from + // branch26 only on ELF. + fixup_aarch64_pcrel_call26, + + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind + }; + +} // end namespace AArch64 +} // end namespace llvm #endif diff --git a/src/Target/AArch64/MCTargetDesc/AArch64MCExpr.h b/src/Target/AArch64/MCTargetDesc/AArch64MCExpr.h index 79da878..e82583c 100644 --- a/src/Target/AArch64/MCTargetDesc/AArch64MCExpr.h +++ b/src/Target/AArch64/MCTargetDesc/AArch64MCExpr.h @@ -22,8 +22,8 @@ namespace llvm { -class AArch64MCExpr: public MCTargetExpr { - public: +class AArch64MCExpr : public MCTargetExpr { +public: enum VariantKind { // Symbol locations specifying (roughly speaking) what calculation should be // performed to construct the final address for the relocated @@ -115,13 +115,17 @@ class AArch64MCExpr: public MCTargetExpr { VK_INVALID = 0xfff }; - private: +private: const MCExpr* Expr; const VariantKind Kind; - explicit AArch64MCExpr(const MCExpr* Expr, VariantKind Kind) : Expr(Expr), Kind(Kind) {} + explicit AArch64MCExpr(const MCExpr* Expr, VariantKind Kind) + : Expr(Expr) + , Kind(Kind) + { + } - public: +public: /// @name Construction /// @{ @@ -132,30 +136,20 @@ class AArch64MCExpr: public MCTargetExpr { /// @{ /// Get the kind of this expression. - VariantKind getKind() const { - return Kind; - } + VariantKind getKind() const { return Kind; } /// Get the expression this modifier applies to. - const MCExpr* getSubExpr() const { - return Expr; - } + const MCExpr* getSubExpr() const { return Expr; } /// @} /// @name VariantKind information extractors. /// @{ - static VariantKind getSymbolLoc(VariantKind Kind) { - return static_cast(Kind & VK_SymLocBits); - } + static VariantKind getSymbolLoc(VariantKind Kind) { return static_cast(Kind & VK_SymLocBits); } - static VariantKind getAddressFrag(VariantKind Kind) { - return static_cast(Kind & VK_AddressFragBits); - } + static VariantKind getAddressFrag(VariantKind Kind) { return static_cast(Kind & VK_AddressFragBits); } - static bool isNotChecked(VariantKind Kind) { - return Kind & VK_NC; - } + static bool isNotChecked(VariantKind Kind) { return Kind & VK_NC; } /// @} @@ -173,14 +167,10 @@ class AArch64MCExpr: public MCTargetExpr { void fixELFSymbolsInTLSFixups(MCAssembler& Asm) const override; - static bool classof(const MCExpr* E) { - return E->getKind() == MCExpr::Target; - } + static bool classof(const MCExpr* E) { return E->getKind() == MCExpr::Target; } - static bool classof(const AArch64MCExpr*) { - return true; - } + static bool classof(const AArch64MCExpr*) { return true; } }; -} // end namespace llvm +} // end namespace llvm #endif diff --git a/src/Target/ARM/MCTargetDesc/ARMFixupKinds.h b/src/Target/ARM/MCTargetDesc/ARMFixupKinds.h index 76acaf6..f5e5883 100644 --- a/src/Target/ARM/MCTargetDesc/ARMFixupKinds.h +++ b/src/Target/ARM/MCTargetDesc/ARMFixupKinds.h @@ -16,112 +16,112 @@ namespace llvm { namespace ARM { -enum Fixups { - // 12-bit PC relative relocation for symbol addresses - fixup_arm_ldst_pcrel_12 = FirstTargetFixupKind, - - // Equivalent to fixup_arm_ldst_pcrel_12, with the 16-bit halfwords reordered. - fixup_t2_ldst_pcrel_12, - - // 10-bit PC relative relocation for symbol addresses used in - // LDRD/LDRH/LDRB/etc. instructions. All bits are encoded. - fixup_arm_pcrel_10_unscaled, - // 10-bit PC relative relocation for symbol addresses used in VFP instructions - // where the lower 2 bits are not encoded (so it's encoded as an 8-bit - // immediate). - fixup_arm_pcrel_10, - // Equivalent to fixup_arm_pcrel_10, accounting for the short-swapped encoding - // of Thumb2 instructions. - fixup_t2_pcrel_10, - // 9-bit PC relative relocation for symbol addresses used in VFP instructions - // where bit 0 not encoded (so it's encoded as an 8-bit immediate). - fixup_arm_pcrel_9, - // Equivalent to fixup_arm_pcrel_9, accounting for the short-swapped encoding - // of Thumb2 instructions. - fixup_t2_pcrel_9, - // 12-bit immediate value. - fixup_arm_ldst_abs_12, - // 10-bit PC relative relocation for symbol addresses where the lower 2 bits - // are not encoded (so it's encoded as an 8-bit immediate). - fixup_thumb_adr_pcrel_10, - // 12-bit PC relative relocation for the ADR instruction. - fixup_arm_adr_pcrel_12, - // 12-bit PC relative relocation for the ADR instruction. - fixup_t2_adr_pcrel_12, - // 24-bit PC relative relocation for conditional branch instructions. - fixup_arm_condbranch, - // 24-bit PC relative relocation for branch instructions. (unconditional) - fixup_arm_uncondbranch, - // 20-bit PC relative relocation for Thumb2 direct uconditional branch - // instructions. - fixup_t2_condbranch, - // 20-bit PC relative relocation for Thumb2 direct branch unconditional branch - // instructions. - fixup_t2_uncondbranch, - - // 12-bit fixup for Thumb B instructions. - fixup_arm_thumb_br, - - // The following fixups handle the ARM BL instructions. These can be - // conditionalised; however, the ARM ELF ABI requires a different relocation - // in that case: R_ARM_JUMP24 instead of R_ARM_CALL. The difference is that - // R_ARM_CALL is allowed to change the instruction to a BLX inline, which has - // no conditional version; R_ARM_JUMP24 would have to insert a veneer. - // - // MachO does not draw a distinction between the two cases, so it will treat - // fixup_arm_uncondbl and fixup_arm_condbl as identical fixups. - - // Fixup for unconditional ARM BL instructions. - fixup_arm_uncondbl, - - // Fixup for ARM BL instructions with nontrivial conditionalisation. - fixup_arm_condbl, - - // Fixup for ARM BLX instructions. - fixup_arm_blx, - - // Fixup for Thumb BL instructions. - fixup_arm_thumb_bl, - - // Fixup for Thumb BLX instructions. - fixup_arm_thumb_blx, - - // Fixup for Thumb branch instructions. - fixup_arm_thumb_cb, - - // Fixup for Thumb load/store from constant pool instrs. - fixup_arm_thumb_cp, - - // Fixup for Thumb conditional branching instructions. - fixup_arm_thumb_bcc, - - // The next two are for the movt/movw pair - // the 16bit imm field are split into imm{15-12} and imm{11-0} - fixup_arm_movt_hi16, // :upper16: - fixup_arm_movw_lo16, // :lower16: - fixup_t2_movt_hi16, // :upper16: - fixup_t2_movw_lo16, // :lower16: - - // Fixup for mod_imm - fixup_arm_mod_imm, - - // Fixup for Thumb2 8-bit rotated operand - fixup_t2_so_imm, - - // Fixups for Branch Future. - fixup_bf_branch, - fixup_bf_target, - fixup_bfl_target, - fixup_bfc_target, - fixup_bfcsel_else_target, - fixup_wls, - fixup_le, - - // Marker - LastTargetFixupKind, - NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind -}; + enum Fixups { + // 12-bit PC relative relocation for symbol addresses + fixup_arm_ldst_pcrel_12 = FirstTargetFixupKind, + + // Equivalent to fixup_arm_ldst_pcrel_12, with the 16-bit halfwords reordered. + fixup_t2_ldst_pcrel_12, + + // 10-bit PC relative relocation for symbol addresses used in + // LDRD/LDRH/LDRB/etc. instructions. All bits are encoded. + fixup_arm_pcrel_10_unscaled, + // 10-bit PC relative relocation for symbol addresses used in VFP instructions + // where the lower 2 bits are not encoded (so it's encoded as an 8-bit + // immediate). + fixup_arm_pcrel_10, + // Equivalent to fixup_arm_pcrel_10, accounting for the short-swapped encoding + // of Thumb2 instructions. + fixup_t2_pcrel_10, + // 9-bit PC relative relocation for symbol addresses used in VFP instructions + // where bit 0 not encoded (so it's encoded as an 8-bit immediate). + fixup_arm_pcrel_9, + // Equivalent to fixup_arm_pcrel_9, accounting for the short-swapped encoding + // of Thumb2 instructions. + fixup_t2_pcrel_9, + // 12-bit immediate value. + fixup_arm_ldst_abs_12, + // 10-bit PC relative relocation for symbol addresses where the lower 2 bits + // are not encoded (so it's encoded as an 8-bit immediate). + fixup_thumb_adr_pcrel_10, + // 12-bit PC relative relocation for the ADR instruction. + fixup_arm_adr_pcrel_12, + // 12-bit PC relative relocation for the ADR instruction. + fixup_t2_adr_pcrel_12, + // 24-bit PC relative relocation for conditional branch instructions. + fixup_arm_condbranch, + // 24-bit PC relative relocation for branch instructions. (unconditional) + fixup_arm_uncondbranch, + // 20-bit PC relative relocation for Thumb2 direct uconditional branch + // instructions. + fixup_t2_condbranch, + // 20-bit PC relative relocation for Thumb2 direct branch unconditional branch + // instructions. + fixup_t2_uncondbranch, + + // 12-bit fixup for Thumb B instructions. + fixup_arm_thumb_br, + + // The following fixups handle the ARM BL instructions. These can be + // conditionalised; however, the ARM ELF ABI requires a different relocation + // in that case: R_ARM_JUMP24 instead of R_ARM_CALL. The difference is that + // R_ARM_CALL is allowed to change the instruction to a BLX inline, which has + // no conditional version; R_ARM_JUMP24 would have to insert a veneer. + // + // MachO does not draw a distinction between the two cases, so it will treat + // fixup_arm_uncondbl and fixup_arm_condbl as identical fixups. + + // Fixup for unconditional ARM BL instructions. + fixup_arm_uncondbl, + + // Fixup for ARM BL instructions with nontrivial conditionalisation. + fixup_arm_condbl, + + // Fixup for ARM BLX instructions. + fixup_arm_blx, + + // Fixup for Thumb BL instructions. + fixup_arm_thumb_bl, + + // Fixup for Thumb BLX instructions. + fixup_arm_thumb_blx, + + // Fixup for Thumb branch instructions. + fixup_arm_thumb_cb, + + // Fixup for Thumb load/store from constant pool instrs. + fixup_arm_thumb_cp, + + // Fixup for Thumb conditional branching instructions. + fixup_arm_thumb_bcc, + + // The next two are for the movt/movw pair + // the 16bit imm field are split into imm{15-12} and imm{11-0} + fixup_arm_movt_hi16, // :upper16: + fixup_arm_movw_lo16, // :lower16: + fixup_t2_movt_hi16, // :upper16: + fixup_t2_movw_lo16, // :lower16: + + // Fixup for mod_imm + fixup_arm_mod_imm, + + // Fixup for Thumb2 8-bit rotated operand + fixup_t2_so_imm, + + // Fixups for Branch Future. + fixup_bf_branch, + fixup_bf_target, + fixup_bfl_target, + fixup_bfc_target, + fixup_bfcsel_else_target, + fixup_wls, + fixup_le, + + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind + }; } -} // namespace llvm +} // namespace llvm #endif diff --git a/src/nyxstone.cpp b/src/nyxstone.cpp index 06f5385..ffc54ad 100644 --- a/src/nyxstone.cpp +++ b/src/nyxstone.cpp @@ -25,35 +25,40 @@ using namespace llvm; namespace emproof { -NyxstoneBuilder& NyxstoneBuilder::with_triple(std::string&& triple) noexcept { +NyxstoneBuilder& NyxstoneBuilder::with_triple(std::string&& triple) noexcept +{ m_triple = std::move(triple); return *this; } // cppcheck-suppress unusedFunction -NyxstoneBuilder& NyxstoneBuilder::with_cpu(std::string&& cpu) noexcept { +NyxstoneBuilder& NyxstoneBuilder::with_cpu(std::string&& cpu) noexcept +{ m_cpu = std::move(cpu); return *this; } // cppcheck-suppress unusedFunction -NyxstoneBuilder& NyxstoneBuilder::with_features(std::string&& features) noexcept { +NyxstoneBuilder& NyxstoneBuilder::with_features(std::string&& features) noexcept +{ m_features = std::move(features); return *this; } // cppcheck-suppress unusedFunction -NyxstoneBuilder& NyxstoneBuilder::with_immediate_style(NyxstoneBuilder::IntegerBase style) noexcept { +NyxstoneBuilder& NyxstoneBuilder::with_immediate_style(NyxstoneBuilder::IntegerBase style) noexcept +{ m_imm_style = style; return *this; } -std::unique_ptr NyxstoneBuilder::build() { +std::unique_ptr NyxstoneBuilder::build() +{ // # Note // We observed that the initialization of LLVM (in build()) is not thread - // safe as deadlocks appear for repeated assemble and disassmble tests in Rust. - // Thus, we guard the initialization with a static mutex so that each function - // call to build() is thread-safe. + // safe as deadlocks appear for repeated assemble and disassmble tests in + // Rust. Thus, we guard the initialization with a static mutex so that each + // function call to build() is thread-safe. static std::mutex build_common_mutex; const std::lock_guard lock(build_common_mutex); @@ -82,8 +87,8 @@ std::unique_ptr NyxstoneBuilder::build() { } llvm::MCTargetOptions target_options; - auto assembler_info = - std::unique_ptr(target->createMCAsmInfo(*register_info, triple.getTriple(), target_options)); + auto assembler_info + = std::unique_ptr(target->createMCAsmInfo(*register_info, triple.getTriple(), target_options)); if (!assembler_info) { throw Nyxstone::Exception("Could not create LLVM object (= MCAsmInfo )"); } @@ -93,8 +98,8 @@ std::unique_ptr NyxstoneBuilder::build() { throw Nyxstone::Exception("Could not create LLVM object (= MCInstrInfo )"); } - auto subtarget_info = - std::unique_ptr(target->createMCSubtargetInfo(triple.getTriple(), m_cpu, m_features)); + auto subtarget_info + = std::unique_ptr(target->createMCSubtargetInfo(triple.getTriple(), m_cpu, m_features)); if (!subtarget_info) { throw Nyxstone::Exception("Could not create LLVM object (= MCSubtargetInfo )"); } @@ -112,53 +117,40 @@ std::unique_ptr NyxstoneBuilder::build() { } switch (m_imm_style) { - case IntegerBase::HexSuffix: - instruction_printer->setPrintHexStyle(HexStyle::Style::Asm); - [[fallthrough]]; - case IntegerBase::HexPrefix: - instruction_printer->setPrintImmHex(true); - break; - - case IntegerBase::Dec: - default: - break; + case IntegerBase::HexSuffix: + instruction_printer->setPrintHexStyle(HexStyle::Style::Asm); + [[fallthrough]]; + case IntegerBase::HexPrefix: + instruction_printer->setPrintImmHex(true); + break; + + case IntegerBase::Dec: + default: + break; } - return std::make_unique( - std::move(triple), + return std::make_unique(std::move(triple), // target is a static object, thus it is safe to take its reference here: - *target, - std::move(target_options), - std::move(register_info), - std::move(assembler_info), - std::move(instruction_info), - std::move(subtarget_info), - std::move(instruction_printer)); + *target, std::move(target_options), std::move(register_info), std::move(assembler_info), + std::move(instruction_info), std::move(subtarget_info), std::move(instruction_printer)); } -void Nyxstone::assemble_to_bytes( - const std::string& assembly, - uint64_t address, - const std::vector& labels, - std::vector& bytes) const { +void Nyxstone::assemble_to_bytes(const std::string& assembly, uint64_t address, + const std::vector& labels, std::vector& bytes) const +{ bytes.clear(); assemble_impl(assembly, address, labels, bytes, nullptr); } -void Nyxstone::assemble_to_instructions( - const std::string& assembly, - uint64_t address, - const std::vector& labels, - std::vector& instructions) const { +void Nyxstone::assemble_to_instructions(const std::string& assembly, uint64_t address, + const std::vector& labels, std::vector& instructions) const +{ instructions.clear(); std::vector output_bytes; assemble_impl(assembly, address, labels, output_bytes, &instructions); // Ensure accumulated instruction byte length matches output byte length - const size_t insn_byte_length = std::accumulate( - instructions.begin(), - instructions.end(), - static_cast(0), + const size_t insn_byte_length = std::accumulate(instructions.begin(), instructions.end(), static_cast(0), [](size_t acc, const Instruction& insn) { return acc + insn.bytes.size(); }); if (insn_byte_length != output_bytes.size()) { std::stringstream error_stream; @@ -169,86 +161,86 @@ void Nyxstone::assemble_to_instructions( } void Nyxstone::disassemble_to_text( - const std::vector& bytes, - uint64_t address, - size_t count, - std::string& disassembly) const { + const std::vector& bytes, uint64_t address, size_t count, std::string& disassembly) const +{ disassemble_impl(bytes, address, count, &disassembly, nullptr); } void Nyxstone::disassemble_to_instructions( - const std::vector& bytes, - uint64_t address, - size_t count, - std::vector& instructions) const { + const std::vector& bytes, uint64_t address, size_t count, std::vector& instructions) const +{ disassemble_impl(bytes, address, count, nullptr, &instructions); } namespace { -const char* const PREPENDED_ASSEMBLY {"bkpt #0x42\n"}; -constexpr std::array PREPENDED_BYTES {0x42, 0xbe}; + const char* const PREPENDED_ASSEMBLY { "bkpt #0x42\n" }; + constexpr std::array PREPENDED_BYTES { 0x42, 0xbe }; -std::string prepend_bkpt(std::string&& assembly, bool needs_prepend) { - if (needs_prepend) { - assembly.insert(0, PREPENDED_ASSEMBLY); + std::string prepend_bkpt(std::string&& assembly, bool needs_prepend) + { + if (needs_prepend) { + assembly.insert(0, PREPENDED_ASSEMBLY); + } + + return assembly; } - return assembly; -} + SmallVector remove_bkpt( + SmallVector&& bytes, std::vector* instructions, bool has_prepend) + { + // If bkpt got prepended for alignment reasons, remove it from instructions + // and bytes + if (has_prepend) { + if (instructions != nullptr) { + const auto& first_instr_bytes = instructions->front().bytes; + const bool has_prepended_bytes = !instructions->empty() && first_instr_bytes.size() == 2 + && std::equal(begin(first_instr_bytes), end(first_instr_bytes), begin(PREPENDED_BYTES)); + if (!has_prepended_bytes) { + throw Nyxstone::Exception("Did not find prepended bkpt at first instruction."); + } + instructions->erase(instructions->begin()); + } -SmallVector -remove_bkpt(SmallVector&& bytes, std::vector* instructions, bool has_prepend) { - // If bkpt got prepended for alignment reasons, remove it from instructions and bytes - if (has_prepend) { - if (instructions != nullptr) { - const auto& first_instr_bytes = instructions->front().bytes; - const bool has_prepended_bytes = !instructions->empty() && first_instr_bytes.size() == 2 - && std::equal(begin(first_instr_bytes), end(first_instr_bytes), begin(PREPENDED_BYTES)); - if (!has_prepended_bytes) { - throw Nyxstone::Exception("Did not find prepended bkpt at first instruction."); + if (bytes.size() < 2 || memcmp(PREPENDED_BYTES.data(), bytes.data(), 2) != 0) { + std::ostringstream error_stream; + error_stream << "Did not find prepended bkpt at first two bytes."; + error_stream << " Found bytes 0x" << std::hex << static_cast(bytes[0]) << " 0x" + << static_cast(bytes[1]); + throw Nyxstone::Exception(error_stream.str()); } - instructions->erase(instructions->begin()); + bytes.erase(bytes.begin(), bytes.begin() + 2); } - if (bytes.size() < 2 || memcmp(PREPENDED_BYTES.data(), bytes.data(), 2) != 0) { - std::ostringstream error_stream; - error_stream << "Did not find prepended bkpt at first two bytes."; - error_stream << " Found bytes 0x" << std::hex << static_cast(bytes[0]) << " 0x" - << static_cast(bytes[1]); - throw Nyxstone::Exception(error_stream.str()); - } - bytes.erase(bytes.begin(), bytes.begin() + 2); + return std::move(bytes); } +} // namespace - return std::move(bytes); -} -} // namespace - -void Nyxstone::assemble_impl( - const std::string& assembly, - uint64_t address, - const std::vector& labels, - std::vector& bytes, - std::vector* instructions) const { +void Nyxstone::assemble_impl(const std::string& assembly, uint64_t address, const std::vector& labels, + std::vector& bytes, std::vector* instructions) const +{ bytes.clear(); if (instructions != nullptr) { instructions->clear(); } - // ARM Thumb has mixed 2-byte and 4-byte instructions. The base address used for branch/load/store offset - // calculations is aligned down to the last 4-byte boundary `base = Align(PC, 4)`. LLVM always assembles - // at address zero and external label definitions are adjusted accordingly. This combination leads to - // alignment issues resulting in wrong instruction bytes. - // Hence, for ARM Thumb Nyxstone prepends 2 bytes for 2-byte aligned, but not 4-byte aligned, start addresses - // to create the correct alignment behavior. In the label offset computation Nyxstone compensates for these - // extra 2 bytes. The breakpoint instruction `bkpt #0x42` was chosen as prepend mechanism as it only has a - // 2-byte encoding on ARMv6/7/8-M and is an unusual instruction. The prepended breakpoint instruction gets - // removed by Nyxstone in output `bytes` and `instructions` to have a clean result. + // ARM Thumb has mixed 2-byte and 4-byte instructions. The base address used + // for branch/load/store offset calculations is aligned down to the last + // 4-byte boundary `base = Align(PC, 4)`. LLVM always assembles at address + // zero and external label definitions are adjusted accordingly. This + // combination leads to alignment issues resulting in wrong instruction bytes. + // Hence, for ARM Thumb Nyxstone prepends 2 bytes for 2-byte aligned, but not + // 4-byte aligned, start addresses to create the correct alignment behavior. + // In the label offset computation Nyxstone compensates for these extra 2 + // bytes. The breakpoint instruction `bkpt #0x42` was chosen as prepend + // mechanism as it only has a 2-byte encoding on ARMv6/7/8-M and is an unusual + // instruction. The prepended breakpoint instruction gets removed by Nyxstone + // in output `bytes` and `instructions` to have a clean result. // // tl;dr - // For Thumb prepend 2 byte in assembly if `(address % 4) == 2` to get correct alignment behavior. - const bool needs_prepend {is_ArmT16_or_ArmT32(triple) && address % 4 == 2}; - const std::string input_assembly {prepend_bkpt(std::move(std::string {assembly}), needs_prepend)}; + // For Thumb prepend 2 byte in assembly if `(address % 4) == 2` to get correct + // alignment behavior. + const bool needs_prepend { is_ArmT16_or_ArmT32(triple) && address % 4 == 2 }; + const std::string input_assembly { prepend_bkpt(std::move(std::string { assembly }), needs_prepend) }; // Add input assembly text llvm::SourceMgr source_manager; @@ -258,16 +250,8 @@ void Nyxstone::assemble_impl( // Equip context with info objects and custom error handling MCContext context( - triple, - assembler_info.get(), - register_info.get(), - subtarget_info.get(), - &source_manager, - &target_options); - context.setDiagnosticHandler([&extended_error]( - const SMDiagnostic& SMD, - bool IsInlineAsm, - const SourceMgr& SrcMgr, + triple, assembler_info.get(), register_info.get(), subtarget_info.get(), &source_manager, &target_options); + context.setDiagnosticHandler([&extended_error](const SMDiagnostic& SMD, bool IsInlineAsm, const SourceMgr& SrcMgr, std::vector& LocInfos) { // Suppress unused parameter warning (void)IsInlineAsm; @@ -294,42 +278,34 @@ void Nyxstone::assemble_impl( } // Create assembler backend - auto assembler_backend = - std::unique_ptr(target.createMCAsmBackend(*subtarget_info, *register_info, target_options)); + auto assembler_backend + = std::unique_ptr(target.createMCAsmBackend(*subtarget_info, *register_info, target_options)); if (!assembler_backend) { throw Nyxstone::Exception("Could not create LLVM object (= MCAsmBackend )"); } - // Create object writer and object writer wrapper (that handles custom fixup and output handling) + // Create object writer and object writer wrapper (that handles custom fixup + // and output handling) SmallVector output_bytes; raw_svector_ostream stream(output_bytes); auto object_writer = assembler_backend->createObjectWriter(stream); - auto object_writer_wrapper = ObjectWriterWrapper::createObjectWriterWrapper( - std::move(object_writer), - stream, - context, - /* write_text_section_only */ true, - extended_error, - instructions); + auto object_writer_wrapper + = ObjectWriterWrapper::createObjectWriterWrapper(std::move(object_writer), stream, context, + /* write_text_section_only */ true, extended_error, instructions); if (!object_writer_wrapper) { throw Nyxstone::Exception("Could not create LLVM object (= ObjectWriterWrapper )"); } - // Create object streamer and object streamer wrapper (that records instruction details) + // Create object streamer and object streamer wrapper (that records + // instruction details) if (!triple.isOSBinFormatELF()) { std::stringstream error_stream; error_stream << "ELF does not support target triple '" << triple.getTriple() << "'."; throw Nyxstone::Exception(error_stream.str()); } - auto streamer = ELFStreamerWrapper::createELFStreamerWrapper( - context, - std::move(assembler_backend), - std::move(object_writer_wrapper), - std::move(code_emitter), - /* RelaxAll */ false, - instructions, - extended_error, - *instruction_printer); + auto streamer = ELFStreamerWrapper::createELFStreamerWrapper(context, std::move(assembler_backend), + std::move(object_writer_wrapper), std::move(code_emitter), + /* RelaxAll */ false, instructions, extended_error, *instruction_printer); streamer->setUseAssemblerInfoForParsing(true); // Create assembly parser and target specific assembly parser @@ -351,9 +327,8 @@ void Nyxstone::assemble_impl( // Search first data fragment auto& fragments = *streamer->getCurrentSectionOnly(); - auto fragment_it = std::find_if(std::begin(fragments), std::end(fragments), [](auto& fragment) { - return fragment.getKind() == MCFragment::FT_Data; - }); + auto fragment_it = std::find_if(std::begin(fragments), std::end(fragments), + [](auto& fragment) { return fragment.getKind() == MCFragment::FT_Data; }); if (fragment_it == std::end(fragments)) { throw Nyxstone::Exception("Could not find initial data fragment."); } @@ -394,12 +369,9 @@ void Nyxstone::assemble_impl( std::copy(output_bytes.begin(), output_bytes.end(), std::back_inserter(bytes)); } -void Nyxstone::disassemble_impl( - const std::vector& bytes, - uint64_t address, - size_t count, - std::string* disassembly, - std::vector* instructions) const { +void Nyxstone::disassemble_impl(const std::vector& bytes, uint64_t address, size_t count, + std::string* disassembly, std::vector* instructions) const +{ if (disassembly == nullptr && instructions == nullptr) { return; } @@ -413,12 +385,9 @@ void Nyxstone::disassemble_impl( // Equip context with info objects and custom error handling SmallString<128> error_msg; - MCContext - context(triple, assembler_info.get(), register_info.get(), subtarget_info.get(), nullptr, &target_options); - context.setDiagnosticHandler([&error_msg]( - const SMDiagnostic& SMD, - bool IsInlineAsm, - const SourceMgr& SrcMgr, + MCContext context( + triple, assembler_info.get(), register_info.get(), subtarget_info.get(), nullptr, &target_options); + context.setDiagnosticHandler([&error_msg](const SMDiagnostic& SMD, bool IsInlineAsm, const SourceMgr& SrcMgr, std::vector& LocInfos) { // Suppress unused parameter warning (void)IsInlineAsm; @@ -456,7 +425,9 @@ void Nyxstone::disassemble_impl( // Generate instruction disassembly text std::string insn_str; raw_string_ostream str_stream(insn_str); - instruction_printer->printInst(&insn, /* Address */ address + pos, /* Annot */ "", *subtarget_info, str_stream); + instruction_printer->printInst(&insn, + /* Address */ address + pos, + /* Annot */ "", *subtarget_info, str_stream); // left trim insn_str.erase(0, insn_str.find_first_not_of(" \t\n\r")); @@ -490,10 +461,11 @@ void Nyxstone::disassemble_impl( } } -/// Detects all ARM Thumb architectures. LLVM doesn't seem to have a short way to check this. -bool is_ArmT16_or_ArmT32(const llvm::Triple& triple) { - return ( - triple.getSubArch() == Triple::SubArchType::ARMSubArch_v6m +/// Detects all ARM Thumb architectures. LLVM doesn't seem to have a short way +/// to check this. +bool is_ArmT16_or_ArmT32(const llvm::Triple& triple) +{ + return (triple.getSubArch() == Triple::SubArchType::ARMSubArch_v6m || triple.getSubArch() == Triple::SubArchType::ARMSubArch_v6t2 || triple.getSubArch() == Triple::SubArchType::ARMSubArch_v7m || triple.getSubArch() == Triple::SubArchType::ARMSubArch_v7em @@ -501,4 +473,4 @@ bool is_ArmT16_or_ArmT32(const llvm::Triple& triple) { || triple.getSubArch() == Triple::SubArchType::ARMSubArch_v8m_mainline || triple.getSubArch() == Triple::SubArchType::ARMSubArch_v8_1m_mainline); } -} // namespace emproof +} // namespace emproof From a734d05dfb07676b3402286f54b21447ee7d6701 Mon Sep 17 00:00:00 2001 From: stuxnot <41650734+Stuxnot@users.noreply.github.com> Date: Fri, 27 Oct 2023 15:56:31 +0200 Subject: [PATCH 7/8] Rename namespace to nyxstone --- bindings/rust/src/nyxstone_ffi.cpp | 2 +- bindings/rust/src/nyxstone_ffi.hpp | 4 ++-- examples/nyxstone-cli.cpp | 4 ++-- examples/sample.cpp | 4 ++-- include/nyxstone.h | 4 ++-- src/ELFStreamerWrapper.cpp | 4 ++-- src/ELFStreamerWrapper.h | 4 ++-- src/ObjectWriterWrapper.cpp | 4 ++-- src/ObjectWriterWrapper.h | 4 ++-- src/nyxstone.cpp | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/bindings/rust/src/nyxstone_ffi.cpp b/bindings/rust/src/nyxstone_ffi.cpp index dade3b5..16f0cca 100644 --- a/bindings/rust/src/nyxstone_ffi.cpp +++ b/bindings/rust/src/nyxstone_ffi.cpp @@ -1,6 +1,6 @@ #include "nyxstone_ffi.hpp" -using namespace emproof; +using namespace nyxstone; struct LabelDefinition final { rust::str name {}; diff --git a/bindings/rust/src/nyxstone_ffi.hpp b/bindings/rust/src/nyxstone_ffi.hpp index 0317740..0dfe828 100644 --- a/bindings/rust/src/nyxstone_ffi.hpp +++ b/bindings/rust/src/nyxstone_ffi.hpp @@ -17,14 +17,14 @@ enum class IntegerBase : uint8_t; // See class and function documentation in Nyxstone.h for further info. class NyxstoneFFI { // Internal Nyxstone instance - std::unique_ptr nyxstone; + std::unique_ptr nyxstone; public: /** * @brief Constructor for NyxstoneFFI. * @param nyxstone Unique_ptr holding the Nyxstone instance. */ - explicit NyxstoneFFI(std::unique_ptr&& nyxstone) + explicit NyxstoneFFI(std::unique_ptr&& nyxstone) : nyxstone(std::move(nyxstone)) { } diff --git a/examples/nyxstone-cli.cpp b/examples/nyxstone-cli.cpp index 133561f..301b54f 100644 --- a/examples/nyxstone-cli.cpp +++ b/examples/nyxstone-cli.cpp @@ -12,8 +12,8 @@ namespace po = boost::program_options; -using emproof::Nyxstone; -using emproof::NyxstoneBuilder; +using nyxstone::Nyxstone; +using nyxstone::NyxstoneBuilder; enum class Architecture; std::optional arch_parse_from_string(const std::string& arch); diff --git a/examples/sample.cpp b/examples/sample.cpp index 5af1c40..c3e598f 100644 --- a/examples/sample.cpp +++ b/examples/sample.cpp @@ -3,8 +3,8 @@ #include #include -using emproof::Nyxstone; -using emproof::NyxstoneBuilder; +using nyxstone::Nyxstone; +using nyxstone::NyxstoneBuilder; int main(int /* argc */, char** /* argv */) { diff --git a/include/nyxstone.h b/include/nyxstone.h index decf317..baeb774 100644 --- a/include/nyxstone.h +++ b/include/nyxstone.h @@ -10,7 +10,7 @@ #include #pragma GCC diagnostic pop -namespace emproof { +namespace nyxstone { /// Nyxstone class for assembling and disassembling for a given architecture. class Nyxstone { public: @@ -237,4 +237,4 @@ class NyxstoneBuilder { /// Detects all ARM Thumb architectures. LLVM doesn't seem to have a short way to check this. bool is_ArmT16_or_ArmT32(const llvm::Triple& triple); -} // namespace emproof +} // namespace nyxstone diff --git a/src/ELFStreamerWrapper.cpp b/src/ELFStreamerWrapper.cpp index 75b9488..40b8abf 100644 --- a/src/ELFStreamerWrapper.cpp +++ b/src/ELFStreamerWrapper.cpp @@ -27,7 +27,7 @@ using namespace llvm; -namespace emproof { +namespace nyxstone { void ELFStreamerWrapper::emitInstruction(const MCInst& Inst, const MCSubtargetInfo& STI) { MCELFStreamer::emitInstruction(Inst, STI); @@ -122,4 +122,4 @@ std::unique_ptr ELFStreamerWrapper::createELFStreamerWrapper(MCConte } return streamer; } -} // namespace emproof +} // namespace nyxstone diff --git a/src/ELFStreamerWrapper.h b/src/ELFStreamerWrapper.h index 6f651fa..d3c65cb 100644 --- a/src/ELFStreamerWrapper.h +++ b/src/ELFStreamerWrapper.h @@ -10,7 +10,7 @@ #include #pragma GCC diagnostic pop -namespace emproof { +namespace nyxstone { /// This class derives from LLVM's MCELFStreamer, which enables us to receive /// information during assembly such as preliminary instruction size and bytes /// before relaxation and fixups (via method 'emitInstruction()'). @@ -64,4 +64,4 @@ class ELFStreamerWrapper : public llvm::MCELFStreamer { /// @brief Calls `MCELFStreamer::emitInstruction` and records instruction details. void emitInstruction(const llvm::MCInst& Inst, const llvm::MCSubtargetInfo& STI) override; }; -} // namespace emproof +} // namespace nyxstone diff --git a/src/ObjectWriterWrapper.cpp b/src/ObjectWriterWrapper.cpp index 3a155fd..223cfed 100644 --- a/src/ObjectWriterWrapper.cpp +++ b/src/ObjectWriterWrapper.cpp @@ -31,7 +31,7 @@ using namespace llvm; -namespace emproof { +namespace nyxstone { /// Performs a value alignment to a specific value. /// /// @param[in] value - Value to align. @@ -293,4 +293,4 @@ std::unique_ptr ObjectWriterWrapper::createObjectWriterWrapper( return std::make_unique( std::move(object_writer), stream, context, write_text_section_only, extended_error, instructions); } -} // namespace emproof +} // namespace nyxstone diff --git a/src/ObjectWriterWrapper.h b/src/ObjectWriterWrapper.h index 218f782..104eade 100644 --- a/src/ObjectWriterWrapper.h +++ b/src/ObjectWriterWrapper.h @@ -20,7 +20,7 @@ #include #pragma GCC diagnostic pop -namespace emproof { +namespace nyxstone { /// This class derives from LLVM's MCObjectWriter, which enables us to include /// user-define symbols/labels into the internal address resolution process /// (via 'executePostLayoutBinding()'). @@ -96,4 +96,4 @@ class ObjectWriterWrapper : public llvm::MCObjectWriter { /// @brief Write object to the stream and update the bytes of the instruction details. uint64_t writeObject(llvm::MCAssembler& Asm, const llvm::MCAsmLayout& Layout) override; }; -} // namespace emproof +} // namespace nyxstone diff --git a/src/nyxstone.cpp b/src/nyxstone.cpp index ffc54ad..e18ecb6 100644 --- a/src/nyxstone.cpp +++ b/src/nyxstone.cpp @@ -24,7 +24,7 @@ using namespace llvm; -namespace emproof { +namespace nyxstone { NyxstoneBuilder& NyxstoneBuilder::with_triple(std::string&& triple) noexcept { m_triple = std::move(triple); @@ -473,4 +473,4 @@ bool is_ArmT16_or_ArmT32(const llvm::Triple& triple) || triple.getSubArch() == Triple::SubArchType::ARMSubArch_v8m_mainline || triple.getSubArch() == Triple::SubArchType::ARMSubArch_v8_1m_mainline); } -} // namespace emproof +} // namespace nyxstone From 09a9b9d43e0d2d8c94734d2e4ded87e1a4b71937 Mon Sep 17 00:00:00 2001 From: stuxnot <41650734+Stuxnot@users.noreply.github.com> Date: Fri, 27 Oct 2023 15:58:37 +0200 Subject: [PATCH 8/8] Use namespace in pybindings --- bindings/python/pynyxstone.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bindings/python/pynyxstone.cpp b/bindings/python/pynyxstone.cpp index 351f660..7dce1c3 100644 --- a/bindings/python/pynyxstone.cpp +++ b/bindings/python/pynyxstone.cpp @@ -9,6 +9,8 @@ namespace py = pybind11; +using namespace nyxstone; + std::vector convert_labels(std::unordered_map&& labels) { std::vector vlabels {};