задачка на смекалку (о выолнении syscalls на разных платформах)

Взгляд изнутри

Модератор: Модераторы разделов

Аватара пользователя
Stauffenberg
Сообщения: 2041
Статус: ☮ PEACE ☮
ОС: открытая и свободная

задачка на смекалку

Сообщение Stauffenberg »

Всем привет!

Вот такая головоломка. Хотя для кого-то головоломка, а для кого-то уже семечки.
На x86 машинах вторым системным вызовом идет fork(), а на x86_64 - sys_open(). Однако этот код запускает fork() на обеих платформах:

Код: Выделить всё

 #include <stdio.h>
 #include <unistd.h>

 int main ()
 {
     printf("--------------------\n");
     __asm__("movl $2, %eax; int $0x80");
     printf("[i am %d]\n", getpid());
 }


Однако... если мы посмотрим вывод strace, то увидим, что на x86_64 действительно запускается open(), а на x86 fork():

x86_64:

Код: Выделить всё

> 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)                          = ?


x86:

Код: Выделить всё

> 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)

Вопрос: почему strace показывает не то, что выполняется на самом деле? :tongue:
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2041
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: задачка на смекалку

Сообщение Stauffenberg »

Не интересно? Никто не знает? Или все знают, но нет желания еще раз это обсуждать? ;p

Подсказка для тех, кто не знает: на x86_64 были добавленны инструкции для syscall, т.е. теперь это работает не только через 80 прерывание.
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Аватара пользователя
moonglow
Сообщения: 90
ОС: CentOS

Re: задачка на смекалку

Сообщение moonglow »

Интересно :-)
Если Вы перенесли его на x86_64 в двоичном виде, то я думаю, что загрузчик запустил его в окружении совместимости, и ядро использовало номера syscalls x86
Когда Вы пересобрали код на обоих системах, то я думаю, что ошибки в выводе strace нет.
Таковы мои догадки на оба вопроса.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: задачка на смекалку

Сообщение NickLion »

Stauffenberg писал(а):
05.12.2012 20:53
Подсказка для тех, кто не знает: на x86_64 были добавленны инструкции для syscall, т.е. теперь это работает не только через 80 прерывание.

Ну да, номера для int $0x80 и syscall не совпадают. Но вот почему strace показывает неверно (заданный вопрос) — не понятно.
Спасибо сказали: