问题
I have two assembly codes, code1.s
and code2.s
and I want to build a relocatable (using -fPIC switch) shared library from these two.
I want code2.s
call a function, named myfun1
, which is defined in code1.s
.
When I use call myfun1@PLT
in code2.s
it finds the function and it works like a charm but it uses PLT section to call this function which is in the same shared library. I want to do this without adhering to PLT section. When I remove @PLT
I get the relocation R_X86_64_PC32 against symbol
error for myfun1
.
How can I do this without using PLT section? Is there any way at all? I think it should be feasible as the shared library should be relocatable but not necessary each of its object files, therefore why calling a function inside the same library should goes through the PLT section.
Here is my compile commands:
For codeX.s:
gcc -c codeX.s -fPIC -DPIC -o codeX.o
or
gcc -c codeX.s -o codeX.o
and for sharelibrary named libcodes.so:
gcc -shared -fPIC -DPIC -o libcodes.so code1.o code2.o
Just as you may be curious why I am doing so, I have many object files and each of them wants to call myfun1
. Here I just made it simpler to ask the technical part. Even I tries to put myfun1
in all codeX.s
files but I get the error that myfun1
is defined multiple times. I don't that much care about space and if I get to put myfun1
in all files.
回答1:
From within one source file you can just use two labels (Building .so with recursive function in it), one with .globl
and the other not. But that's not sufficient across source files within the shared library.
Still useful in combination with the below answer for functions that are also exported: one .hidden and one not, so you can efficiently call within the library.
Use .globl
and .hidden to create a symbol that can be seen outside the current object file, but not outside the shared library. Thus it's not subject to symbol-interposition, and calls from other files in the same shared library can call it directly, not through the PLT or GOT.
Tested and working example:
## foo.S
.globl myfunc
.hidden myfunc
myfunc:
#.globl myfunc_external # optional, a non-hidden symbol at the same addr
#myfunc_external:
ret
## bar.S
.globl bar
bar:
call myfunc
ret
Build with gcc -shared foo.S bar.S -o foo.so
, and objdump -drwC -Mintel foo.so
:
Disassembly of section .text:
000000000000024d <myfunc>:
24d: c3 ret
000000000000024e <bar>:
24e: e8 fa ff ff ff call 24d <myfunc> # a direct near call
253: c3 ret
(I actually built with -nostdlib
as well to keep the disassembly output clean for example purposes by omitting the other functions like __do_global_dtors_aux
and register_tm_clones
, and the .init
section.)
I think Glibc uses strong or weak_alias
for this (what does the weak_alias function do and where is it defined), so calls from within the shared library can use the normal name. Where are syscalls located in glibc source, e.g. __chdir
and chdir
.
e.g. glibc's printf.c defines __printf
and makes printf
a strong alias for it.
io/chdir.c defines __chdir
and makes chdir
a weak alias for it.
One of the x86-64 memchr asm implementations also uses a strong_alias
macro (at the bottom of the file).
The relevant GAS directives are:
- .weak names
- .weakref foo, foo_internal
There's no strong alias GAS directive. That may be equivalent to simply foo = foo_internal
or an equivalent .set foo, foo_internal
.
(TODO: complete example and more details of what strong/weak do exactly. I don't currently know, so edits welcome if I don't get around to reading the docs myself. I know this stuff exists and solves this problem, but I don't know exactly how.)
回答2:
Well, I was not able to find any way to do so but as I edited my question I do not care to put myfun1
in all object files.
The problem I had was that linker outputted error that I have defined myfun1
in multiple places and that was all because I had globl
directive for myfun1
which when I removed that line it get fixed.
Thanks Ross Ridge for pushing me again to try that.
来源:https://stackoverflow.com/questions/51573771/call-a-function-in-another-object-file-without-using-plt-within-a-shared-library