strace pwd
:
getcwd("/root"..., 4096) = 6
ltrace pwd
:
getcwd(NULL, 0) = "/root"
Why the 1st parameter is NULL
in ltrace
?
It eems strace/ltrace both uses the ptrace
syscall,but why 开发者_如何学运维they get different info?
Right, they both use ptrace
, and also they get different info. This is because they use ptrace
differently.
If you have a look at the ptrace man page, you will see that there exist several 'request' values, which decide the behaviour of ptrace.
More concretely, if you use ptrace
to previously set the option PTRACE_O_TRACESYSGOOD
, you have a way to distinguish between the traps leading to system calls and the traps that are not leading to system calls.
ltrace
shows the library call. In this case, it shows the function from the libc
that the source code is calling.
If you see pwd
's source, you will see (coreutils-8.13, file lib/xgetcwd.c):
char *cwd = getcwd (NULL, 0);
So, ltrace
's output is correct: pwd
executes getcwd(NULL, 0)
. According to the Linux man page getcwd(3)
:
getcwd() allocates the buffer dynamically using malloc(3) if buf is NULL.
However, the system call getcwd(2)
always needs a first argument different from NULL, to copy there the pathname. You can see how this is done in the libc source (eglibc-3.13, file sysdeps/unix/sysv/linux/getcwd.c).
The library call getcwd(NULL, 0)
executes the system call getcwd(path, alloc_size)
, where path
is the result of a previous malloc(), and alloc_size
is the page size (4096).
To confirm this, if you run ltrace -S pwd
you will see both the library calls and the system calls: you will see something like:
getcwd(NULL, 0 <unfinished ...>
SYS_getcwd("/root", 4096) = 6
<... getcwd resumed> ) = "/root"
Because the system call and the library call are different. Read the manpage for the getcwd function and you'll see that it has the following prototype:
long getcwd(char *buf, unsigned long size);
精彩评论