Что может заставить ГБД отказаться от взлома? - PullRequest
5 голосов
/ 21 сентября 2011

Я в растерянности здесь. Я пишу компилятор на C (для хобби) и компилирую с GCC 4.6.1 на amd64 Linux 2.6.32, используя GDB 7.3. Флаги "-Wall -Wextra -O0 -g", в дополнение к обычным -I и еще много чего. У меня есть функция, целью которой является сообщить об ошибке разбора, определенная следующим образом:

void cerror_at (struct lex *lex, struct token *tok, const char *fmt, ...)

Кроме того, что ты вариад, ничего странного. Проблема в том, что ГБД НЕ сломается. Я пробовал все возможные способы (точка останова в функции, внутри функции, прежде чем она вызывается, вы называете ее), но как только моя программа находится внутри функции, я получаю сообщения типа «предупреждение: ошибка при удалении точки останова» 0 "и GDB просто позволяет программе закончить. В этом больше нет ничего плохого (с тех пор я исправил ошибку, которую пытался найти, и все работает как надо), но я не могу войти в функцию. Любые идеи о том, что может вызвать это?

Редактировать: Больше информации! GDB устанавливает точку останова на 0x403057. Функция начинается с 0x403025. Посмотрите на эту часть разборки:

0x0000000000403053 <+46>:   test   %al,%al
0x0000000000403055 <+48>:   je     0x403077 <cerror_at+82>

В этот момент он переходит вперед к 0x403077 (после точки останова). Я проверил, что размещение точки останова по адресу до «je» работает, а также по адресу 0x403077 или после него, цель перехода, но не между (где GDB пытается его разместить). Зачем GDB размещать точку останова в середине функции? Даже GDB говорит мне, что адрес функции, по сути, 0x403025.

Ответы [ 4 ]

3 голосов
/ 21 сентября 2011

Может быть, я просто дремучий, но наиболее распространенные причины, по которым я сталкивался с отказом отладчика в отладчике, - самые простые.

  1. Код, который я пытаюсь использоватьdebug не совсем соответствует коду в отладчике.
  2. Я забыл скомпилировать эту библиотеку с параметрами отладки.

Убедитесь, что вы проверяете оба из них в любое время, когда вы получаете ошибку отладкитак, даже если вы думаете, что это не проблема.

1 голос
/ 21 сентября 2011

Это звучит как ошибка в GDB. В частности, Error removing breakpoint 0 очень подозрительно (это точка останова, GDB автоматически вставляется куда-то; вставленные пользователем точки останова имеют положительные числа).

Возможно, вам следует попытаться создать сокращенный тестовый пример и сообщить об ошибке здесь .

0 голосов
/ 21 сентября 2011

На основании вашего последнего редактирования, я уверен, что это ошибка компилятора.В частности, я уверен, что существует проблема с генерацией отладочной информации DWARF, которая используется GDB для сопоставления адресов в коде объекта и номеров файлов / процедур / строк в источнике.

Вы можете попробовать поэкспериментироватьс -gdwarf-4, -gdwarf-3 или даже -gdwarf-2, чтобы увидеть, имеет ли это какое-то значение.

Если вы можете сократить это до простого теста, я подозреваю, что разработчики gcc примут это как ошибку.

Конечно, это также может быть ошибка в GDB.Но учитывая это поведение, я думаю, что это менее вероятно.

0 голосов
/ 21 сентября 2011

Как уже упоминалось в комментариях, вы должны попытаться понять, какой машинный код был сгенерирован компиляцией:

в GDB, вы можете увидеть фактический код функции с помощью disassemble cerror_at который должен дать что-то вроде (x86_64):

(gdb) disassemble dive
Dump of assembler code for function dive:
   0x0000000000400504 <+0>: push   %rbp
   0x0000000000400505 <+1>: mov    %rsp,%rbp
   0x0000000000400508 <+4>: sub    $0x10,%rsp
   0x000000000040050c <+8>: mov    %edi,-0x4(%rbp)
   0x000000000040050f <+11>:    mov    -0x4(%rbp),%eax
   0x0000000000400512 <+14>:    add    $0x1,%eax
   0x0000000000400515 <+17>:    mov    %eax,%edi
   0x0000000000400517 <+19>:    callq  0x400504 <dive>
   0x000000000040051c <+24>:    leaveq
   0x000000000040051d <+25>:    retq   
End of assembler dump.

Затем убедитесь, что подпрограмма действительно вызвана: прервите выполнение за несколько инструкций перед вызовом функции, затем:

   (gdb) x/5i $p
=> 0x400539 <main+27>:  mov    $0x1,%esi
   0x40053e <main+32>:  mov    %rax,%rdi
   0x400541 <main+35>:  callq  0x400408 <fwrite@plt>
   0x400546 <main+40>:  mov    $0x1,%edi
-->0x40054b <main+45>:  callq  0x400504 <dive> <------

выходные данные должны немного отличаться от другой архитектуры ЦП, но вы должны увидеть инструкцию ветвления, указывающую на адрес вашей функции.

-

И вы можете выполнить maint info breakpoint всего за до того момента, когда вы увидите Error removing breakpoint 0, чтобы узнать, где был установлен breakpoint 0, это может помочь понять, что с ним не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...