我正在寻找一种方便的方法(用于构建测试脚本)来查询目标文件中的各个符号.是否有一个工具可以回答问题(最好是通过退出状态)"文件Y中是否存在符号X?" 或者我只需要解析输出nm(1),例如grep和适当的正则表达式?如果这样的工具可以提供关于符号(大小,类型,值,......)的详细信息,那就更好了.
我反汇编了编译非常简单的源文件test.c的代码,它看起来像这样:
void main() {}
Run Code Online (Sandbox Code Playgroud)
这就是我得到的:
gcc -c test.c
ld -o test -Ttext 0x0 -e main test.o
objcopy -R .note -R .comment -S -O binary test test.bin
ndisasm -b 32 test.bin
Run Code Online (Sandbox Code Playgroud)
前四行的所有目的是什么?为什么它会添加到eax指向的内存位置,2*eax,edx + 0x52,比较等等?这是关于检查程序是否正确执行或其他什么?
我正在尝试在C++文件中计算静态初始值设定项.
我已经拥有的解决方案(曾经使用过gcc-4.4)正在查看.ctors ELF部分的大小.
在升级到gcc-4.6之后,这似乎不再返回有效结果(计算出的静态初始化器的数量为0,这与现实不匹配,例如由nm返回).
现在的问题是,即使没有符号,我也希望解决方案能够工作(否则我会使用nm).
下面是示例可执行文件的readelf -SW的输出:
从偏移量0x4f39820开始有35个节标题:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 00000174 000174 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 00000188 000188 000020 00 A 0 0 4
[ 3] .note.gnu.build-id NOTE 000001a8 0001a8 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 000001cc 0001cc 000918 04 A 5 0 4
[ …Run Code Online (Sandbox Code Playgroud) 在的outupt readelf -S,我想知道是什么的列标题ES,Lk,Inf和Al的意思.
例如:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 00000d 00 AX 0 0 4
[ 2] .rel.text REL 00000000 000394 000008 08 10 1 4
[ 3] .data PROGBITS 00000000 000044 000000 00 WA 0 0 4
[...]
Run Code Online (Sandbox Code Playgroud) 我正在寻找手动生成ELF核心转储文件.
我的程序有一个RAM转储,也可以检索寄存器信息等等.
有了这些数据,我想构建一个ELF核心转储文件,类似于Linux内核在程序崩溃时生成的文件,目标是使用专门为我的平台制作的GDB来分析这个核心转储.
我一直在寻找核心转储规格或详细格式,但没找到我想要的东西:
这必须最好用C语言完成,我想我可以使用libelf库来帮助我构建文件,但是我没有找到关于该文件放什么的相关信息,以及格式,所以任何线索,链接或建议很受欢迎.
注意:这不是关于提高异常并且为我完成内核的工作,我可以这样做,但我真的需要自己收集RAM并手动将数据注册到elf核心转储中.
谢谢 !
这主要是出于好奇.我理解库函数的定义可以替换(?)如果我LD_PRELOAD我自己的库与我自己的库函数定义.我可以对可执行文件的主要方法执行相同的操作吗?
也就是说,如果不重建可执行文件,我可以对运行时执行某些操作,以便调用不同的main()吗?
我正在编写一些C代码,以挂接加载到内存中的.so ELF(共享库)的某些功能。
我的C代码应该能够重定向另一个已加载到应用程序/程序的内存中的.so库的导出函数。
这里有一些阐述:

Android应用将加载多个.so文件。我的C代码必须浏览属于另一个共享.so库(在本例中称为target.so)的导出功能
这不是常规的dlsym方法,因为我不仅想要函数的地址,而且想用自己的功能替换它;这样做的方式是:当另一个库调用其自己的函数时,将改为调用我的hook_func,然后从我的hook_func中调用原始函数。
对于导入功能,这可以工作。但是对于导出功能,我不确定该怎么做。导入函数的符号表中的条目在重定位表中具有相应的条目,这些条目最终给出了全局偏移表(GOT)中的条目地址。但是对于导出函数,符号的st_value元素本身具有过程的地址,而不具有GOT地址(如果我错了,请纠正我)。
如何执行导出功能的挂钩?
从理论上讲,我应该获取导出功能st_value的动态符号表项(Elf32_Sym)元素的存储位置。如果得到该位置,则应该可以用我的hook_func的地址替换该位置中的值。但是,到目前为止,我无法写入该位置。我必须假设动态符号表的内存是只读的。如果是这样,那该怎么办?
非常感谢您的阅读和帮助。
更新: LD_PRELOAD只能用我自己的函数替换原始函数,但是然后我不确定是否有任何方法可以调用原始函数。以我为例:
应用程序通过调用来初始化音频引擎Audio_System_Create,并将AUDIO_SYSTEM对象的引用传递给Audio_System_Create(AUDIO_SYSTEM **);
AUDIO API,以分配此struct / object和函数返回。现在,只要我可以访问该AUDIO_SYSTEM对象,就可以轻松地向该对象附加一个回调并开始接收音频数据。因此,我的最终目标是获得对AUIOD_SYSTEM对象的引用。根据我的理解,只有在我第一次通过分配该对象的地方拦截该调用时,我才能得到该信息Audio_System_Create(AUIOD_SYSTEM **)。当前没有直接的方法来在android上获取输出音频。(所有示例都谈到仅录制来自麦克风的音频)
Update2: 正如Basile在他的回答中所建议的那样,我使用了dladdr(),但奇怪的是它给了我与传递给它相同的地址。
void *pFunc=procedure_addr; //procedure address calculated from the st_value of symbol from symbol table in ELF file (not from loaded file)
int nRet;
// Lookup the name of the function given the function pointer
if ((nRet = dladdr(pFunc, &DlInfo)) != 0)
{
LOGE("Symbol …Run Code Online (Sandbox Code Playgroud) 为了构建ELF 32位二进制文件,我可以设置任何组合GOARCH和GOOS值吗?
交流程序中变量的外部声明在ELF中的大小为0。为什么已知的实际大小没有存储在ELF中?对于不完整的数组,我知道没有大小信息,但是对于其他情况,应该可以存储大小。
我尝试了一些简单的代码,并验证了发出的ELF大小为零。
// file1.c
extern int var;
int main()
{
var = 2;
}
Run Code Online (Sandbox Code Playgroud)
// file 2.c
long long int var = 8;
Run Code Online (Sandbox Code Playgroud)
gcc -c file1.c
readelf -s file1.o
...
9: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND var
...
Run Code Online (Sandbox Code Playgroud)
gcc -c file2.c
readelf -s file2.o
...
7: 0000000000000000 8 OBJECT GLOBAL DEFAULT 2 var
...
Run Code Online (Sandbox Code Playgroud)
如果在file1.o中将var的大小存储为4,则链接器实际上可以在与file2.o链接时检测到由于大小引起的潜在不匹配。
那么,为什么不发送大小,因为它可以帮助捕获一些细微的问题呢?