Различные адреса инструкций, показанные в ltrace и objdump

Я использую ltrace и objdump для анализа простого кода ниже. Но я обнаружил, что есть разница в адресах инструкций, показанных между ltrace и objdump.

#include <iostream>
int main() {
    std::cout << "Hello";
    return 0;
}

Из следующей информации видно, что адрес [call std::basic_ostream] равен [0x400789] в ltrace. (0x400789 - это адрес инструкции call, а не std::basic_ostream)

binary@binary-VirtualBox:~/code/chapter5/test$ ltrace -i -C ./a.out
[0x4006a9] __libc_start_main(0x400776, 1, 0x7fff06c6ad28, 0x4007f0 <unfinished ...>
[0x4007b7] std::ios_base::Init::Init()(0x601171, 0xffff, 0x7fff06c6ad38, 160)             = 0
[0x4007cb] __cxa_atexit(0x400650, 0x601171, 0x601048, 0x7fff06c6ab00)                     = 0
[0x400789] std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)(0x601060, 0x400874, 0x7fff06c6ad38, 192) = 0x601060
[0x7f220180aff8] std::ios_base::Init::~Init()(0x601171, 0, 0x400650, 0x7f2201b96d10Hello)      = 0x7f2201f19880
[0xffffffffffffffff] +++ exited (status 0) +++

Однако адрес [call std::basic_ostream], показанный в objdump, равен [0x400784] и другая инструкция [mov eax,0x0] находится на [0x400789]. То же самое верно и для других команд «вызова».

0000000000400776 <main>:
  400776:       55                      push   rbp
  400777:       48 89 e5                mov    rbp,rsp
  40077a:       be 74 08 40 00          mov    esi,0x400874
  40077f:       bf 60 10 60 00          mov    edi,0x601060
  400784:       e8 d7 fe ff ff          call   400660 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
  400789:       b8 00 00 00 00          mov    eax,0x0
  40078e:       5d                      pop    rbp
  40078f:       c3                      ret    

Я действительно хочу знать, что вызывает разрыв. Спасибо большое.

Например, почему адрес функции и адрес, который вы видите в ltrace, не совпадают? Это, вероятно, в середине функции.

Fatih BAKIR 01.04.2022 07:32

Это адреса возврата (инструкция после call в родительском элементе; ltrace не может знать, как долго длилась инструкция, вызвавшая функцию, только адрес возврата, который она получила. Или, если бы она была вызвана хвостом, выполнение достигло бы ее из jmp или что-то в этом роде.

Peter Cordes 01.04.2022 07:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это адреса возврата (инструкция после call в родительском адресе, который call помещает в стек).

ltrace не может знать, как долго длилась инструкция, вызывающая функцию, например. call reg с указателем на функцию составляет всего 2 байта против 5 для call rel32 против 6 для call [RIP + rel32] (косвенный вызов памяти, который будет использовать GCC, если вы компилируете с -fno-plt.)

Или, если бы он был вызван хвостом, выполнение достигло бы его из jmp или чего-то еще, поэтому даже на ISA с инструкциями фиксированной длины, такими как MIPS или AArch64, ltrace все еще не мог надежно печатать, откуда он был вызван. Лучше не пытаться делать слишком много вещей и сохранять простоту, печатая адрес, который он действительно может видеть в стеке вызовов.

Другие вопросы по теме