英文:
why isn't shared library fini function called when preloaded to dash?
问题
我使用的是最新的Ubuntu Linux。
这是一个包含在加载和卸载时调用的函数的共享库:
shared.c
:
#include <fcntl.h>
#include <sys/stat.h>
void init() {
open("init", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
}
void fini() {
open("fini", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
}
它与以下命令编译:
gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini shared.c -o shared.so
然后我执行以下步骤:
$ rm init fini
$ LD_PRELOAD=$PWD/shared.so dash /dev/null
$ echo $?
0
$ ls init
init
$ ls fini
ls: 无法访问'fini': 没有那个文件或目录
所以... 加载函数被调用,但卸载函数没有被调用。
如果我将dash
替换为bash
,两者都被调用。
使用__attribute__((destructor))
没有任何区别。
为什么对于dash
卸载函数没有被调用?
根据Marco Bonelli的请求添加:
$ file $(which dash)
/usr/bin/dash: ELF 64-bit LSB pie 可执行文件, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f7ab02fc1b8ff61b41647c1e16ec9d95ba5de9f0, for GNU/Linux 3.2.0, stripped
$ ldd $(which dash)
linux-vdso.so.1 (0x00007ffd931c0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6b19e84000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6b1a0ec000)
英文:
I am on the latest Ubuntu Linux.
Here is a shared library with functions that are called when loading and unloading:
shared.c
:
#include <fcntl.h>
#include <sys/stat.h>
void init() {
open("init", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
}
void fini() {
open("fini", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
}
and this is compiled with
gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini shared.c -o shared.so
and then I do this:
$ rm init fini
$ LD_PRELOAD=$PWD/shared.so dash /dev/null
$ echo $?
0
$ ls init
init
$ ls fini
ls: cannot access 'fini': No such file or directory
So... loading function is called, but unloading function is not
If I replace dash
with bash
, both are called.
Using __attribute__((destructor))
does not make a difference.
Why isn't the unloading function called for dash
?
Added per Marco Bonelli's request:
$ file $(which dash)
/usr/bin/dash: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f7ab02fc1b8ff61b41647c1e16ec9d95ba5de9f0, for GNU/Linux 3.2.0, stripped
$ ldd $(which dash)
linux-vdso.so.1 (0x00007ffd931c0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6b19e84000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6b1a0ec000)
答案1
得分: 2
因为dash在这里调用_exit
,它调用exit_group系统调用,这里立即终止程序。
让我们也做一个小例子:
# Makefile
all:
gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini -Wl,-soname,shared.so shared.c -o shared.so
gcc main.c -o main.out
LD_PRELOAD=$(PWD)/shared.so ./main.out /dev/null
# main.c
#include <unistd.h>
int main() {
_exit(0);
}
# shared.c
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
void out(const char *str) {
int fd = open("/dev/tty", O_WRONLY);
write(fd, str, strlen(str));
close(fd);
}
void init() {
out("\nstart\n\n");
}
void fini() {
out("\nstop\n\n");
}
执行时不会输出"stop":
$ make
gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini -Wl,-soname,shared.so shared.c -o shared.so
gcc main.c -o main.out
LD_PRELOAD=..../shared.so ./main.out /dev/null
start
英文:
> why isn't shared library fini function called when preloaded to dash?
Because dash calls _exit
here which calls exit_group syscall here which terminates the program immediately.
Let's also do a small example:
# Makefile
all:
gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini -Wl,-soname,shared.so shared.c -o shared.so
gcc main.c -o main.out
LD_PRELOAD=$(PWD)/shared.so ./main.out /dev/null
# main.c
#include <unistd.h>
int main() {
_exit(0);
}
# shared.c
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
void out(const char *str) {
int fd = open("/dev/tty", O_WRONLY);
write(fd, str, strlen(str));
close(fd);
}
void init() {
out("\nstart\n\n");
}
void fini() {
out("\nstop\n\n");
}
On execution does not output stop:
$ make
gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini -Wl,-soname,shared.so shared.c -o shared.so
gcc main.c -o main.out
LD_PRELOAD=..../shared.so ./main.out /dev/null
start
答案2
得分: 1
问题不在于“redirection”和“touch”之间的区别,因为在您的“dash/touch”运行中,已加载了shared.so两次,一次用于dash,一次用于touch。
“fini”仅在“touch”中触发。
您可以通过以下两次运行来看到差异:
$ LD_PRELOAD=$PWD/shared.so dash /dev/null
# fini未被调用
$ LD_PRELOAD=$PWD/shared.so touch /dev/null
# fini被调用
因此,这与“dash”有关。
希望这为您的调查提供了更多材料。
英文:
I should have put this as a comment, but I put it as an answer for formatting purposes.
The problem is not about the difference between redirection
and touch
, because in your dash/touch run, shared.so has been loaded twice, once for dash, once for touch.
fini
fired only with touch
.
You can see the diffrence with these two runs :
$ LD_PRELOAD=$PWD/shared.so dash /dev/null
# fini is not called
$ LD_PRELOAD=$PWD/shared.so touch /dev/null
# fini is called
So this has something to do with dash
.
Hope this provide more materials for your investigation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论