В ходе разборок с 6060 обнаружилось, что текущий API бэктрейсов некорректно работает на M1. В то же время, для реализации 4002 планируется добавить новый API, который в том числе должен работать одинаково на всех поддерживаемых платформах. Предлагается перенести все бэктрейсы на этот API.
@alyapunov | @unera |
---|---|
– | – |
На данный момент есть одна функция, отвечающая за сбор бэктрейсов произвольной корутины:
backtrace_foreach()
для стека чужой корутины реализуется через сбор ее libunwind-контекста с последующим проходом по этому контексту в своем стеке для получения информации о фреймах.
callback_cb
– тип callback'а для обработки информации о фрейме (одинаковый для любого API бэктрейсов):
backtrace_foreach()
работает корректно только еслиcoro_context == NULL
.Основная идея API - отделение сбора общего (для Lua и С) контекста бэктрейса (backtrace_collect()
) от резолвинга информации о фреймах по данному контексту (backtrace_foreach()
) и объединения контекстов (backtrace_append()
).
API реализуется через такие же процедуры для Lua-контекста и C-контекста.
Для Lua-бэктрейсов фрейм хранит всю необходимую информацию о функции, для C-бэктрейсов сохраняется адрес исполняемого кода (значений регистра RIP) по аналогии с подходом backtrace()
и backtrace_symbols()
из <execinfo.h>
в Linux.
Все размеры буферов задаются статически, чтобы избавиться от необходимости аллокаций памяти.
Количество сохраняемых фреймов предлагается сделать достаточно большим чтобы иметь возможность сохранять бэктрейсы предков файберов:
Файбер хранит в себе экземпляр bt_ctx
, содержащий информацию о фиксированном числе фреймов его предков.
При выводе в fiber.info
собирается контекст текущего файбера, сливается с контекстом его предков и с помощью backtrace_foreach_ctx()
последовательно добавляется в нужную Lua - таблицу.
lj_BC_FUNCC
. В новой реализации необходимо изменить этот подход.Реализация разбивается на 3 основных этапа, первые 2 уже частично реализованы в патче для 4002 (см. PR)
Основная часть реализации будет привязана к патчсету для 6060, так как он вызвал необходимость поменять API.
С++
-имен для сохранения совместимости со старым API.unw_backtrace()
, для резолвинга фреймов – unw_get_accessors()->get_proc_name()
из внутреннего функционала libunwind. В случае отсутствия такого функционала используем unw_get_reg(UNW_REG_IP)
и dladdr()
соответственно.backtrace_foreach()
через новый API.