Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.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
是否可以重写对象模块(gcc、ld、x86、objcopy)中的静态函数?_C_Gcc_Ld_Objcopy_Interposing - Fatal编程技术网

是否可以重写对象模块(gcc、ld、x86、objcopy)中的静态函数?

是否可以重写对象模块(gcc、ld、x86、objcopy)中的静态函数?,c,gcc,ld,objcopy,interposing,C,Gcc,Ld,Objcopy,Interposing,有没有办法用静态作用域重写函数 在对象模块内 如果我从这样的东西开始,一个模块 带有全局符号的“foo”是一个调用 本地符号“bar”,称为本地符号“baz” 现在,酒吧和巴兹是全球性的符号,可以从 在模块外部。到目前为止还不错 但是如果我想在上面插入我自己的函数呢 “baz”的,有“bar”称我的插入的“baz”吗 有办法吗 --包裹选项似乎不起作用 [scameron@localhost ~]$ cat ibaz.c #include <stdio.h> extern void

有没有办法用静态作用域重写函数 在对象模块内

如果我从这样的东西开始,一个模块 带有全局符号的“foo”是一个调用 本地符号“bar”,称为本地符号“baz”

现在,酒吧和巴兹是全球性的符号,可以从 在模块外部。到目前为止还不错

但是如果我想在上面插入我自己的函数呢 “baz”的,有“bar”称我的插入的“baz”吗

有办法吗

--包裹选项似乎不起作用

[scameron@localhost ~]$ cat ibaz.c
#include <stdio.h>
extern void foo();
extern void bar();

void __wrap_baz()
{
    printf("wrapped baz\n");
}
int main(int argc, char *argv[])
{
    foo();
    baz();
}

[scameron@localhost ~]$ gcc -o ibaz ibaz.c foo2.o -Xlinker --wrap -Xlinker baz
[scameron@localhost ~]$ ./ibaz
foo
bar
baz
wrapped baz
[scameron@localhost ~]$
[scameron@localhost~]$cat ibaz.c
#包括
外部无效foo();
外部空心条();
void uuu wrap_ubaz()
{
printf(“包装的baz\n”);
}
int main(int argc,char*argv[])
{
foo();
baz();
}
[scameron@localhost~]$gcc-o ibaz ibaz.c foo2.o-Xlinker--wrap-Xlinker baz
[scameron@localhost~]$/ibaz
福
酒吧
巴兹
包巴兹
[scameron@localhost ~]$
从main()调用的baz被包装,但是 bar仍然称本地baz为非包装baz

有没有办法让酒吧称之为包裹的巴兹

即使它需要修改目标代码来修补函数调用的地址,如果可以以自动化的方式完成,这可能已经足够好了,但在这种情况下,它至少需要在i386和x86_64上工作


--steve

由于
static
向C编译器承诺函数或变量是文件的本地变量,因此编译器可以自由删除该代码,如果没有它也可以得到相同的结果

这可能是内联函数调用。这可能意味着用常量替换变量。如果代码位于始终为false的
If
语句中,则该函数甚至可能不存在于编译结果中

所有这些都意味着您无法可靠地将调用重定向到该函数


如果使用新的
-lto
选项进行编译,情况会更糟,因为编译器可以自由地重新排序、删除或内联整个项目中的所有代码。

我收到了伊恩·兰斯·泰勒(Ian Lance Taylor,gold的作者,ld的替代链接器):

有没有办法用静态作用域重写函数 在对象模块内?(我使用x86_64和i386 linux)

不,没有。特别是,编译器可以内联调用static 函数,它还可以重写函数以使用不同的 调用约定(GCC执行这两种优化)。确实如此 没有可靠的方法在代码被删除后重写静态功能 编译

我认为,内联可以通过-fno内联来处理,但是更改调用约定可能太多了

话虽如此,迪纳莫里奥的人声称能够做到这一点,但我还没有证实:

如果您可以修改机器代码,那么修改源代码应该没有问题


编写脚本以机械地从真实源生成单元测试源。Perl在这方面做得很好。

我还没有使用弱符号,但它们听起来像是削弱了原始模块的baz,可以让您用新模块替换它。我想,如果他尝试做这些事情,他就无法访问源代码,我可以访问源代码,但我不希望以通常的单元测试方式修改源代码。实际上,这是为了测试linux内核模块。在上游,他们通常不喜欢你仅仅为了适应非内核的东西而在源代码中进行更改,并且为了补丁兼容性,我不想不必要地干扰源代码。弱化不起作用:[scameron@localhost~]$objcopy——弱化符号=baz foo2.o foo3.o[scameron@localhost ~]$gcc-o ibaz ibaz.c foo3.o-Xlinker--wrap-Xlinker baz[scameron@localhost~]$/ibaz foo bar baz包装baz[scameron@localhost~]$(Ugh.Stackoverflow注释格式糟糕透了。)这看起来很有趣:我通过使用-fno-inline编译来绕过内联。没有我感兴趣的函数会被编译器完全删除(否则我自己就已经删除了)。可能有一些我无法处理的特殊情况,但这没关系。我对典型案例更感兴趣。我并不反对在调用站点机械地修改机器代码来达到这个目的,只是需要弄清楚怎么做。当然,内联也只能通过重新编译代码来处理。
[scameron@localhost ~]$ cat barbaz
bar
baz
[scameron@localhost ~]$ objcopy --globalize-symbols=barbaz foo.o foo2.o
[scameron@localhost ~]$ objdump -x foo2.o | egrep 'foo|bar|baz'
foo2.o:     file format elf32-i386
foo2.o
00000000 l    df *ABS*  00000000 foo.c
00000000 g     F .text  00000014 baz
00000014 g     F .text  00000019 bar
0000002d g     F .text  00000019 foo
[scameron@localhost ~]$ 
[scameron@localhost ~]$ cat ibaz.c
#include <stdio.h>
extern void foo();
extern void bar();

void __wrap_baz()
{
    printf("wrapped baz\n");
}
int main(int argc, char *argv[])
{
    foo();
    baz();
}

[scameron@localhost ~]$ gcc -o ibaz ibaz.c foo2.o -Xlinker --wrap -Xlinker baz
[scameron@localhost ~]$ ./ibaz
foo
bar
baz
wrapped baz
[scameron@localhost ~]$