«Как я могу прочитать данные (значения переменных) процесса, который создан с помощью ./test?".
Вы можете изучить формат отладки DWARF. Часть 3 ссылки Как работают отладчикиниже кратко обсуждает DWARF. Существуют и другие способы разрешения символов, но почему бы не поступить так, как GDB, и не использовать DWARF? [править: Извлечение функций из исходного кода gdb для использования их в более простых программах — нетривиальная задача]. Исходный код в любом случае доступен, проверьте 'Как загружается GDB Файлы символов" ниже, где ссылки указывают прямо на него.Третий вариант - ручной анализ таблиц символов ELF с вашими собственными функциями.Это уродливее и, вероятно, более сложный путь, но он не полагается на символы отладки, которые предоставляет dwarf.
Что касается точек останова, вы можете установить их с помощью ptrace и trap = memory & 0xffffff00 | 0xccпосле сохранения инструкции по адресу и восстановления инструкции после попадания в ловушку, как описано в Как работают отладчики. Байт 0xcc — это код операции int 3.
Чтобы увидеть, как это делает gdb, вот ссылка для вас: Как GDB загружает файлы символов
Нижеследующее предназначено исключительно для того, чтобы намекнуть, откуда берутся эти 5000+ шагов, запустив программу сборки без связанных библиотек через аналогичный трассировщик:
;hello.asm section .text global _start _start: mov edx,5 mov ecx,msg mov ebx,1 mov eax,4 int 0x80 mov eax,1 int 0x80 msg: db "Hello"
Программа, которую я использовал для подсчета аналогично (из Как работают отладчики)
#include
#include #include #include #include void run_debugger(pid_t child_pid) { int wait_status; unsigned icounter = 0; printf("debugger started\n"); /* Wait for child to stop on its first instruction */ wait(&wait_status); while (WIFSTOPPED(wait_status)) { icounter++; /* Make the child execute another instruction */ if (ptrace(PTRACE_SINGLESTEP, child_pid, 0, 0) < 0) { perror("ptrace"); return; } /* Wait for child to stop on its next instruction */ wait(&wait_status); } printf("\nthe child executed %u instructions\n", icounter); } void run_target(const char* programname) { printf("target started. will run '%s'\n", programname); /* Allow tracing of this process */ if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) { perror("ptrace"); return; } /* Replace this process's image with the given program */ execl(programname, programname, NULL); } int main(int argc, char** argv) { pid_t child_pid; if (argc < 2) { fprintf(stderr, "Expected a program name as argument\n"); return -1; } child_pid = fork(); if (child_pid == 0) run_target(argv[1]); else if (child_pid > 0) run_debugger(child_pid); else { perror("fork"); return -1; } return 0; } Скомпилировал это как a.out и запустил:
$ ./a.out helloasm debugger started target started. will run 'helloasm' Hello the child executed 7 instructions
vs.
#include
int main() { printf("Hello World\n"); return 0; } , что в сумме составляет 141 690 инструкций.
В Perl символ может повторяться несколько раз с помощью оператора x
:
$ perl -e 'print "#" x 10, "\n"'
##########
Давайте воспользуемся этим.
Вместо разбора выводаfind
:
find. -type f -exec file -b {} + | sort | uniq -c | sort -rn |
perl -ne 'chomp; s/\s+(\d+)\s+// && printf("%-3d %-50s: %s\n", $1, $_, "#" x $1)'
Первая часть, вплоть до Perl-скрипта, будет выводить примерно так
23 ASCII C program text
12 ASCII text
10 ELF 64-bit LSB relocatable, x86-64, version 1
3 ASCII English text
1 ELF 64-bit LSB shared object, x86-64, version 1
Сценарий Perl удалит завершающую новую строку с chomp
, а затем выберет число в $1
. Затем он использует printf()
для вывода числа, типа файла и столько символов #
, сколько указано числом.
Конечный результат будет примерно таким:
23 ASCII C program text : #######################
12 ASCII text : ############
10 ELF 64-bit LSB relocatable, x86-64, version 1 : ##########
3 ASCII English text : ###
1 ELF 64-bit LSB shared object, x86-64, version 1 : #
Чтобы ответить на ваш главный вопрос «как символизировать число N последовательностью из N символов, вот команда оболочки, которая сделает именно это:
n=17 # Number to translate to a sequence
printf "%${n}s" '' | tr ' ' '#'
(альтернативный синтаксис:printf '%*s' "$n" '' | tr ' ' '#'
; есть и другие альтернативы, вы поняли)
Он генерирует пустую строку, состоящую из n
пробелов (части printf
), а затем преобразует каждый пробел в нужный символ (часть tr
).
Предполагая, что у вас есть команда count_files
, которая выводит список, который вы включили в свой вопрос, эту команду можно использовать следующим образом:
count_files \
| while read n type; do
printf '%4d %-30s %s\n' "$n" "$type" "$(printf "%${n}s" '' | tr ' ' '#')"
done
... и ты получишь это:
8 empty ########
6 ASCII text ######
3 Vim swap file, version 7.4 ###
1 UTF-8 Unicode text #