有的系统调用会返回复杂的C类型的数据结构,下面就介绍如何在汇编里使用这种类型的系统调用...
NAME sysinfo - returns information on overall system statistics SYNOPSIS #include <sys/sysinfo.h> int sysinfo(struct sysinfo *info); .......................................... .......................................... |
struct sysinfo { long uptime; /* Seconds since boot */ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ unsigned long totalram; /* Total usable main memory size */ unsigned long freeram; /* Available memory size */ unsigned long sharedram; /* Amount of shared memory */ unsigned long bufferram; /* Memory used by buffers */ unsigned long totalswap; /* Total swap space size */ unsigned long freeswap; /* swap space still available */ unsigned short procs; /* Number of current processes */ unsigned long totalhigh; /* Total high memory size */ unsigned long freehigh; /* Available high memory size */ unsigned int mem_unit; /* Memory unit size in bytes */ char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding for libc5 */ }; |
.section .data result: uptime: .int 0 load1: .int 0 load5: .int 0 load15: .int 0 totalram: .int 0 freeram: .int 0 sharedram: .int 0 bufferram: .int 0 totalswap: .int 0 freeswap: .int 0 procs: .byte 0x00, 0x00 totalhigh: .int 0 freehigh: .int 0 memunit: .int 0 |
# sysinfo.s - Retrieving system information via kernel system calls .section .data result: uptime: .int 0 load1: .int 0 load5: .int 0 load15: .int 0 totalram: .int 0 freeram: .int 0 sharedram: .int 0 bufferram: .int 0 totalswap: .int 0 freeswap: .int 0 procs: .byte 0x00, 0x00 totalhigh: .int 0 freehigh: .int 0 memunit: .int 0 .section .text .globl _start _start: nop movl $result, %ebx movl $116, %eax int $0x80 movl $0, %ebx movl $1, %eax int $0x80 |
$ as -gstabs -o sysinfo.o sysinfo.s $ ld -o sysinfo sysinfo.o $ gdb -q sysinfo Reading symbols from /home/zengl/Downloads/asm_example/syscall/sysinfo...done. (gdb) b *_start Breakpoint 1 at 0x8048074: file sysinfo.s, line 35. (gdb) r Starting program: /home/zengl/Downloads/asm_example/syscall/sysinfo Breakpoint 1, _start () at sysinfo.s:35 35 nop (gdb) s 36 movl $result, %ebx (gdb) s 37 movl $116, %eax (gdb) s 38 int $0x80 (gdb) s 39 movl $0, %ebx (gdb) x/d &uptime 0x8049090 <uptime>: 2453 (gdb) x/d &load1 0x8049094 <load1>: 6432 (gdb) x/d &load5 0x8049098 <load5>: 4544 (gdb) x/d &load15 0x804909c <load15>: 3904 (gdb) x/d &totalram 0x80490a0 <totalram>: 519663616 (gdb) x/d &freeram 0x80490a4 <freeram>: 8466432 (gdb) x/d &sharedram 0x80490a8 <sharedram>: 0 (gdb) x/d &bufferram 0x80490ac <bufferram>: 40206336 (gdb) x/d &totalswap 0x80490b0 <totalswap>: 534769664 (gdb) x/d &freeswap 0x80490b4 <freeswap>: 531910656 (gdb) x/d &procs 0x80490b8 <procs>: 304 (gdb) x/d &totalhigh 0x80490ba <totalhigh>: 0 (gdb) x/d &freehigh 0x80490be <freehigh>: 0 (gdb) x/d &memunit 0x80490c2 <memunit>: 65536 (gdb) |
$ strace ./syscalltest2 execve("./syscalltest2", ["./syscalltest2"], [/* 52 vars */]) = 0 getpid() = 3134 getuid() = 1000 getgid() = 1000 _exit(0) = ? $ |
$ strace -c ./syscalltest2 % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- -nan 0.000000 0 1 execve -nan 0.000000 0 1 getpid -nan 0.000000 0 1 getuid -nan 0.000000 0 1 getgid ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000000 4 total $ |
|
-e trace=call_list |
$ strace -e trace=getpid,getgid ./syscalltest2 getpid() = 2680 getgid() = 1000 $ |
$ strace -o mytrace id uid=1000(zengl) gid=1000(zengl) 组=1000(zengl),4(adm),24(cdrom),27(sudo),29(audio),30(dip),46(plugdev),109(lpadmin),123(sambashare) $ cat mytrace execve("/usr/bin/id", ["id"], [/* 52 vars */]) = 0 brk(0) = 0x9dce000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76e9000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=87327, ...}) = 0 mmap2(NULL, 87327, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb76d3000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i386-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@A\0\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0644, st_size=120748, ...}) = 0 mmap2(NULL, 125852, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb76b4000 mmap2(0xb76d1000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c) = 0xb76d1000 close(3) = 0 .......................................... .......................................... $ |
$ strace -c id uid=1000(zengl) gid=1000(zengl) 组=1000(zengl),4(adm),24(cdrom),27(sudo),29(audio),30(dip),46(plugdev),109(lpadmin),123(sambashare) % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 38.71 0.000036 2 17 read 37.63 0.000035 9 4 4 connect 23.66 0.000022 1 32 2 open 0.00 0.000000 0 1 write 0.00 0.000000 0 36 close 0.00 0.000000 0 1 execve 0.00 0.000000 0 9 9 access 0.00 0.000000 0 3 brk 0.00 0.000000 0 19 munmap 0.00 0.000000 0 9 mprotect 0.00 0.000000 0 22 _llseek 0.00 0.000000 0 42 mmap2 0.00 0.000000 0 29 fstat64 0.00 0.000000 0 1 getuid32 0.00 0.000000 0 1 getgid32 0.00 0.000000 0 1 geteuid32 0.00 0.000000 0 1 getegid32 0.00 0.000000 0 2 getgroups32 0.00 0.000000 0 1 set_thread_area 0.00 0.000000 0 1 statfs64 0.00 0.000000 0 4 socket ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000093 236 15 total $ |
$ strace -e trace=open,connect id open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/proc/filesystems", O_RDONLY|O_LARGEFILE) = 3 open("/proc/filesystems", O_RDONLY|O_LARGEFILE) = 3 open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3 open("/usr/share/locale/zh_CN/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale/zh/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale-langpack/zh_CN/LC_MESSAGES/coreutils.mo", O_RDONLY) = 3 open("/usr/lib/i386-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3 connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libnss_compat.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libnsl.so.1", O_RDONLY|O_CLOEXEC) = 3 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libnss_nis.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/proc/sys/kernel/ngroups_max", O_RDONLY) = 3 open("/proc/sys/kernel/ngroups_max", O_RDONLY) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 uid=1000(zengl) gid=1000(zengl) 组=1000(zengl),4(adm),24(cdrom),27(sudo),29(audio),30(dip),46(plugdev),109(lpadmin),123(sambashare) $ |
# nanotest.s - Another example of using system calls .section .data timespec: .int 5, 0 output: .ascii "This is a test\n" output_end: .equ len, output_end - output .section .bss .lcomm rem, 8 .section .text .globl _start _start: nop movl $10, %ecx loop1: pushl %ecx movl $4, %eax movl $1, %ebx movl $output, %ecx movl $len, %edx int $0x80 movl $162, %eax movl $timespec, %ebx movl $rem, %ecx int $0x80 popl %ecx loop loop1 movl $1, %eax movl $0, %ebx int $0x80 |
NAME nanosleep - high-resolution sleep SYNOPSIS #include |
struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; |
#include <errno.h> #include <time.h> int better_sleep (double sleep_time) { struct timespec tv; /* Construct the timespec from the number of whole seconds... */ tv.tv_sec = (time_t) sleep_time; /* ... and the remainder in nanoseconds. */ tv.tv_nsec = (long) ((sleep_time - tv.tv_sec) * 1e+9); while (1) { /* Sleep for the time specified in tv. If interrupted by a signal, place the remaining time left to sleep back into tv. */ int rval = nanosleep (&tv, &tv); if (rval == 0) /* Completed the entire sleep time; all done. */ return 0; else if (errno == EINTR) /* Interrupted by a signal. Try again. */ continue; else /* Some other error; bail out. */ return rval; } return 0; } |
timespec: .int 5, 0 .................... .................... .section .bss .lcomm rem, 8 |
$ as -gstabs -o nanotest.o nanotest.s $ ld -o nanotest nanotest.o $ ./nanotest This is a test This is a test |
$ su - 密码: root# ps aux | grep nanotest zengl 2885 1.4 5.9 223420 30276 ? Sl 14:48 0:04 gedit /home/zengl/Downloads/asm_example/syscall/nanotest.s zengl 3080 0.0 0.0 148 4 pts/0 S+ 14:53 0:00 ./nanotest root 3082 0.0 0.1 6084 832 pts/1 S+ 14:53 0:00 grep --color=auto nanotest root# strace -p 3080 Process 3080 attached - interrupt to quit restart_syscall(<... resuming interrupted call ...>) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 _exit(0) = ? Process 3080 detached root# |
root# ./nanotest & [1] 3217 This is a test root# strace -p 321This is a test 7 Process 3217 attached - interrupt to quit restart_syscall(<... resuming interrupted call ...>) = 0 write(1, "This is a test\n", 15This is a test ) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15This is a test ) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15This is a test ) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15This is a test ................................... ................................... |
EXIT(3) Linux Programmer's Manual EXIT(3) NAME exit - cause normal process termination SYNOPSIS #include <stdlib.h> void exit(int status); DESCRIPTION The exit() function causes normal process termination and the value of status & 0377 is returned to the parent (see wait(2)). All functions registered with atexit(3) and on_exit(3) are called, in the reverse order of their registration. (It is possible for one of these functions to use atexit(3) or on_exit(3) to register an addi‐ tional function to be executed during exit processing; the new regis‐ tration is added to the front of the list of functions that remain to be called.) If one of these functions does not return (e.g., it calls _exit(2), or kills itself with a signal), then none of the remaining functions is called, and further exit processing (in particular, flush‐ ing of stdio(3) streams) is abandoned. If a function has been regis‐ tered multiple times using atexit(3) or on_exit(3), then it is called as many times as it was registered. All open stdio(3) streams are flushed and closed. Files created by tmpfile(3) are removed. The C standard specifies two constants, EXIT_SUCCESS and EXIT_FAILURE, that may be passed to exit() to indicate successful or unsuccessful termination, respectively. RETURN VALUE The exit() function does not return. ..................................................... ..................................................... |
printf(“The answer is %d\n”, k); |
pushl k pushl $output call printf addl $8, %esp |
# cfunctest.s - An example of using C functions .section .data output: .asciz "This is a test\n" .section .text .globl _start _start: movl $10, %ecx loop1: pushl %ecx pushl $output call printf addl $4, %esp pushl $5 call sleep addl $4, %esp popl %ecx loop loop1 pushl $0 call exit |
$ as -gstabs -o cfunctest.o cfunctest.s $ ld -dynamic-linker /lib/ld-linux.so.2 -lc -o cfunctest cfunctest.o $ |
$ strace ./cfunctest execve("./cfunctest", ["./cfunctest"], [/* 52 vars */]) = 0 brk(0) = 0x95fe000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d8000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=87327, ...}) = 0 mmap2(NULL, 87327, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77c2000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000\226\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1734120, ...}) = 0 mmap2(NULL, 1743580, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7618000 mmap2(0xb77bc000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a4) = 0xb77bc000 mmap2(0xb77bf000, 10972, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb77bf000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7617000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb7617900, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0xb77bc000, 8192, PROT_READ) = 0 mprotect(0xb77fb000, 4096, PROT_READ) = 0 munmap(0xb77c2000, 87327) = 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) = 0xb77d7000 write(1, "This is a test\n", 15This is a test ) = 15 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 nanosleep({5, 0}, 0xbfd65780) = 0 ........................................... ........................................... |
$ strace -rc ./cfunctest This is a test .......................................... .......................................... This is a test % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 63.16 0.000036 4 10 write 36.84 0.000021 11 2 mprotect 0.00 0.000000 0 1 read 0.00 0.000000 0 2 open 0.00 0.000000 0 2 close 0.00 0.000000 0 1 execve 0.00 0.000000 0 3 3 access 0.00 0.000000 0 1 brk 0.00 0.000000 0 1 munmap 0.00 0.000000 0 10 nanosleep 0.00 0.000000 0 10 rt_sigaction 0.00 0.000000 0 20 rt_sigprocmask 0.00 0.000000 0 7 mmap2 0.00 0.000000 0 3 fstat64 0.00 0.000000 0 1 set_thread_area ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000057 74 3 total $ |