Linux, разработка программы Отладчика

Это - 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 (выполнения, когда пакеты будут установлены).

3
09.01.2013, 16:29
2 ответа

На самом деле это - корректное поведение.

Ниже кавычка отсюда:

Ответ очень интересен. По умолчанию, gcc на Linux связывает программы с библиотеками времени выполнения C динамично. То, что это означает, - то, что одной из первых вещей, которая работает, когда любая программа выполнена, является динамический загрузчик библиотеки, который ищет необходимые общие библиотеки. Это - довольно много кода – и помните, что наш основной трассировщик здесь смотрит на каждую инструкцию, не просто основной функции, а целого процесса.

2
27.01.2020, 21:28

«Как я могу прочитать данные (значения переменных) процесса, который создан с помощью ./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 инструкций.

0
27.01.2020, 21:28

Теги

Похожие вопросы