Какие библиотеки разворачивания стека существуют и в чем разница?

Пытаясь создать свою собственную не-GNU кроссплатформенную среду C ++, я столкнулся с тем фактом, что я не совсем понимаю основы раскрутки стека. Среда, которую я создаю, выглядит следующим образом:

libc++libc++abilibunwind (или какой-то другой раскручивать).

Я нашел это libc++abi уже содержит какой-то libunwind, но не использует его в Linux. Из комментариев я понял, что это специальный libunwind: LLVM Stack Unwinder, который поддерживает только Darwin и ARM, но не x86_64 — и это сбивает с толку. Как получилось, что архитектура процессора влияет на процесс раскручивания стека?

Также я знаю о следующих разматывателях стека:

  1. glibc встроенный.
  2. libc ++ abi LLVM libunwind.
  3. GNU libunwind (из саванны).

Вопросы:

  1. Как архитектура платформы или процессора влияет на процесс раскручивания стека?
  2. Зачем иметь много разматывателей, а не только один?
  3. Какие виды наматывания существуют и в чем разница между ними?

Ожидания от ответа:

Я ожидаю получить ответ, который охватывает эту тему в целом, а не только отдельные вопросы по каждому вопросу.

7

Решение

По сути, компоновка стека зависит от компилятора. Он может выложить стек практически любым удобным для него способом. Стандарт языка ничего не говорит о том, как устроен стек.

На практике разные компиляторы размещают стек по-разному, и один и тот же компилятор может также размещать его по-разному при запуске с разными параметрами. Расположение стека будет зависеть от размера типов на целевой платформе (особенно от размера типов указателей), таких опций компилятора, как GCC -fomit-frame-pointerТребования ABI платформы (например, x64 имеет определенный ABI, а x86 — нет). Способ интерпретации стека также будет зависеть от того, как компилятор хранит соответствующую информацию. Это, в свою очередь, частично зависит от формата исполняемого файла (в наши дни это может быть либо ELF, либо COFF, но на самом деле, пока ОС может загрузить исполняемый файл и найти точку входа, все остальное в значительной степени готово к захвату) и частично на отладке. формат информации — опять же специфичный для используемой комбинации компилятор / отладчик. В конце концов, вполне возможно написать встроенный ассемблер, который управляет стеком и потоком программы таким образом, чтобы нет Размотчик сможет следить. Некоторые компиляторы также позволяют настраивать пролог и эпилог функции, предоставляя вам еще одну возможность запутать любой алгоритм раскрутки.

Общий эффект всего этого заключается в том, что невозможно написать единственный алгоритм раскрутки стека, который будет работать везде. Алгоритм раскручивания должен соответствовать компилятору, ОС и, для большей информации, отладчику. Лучшее, что вы можете сделать, — это написать простой интерфейс для разворачивания стека и реализовать его по-разному для каждой поддерживаемой вами комбинации компилятор / ОС / отладчик.

2

Другие решения


По вопросам рекламы [email protected]