HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
0222
Flat割り込みが発生した場所を取得したい9解決


Flat

リンク

2015/2/22(Sun) 05:57:45|NO.67478

割り込みが発生した際、どこを実行していたのかを取得したいです。

onerror *error mes "a" err mes "b" *error mes "Error!" mes wparam stop
このスクリプトだとerrのところで割り込みが発生します。
そのerrの直前(mes "a"の直後)のPCポインタを取得することはできますか?
もし可能ならその方法を教えてくださるとありがたいです。
mcs、mcs_bak、stm_curのいずれかを取得するという方針を立ててみましたが、方法が考えつきませんでした。

割り込みの種類はgotoでもgosubでもどちらでも問題ありません。
ランタイム自体を改造したり各命令の後にコードを入れたりといった方法は避けたいです。



この記事に返信する


skyblue

リンク

2015/2/22(Sun) 10:38:27|NO.67479

>そのerrの直前(mes "a"の直後)のPCポインタを取得することはできますか?
PCポインタは意味が重複(プログラマカウンタポインタ)しているのでPCまたはIPと言いましょう。
PCはOS以外取得できません。それ以外はPCとは呼べません。意味が違いますので
普通は障害発生箇所とは言いますが。
質問の回答ですが、そういうものなので不可能です。
例えランタイムを改造したとしても難しいです。
errは例外や割り込みとは別物で名前の通りエラーを発生させるものです。
wparamやlparamはポインタや環境依存のハンドルを取得するためのものなのでPCとは別物です。
PC(IP)はメモリダンプした時の障害発生アドレスが相当します。



Flat

リンク

2015/2/22(Sun) 10:44:23|NO.67480

すみません、説明が抜けました。

PCポインタとは、
http://dev.onionsoft.net/trac/openhsp/browser/trunk/hsp3/hsp3code.cpp#L34
http://dev.onionsoft.net/trac/openhsp/browser/trunk/hsp3/hsp3code.cpp#L27
でのmcsのことを指しています。
この値が取得できれば目的が果たせるのですが…



Flat

リンク

2015/2/22(Sun) 10:49:45|NO.67481

errはonerrorでの割り込みを発生させるためにわざと書きました。



cats

リンク

2015/2/22(Sun) 11:32:16|NO.67482

openhspの方はあまり読んでいないのですが、mcsというのはEIPやRIPを指すのでしょうか。
それともHSPのインタプリタが持つ、機械語とは関係の無い内部のプログラムカウンタですか。



Flat

リンク

2015/2/22(Sun) 11:32:57|NO.67483

内部のプログラムカウンタのようです。



3k

リンク

2015/2/22(Sun) 13:21:01|NO.67484

「何のために?」はひとまず置いといて,状況が読み込めてないので質問を混ぜつつ個人的な見解をば.

> mcs、mcs_bak、stm_curのいずれかを取得するという方針を立ててみましたが、方法が考えつきませんでした。
これは『「mcs」や「mcsbak」などの変数が(OpenHSPを見て)存在することが分かったが,HSP側から取得する方法が分からない』というコトでしょうか?

「mcs」については,DLLやプラグイン作成者のためのマニュアル hspsdk -> hspdll.txt にあるように HSPCTX を介することによって取得可能…のようです.
ただ,確か「mcs」は現在実行中の命令のPCを持っているので,
「onerror後にエラー命令のPCを取る命令」を作ったとすると,「mcs」はその命令実行自体のPCになってしまうので今回の用途には不適かも,と思います.
(なお,詳細は割愛しますが確認したところHSPCTX内の mcs は値が入っていないので使えません(代入しているところがない),マニュアルとは一体…)

次,「mcsbak」についてですがこいつは外部に公開されてないっぽい(内部リンケージかつポインタはどこにも格納されていない)です.
HSPのエラー表示部分でデバッグ情報を取ってくる箇所でも「mcsbak」から計算しているので使えそうに思えますが,
「mcs」の時と似たような議論があるので本当にHSP側の命令からエラー場所とるときに使えるかはやってみないと微妙な気がします.
 (参考:デバッグ情報としてエラー行とってくるとこのコード http://dev.onionsoft.net/trac/openhsp/browser/trunk/hsp3/hsp3code.cpp#L2359

最後,「stm_cur」は「ptr」(HSPROUTINE)内に戻る場所のPC「mcsret」を保持しています.
「stm_cur」自体は非公開ですが,「stm_cur」”相当”のものは「関数・コマンド呼び出し」時に限り実は HSPCTX の prmstack から計算可能です.
 (参考: Stackからprmstackに代入しているところ http://dev.onionsoft.net/trac/openhsp/browser/trunk/hsp3/hsp3code.cpp#L1186

これを使えば「onerror」で飛んだ先でも戻ってくるPCがとれるかも,と思ったのですが「gosub」時はスタックには積むが HSPCTX へは反映されないのでどうやらとれなさそうです.
 (参考: gosubで他のコードにとぶところ http://dev.onionsoft.net/trac/openhsp/browser/trunk/hsp3/hsp3code.cpp#L1148


★結局どうなのか
散々長々と説明してきて残念な感じですが,

 ・「mcs」→(マニュアルでは参照できると書いてあるが)参照できない,ダメ
 ・「mcsback」→参照できない,ダメ
 ・「stm_cur」→(関数・コマンド呼び出し時にはいけそうだが)「gosub」では参照できない,ダメ

ということでダメっぽいです.
ただし,あくまで私の見解なので,うまく探せば何か手が見つかるかもしれません….


○参考:関数・コマンド呼び出し時にmcsretをとりだすコード

本当にただの補助情報として,となりますがこんな感じで,「関数・コマンド」の時は可能ではあります.

f stop #deffunc f mref hspctx, 68 mcs = lpeek( hspctx, 4 )// 常にnull mem_mcs = lpeek( hspctx, 8 ) prmstack = lpeek( hspctx, 828 )// addressof( HSPROUTINE -> prmstack ) hsproutine = 0 mcsret = 0 acpc = 0 if ( prmstack != 0 ) {// if not nullptr hsproutine = prmstack -4*5// - sizeof( HSPROUTINE ) dupptr ihsproutine, hsproutine, 4*5 mcsret = lpeek( ihsproutine, 4 ) acpc = mcsret - mem_mcs// 中間コード的には何Byte目か } // print them mes "mcs="+mcs mes "mem_mcs="+mem_mcs mes "prmstack="+prmstack mes "hsproutine="+hsproutine mes "mcsret="+mcsret// 戻る箇所のPC : 実体はunsigned short*でラベル値と等価 mes "acpc="+acpc return

他にも(ほぼ隠れ)命令として「newlab」などどこでもでPC(ラベル値)を取り出すことが可能ではあるのですけどね….



Flat

リンク

2015/2/22(Sun) 13:54:28|NO.67485

>>3kさん
できました!
割り込み先で関数を呼び出し、一個前のスタックを参照することで見事にPCを取得することができました!
一応ソースコードを載せておきます。

onerror gosub *error mes "a" err mes "b" stop *error onerror 0 mes f stop #deffunc f mref hspctx, 68 mcs = lpeek( hspctx, 4 )// 常にnull mem_mcs = lpeek( hspctx, 8 ) prmstack = lpeek( hspctx, 828 )// addressof( HSPROUTINE -> prmstack ) hsproutine = 0 mcsret = 0 acpc = 0 if ( prmstack != 0 ) {// if not nullptr hsproutine = prmstack -72 -4*5// - sizeof( STMDATA ) - sizeof( HSPROUTINE ) dupptr ihsproutine, hsproutine, 4*5 mcsret = lpeek( ihsproutine, 4 ) acpc = mcsret - mem_mcs// 中間コード的には何Byte目か } // print them mes "mcs="+mcs mes "mem_mcs="+mem_mcs mes "prmstack="+prmstack mes "hsproutine="+hsproutine mes "mcsret="+mcsret// 戻る箇所のPC : 実体はunsigned short*でラベル値と等価 mes "acpc="+acpc return



3k

リンク

2015/2/22(Sun) 14:04:34|NO.67486

>> Flatさん
おー,なるほど,「gosub」のスタック分からないけど後からprmstackに乗っけるのはOKだからそっちから計算しちゃうわけですね.
なかなか面白いもの見れました,ありがとうございますー!



skyblue

リンク

2015/2/22(Sun) 16:43:16|NO.67487

ラベル値やmcsなどはPCとはいささか違うような気がします。
特にラベル値は違います。
mcsは現在の命令アドレスを指すと書かれていますので、
本来のPCの役目は次の命令のアドレスを指すものなので違いが明確です。
本来、PCはソフトウェア側から簡単に変更できてはいけないものなので特にです。



ONION software Copyright 1997-2021(c) All rights reserved.