Эта диаграмма из статьи Википедии Стек вызовов может помочь:
GDB info frame
соответствует функциям, вызываемым в вашей программе во время выполнения.Из выходных данных мы можем сделать вывод о макете кадра стека:
- 0xb75f7388 : начиная с 4 байтов здесь сохраняется старое значение EBP , 0xb75f73a8 .Первое значение, выдаваемое прологом функции
base::func()
- 0xb75f738c : 4 байта, начиная с этого здесь, сохраняют адрес возврата, 0x804869a .Нажимается инструкцией
call
в предыдущем кадре - 0xb75f7390 : начиная с 4-х байтов здесь неявный аргумент
this
сохраняется в base::func()
, 0x00000000 .
Я объясню вывод info frame
построчно:
Stack level 0, frame at 0xb75f7390:
Уровень стека 0 означает, что это самый новый кадр 1040 *.Адрес после frame at
называется каноническим адресом кадра (CFA).На x86 это определяется как значение указателя стека ( ESP ) в предыдущем кадре перед выполнением инструкции call .
eip = 0x804877f in base::func() (testing.cpp:16); saved eip 0x804869a
EIP - указатель инструкции x86.saved eip
- обратный адрес.Если вы попытаетесь найти функцию, которая содержит 0x804869a с info symbol 0x804869a
, она должна указывать внутри функции, вызывая base::func()
.
called by frame at 0xb75f73b0
called by
показывает адрес канонического кадрапредыдущего кадра.Мы можем видеть, что указатель стека продвинулся на 32 байта (0xb75f73b0 - 0xb75f7390 = 32) между двумя кадрами.
source language c++.
Arglist at 0xb75f7388, args: this=0x0
Locals at 0xb75f7388, Previous frame's sp is 0xb75f7390
ABI x86 передает аргументы в стек.base::func()
имеет только один неявный аргумент this
.Тот факт, что это 0x0
то есть NULL
сулит зло.С другой стороны, Arglist
и Locals
, кажется, всегда имеют одинаковое значение в info frame
на x86 и x86-64.
Saved registers:
ebp at 0xb75f7388, eip at 0xb75f738c
Saved registers
отражает регистры, которые были сохранены в функциизапись.Он перечисляет, где старые значения регистра сохраняются в стеке.Сохраненный EIP является обратным адресом, поэтому если вы изучите адрес, сохраненный в 0xb75f738c с x/a 0xb75f738c
, он должен дать 0x804869a .Тот факт, что EBP указан здесь, подразумевает, что ваш код, вероятно, не был скомпилирован с -fomit-frame-pointer
и имеет стандартный пролог функции:
push %ebp
movl %esp, %ebp
в самом начале base::func()
, чтоустанавливает EBP в качестве указателя кадра.