前言
ubuntu24.04 环境下使用gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0 版本测试;
一、代码样例
test.c
int main(int argc, char** argv)
{
printf("hello\r\n");
printf("argc:%d\r\n",argc);
for(int i=0;i<argc;i++)
printf("%s ",argv[i]);
printf("\r\n");
return 0;
}
编译 gcc test.c -o test;
argc :表示程序运行时的命令行参数的个数,程序本身的执行也是一个参数,如./test 或 /绝对路径/test , argc的值为1;
argv: 是个二级指针,这里可以理解成一个指针数组,存储指针的数组,这里的指针为字符串指针,每个命令行参数会被解析成一个字符串,字符串的头指针存储在argv中;
argc和argv的配合使用可以明确获取程序执行时的命令行参数情况,如
root@vmmachine:~/testprogram# ./test hekko geggeg hegegeg vgvegeg
hello
argc:5
./test hekko geggeg hegegeg vgvegeg
main函数的写法不只一种,也可能是void main() 、int main() 、int main(int argc)等,对于main是按可变参数处理的,最好按以上最全的方式定义;
二、系统调用执行过程
strace ./test ,显示如下
execve("./test", ["./test"], 0x7fffcf855940 /* 26 vars */) = 0
brk(NULL) = 0x5c495de9c000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f08f47f9000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=69903, ...}) = 0
mmap(NULL, 69903, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f08f47e7000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\243\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
fstat(3, {st_mode=S_IFREG|0755, st_size=2125328, ...}) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2170256, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f08f4400000
mmap(0x7f08f4428000, 1605632, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7f08f4428000
mmap(0x7f08f45b0000, 323584, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b0000) = 0x7f08f45b0000
mmap(0x7f08f45ff000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1fe000) = 0x7f08f45ff000
mmap(0x7f08f4605000, 52624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f08f4605000
close(3) = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f08f47e4000
arch_prctl(ARCH_SET_FS, 0x7f08f47e4740) = 0
set_tid_address(0x7f08f47e4a10) = 9257
set_robust_list(0x7f08f47e4a20, 24) = 0
rseq(0x7f08f47e5060, 0x20, 0, 0x53053053) = 0
mprotect(0x7f08f45ff000, 16384, PROT_READ) = 0
mprotect(0x5c495cc57000, 4096, PROT_READ) = 0
mprotect(0x7f08f4831000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7f08f47e7000, 69903) = 0
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x2), ...}) = 0
getrandom("\x23\xb6\x29\xf8\xfa\x90\x52\x4e", 8, GRND_NONBLOCK) = 8
brk(NULL) = 0x5c495de9c000
brk(0x5c495debd000) = 0x5c495debd000
write(1, "hello\r\n", 7hello
) = 7
write(1, "argc:1\r\n", 8argc:1
) = 8
write(1, "./test \r\n", 9./test
) = 9
exit_group(0) = ?
+++ exited with 0 +++
三、断点调试
gcc test.c -g -o test
如下调试
root@vmmachine:~/testprogram# gdb test
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(gdb) b _start
Breakpoint 1 at 0x1080
(gdb) b main
Breakpoint 2 at 0x117c: file testmain.c, line 5.
(gdb) r
Starting program: /root/testprogram/test
This GDB supports auto-downloading debuginfo from the following URLs:
<https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) y
Debuginfod has been enabled.
To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.
Breakpoint 1.2, 0x00007ffff7fe4540 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) c
Continuing.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1.1, 0x0000555555555080 in _start ()
(gdb) c
Continuing.
Breakpoint 2, main (argc=1, argv=0x7fffffffe2c8) at testmain.c:5
5 printf("hello\r\n");
(gdb) c
Continuing.
hello
argc:1
/root/testprogram/test
[Inferior 1 (process 9293) exited normally]
(gdb)
以上可知main执行前会执行C库函数构造环境,随后执行main;