Load the Shared Library (SO) to the specified memory address in linux

Source: Internet
Author: User
In linux, load the Shared Library (SO) to the specified memory address-Linux general technology-Linux programming and kernel information. The following is a detailed description. A friend recently encountered a tricky problem. He hoped to load the Shared Library (SO) to the specified memory address, probably to speed up application startup through prelink. He asked me if I could do anything. I know that it works in Windows. For example, you can set the/base value in VC6, so I believe it is feasible in linux.

You can set the compilation options for VC. I guess gcc should also be available. Gcc itself is only a shell, and the link work is completed by ld. Of course, you should read the ld command line option document. Soon we found that ld has a-image-base option, which allows you to set the loading address of the dynamic library.

This parameter is passed to ld through Xlinker, but ld cannot recognize this option:
Gcc-g-shared test. c-Xlinker -- image-base-Xlinker 0x00c00000-o libtest. so
/Usr/bin/ld: unrecognized option '-- image-base'
/Usr/bin/ld: use the -- help option for usage information
Collect2: ld returned 1 exit statu
S
Take a closer look at the manual. In the past, this option only applies to PE files. PE files are dedicated in Windows and cannot be used in linux. It seems that you have to find another method.

I know that ld script can control the behavior of ld, So I studied the writing of ld script. According to the instructions in the manual, I wrote a simple ld script:
SECTIONS
{
. = 0x00c00000;
. Text: {* (. text )}
. Data: {* (. data )}
. Bss: {* (. bss )}
}


Compile as follows:
Gcc-shared-g-Xlinker -- script-Xlinker ld. s test. c-o libtest. so
Gcc-g main. c-L./-ltest-o test.exe

Use ldd to check whether the load address is correct.
[Root @ localhost lds] # ldd test.exe
Linux-gate.so.1 => (0x00aff000)
Libtest. so =>./libtest. so (0x00c00000)
Libc. so.6 =>/lib/libc. so.6 (0x007fa000)
/Lib/ld-linux.so.2 (0x007dd000)

However, crash:
[Root @ localhost lds] #./test.exe
Segmentation fault

Debugging and running can be found:
(Gdb) r
Starting program:/work/test/lds/test.exe
Reading symbols from shared object read from target memory... done.
Loaded system susupplied DSO at 0x452000

Program received signal SIGSEGV, Segmentation fault.
0x007e7a10 in _ dl_relocate_object () from/lib/ld-linux.so.2
(Gdb) bt
#0 0x007e7a10 in _ dl_relocate_object () from/lib/ld-linux.so.2
#1 0x007e0833 in dl_main () from/lib/ld-linux.so.2
#2 0x007f056b in _ dl_sysdep_start () from/lib/ld-linux.so.2
#3 0x007df48f in _ dl_start () from/lib/ld-linux.so.2
#4 0x007dd847 in _ start () from/lib/ld-linux.so.2

The conjecture may be that ld. s is not fully written, resulting in incorrect information. So use ld? Verbose exports a default ld script. As expected, the default ld script is very lengthy. The following is the first section:
/* Script for-z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT ("elf32-i386", "elf32-i386 ",
Elf32-i386 ")
OUTPUT_ARCH (i386)
ENTRY (_ start)
SEARCH_DIR ("/usr/i386-redhat-linux/lib"); SEARCH_DIR ("/usr/local/lib"); SEARCH_DIR ("/lib "); SEARCH_DIR ("/usr/lib ");
SECTIONS
{
/* Read-only sections, merged into text segment :*/
PROVIDE (_ executable_start = 0x08048000);. = 0x08048000 + SIZEOF_HEADERS;
. Interp: {* (. interp )}
. Hash: {* (. hash )}
. Dynsym: {* (. dynsym )}
. Dynstr: {* (. dynstr )}
. Gnu. version: {* (. gnu. version )}
. Gnu. version_d: {* (. gnu. version_d )}
. Gnu. version_r: {* (. gnu. version_r )}



According to the ld script syntax, I changed it to (the red part is the new row ):
/* Script for-z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT ("elf32-i386", "elf32-i386 ",
Elf32-i386 ")
OUTPUT_ARCH (i386)
ENTRY (_ start)
SEARCH_DIR ("/usr/i386-redhat-linux/lib"); SEARCH_DIR ("/usr/local/lib"); SEARCH_DIR ("/lib "); SEARCH_DIR ("/usr/lib ");
SECTIONS
{
/* Read-only sections, merged into text segment :*/
PROVIDE (_ executable_start = 0x08048000);. = 0x08048000 + SIZEOF_HEADERS;
. = 0x00c00000;
. Interp: {* (. interp )}
. Hash: {* (. hash )}
. Dynsym: {* (. dynsym )}
. Dynstr: {* (. dynstr )}
. Gnu. version: {* (. gnu. version )}
. Gnu. version_d: {* (. gnu. version_d )}
. Gnu. version_r: {* (. gnu. version_r )}



Use this ld script to test again. Everything works. It is also normal to verify the situation of multiple shared libraries. The following is the test data:

Test. c
Int test (intn)
{
Returnn;
}

Test1.c
Inttest1 (intn)
{
Returnn;
}

Main. c
Externinttest (intn );
Externinttest1 (intn );
# Include

Intmain (intargc, char * argv [])
{
Printf ("Hello: % d \ n", test (100), test1 (200 ));

Getchar ();
Return 0;
}

Makefile
All:
Gcc-shared-g-Xlinker -- script-Xlinker ld. s test. c-o libtest. so
Gcc-shared-g-Xlinker -- script-Xlinker ld1.s test1.c-o libtest1.so
Gcc-g main. c-L./-ltest-ltest1-o test.exe

Clean:
Rm-f *. so *. exe


Libtest. so: 0x00c00000
Libtest1.so is loaded at 0x00d00000.

Ldd display result:
Linux-gate.so.1 => (0x00aa3000)
Libtest. so =>./libtest. so (0x00c00000)
Libtest1.so =>./libtest1.so (0x00d00000)
Libc. so.6 =>/lib/libc. so.6 (0x007fa000)
/Lib/ld-linux.so.2 (0x007dd000)

The content of maps is:
007dd000-007f6000 r-xp 00000000 0:01 521466/lib/ld-2.4.so
007f6000-007f7000 r-xp 00018000 0:01 521466/lib/ld-2.4.so
007f7000-007f8000 rwxp 00019000 0:01 521466/lib/ld-2.4.so
007fa000-00926000 r-xp 00000000 0:01 523579/lib/libc-2.4.so
00926000-00929000 r-xp 0012b000 0:01 523579/lib/libc-2.4.so
00929000-0092a000 rwxp 0012e000 0:01 523579/lib/libc-2.4.so
0092a000-0092d000 rwxp 0092a000 00:00 0
00c00000-00c01000 r-xp 00001000 16370/work/test/ldsex/libtest. so
00c01000-00c02000 rwxp 00001000 16370/work/test/ldsex/libtest. so
00cf1000-00cf2000 r-xp 00cf1000 00:00 0 [vdso]
00d00000-00d01000 r-xp 00001000 16373/work/test/ldsex/libtest1.so
00d01000-00d02000 rwxp 00001000 16373/work/test/ldsex/libtest1.so
08048000-08049000 r-xp 00000000 16374/work/test/ldsex/test.exe
08049000-0804a000 rw-p 00000000 16374/work/test/ldsex/test.exe
B7fdf000-b7fe0000 rw-p b7fdf000 0
B7fed000-b7ff0000 rw-p b7fed000 0
Bf8db000-bf8f0000 rw-p bf8db000 0 [stack]

The above test results show that this method is feasible.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.