cpointersfile-descriptorstrace

Linux read system call logged by strace - how to understand pointer to buffer value?


I ran strace and in its output I got lines like:

read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\273\0\0\0\0\0\0"..., 832) = 832

I've read man on read, so string "" is pointer to buf (ssize_t read(int fd, void *buf, size_t count);), but what does that particular string mean? In particular:


Solution

  • What you're seeing here is the dynamic loader opening and reading the header of the needed libraries. Almost any strace of an ELF program (which is the standard executable format in Linux) starts with a bunch of open/read/mmap/close for this reason: the dynamic loader is loading the needed libraries.

    What you see here:

    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\273\0\0\0\0\0\0"..., 832) = 832
    

    Is just what the loader is reading from the file:

    In other words, those escape sequences, are just a way to make non-printable bytes human readable. You can test this running od -bc on the file that the loader is trying to open, you can see its content in octal form plus with printable characters and backslash escapes:

    $ od -bc /lib/x86_64-linux-gnu/libc.so.6 | head -n4
    0000000 177 105 114 106 002 001 001 003 000 000 000 000 000 000 000 000
            177   E   L   F 002 001 001 003  \0  \0  \0  \0  \0  \0  \0  \0
    0000020 003 000 076 000 001 000 000 000 260 034 002 000 000 000 000 000
            003  \0   >  \0 001  \0  \0  \0 260 034 002  \0  \0  \0  \0  \0
    

    A more complete example would be the following, from strace /bin/true:

    open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 4
    read(4, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\4\2\0\0\0\0\0"..., 832) = 832
    fstat(4, {st_mode=S_IFREG|0755, st_size=1689360, ...}) = 0
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0d3d877000
    mmap(NULL, 3795296, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x7f0d3d2dd000
    mprotect(0x7f0d3d472000, 2097152, PROT_NONE) = 0
    mmap(0x7f0d3d672000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x195000) = 0x7f0d3d672000
    mmap(0x7f0d3d678000, 14688, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0d3d678000
    close(4)  
    

    You can see that the loader is opening "libc", which is the ELF file for the standard C library. It reads its header to determine which sections are to be loaded, and then mmaps all the needed sections in memory, assigning the right permissions.