GDB не может перешагнуть через функцию, если следующие строки не включают и решение или ответвление - PullRequest
1 голос
/ 23 января 2020

У меня проблемы с отладкой (перешагиванием) в c ++ с помощью gdb. У меня есть собственный rtos, работающий на цели powerp c e500m c. Версии программного обеспечения: g cc 4.9.2, gdb-server 5 ~ (не знаю точную версию), gdb 7.9.1 также пробовал 8.3.1. Исходный файл, скомпилированный с параметрами -g и -O0 Проблема, похоже, возникает в c ++ после перехода через функцию, если в следующих строках нет перехода, инструкция перехода на определенную величину, GDB потерял дорожку, где останавливаться при возврате функции и продолжай бежать. Я пробовал тот же код на целевой версии x86-64, он работает, как и ожидалось, без каких-либо проблем. Первым делом проверил целевую часть портирования gdb-сервера, затем зарегистрировал обмен сообщениями между хостом и целью. Как вы можете видеть ниже, проблема, кажется, находится на стороне GDB, так как GDB сам решает, где поставить точку останова.

В примере кода используется ошибка, я также добавил файл журнала. Строки, начинающиеся с "gdb:" - это сообщения от gdb к цели. Я не включаю ответы gdb-сервера, чтобы избежать путаницы. Другие строки печатаются по цели. <..> комментарии, добавленные мной позже, рассказывают о значении кода, данных или адреса, а также о том, что я делал в то время. Я также включил связанную часть файла эльфа, чтобы сделать его более понятным.

Вот что происходит. Сначала я загружаю свою программу в целевой режим с отключенным автоматическим запуском. Программа находится в памяти и ожидает запуска моей команды. Тогда я присоединяюсь к процессу для отладки. GDB вступает во владение и начинает общение, после некоторого рукопожатия и запросов ловит процесс. Он не работал, поэтому он зацикливается на самом начале кода инициализации перед основной функцией @ 210106e8. Итак, GDB знает, что я хочу остановиться на своем коде (main), ставит точку останова в первой инструкции main после операций со стеком функций @ 21010250. Затем программы запускаются по цели и ловят исключение ловушки в точке останова. Когда выполнение останавливается, GDB удаляет точку останова (инструкцию trap) и возвращает исходную инструкцию.

Позже я делаю шаг, который является строкой int i = 0. GDB устанавливает режим трассировки и запускает выполнение. Программа перехватывает исключение трассировки после выполнения первой инструкции. Поскольку я не в режиме пошагового выполнения инструкций, GDB начинает выполнение снова, пока строка c не завершится, GDB перехватит второе исключение трассировки и достигнет конца c наборов строк режима трассировки.

Теперь мы находимся на линии вызова функции и перешагнуть снова. GDB устанавливает режим трассировки и начинает выполнение программы. Программа вызывает функцию и перехватывает исключение трассировки. Gdb видит, что это не та функция (main), которая нас интересует, поскольку мы переходим, устанавливаем точку останова для точки возврата функции. Программа начинает выполнение, печатает сообщение и возвращает функцию и достигает точки останова @ 2101025 c. Все идет нормально.

Здесь он должен был остановиться, так как моя начальная команда, которая переходит к вызову функции, завершена, но продолжается.

Теперь, как вы можете видеть в выводе журнала, GDB начинает запросы о блоке кода , что он делал раньше, но не с гораздо большим числом, ожидая 52 инструкции впереди (которые все i ++). Gdb удаляет точку останова, включает режим трассировки и выполняет первую инструкцию команды i ++. После выполнения первого вмешательства и отлова исключения снова 52 запроса команд. После всего этого GDB должен установить режим трассировки и начать выполнение. Вместо этого он ставит точку останова перед текущим значением p c по адресу только что выполненной инструкции. При отключенном режиме трассировки, когда начинается выполнение, программа выполняется до завершения, так как точка останова не будет достигнута.

Если я уменьшу количество i ++ до точки, где в 52 запросе инструкции gdb увидит некоторый скачок или ветвь, все работает как положено.

И если тот же код скомпилирован как c, а не c ++, снова все работает как положено.

Как я упоминал ранее, один и тот же код работает на цели x86, все работает как положено.

код:

#include <iostream>

using namespace std;

void printHello(void)
{
    cout << "Hello World" << endl;
}

int main()
{
    int i = 0;
    printHello();
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    i++;
    return 0;
}

вывод терминала:

<attach to process>
gdb:qSupported:multiprocess+;qRelocInsn+
gdb:!
gdb:Hgp0.0
gdb:QNonStop:0
gdb:qTStatus
gdb:?
gdb:qXfer:osdata:read:processes:0,35b
gdb:qXfer:threads:read::0,35b
gdb:vAttach;10000
stopping 65537 @210106e8 <_posix_lib_process_start>
gdb:qC
gdb:Hgp10000.10001
gdb:g
gdb:qSymbol::
gdb:m21010250,4 <main>
gdb:m21010250,4
gdb:m21010250,4
gdb:m210151c8,4 <_ZSt9terminatev>
gdb:m2102e288,4 <_Unwind_DebugHook>
gdb:qXfer:threads:read::0,763
gdb:qXfer:osdata:read:processes:0,763
gdb:qXfer:threads:read::0,763
gdb:Z0,21010250,4
gdb:m21010250,4 <backup>
gdb:X21010250,0:
gdb:X21010250,4:}] <put breakpoint @ main>
gdb:vCont?
gdb:vCont;c:p10000.-1 <cont all, breakpoint ready>
starting 65537 @210106e8
trap callback
stopping 65537 @21010250 <stop @ breakpoint>
gdb:m21010250,4
gdb:m21010254,4
gdb:m21010258,4
gdb:m2101023c,4 <main's head>
gdb:m2101023c,4
gdb:m21010240,4
gdb:m21010244,4
gdb:m21010248,4
gdb:m2101024c,4
gdb:m21441fa0,4
gdb:g
gdb:qXfer:threads:read::0,763
gdb:X21010250,4:9 <remove breakpoint>
gdb:qXfer:threads:read::0,763
gdb:qXfer:threads:read::0,763
gdb:qXfer:threads:read::0,763
<stop @ int=0 line>

<step>
gdb:m2102e288,4 <backup>
gdb:X2102e288,4:}] <??put breakpoint>
gdb:m21010250,4
gdb:vCont;s:p10000.10001;c:p10000.-1 <stop thread, set trace>
single step set
starting 65537 @21010250
trace callback <instruction complete exception>
stopping 65537 @21010254 
single step reset
gdb:m21010254,4
gdb:m21010258,4
gdb:m2101023c,4
gdb:m2101023c,4
gdb:m21010240,4
gdb:m21010244,4
gdb:m21010248,4
gdb:m2101024c,4
gdb:m21010250,4
gdb:m21441fa0,4
gdb:g
gdb:m21010254,4
gdb:vCont;s:p10000.10001;c:p10000.-1 <stop thread, set trace>
single step set
starting 65537 @21010254
trace callback <instruction complete exception>
stopping 65537 @21010258
single step reset <step done, new c line>
gdb:m21010258,4
gdb:m2101023c,4
gdb:m2101023c,4
gdb:m21010240,4
gdb:m21010244,4
gdb:m21010248,4
gdb:m2101024c,4
gdb:m21010250,4
gdb:m21441fa0,4
gdb:g
gdb:qXfer:threads:read::0,763
gdb:X2102e288,4:N <??remove breakpoint>
gdb:qXfer:threads:read::0,763
gdb:qXfer:threads:read::0,763
<stop @ printHello() line>

<step>
gdb:m2102e288,4
gdb:X2102e288,4:}] <??put breakpoint>
gdb:m21010258,4
gdb:vCont;s:p10000.10001;c:p10000.-1 <stop thread, set trace>
single step set
starting 65537 @21010258
trace callback
stopping 65537 @210101e8 <printHello>
single step reset
gdb:m210101e8,4
gdb:m210101ec,4
gdb:m210101f0,4
gdb:m210101f4,4
gdb:m210101f8,4
gdb:m210101fc,4
gdb:m21010200,4
gdb:m21010204,4
gdb:m21010208,4
gdb:m2101020c,4
gdb:m210101e8,4
gdb:g
gdb:m2101023c,4
gdb:m2101023c,4
gdb:m21010240,4
gdb:m21010244,4
gdb:m21010248,4
gdb:m2101024c,4
gdb:m21010250,4
gdb:m21441fa0,4
gdb:m2101025c,4
gdb:m2101025c,4
gdb:X2101025c,4:}] <put breakpoint>
gdb:vCont;c:p10000.-1 <cont all, breakpoint ready>
starting 65537 @210101e8
Hello World
trap callback <stop @ breakpoint>
stopping 65537 @2101025c
gdb:m2101025c,4
gdb:m21010260,4
gdb:m21010264,4
gdb:m21010268,4
gdb:m2101026c,4
gdb:m21010270,4
gdb:m21010274,4
gdb:m21010278,4
gdb:m2101027c,4
gdb:m21010280,4
gdb:m21010284,4
gdb:m21010288,4
gdb:m2101028c,4
gdb:m21010290,4
gdb:m21010294,4
gdb:m21010298,4
gdb:m2101029c,4
gdb:m210102a0,4
gdb:m210102a4,4
gdb:m210102a8,4
gdb:m210102ac,4
gdb:m210102b0,4
gdb:m210102b4,4
gdb:m210102b8,4
gdb:m210102bc,4
gdb:m210102c0,4
gdb:m210102c4,4
gdb:m210102c8,4
gdb:m210102cc,4
gdb:m210102d0,4
gdb:m210102d4,4
gdb:m210102d8,4
gdb:m210102dc,4
gdb:m210102e0,4
gdb:m210102e4,4
gdb:m210102e8,4
gdb:m210102ec,4
gdb:m210102f0,4
gdb:m210102f4,4
gdb:m210102f8,4
gdb:m210102fc,4
gdb:m21010300,4
gdb:m21010304,4
gdb:m21010308,4
gdb:m2101030c,4
gdb:m21010310,4
gdb:m21010314,4
gdb:m21010318,4
gdb:m2101031c,4
gdb:m21010320,4
gdb:m21010324,4
gdb:m21010328,4
gdb:m21010258,4
gdb:g
gdb:X2101025c,4:? <remove breakpoint>
gdb:m2101025c,4
gdb:vCont;s:p10000.10001 <stop thread, trace ready><??c:-1 neden yok>
single step set
starting 65537 @2101025c
trace callback <instruction complete exception>
stopping 65537 @21010260
single step reset 
gdb:m21010260,4
gdb:m21010264,4
gdb:m21010268,4
gdb:m2101026c,4
gdb:m21010270,4
gdb:m21010274,4
gdb:m21010278,4
gdb:m2101027c,4
gdb:m21010280,4
gdb:m21010284,4
gdb:m21010288,4
gdb:m2101028c,4
gdb:m21010290,4
gdb:m21010294,4
gdb:m21010298,4
gdb:m2101029c,4
gdb:m210102a0,4
gdb:m210102a4,4
gdb:m210102a8,4
gdb:m210102ac,4
gdb:m210102b0,4
gdb:m210102b4,4
gdb:m210102b8,4
gdb:m210102bc,4
gdb:m210102c0,4
gdb:m210102c4,4
gdb:m210102c8,4
gdb:m210102cc,4
gdb:m210102d0,4
gdb:m210102d4,4
gdb:m210102d8,4
gdb:m210102dc,4
gdb:m210102e0,4
gdb:m210102e4,4
gdb:m210102e8,4
gdb:m210102ec,4
gdb:m210102f0,4
gdb:m210102f4,4
gdb:m210102f8,4
gdb:m210102fc,4
gdb:m21010300,4
gdb:m21010304,4
gdb:m21010308,4
gdb:m2101030c,4
gdb:m21010310,4
gdb:m21010314,4
gdb:m21010318,4
gdb:m2101031c,4
gdb:m21010320,4
gdb:m21010324,4
gdb:m21010328,4
gdb:m2101032c,4
gdb:m2101025c,4
gdb:m21010258,4
gdb:g
gdb:m2101025c,4
gdb:X2101025c,4:}] <HATA put breakpoint>
gdb:vCont;c:p10000.-1 <cont all><HATA -1 gönderdiği için, trace yapmıyor>
starting 65537 @21010260

файл эльфа

void printHello(void)
{
210101e8:   94 21 ff f0     stwu    r1,-16(r1)
210101ec:   7c 08 02 a6     mflr    r0
210101f0:   90 01 00 14     stw     r0,20(r1)
210101f4:   93 e1 00 0c     stw     r31,12(r1)
210101f8:   7c 3f 0b 78     mr      r31,r1
     cout << "Hello World" << endl;
210101fc:   3d 20 21 04     lis     r9,8452
21010200:   38 69 01 78     addi    r3,r9,376
21010204:   3d 20 21 04     lis     r9,8452
21010208:   38 89 82 48     addi    r4,r9,-32184
2101020c:   48 02 1f a9     bl      210321b4
21010210:   7c 69 1b 78     mr      r9,r3
21010214:   7d 23 4b 78     mr      r3,r9
21010218:   3d 20 21 03     lis     r9,8451
2101021c:   38 89 26 ec     addi    r4,r9,9964
21010220:   48 02 25 45     bl      21032764
}
21010224:   39 7f 00 10     addi    r11,r31,16
21010228:   80 0b 00 04     lwz     r0,4(r11)
2101022c:   7c 08 03 a6     mtlr    r0
21010230:   83 eb ff fc     lwz     r31,-4(r11)
21010234:   7d 61 5b 78     mr      r1,r11
21010238:   4e 80 00 20     blr

2101023c <main>:

int main()
{
2101023c:   94 21 ff e0     stwu    r1,-32(r1)
21010240:   7c 08 02 a6     mflr    r0
21010244:   90 01 00 24     stw     r0,36(r1)
21010248:   93 e1 00 1c     stw     r31,28(r1)
2101024c:   7c 3f 0b 78     mr      r31,r1
    int i = 0;
21010250:   39 20 00 00     li      r9,0
21010254:   91 3f 00 08     stw     r9,8(r31)
    printHello();
21010258:   4b ff ff 91     bl      210101e8 <_Z10printHellov>
        i++;
2101025c:   81 3f 00 08     lwz     r9,8(r31)
21010260:   39 29 00 01     addi    r9,r9,1
21010264:   91 3f 00 08     stw     r9,8(r31)
        i++;
21010268:   81 3f 00 08     lwz     r9,8(r31)
2101026c:   39 29 00 01     addi    r9,r9,1
21010270:   91 3f 00 08     stw     r9,8(r31)
        i++;
21010274:   81 3f 00 08     lwz     r9,8(r31)
21010278:   39 29 00 01     addi    r9,r9,1
2101027c:   91 3f 00 08     stw     r9,8(r31)

1 Ответ

0 голосов
/ 18 февраля 2020

Проблема решена, по крайней мере, перешагнуть работает нормально сейчас. Ошибка, вызванная функцией rs6000_in_function_epilogue_frame_p (). Как вы можете видеть, функция сканирует вперед до следующего BLR для 52 (кажется знакомым) инструкции. И сканирует в обратном направлении до корректировки на указатель стека. Это приводит к установке точки останова для предыдущего кода из p c, и выполнение не может быть остановлено. Функция изменена только для возврата 0. У меня нет глубокого понимания на стороне хоста, может быть, вы найдете лучшее решение. Я подозреваю, что в предыдущих версиях в пошаговом функционале произошли изменения в дизайне, обновлен код архитектуры Intel, но powerp c забыт.

...