ld -R behaviour

Kristis Makris kristis.makris@asu.edu
Wed Oct 1 22:13:00 GMT 2003


Hello, 

I have a question about use of the -R argument on GNU ld. First let me
explain what I am trying to accomplish. 

I am trying to compile a module for the linux kernel that includes calls
to symbols that are not exported by the kernel. In particular, here is
the output of nm on my object file: 

$ nm dynreplace_file.o 
00000040 ? __module_description 
00000000 ? __module_kernel_version 
0000001d ? __module_license 
00000000 t gcc2_compiled. 
00000000 t get_pid_v3 
0000016c T get_pid_v3_endlabel 
         U init_task_union 
         U last_pid 
00000000 d next_safe.993 
         U printk 
$ ls -l dynreplace_file.o 
-rw-r--r--    1 mkgnu    mkgnu        2083 Sep 29 18:40
dynreplace_file.o 

There exist 3 undefined symbols in this object file, one of which
(last_pid) is not exported by the kernel. This has the effect of insmod
refusing to load the object file: 

$ insmod dynreplace_file.o 
dynreplace_file.o: unresolved symbol last_pid 

However, I want to bypass this restriction that exists in the linker
inside the kernel, and hopefully load an object file that does include
references to symbols that have not been exported by the kernel, since
the absolute address of all symbols are known if one regenerated the
System.map for the kernel without stripping some symbols (which is what
the kernel Makefile does). 


$ nm  vmlinux |grep -i last_pid 
c02684a8 B last_pid 

After reading the ld manual, it looks like one should be able to use the
linker to resolve the undefined symbols by providing the absolute memory
addresses of the undefined symbols. 

The description of the -R argument reads: 

-R filename 
--just-symbols=filename 
Read symbol names and their addresses from filename, but do not relocate
it or include it in the output. This allows your output file to refer
symbolically to absolute locations of memory defined in other programs.
You may use this option more than once. For compatibility with other ELF
linkers, if the -R option is followed by a directory name, rather than a
file name, it is treated as the -rpath option. 


I have tried the following, but can't seem to be able to generate a .o
file that includes absolute memory addresses: 

$ ld dynreplace_file.o -R
../../../../kernel/kernel-source-2.4.20.mod/vmlinux -o
dynreplace_file_final.o 
ld: warning: cannot find entry symbol _start; defaulting to 08048080 
dynreplace_file.o: In function `get_pid_v3': 
dynreplace_file.o(.text+0x14): undefined reference to `printk' 
dynreplace_file.o(.text+0x32): undefined reference to `last_pid' 
dynreplace_file.o(.text+0x3a): undefined reference to `last_pid' 
dynreplace_file.o(.text+0x47): undefined reference to `last_pid' 
dynreplace_file.o(.text+0x68): undefined reference to `init_task_union' 
dynreplace_file.o(.text+0x71): undefined reference to `init_task_union' 
dynreplace_file.o(.text+0x84): undefined reference to `last_pid' 
dynreplace_file.o(.text+0xa5): undefined reference to `last_pid' 
dynreplace_file.o(.text+0xae): undefined reference to `last_pid' 
dynreplace_file.o(.text+0xc5): undefined reference to `last_pid' 
dynreplace_file.o(.text+0xd9): undefined reference to `last_pid' 
dynreplace_file.o(.text+0xff): more undefined references to `last_pid'
follow 
dynreplace_file.o: In function `get_pid_v3': 
dynreplace_file.o(.text+0x14d): undefined reference to `init_task_union'
dynreplace_file.o(.text+0x158): undefined reference to `last_pid' 


The following works though: 

$ ld dynreplace_file.o -R
../../../../kernel/kernel-source-2.4.20.mod/vmlinux -o
dynreplace_file_final.o -r 
$  ls -l dynreplace_file_final.o 
-rw-r--r--    1 mkgnu    mkgnu      194942 Sep 29 21:47
dynreplace_file_final.o 

With the exception that the final .o file generated is huge. It is 194K
versus 2K that the original was. The size of the actual code in it makes
sense: 

$ size *.o 
   text    data     bss     dec     hex filename 
    608       4       0     612     264 dynreplace_file.o 
    608       4       0     612     264 dynreplace_file_final.o 
    608       4       0     612     264 dynreplace_get_pid_v3.o 
     24       0       0      24      18 test.o 

But is there a way to "merge in" only the undefined symbols I am
missing, instead of merging in the final .o the entire list of symbols?
I got the impression from the description of the "-R" argument that the
result of using this argument would be that the output file would refer
to absolute locations of memory for the symbols it found more
information about, rather than include ALL symbols in the final .o file.
Is this the correct way to use the -R argument ? Was this the intented
use of this argument ? 

I was able to script my way around extracting with nm only the symbols I
wanted from the original .o file and stripping out all the extra ones
by  running strip --keep-symbol for each symbol I wanted to keep, but
this does not seem to be intuitive, given the original decsription of
"-R" in the manual. It does not just "read symbol names". it reads them
and includes them in the final .o file.

Thanks, 
Kristis 




More information about the Gcc-help mailing list