Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C JITs基础_C_Assembly_Compilation_Jit - Fatal编程技术网

C JITs基础

C JITs基础,c,assembly,compilation,jit,C,Assembly,Compilation,Jit,我在某种程度上理解了如何将“inta=b+abs(c)”转换成简单的组装指令,然后再转换成一些二进制blob。但是,如何在内存中动态地运行并与之交互呢 --编辑-- 我知道C没有评估功能。但它的编译目的是什么。我的意思是,这就是使类似Java的JIT成为可能的原因,就这一点而言,代码注入恶意软件是不可能的?例如,abs()函数只是一个指针,可以按照cdecl协议调用它。新函数应该能够通过传递cdecl函数指针来公开。我不明白的是如何在运行时注入新代码 我问这个更多的是出于长期的学术好奇心,然后是

我在某种程度上理解了如何将“inta=b+abs(c)”转换成简单的组装指令,然后再转换成一些二进制blob。但是,如何在内存中动态地运行并与之交互呢

--编辑--

我知道C没有评估功能。但它的编译目的是什么。我的意思是,这就是使类似Java的JIT成为可能的原因,就这一点而言,代码注入恶意软件是不可能的?例如,abs()函数只是一个指针,可以按照cdecl协议调用它。新函数应该能够通过传递cdecl函数指针来公开。我不明白的是如何在运行时注入新代码

我问这个更多的是出于长期的学术好奇心,然后是为了最有效地解决实际问题

--范例--

假设我有一段嵌入式python代码,它经常从本机程序调用,也调用本机绑定notify():

要做到这一点,函数可能应该包含更多的代码(而且更有用),但请耐心听我说。探查器(或来自c绑定的提示)还识别出所有调用都带有整数,包括所有参数和返回值。 这符合:

int add(int a, int b) {
    notify();
    return a + b;
}
可以编译成x86 cdecl,类似于:

:_add
push ebp ;setting up scope
mov ebp, esp
call _notify ;or more likely by a pointer reference
mov eax, [ebp + 8]
mov edx, [ebp + 12]
add eax, edx
pop ebp
ret
然后最后组装成一个二进制字符串。当然,要达到这一目标,必须为每个平台实现一个基本的编译器。但撇开这个问题不谈,假设我现在有一个指向这个有效的二进制x86代码的char指针。是否有可能以任何方式从中提取可用于本机程序的cdecl函数指针

很抱歉,我的问题的意图不明确

C缺少任何类型的“eval”功能,这既是一个限制,也是使其高效的因素之一。如果您只需要使用一小部分内置数学函数(如
abs()
)对数学表达式求值,而不是任意的C代码,那么编写这样的表达式求值器相当容易

这里有一个链接指向一个类似主题的过去SO线程: C缺少任何类型的“eval”功能,这既是一个限制,也是使其高效的因素之一。如果您只需要使用一小部分内置数学函数(如
abs()
)对数学表达式求值,而不是任意的C代码,那么编写这样的表达式求值器相当容易

这里有一个链接指向一个类似主题的过去SO线程:

假设您已经在内存块中编译了代码,并且您拥有该块的地址,则可以将其强制转换为函数指针:

typedef int (*func)(int, int);
...
char * compiledCode = ...;
func f = (func) compiledCode;
然后可以调用该函数:

int x = f(2, 3);

假设您已经在内存块中编译了代码,并且您拥有该块的地址,则可以将其强制转换为函数指针:

typedef int (*func)(int, int);
...
char * compiledCode = ...;
func f = (func) compiledCode;
然后可以调用该函数:

int x = f(2, 3);

程序必须位于允许执行的内存区域中

在linux上,您可以执行以下操作:

void *address;
functype proc;
int prot, flags;

prot = PROT_READ|PROT_WRITE|PROT_EXEC;
flags = MAP_PRIVATE|MAP_ANONYMOUS;
address = mmap(NULL, length, prot, flags, -1, 0);
if (address == NULL) error;

memcpy(address, program, length);
link(address, program_info);

proc = (functype)address;

程序必须位于允许执行的内存区域中

在linux上,您可以执行以下操作:

void *address;
functype proc;
int prot, flags;

prot = PROT_READ|PROT_WRITE|PROT_EXEC;
flags = MAP_PRIVATE|MAP_ANONYMOUS;
address = mmap(NULL, length, prot, flags, -1, 0);
if (address == NULL) error;

memcpy(address, program, length);
link(address, program_info);

proc = (functype)address;

C通常是作为编译语言实现的——您似乎在问如何解释C语句。通常情况下,它们是不可能的。C通常是作为编译语言实现的——您似乎在询问如何解释C语句。通常情况下,它们是不可能的。对于性能要求适中的数学表达式,您完全正确。更新了原始问题并进行了澄清。您的问题仍然不清楚。是否只想添加可以调用的新函数,但仍然只支持表达式求值?或者您想要完整的C语言(循环构造等)?如果是后者,唯一的可移植解决方案是编写一个完整的C解释器或编译器,生成在虚拟机上运行的代码(您也需要实现)。如果您不寻求可移植性,并且您的平台具有共享库/动态加载,那么您可以运行C编译器和链接器来构建一个新库,然后加载它…因此,基本上运行新机器编译代码的唯一方法,是创建一个共享库并加载它吗?对于性能要求适中的数学表达式,您完全正确。更新了原始问题并进行了澄清。您的问题仍然不清楚。是否只想添加可以调用的新函数,但仍然只支持表达式求值?或者您想要完整的C语言(循环构造等)?如果是后者,唯一的可移植解决方案是编写一个完整的C解释器或编译器,生成在虚拟机上运行的代码(您也需要实现)。如果您不寻求可移植性,并且您的平台具有共享库/动态加载,那么您可以运行C编译器和链接器来构建一个新库,然后加载它……因此,基本上运行新的机器编译代码的唯一方法是创建一个共享库并加载它?