LINUX_book
456 pág.

LINUX_book


DisciplinaLinux714 materiais1.845 seguidores
Pré-visualização50 páginas
to use strace. The
program attempts to open a file as \u201cread only\u201d and then exits. The program
only contains one system call, open:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main( )
{
 int fd ;
 int i = 0 ;
 fd = open( \u201c/tmp/foo\u201d, O_RDONLY ) ;
 if ( fd < 0 )
 i=5;
 else
 i=2;
 return i;
}
There is some trivial code after the call to open, the details of which will not be
shown in the strace output because the trivial code does not invoke any system
calls. Here is the system call trace output:
50 strace and System Call Tracing Explained Chap. 2
ion 216% gcc main.c -o main
ion 217% strace -o main.strace main
ion 218% cat main.strace
1. execve(\u201c./main\u201d, [\u201cmain\u201d], [/* 64 vars */]) = 0
2. uname({sys=\u201dLinux\u201d, node=\u201dion\u201d, ...}) = 0
3. brk(0) = 0x80494f8
4. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
\u27a5-1, 0) = 0x40013000
5. open(\u201c/etc/ld.so.preload\u201d, O_RDONLY) = -1 ENOENT (No such file
\u27a5or directory)
6. open(\u201c/lib/i686/mmx/libc.so.6\u201d, O_RDONLY) = -1 ENOENT (No such
\u27a5file or directory)
7. stat64(\u201c/lib/i686/mmx\u201d, 0xbfffe59c) = -1 ENOENT (No such file
\u27a5or directory)
8. open(\u201c/lib/i686/libc.so.6\u201d, O_RDONLY) = -1 ENOENT (No such file
\u27a5or directory)
9. stat64(\u201c/lib/i686\u201d, 0xbfffe59c) = -1 ENOENT (No such file
\u27a5or directory)
10.open(\u201c/lib/mmx/libc.so.6\u201d, O_RDONLY) = -1 ENOENT (No such file
\u27a5or directory)
11.stat64(\u201c/lib/mmx\u201d, 0xbfffe59c) = -1 ENOENT (No such file
\u27a5or directory)
12.open(\u201c/lib/libc.so.6\u201d, O_RDONLY) = 3
13.read(3,
\u27a5\u201c\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\300\205\u201d...,
\u27a51024) = 1024
14.fstat64(3, {st_mode=S_IFREG|0755, st_size=1312470, ...}) = 0
15.mmap2(NULL, 1169856, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) =
\u27a50x40014000
16.mprotect(0x40128000, 39360, PROT_NONE) = 0
17.mmap2(0x40128000, 24576, PROT_READ|PROT_WRITE,
\u27a5MAP_PRIVATE|MAP_FIXED, 3, 0x113) = 0x40128000
18.mmap2(0x4012e000, 14784, PROT_READ|PROT_WRITE,
\u27a5MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4012e000
19.close(3) = 0
20.open(\u201c/tmp/foo\u201d, O_RDONLY) = -1 ENOENT (No such file
\u27a5or directory)
21.exit(5) = ?
Note: The line numbers to the left are not actually part of the
strace output and are used for illustration purposes only.
In this strace output, the vast majority of the system calls are actually for
process initialization. In fact, the only system call (on line 20) from the actual
program code is open(\u201c/tmp/foo\u201d, O_RDONLY). Also notice that there are no system
calls from the if statement or any other code in the program because the if
statement does not invoke a system call. As mentioned before, system call
512.2 What Is strace?
tracing is rarely useful for code logic problems, but it can be very useful to find
a problem that relates to the interaction with the operating system.
It takes a bit of practice to understand a system call trace, but a good
example can go a long way. For those who are not familiar with the standard
system calls, it is quick and easy to read the man pages for the system calls for
more information. For example, the first system call in the trace is execve. The
man page can be referenced using
ion 225% man 2 execve
The arguments for a system call in the strace output should match those listed
in the man page. The first argument listed in the man page for execve is const
char *filename, and the documentation in the man page mentions that this
system call executes the program pointed to by filename. The functionality of
execve is not the point of this but rather that man pages can be used to help
understand strace output for beginners.
Line #1: The execve system call (or one of the exec system calls) is always the
first system call in the strace output if strace is used to trace a program off the
command line. The strace tool forks, executes the program, and the exec system
call actually returns as the first system call in the new process. A successful
execve system call will not return in the calling process\u2019 code (because exec
creates a new process).
Line #2: The uname system call is being called for some reason\u2014but is not
immediately important.
Line #3: The brk system call is called with an argument of zero to find the
current \u201cbreak point.\u201d This is the beginning of memory management (for
example, malloc and free) for the process.
Line #4: The mmap call is used to create an anonymous 4KB page. The address
of this page is at 0x40013000.
Line #5: This line attempts to open the ld.so.preload file. This file contains a
list of ELF shared libraries that are to be pre-loaded before a program is able
to run. The man page for ld.so may have additional information.
Lines #6 - #12. These lines involve finding and loading the libc library.
52 strace and System Call Tracing Explained Chap. 2
Note: If the LD_LIBRARY_PATH lists the library paths in the wrong
order, process initialization can involve a lot of searching to find the right
library.
Line #13: Loads in the ELF header for the libc library.
Line #14: Gets more information (including size) for the libc library file.
Line #15: This line actually loads (mmaps) the contents of libc into memory at
address 0x40014000.
Line #16: This removes any protection for a region of memory at 0x40128000
for 39360 bytes.
Line #17: This line loads the data section at address 0x40128000 for 24576
bytes. The address of 0x40128000 is 0x114000 bytes from the beginning of the
memory segment (0x40014000). According to the ELF layout of libc.so.6, the
data section starts at 0x114920, but that section must be aligned on 0x1000
boundaries (hence the offset of 0x114000).
ion 722% readelf -l /lib/libc.so.6
Elf file type is DYN (Shared object file)
Entry point 0x185c0
There are 7 program headers, starting at offset 52
Program Headers:
 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
 PHDR 0x000034 0x00000034 0x00000034 0x000e0 0x000e0 R E 0x4
 INTERP 0x113610 0x00113610 0x00113610 0x00013 0x00013 R 0x1
 [Requesting program interpreter: /lib/ld-linux.so.2]
 LOAD 0x000000 0x00000000 0x00000000 0x113918 0x113918 R E
\u27a50x1000
 LOAD 0x113920 0x00114920 0x00114920 0x04f8c 0x090a0 RW 0x1000
 DYNAMIC 0x117ba4 0x00118ba4 0x00118ba4 0x000d8 0x000d8 RW 0x4
 NOTE 0x000114 0x00000114 0x00000114 0x00020 0x00020 R 0x4
 GNU_EH_FRAME 0x113624 0x00113624 0x00113624 0x002f4 0x002f4 R 0x4
ion 723% readelf -S /lib/libc.so.6
There are 53 section headers, starting at offset 0x11d170:
Section Headers:
 [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
...
 [16] .data PROGBITS 00114920 113920 0031f8 00 WA 0 0 32
...
53
 [25] .bss NOBITS 001198c0 1188c0 004100 00 WA 0 0 32
...
Line #18: Creates an anonymous memory segment for the bss section (more
on this in the ELF chapter). This is a special section of a loaded executable or
shared library for uninitialized data. Because the data is not initialized, the
storage for it is not included in an ELF object like a shared library (there are
no real data values to store). Instead, memory is allocated for the bss section
when the library is loaded. One thing worth noting is that part (0x740 bytes) of
the bss section is on the last page of the data section. Whenever dealing with
memory at the system level, the minimum unit of memory is always a page
size, 0x1000 by default on IA-32. The offset of the bss is 0x00114920, which is not
on a page size boundary. The next page boundary is at 0x4012e000, which is
where the rest of the memory for the bss segment is allocated. Given that the
size of the bss is 0x4100 and since 0x740 of the bss is included on the last page of
the data section, the rest of the bss segment is 0x39C0 (14784 in decimal)