Всем привет На 32bit машинах вторым системным вызовом идет fork(), а на 64bit - sys_open(). Однако этот код запускает fork() на обеих платформах: Код (Text): #include <stdio.h> #include <unistd.h> int main () { printf("--------------------\n"); __asm__("movl $2, %eax; int $0x80"); printf("[i am %d]\n", getpid()); } Однако... если мы посмотрим вывод strace, то увидим, что на 64bit действительно запускается open(), а на 32bit fork() Debian, x86_64: Код (Text): > gcc asm.c -o asm && ./asm -------------------- [i am 4628] [i am 4629] > strace ./asm execve("./asm", ["./asm"], [/* 41 vars */]) = 0 brk(0) = 0x823000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5bbfa2000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=111792, ...}) = 0 mmap(NULL, 111792, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fa5bbf86000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\355\1\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1432968, ...}) = 0 mmap(NULL, 3541032, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fa5bba26000 mprotect(0x7fa5bbb7e000, 2093056, PROT_NONE) = 0 mmap(0x7fa5bbd7d000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x157000) = 0x7fa5bbd7d000 mmap(0x7fa5bbd82000, 18472, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fa5bbd82000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5bbf85000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5bbf84000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5bbf83000 arch_prctl(ARCH_SET_FS, 0x7fa5bbf84700) = 0 mprotect(0x7fa5bbd7d000, 16384, PROT_READ) = 0 mprotect(0x7fa5bbfa4000, 4096, PROT_READ) = 0 munmap(0x7fa5bbf86000, 111792) = 0 fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 5), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5bbfa1000 write(1, "--------------------\n", 21-------------------- ) = 21 open(0xffffffff, O_RDONLY|O_SYNC|O_NOFOLLOW|O_CLOEXEC|0xbbf00000) = 4635 getpid() = 4634 [i am 4635] write(1, "[i am 4634]\n", 12) = ? ERESTARTSYS (To be restarted) --- SIGCHLD (Child exited) @ 0 (0) --- write(1, "[i am 4634]\n", 12[i am 4634] ) = 12 exit_group(12) = ? CentOS, x86: Код (Text): > gcc asm.c -o asm && ./asm -------------------- [i am 5163] [i am 5162] > strace ./asm execve("./asm", ["./asm"], [/* 22 vars */]) = 0 brk(0) = 0x9a32000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=40948, ...}) = 0 mmap2(NULL, 40948, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7ef8000 close(3) = 0 open("/lib/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\340_\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1686224, ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ef7000 mmap2(NULL, 1410500, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x110000 mmap2(0x263000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x152) = 0x263000 mmap2(0x266000, 9668, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x266000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ef6000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb7ef66c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0x263000, 8192, PROT_READ) = 0 mprotect(0x79e000, 4096, PROT_READ) = 0 munmap(0xb7ef8000, 40948) = 0 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f01000 write(1, "--------------------\n", 21-------------------- ) = 21 fork() = 5192 [i am 5192] getpid() = 5191 write(1, "[i am 5191]\n", 12[i am 5191] ) = 12 exit_group(12) У меня в openSUSE (x86_64), в файле /usr/src/linux/include/asm-x86/unistd_64.h, стоит второй вызов - sys_open(), так почему же все-таки запускается fork()? Есть у кого какие соображения на данный счет?
strace наверное, как и ты, не в курсе, что на amd64 сисколл надо вызывать инструкцией syscall. strace ведь просто ловит факт сисколла и определяет что именно вызывается по номеру сисколла. И если strace, как и ты, выясняет название сисколла по файлу unistd_64.h, то вот она и получает то же самое, что и ты. Делай то же самое, но вместо "int $0x80" пиши "syscall". На amd64, насколько я понимаю, int $0x80 для 32-х битных процессов. AFAIK если собрать ядро без поддержки 32-х битных процессов, то int $0x80 вообще перестанет работать.
Большое спасибо за ответ! Хоть замена "int $0x80" на "syscall" ничего не изменила, все же формулировка, а главное - манера ответа, улыбнули
На debian выполни `uname -a'. И ещё `file my-file' Вместо my-file подставь имя файла, который себя так странно ведёт. Или не `file my-fie', а `ldd my-file'. У меня syscall при двойке вызывает именно open.
Тоже интересна эта тема. Замена на syscall исправляет ситуацию и вызывается open. Но теперь встает другой вопрос - получается strace можно обмануть и вызывать 32 битный номер сискола, когда он думает что это 64битный (и внутри детектирует как 64 битный ABI). Соответственно как можно определить что это был вызов по int 80, а не syscall, чтобы поправить strace? UPD: оказывается в strace есть код, чтобы это предотвратить, но он почемуто отключен. Делается путем анализа инструкции. На это надо 2 сискола peekuser+peektext. Остается вопрос, можно ли обойтись одним peekuser?