如何确定函数是否属于 kernel/user 模式?
How to find out if a function is part of the kernel/user mode?
如何检查函数是内核还是用户的一部分 space? (或者两者都可以)是否有所有内核的概述libs/functions?
在 Unix 环境中使用 C。
例如rand()
是纯用户 space, malloc()
是用户和内核 space 等..
手册页不包含任何信息。
在整个 运行 时间里,一个进程计算很多系统调用,甚至在它实际 运行 之前就开始了。
您有一些调试选项:
- 使用调试信息编译您自己的
glibc
strace
gdb
第三个选项可能是最好的,特别是如果您只对一个函数而不是一组函数感兴趣(strace
会更好)。实际上,gdb
允许您捕获附加进程或某些特定进程发出的系统调用;你可以通过 catch syscall
number 或 catch syscall
来获取它们。
您可能还想通过使用 -static
.
编译代码来避免动态链接器在 运行 时进行的调用
This 文章应该给你一些关于系统调用的信息(进入内核 space)。现在您可以使用这个粗略的(不是很准确的)指南:
第 2 部分中的所有手册页都是系统调用。
如果手册页来自第 3 节,请查看底部的“另请参阅”部分,看看它是否使用了第 2 节中的任何命令。(可能还需要通读手册页本身.)
再说一次,这不是很准确,但没有阅读源代码,它应该会给你一个想法。
取决于你调用的"kernel mode"函数。如果我理解你是对的,你的意思是一些 C 函数要求做一些事情,比如 malloc()
调用 brk()
这样内核会增加进程堆大小。
所以你需要做的就是检测哪些函数向内核请求某些东西,通常通过调用 系统调用 来完成,例如 brk()
.
现在是时候确定哪些函数调用哪些系统调用了。有两种方法可以做到这一点:
- 静态代码分析。只需构建 glibc 的调用图,然后绘制 root 是系统调用的图。唯一的问题是 glibc 的复杂性,因此很难构建整个调用图。
- 动态代码分析。将 debugger/tracer 附加到您的进程,当进程调用系统调用时,打印其堆栈。这种方法并没有涵盖所有的功能和案例,但是很容易实现。
即使用 gdb:
myaut@panther:~> gdb /bin/cat
...
(gdb) b brk
Function "brk" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
(gdb) commands 1
> bt
> cont
> end
(gdb) r
Starting program: /bin/cat
...
Breakpoint 1, __brk (addr=0x62d000) at ../sysdeps/unix/sysv/linux/x86_64/brk.c:28
28 in ../sysdeps/unix/sysv/linux/x86_64/brk.c
#0 __brk (addr=0x62d000) at ../sysdeps/unix/sysv/linux/x86_64/brk.c:28
#1 0x00007ffff7b0eea5 in __GI___sbrk (increment=135168) at sbrk.c:53
#2 0x00007ffff7aaeda9 in __GI___default_morecore (increment=<optimized out>) at morecore.c:48
#3 0x00007ffff7aaaa37 in sysmalloc (av=0x7ffff7dd5640 <main_arena>, nb=32) at malloc.c:2454
#4 _int_malloc (av=0x7ffff7dd5640 <main_arena>, bytes=5) at malloc.c:3718
#5 0x00007ffff7aac263 in __GI___libc_malloc (bytes=5) at malloc.c:2859
...
#10 0x0000000000401d8a in main (argc=1, argv=0x7fffffffdd08) at cat.c:563
或一些动态跟踪引擎,例如 SystemTap (Linux):
# stap -e '
probe syscall.brk {
if(pid() == target())
print_ubacktrace();
} ' -c /bin/cat -d /lib/x86_64-linux-gnu/libc.so.6
...
0x7f5edb427ffa : brk+0xa/0x70 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb4280ad : sbrk+0x4d/0xb0 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb3d0ae9 : __default_morecore+0x9/0xb0 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb3cd1e6 : malloc_trim+0x15e6/0x23c0 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb3cec00 : malloc+0x70/0x340 [/lib/x86_64-linux-gnu/libc-2.13.so]
...
0x401bea [/bin/cat+0x1bea/0xc000]
或 DTrace:
root@sol11:~# dtrace -n '
syscall::brk:entry
/pid == $target/ {
ustack()
}' -c '/bin/cat'
CPU ID FUNCTION:NAME
0 58 brk:entry
libc.so.1`_brk_unlocked+0x15
libc.so.1`sbrk+0x38
...
libc.so.1`malloc+0x38
libc.so.1`strdup+0x29
libc.so.1`expand_locale_name+0x333
libc.so.1`setlocale+0x89c
cat`main+0x23
cat`_start+0x7d
如何检查函数是内核还是用户的一部分 space? (或者两者都可以)是否有所有内核的概述libs/functions?
在 Unix 环境中使用 C。
例如rand()
是纯用户 space, malloc()
是用户和内核 space 等..
手册页不包含任何信息。
在整个 运行 时间里,一个进程计算很多系统调用,甚至在它实际 运行 之前就开始了。
您有一些调试选项:
- 使用调试信息编译您自己的
glibc
strace
gdb
第三个选项可能是最好的,特别是如果您只对一个函数而不是一组函数感兴趣(strace
会更好)。实际上,gdb
允许您捕获附加进程或某些特定进程发出的系统调用;你可以通过 catch syscall
number 或 catch syscall
来获取它们。
您可能还想通过使用 -static
.
This 文章应该给你一些关于系统调用的信息(进入内核 space)。现在您可以使用这个粗略的(不是很准确的)指南:
第 2 部分中的所有手册页都是系统调用。
如果手册页来自第 3 节,请查看底部的“另请参阅”部分,看看它是否使用了第 2 节中的任何命令。(可能还需要通读手册页本身.)
再说一次,这不是很准确,但没有阅读源代码,它应该会给你一个想法。
取决于你调用的"kernel mode"函数。如果我理解你是对的,你的意思是一些 C 函数要求做一些事情,比如 malloc()
调用 brk()
这样内核会增加进程堆大小。
所以你需要做的就是检测哪些函数向内核请求某些东西,通常通过调用 系统调用 来完成,例如 brk()
.
现在是时候确定哪些函数调用哪些系统调用了。有两种方法可以做到这一点:
- 静态代码分析。只需构建 glibc 的调用图,然后绘制 root 是系统调用的图。唯一的问题是 glibc 的复杂性,因此很难构建整个调用图。
- 动态代码分析。将 debugger/tracer 附加到您的进程,当进程调用系统调用时,打印其堆栈。这种方法并没有涵盖所有的功能和案例,但是很容易实现。
即使用 gdb:
myaut@panther:~> gdb /bin/cat
...
(gdb) b brk
Function "brk" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
(gdb) commands 1
> bt
> cont
> end
(gdb) r
Starting program: /bin/cat
...
Breakpoint 1, __brk (addr=0x62d000) at ../sysdeps/unix/sysv/linux/x86_64/brk.c:28
28 in ../sysdeps/unix/sysv/linux/x86_64/brk.c
#0 __brk (addr=0x62d000) at ../sysdeps/unix/sysv/linux/x86_64/brk.c:28
#1 0x00007ffff7b0eea5 in __GI___sbrk (increment=135168) at sbrk.c:53
#2 0x00007ffff7aaeda9 in __GI___default_morecore (increment=<optimized out>) at morecore.c:48
#3 0x00007ffff7aaaa37 in sysmalloc (av=0x7ffff7dd5640 <main_arena>, nb=32) at malloc.c:2454
#4 _int_malloc (av=0x7ffff7dd5640 <main_arena>, bytes=5) at malloc.c:3718
#5 0x00007ffff7aac263 in __GI___libc_malloc (bytes=5) at malloc.c:2859
...
#10 0x0000000000401d8a in main (argc=1, argv=0x7fffffffdd08) at cat.c:563
或一些动态跟踪引擎,例如 SystemTap (Linux):
# stap -e '
probe syscall.brk {
if(pid() == target())
print_ubacktrace();
} ' -c /bin/cat -d /lib/x86_64-linux-gnu/libc.so.6
...
0x7f5edb427ffa : brk+0xa/0x70 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb4280ad : sbrk+0x4d/0xb0 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb3d0ae9 : __default_morecore+0x9/0xb0 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb3cd1e6 : malloc_trim+0x15e6/0x23c0 [/lib/x86_64-linux-gnu/libc-2.13.so]
0x7f5edb3cec00 : malloc+0x70/0x340 [/lib/x86_64-linux-gnu/libc-2.13.so]
...
0x401bea [/bin/cat+0x1bea/0xc000]
或 DTrace:
root@sol11:~# dtrace -n '
syscall::brk:entry
/pid == $target/ {
ustack()
}' -c '/bin/cat'
CPU ID FUNCTION:NAME
0 58 brk:entry
libc.so.1`_brk_unlocked+0x15
libc.so.1`sbrk+0x38
...
libc.so.1`malloc+0x38
libc.so.1`strdup+0x29
libc.so.1`expand_locale_name+0x333
libc.so.1`setlocale+0x89c
cat`main+0x23
cat`_start+0x7d