直接执行数据
Direct execution of the data
让程序执行数据的最佳方法是什么。比如说,我为x86_64机器编写了(所谓的)编译器:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cstdint>
struct compiler
{
void op() const { return; }
template< typename ...ARGS >
void op(std::uint8_t const _opcode, ARGS && ..._tail)
{
code_.push_back(_opcode);
return op(std::forward< ARGS >(_tail)...);
}
void clear() { code_.clear(); }
long double operator () () const
{
// ?
}
private :
std::vector< std::uint8_t > code_;
};
int main()
{
compiler compiler_; // long double (*)();
compiler_.op(0xD9, 0xEE); // FLDZ
compiler_.op(0xC3); // ret
std::cout << compiler_() << std::endl;
return EXIT_SUCCESS;
}
但是我不知道如何正确地实现operator ()
。我怀疑,我必须将code_
的所有内容放入连续的内存块中,然后强制转换为long double (*)();
并调用它。但也有一些困难:
- 我应该在Windows上使用
VirtualProtect(Ex)
(+FlushInstructionCache
)吗?Linux上也有类似的东西吗 - 什么是容器,它以正确的方式(即一个接一个)将字节可靠地放置在内存中?并且还允许获取指向内存块的指针
首先,您需要将代码分配为可执行代码[在Windows中使用带有"可执行"标志的VirtualAlloc,并使用"MAP_executable"作为标志之一的mmap]。分配这种内存的大区域,然后为内容设置"分配功能",可能会容易得多。您可以在Linux中使用virtualprotect和任何相应的函数,但我认为首先将其分配为可执行文件是一个更好的选择。我认为你不需要刷新指令缓存——内存已经被分配为可执行的——当然至少在x86上不是这样——而且由于你的指令是x86指令,我想这是一个合理的限制。
其次,您需要制作一个类似于指向代码的函数指针的东西。像这样的东西应该可以做到:
typedef void (*funcptr)(void);
funcptr f = reinterpret_cast<funcptr>(&code_[0]);
应该做到这一点。
相关文章:
- 防止主数据类型C++的隐式转换
- 用于访问容器<T>数据成员的正确 API
- 嵌套在类中时无法设置成员数据
- 使用流处理接收到的数据
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 在cuda线程之间共享大量常量数据
- C++将文本文件中的数据读取到结构数组中
- 如何在C++中序列化结构数据
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 在c代码之间共享数据的最佳方式
- 链表,反向函数,数据结构
- 数据成员SFINAE的C++17测试:gcc vs clang
- C++浮点数据类型和字符串数据类型无法子到模板函数中
- 如何对点云数据进行排序
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- Cuda C++:设备上的Malloc类,并用来自主机的数据填充它
- 在运行时处理类型擦除的数据-如何不重新发明轮子