linux read системный вызов, производимый strace - как понять указатель на значение буфера? - PullRequest
1 голос
/ 22 сентября 2019

Я запустил strace и в его выводе я получил такие строки:

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

Я прочитал man на read , поэтому строка "" является указателем на buf (ssize_t read(int fd, void *buf, size_t count);), но что означает эта конкретная строка?В частности:

  • ELF, наиболее вероятно, связанный с исполняемым файлом - зачем здесь указатель?
  • \ позволяет экранировать специальные символы - зачем экранировать цифры здесь?
  • > для чего он нужен?

1 Ответ

4 голосов
/ 22 сентября 2019

Здесь вы видите, как динамический загрузчик открывает и читает заголовок нужных библиотек.Почти любая strace программа ELF (это стандартный исполняемый формат в Linux) начинается с набора open / read / mmap / close по этой причине: динамический загрузчик загружает необходимыйбиблиотеки.

То, что вы видите здесь:

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

Это то, что загрузчик читает из файла:

  • 3: это fd, который был назначен открытому файлу open().
  • "\177ELF\2\1\1\0...": это содержимое файла, который читается.Числа существуют потому, что это восьмеричные escape-последовательности, например, \1 означает байт 1. Они печатаются так, потому что в противном случае вы бы не смогли их увидеть и создали бы беспорядок на вашем терминале, так как большинство из нихспециальные непечатаемые символы.
  • 832: это количество байтов, которое загрузчик хочет прочитать из файла.
  • = 832: это результат read(),Это означает, что все запрошенные байты были прочитаны.

Другими словами, эти escape-последовательности - просто способ сделать непечатные байты удобочитаемыми для человека .Вы можете протестировать этот запуск od -bc для файла, который пытается открыть загрузчик, вы можете увидеть его содержимое в восьмеричной форме, а также с печатными символами и символами обратной косой черты:

$ 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

Более полныйНапример, из 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)  

Вы можете видеть, что загрузчик открывает «libc», который является ELF-файлом для стандартной библиотеки C.Он читает свой заголовок, чтобы определить, какие разделы должны быть загружены, а затем mmap все необходимые разделы в памяти, назначая необходимые разрешения.

...