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:
ELF
most probably executable-linked - why here for pointer? \
lets escape special characters - why escape digits here? >
what is it for? 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:
3
: this is the fd
that was assigned to the open file by open()
."\177ELF\2\1\1\0..."
: this is is the content of the file that is being read. Numbers are there because those are octal escape sequences, for example \1
means the byte 1. They are printed like this because otherwise you would not be able to see them, and would create a mess on your terminal, since most of those are special non printable characters.832
: this is the number of bytes the loader wants to read from the file.= 832
: this is the result of the read()
, which means that all the requested bytes were read.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 mmap
s all the needed sections in memory, assigning the right permissions.