我读了Here。
据我了解,R_386_32
用于静态数据,R_386_PC32
用于功能。对吧?
但是我仍然对R_386_32
类型符号的用法感到困惑。
请参见以下示例。
示例1
readelf -a --wide /usr/lib/i386-linux-gnu/crt1.o | grep R_386_32
0000000c 00000901 R_386_32 00000000 __libc_csu_fini
00000011 00000b01 R_386_32 00000000 __libc_csu_init
00000018 00000c01 R_386_32 00000000 main
示例2
readelf -a --wide /usr/local/lib/gcc/i686-pc-linux-gnu/5.5.0/crtbegin.o
00000001 00001501 R_386_32 00000000 __TMC_END__
00000010 00001601 R_386_32 00000000 _ITM_deregisterTMCloneTable
00000031 00001501 R_386_32 00000000 __TMC_END__
00000049 00001701 R_386_32 00000000 _ITM_registerTMCloneTable
000000a1 00001901 R_386_32 00000000 _Jv_RegisterClasses
问题
R_386_32
类型的数据会自动添加到 Application _Jv_RegisterClasses
吗?R_386_32
类型?R_386_PC32
,因为它不是静态数据,而是函数。 答案 0 :(得分:3)
您正在查看的是重定位,不是符号。重定位只是汇编器要引用其值未知的符号时生成的内容。这是指示链接器在链接时填写正确的值。重定位不是符号类型;可以通过任意数量的任意类型的重定位来引用每个符号。还要注意,符号表根本不知道符号所指的是什么类型的基准。符号只是地址和名称。
重定位类型R_386_32
的意思是“在此处将符号的值粘贴为32位。”无法说出所使用的符号是用于数据还是文本。例如,如果您加载符号的地址或执行绝对存储器访问,则使用此方法。这两条指令都生成R_386_32
重定位:
mov $foo, %eax # move value of symbol to register
mov foo, %eax # perform absolute memory access
另一方面,重定位类型R_386_PC32
从符号中减去指令指针的值( p rogram c unter)并将其粘贴。此重定位类型主要用于直接跳转和调用指令:
jmp foo # jump to foo
call foo # call foo
通常,无法通过查看重定位来猜测符号定义在哪个节中。实际上,重定位根本不提供任何有关此的信息,并且目标文件不能要求外部符号引用数据或文本。对于已定义的符号,您可以通过运行nm
实用程序来找出它们所在的部分。标记为t
或T
的符号是文本,d
或D
是数据,r
或R
是只读数据,{{ 1}}或b
是BSS。
第二个问题:是的,可以。使用这样的C代码来打印B
的值。请注意,符号的值是它所引用的变量的地址。
_Jv_RegisterClasses