никогда ничего не было записано. Я пытался найти соглашение о вызовах OCaml, чтобы я мог вручную интерпретировать трассировки стека, которые gdb не может проанализировать. К сожалению, кажется, что ничего никогда не было записано на английском языке, кроме общих замечаний. Например, в блогах люди будут комментировать, что OCaml передает много аргументов в регистры. (Если где-то есть документация на английском языке, буду признательна за ссылку.)
Итак, я пытался разгадать это из источника окамлопта.Кто-нибудь может подтвердить правильность этих догадок?
И, если я прав насчет того, что первые десять аргументов передаются в регистры, неужели вообще невозможно восстановить аргументы для вызова функции? В C аргументы все равно будут помещаться куда-нибудь в стек, если только я вернусь к нужному фрейму. В OCaml кажется, что вызываемые объекты могут уничтожать аргументы своих вызывающих объектов.
Распределение регистров(из/asmcomp/amd64/proc.ml
)
Для вызова функций OCaml
Для вызова функций C используется стандартное соглашение amd64 C :
. Обратный адрес(из/asmcomp/amd64/emit.mlp
)
Адрес возврата — это первый указатель, помещаемый в кадр вызова, в соответствии с соглашением amd64 C. (Я предполагаю, что инструкция ret
предполагает такую компоновку.)
Исключения(из/asmcomp/linearize.ml
)
Код try (...body...) with (...handler...); (...rest...)
линеаризуется следующим образом:
Lsetuptrap.body
(...handler...)
Lbranch.join
Llabel.body
Lpushtrap
(...body...)
Lpoptrap
Llabel.join
(...rest...)
а затем выпускается в виде сборки, подобной этой (места назначения справа):
call.body
(...handler...)
jmp.join
.body:
pushq %r14
movq %rsp, %r14
(...body...)
popq %r14
addq %rsp, 8
.join:
(...rest...)
Где-то в теле есть линеаризованный код операции Lraise
, который генерируется как эта точная сборка :
movq %r14, %rsp
popq %r14
ret
. Что действительно аккуратно! Вместо этого setjmp/longjmp мы создаем фиктивный фрейм, адрес возврата которого является обработчиком исключений, и единственным локальным адресом которого является предыдущий такой фиктивный фрейм. В /asmcomp/amd64/proc.ml
есть комментарий, в котором $r14 называется «указатель ловушки», поэтому я буду называть этот фиктивный кадр кадром-ловушкой. Когда мы хотим вызвать исключение, мы устанавливаем указатель стека на самый последний кадр ловушки, устанавливаем указатель ловушки на кадр ловушки перед ним, а затем «возвращаемся» в обработчик исключений. Бьюсь об заклад, если обработчик исключений не сможет обработать это исключение, он просто вызовет его повторно.
Исключение составляет %eax.