Это - Heisenbug и возможно тот, который был зафиксирован в последних версиях mandb. Это имеет отношение к поврежденным страницам справочника, порядок обхода файловой системы, и возрастающий восстанавливает mandb, превращающегося очень медленный полный, восстанавливает (приблизительно 15 миллионов отсутствий страницы, который занимает минуты на вращающейся ржавчине).
Если Вы хотите диагностировать его, работать:
sudo mandb --no-purge --debug
и никогда не выполняйте mandb с --create
или без --no-purge
. Затем удостоверьтесь, что Вы имеете последнюю версию и сообщаете об ошибке, где cjwatson видит его.
Если, с другой стороны, Вы просто хотите избавиться от проблемы, работать:
echo 'man-db man-db/auto-update boolean false' |sudo debconf-set-selections
который отключит дб человека cronjob (выполнения ежедневно) и триггер dpkg (выполнения, когда пакеты будут установлены).
На самом деле это - корректное поведение.
Ниже кавычка отсюда:
Ответ очень интересен. По умолчанию, gcc на Linux связывает программы с библиотеками времени выполнения C динамично. То, что это означает, - то, что одной из первых вещей, которая работает, когда любая программа выполнена, является динамический загрузчик библиотеки, который ищет необходимые общие библиотеки. Это - довольно много кода – и помните, что наш основной трассировщик здесь смотрит на каждую инструкцию, не просто основной функции, а целого процесса.
«Как я могу прочитать данные (значения переменных) процесса, который создан с помощью ./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 <sys/ptrace.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
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 <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
, что в сумме составляет 141 690 инструкций.