OberonCore https://forum.oberoncore.ru/ |
|
#017 Консольный дамп из ядра и GetRefFrame https://forum.oberoncore.ru/viewtopic.php?f=134&t=6550 |
Страница 1 из 1 |
Автор: | adimetrius [ Суббота, 08 Февраль, 2020 23:37 ] |
Заголовок сообщения: | #017 Консольный дамп из ядра и GetRefFrame |
Коллеги, предлагаю улучшить ядро. Опять ). Предлагаю дополнить его средством консольной "раскрутки стека" при авосте. Исключительно необходимая вещь при системном программировании, поскольку красивые ББ-шные стеки далеко не всегда могут быть показаны при системных ошибках. Вот пример консольного дампа, заимствован у Ивана Андреевича Денисова: ivan@debian:~/bbcp/BlackBox$ ./blackbox TRAP 21 (precondition violated) 0: Ports.Port.Init [@=1841] <PC=0000002C FP=FFA0160C> 1: HostWindows.Directory.Open [@=34116] <PC=000032A1 FP=FFA01634> 2: StdDialog.Open [@=8136] <PC=00000EFD FP=FFA01990> 3: StdLog.Open [@=3796] <PC=00000541 FP=FFA01BD0> 4: Kernel.Call [@=37184] <PC=00002397 FP=FFA01BFC> Как видите, за образец принят обычный ББ-шный дамп (трамп = трап-дамп:) Чтобы сделать это счастье системщикам, я переделал DefaultTrapViewer и то, как он в ядре вызывается. Затем я наткнулся на проблему повторных авостов - тех, которые возникают во время обработки ранее возникшего авоста. И, чтобы ББ не падал молча, пришлось еще больше правок внести в механизм отработки авостов. Поскольку эту работу я проделывал в тесном контакте с Иваном Андреичем, она внесена в ядро 1,8 и там может быть прочитана, попробована и критикована. Поскольку обход стека используется не только при авосте, я выделил его в отдельный механизм в ядре. Он не экспортирован )). Однако, кмк, он хорош, и относится к разряду средств метапрограммирования или рефлексии - похож на GetRefProc и GetRefVar. Поэтому называется GetRefFrame. Поскольку интерфейс ядра нужно беречь, и "пальцами и яйцами в солонку не тыкать", интерфейс GetRefFrame не экспортирован. Однако для своих нужд в другом модуле я дублирую этот код; это вполне возможно, и не опирается ни на какие другие секретные внутренности ядра. Мне было бы удобно, если бы ядро этот интерфейс опубликовало. Сначала пробовали разместить эти средства в Services, однако, поскольку они используются именно в самом ядре, это оказалось невозможным. Приглашаю заинтересованных лиц вникнуть в предложение и высказать свою конструктивную критику и предложения. Вникнуть можно, скачав версию 1.8. (На днях туда из "горящего хобота" добавятся поправки для повторных авостов). |
Автор: | adimetrius [ Суббота, 08 Февраль, 2020 23:40 ] |
Заголовок сообщения: | Re: Консольный дамп из ядра и GetRefFrame |
Если бы интерфейс GetRefFrames экспортировался, то его документация была бы примерно такой: FrameDesc* = RECORD (** Activation frame descriptor. *) m*: Ident; (** m and p identify the procedure that the frame belongs to *) p*: Ident; depth*: INTEGER; (** depth of this frame: it's distance, in frames, from top of stack, or from the activation frame that was used to initialize FrameDesc with GetThisRefFrame *) pos*: INTEGER; (** position in source text of the call of m.p that created this frame, if available; -1 => pc outside of BB; -2: module unloaded *) ref-: INTEGER; (** reference number to be used with GetRefVar to explore m.p's frame vars *) pc-: ADDRESS; (** address within the instruction that called m.p (instructions are multibyte) *) fp-: ADDRESS; (** m.p's frame pointer, i.e. address of the frame *) eos-: BOOLEAN (** end of stack *) END; PROCEDURE GetThisRefFrame* (VAR fr: FrameDesc; pc, fp: ADDRESS); (** Initializes fr with descriptor of activation frame anchored with fp and belonging to procedure that pc belongs to (or points into). Инициализирует fr и помещает в нее дескриптор кадра с базовым адресом fp и принадлежащей процедуре, которой принадлежит команда по адресу pc. Например, если текущее значение регистра EIP присвоить pc, а регистра EBP присвоить fp, то fr будет содержать дескриптор текущей активации. GetThisRefFrame не производит никаких проверок и не гарантирует безопасности: если ей передать произвольные или ошибочные значения, fr будет гарантированно содержать мусорные данные. Используйте на свой страх и риск. GetThisRefFrame может быть полезна для узкого круга системных низкоуровневых задач, когда точно известно сочетание pc/fp в текущей цепочке вызовов; пример использования - в обработчике авостов.*) PROCEDURE GetRefFrame* (VAR fr: FrameDesc); (* based on Kernel.DefaultTrapView *) (** Allows to 'scan' thru the current activation chain frames (call stack). Assuming the current call chain is P0 -> P1 -> Pn -> GetRefFrame, and 'Frame/P' stands for 'activation frame of procedure P', the following postcondition describes GetRefFrame: Post fr is not initialized fr' = Frame/Pn (* returns the frame description of caller of GetRefFrame *) fr = Frame/Pn fr' = Frame/Pn-1 (* goes back one step in the activation chain and returns the description of that frame *) Позволяет получить дескрипторы процедурных кадров в текущей цепочке вызовов (стек вызовов). Пусть P0 -> P1 -> ... Pn -> GetRefFrame - текущая цепочка вызовов, а 'Frame/P' обозначает дескриптор активации процедуры P. Тогда следующее постусловие описывает GetRefFrame: Post fr не инициализирована fr' = Frame/Pn (* fr инициализирована и содержит дескриптор кадра процедуры, вызвавшей GetRefFrame *) fr = Frame/Pn fr' = Frame/Pn-1 (* возвращается на шаг назад по цепочке вызовов *) Т.о. для инициализации fr достаточно вызвать GetRefFrame(fr), и fr будет содержать "собственный" дескриптор кадра процедуры, вызвавшей GetRefFrame. Полный обход текущей цепочки активации обеспечивается так: GetRefFrame(fr); REPEAT ... GetRefFrame(fr) UNTIL fr.eos GetRefFrame безопасна, если fr инициализирована ею же. Другой способ - инициализировать fr с помощью GetThisRefFrame. В этом случае GetRefFrame небезопасна (т.е. может привести к бесконечным циклам и авостам).*) |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |