source: azure_iot_hub/trunk/asp3_dcre/tecsgen/tecslib/plugin/HRPSVCPlugin.rb@ 389

Last change on this file since 389 was 389, checked in by coas-nagasima, 5 years ago

ビルドが通るよう更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 33.6 KB
Line 
1# coding: utf-8
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2018 by TOPPERS Project
7#--
8# 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
9# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
10# 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
11# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
12# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13# スコード中に含まれていること.
14# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
15# 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
16# 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
17# の無保証規定を掲載すること.
18# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
19# 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
20# と.
21# (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22# 作権表示,この利用条件および下記の無保証規定を掲載すること.
23# (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
24# 報告すること.
25# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
26# 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
27# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
28# 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
29# 免責すること.
30#
31# 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
33# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
34# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
35# の責任を負わない.
36#
37# $Id$
38#++
39
40# mikan through plugin: namespace が考慮されていない
41# これを利用する場合、以下のように toppers_jsp.cdl sChannel.cdl を指定する必要がある
42# tecsgen toppers_jsp.cdl sChannel.cdl your_description.cdl
43
44# 以下を仮定(制限事項)
45# 呼び元、呼び先のエンディアン、char, short, int_t, long_t, intptr_t のサイズが同じ
46# 有符号、無符号でサイズが同じ
47
48class SVCManage
49 #
50 # @@id: TECSのプラグインで生成した拡張サービスコールに割り当てるid
51 # 実際の拡張サービスコールIDは,TFN_TECSGEN_ORIGINで下駄を
52 # 履かせた値となる
53 # TFN_TECSGEN_ORIGINは,hrp3/include/extsvc_fncode.h で定義
54 # される
55 # @@func_ids: 拡張サービスコールの関数名と拡張サービスコールIDを
56 #    対応づけるハッシュ
57 #
58 @@id = 0
59 @@func_ids = {}
60 def initialize()
61 #
62 # 本クラスはインスタンスを持たない仮想的なクラスである
63 #
64 raise "class #{self.class.name} shall not have instances"
65 end
66 def self.get_func_id func_name
67 return @@func_ids[ func_name ]
68 end
69 def self.set_func_id func_name
70 @@func_ids[ func_name ] = self.assign_id
71 # puts @@func_ids[ func_name ]
72 end
73 def self.get_id
74 return @@id
75 end
76 def self.set_id id
77 @@id = id
78 end
79 def self.assign_id
80 assignedId = @@id
81 @@id += 1
82 return assignedId
83 end
84end
85
86#
87# 拡張サービスコールを用いたドメイン間通信の
88# throughプラグイン
89# HRPドメインプラグインによって挿入される
90# 前提条件: 呼出し先がカーネルオブジェクトかどうかの判定はHRPドメインプラグイン
91#      で実施されるため,ここでは判定しないこととした
92#
93class HRPSVCPlugin < ThroughPlugin
94
95 NUM_SVC_ARG_MAX = 5 # HRP3 の拡張サービスコールで扱うことのできる引数の最大個数
96
97 @@generated_celltype ={} # セルタイプの重複排除用
98 @@generated_cell = {} # セルの重複排除用
99
100 def initialize( cell_name, plugin_arg, next_cell, next_cell_port_name, next_cell_port_subscript, signature, celltype, caller_cell )
101 super
102
103 # 受け口配列の場合、配列添数ごとに別のセルタイプとする
104 # セルタイプをシングルトン化したいため。
105 # さもないと、セルを識別する引数を渡す必要があり、NUM_SVC_ARG_MAX(5) つしか渡せない引数の一つを消費することになるため。
106 if @next_cell_port_subscript then
107 subscript = "__" + @next_cell_port_subscript.to_s
108 else
109 subscript = ""
110 end
111 @ct_name_body = "#{@ct_name}SVCBody_#{@next_cell.get_name}_#{@next_cell_port_name}#{subscript}".to_sym
112 @ct_name = "#{@ct_name}SVCCaller_#{@next_cell.get_name}_#{@next_cell_port_name}#{subscript}".to_sym
113 @cell_name_body = "#{@cell_name}SVCBody".to_sym
114 @cell_name = "#{@cell_name}SVCCaller".to_sym
115 # puts "%%%% "
116 # p @next_cell.get_name
117 # p @caller_cell.get_name
118 @b_printed_include_stdint = false
119 check_signature signature
120 end
121
122 #=== NamespacePath を得る
123 # 生成するセルの namespace path を生成する
124 def get_cell_namespace_path
125# nsp = @region.get_namespace.get_namespace_path
126 nsp = @start_region.get_namespace_path
127 return nsp.append( @cell_name )
128 end
129
130 def gen_plugin_decl_code( file )
131
132 # このセルタイプ(同じシグニチャ)は既に生成されているか?
133 if @@generated_celltype[ @ct_name_body ] == nil then
134 @@generated_celltype[ @ct_name_body ] = [ self ]
135 file2 = CFile.open( "#{$gen}/#{@ct_name_body}.cdl", "w" )
136 file2.print <<EOT
137import_C( "t_stdlib.h" );
138
139/* HRPSVC0001 */
140[active,singleton]
141celltype #{@ct_name_body} {
142 call #{@signature.get_name} #{@call_port_name};
143 FACTORY {
144 write("$ct$_tecsgen.h", "#include \\"kernel_cfg.h\\"");
145 };
146};
147EOT
148 file2.close
149 else
150 @@generated_celltype[ @ct_name_body ] << self
151 end
152 file.print "import( \"#{$gen}/#{@ct_name_body}.cdl\" );\n"
153
154 # このセルタイプ(同じシグニチャ)は既に生成されているか?
155 if @@generated_celltype[ @ct_name ] == nil then
156 @@generated_celltype[ @ct_name ] = [ self ]
157 file2 = CFile.open( "#{$gen}/#{@ct_name}.cdl", "w" )
158 file2.print <<EOT
159/* HRPSVC0002 */
160celltype #{@ct_name} {
161 entry #{@signature.get_name} #{@entry_port_name};
162 FACTORY {
163 write("$ct$_tecsgen.h", "#include \\"extsvc_fncode.h\\"");
164 };
165};
166EOT
167 file2.close
168 else
169 @@generated_celltype[ @ct_name ] << self
170 end
171 file.print "import( \"#{$gen}/#{@ct_name}.cdl\" );\n"
172
173=begin
174 # TODO: send. receive 対応
175 send_receive = []
176 if @signature != nil then
177 @signature.each_param{ |fd,param|
178 dir =param.get_direction
179 case dir
180 when :SEND, :RECEIVE
181 send_receive << [ dir, fd, param ]
182 end
183 }
184 end
185=end
186
187=begin
188composite #{@ct_name} {
189 entry #{@signature.get_name} #{@entry_port_name};
190 call #{@signature.get_name} #{@call_port_name};
191
192 cell #{@ct_name}Client #{@cell_name}Client{
193 };
194
195 [active]
196 cell #{@ct_name}Server #{@cell_name}Server{
197 #{@call_port_name} => composite.#{@call_port_name};
198 };
199
200 composite.#{@entry_port_name} => #{@cell_name}.#{@entry_port_name};
201};
202=end
203
204 end
205
206 #=== through cell コードを生成
207 #
208 #
209 def gen_through_cell_code( file )
210
211 # gen_plugin_decl_code( file ) this is called from super.
212
213 # セルを探す
214 # path =["::",@next_cell.get_name] # mikan namespace
215 # cell = Namespace.find( path )
216 # cell = Namespace.find( @next_cell.get_namespace_path )
217
218 ##### クライアント側のセルの生成 #####
219 # file.print "[domain(HRP, \"kernel\")]"
220 nest = @start_region.gen_region_str_pre file
221 nest_str = " " * nest
222
223 # クライアント側チャンネルの生成
224 # 拡張サービスコール呼出し
225 file.print <<EOT
226/* HRPSVC0003 */
227#{nest_str} // Client Side Channel
228#{nest_str} cell #{@ct_name} #{@cell_name}{
229#{nest_str} };
230
231EOT
232
233 @start_region.gen_region_str_post file
234 file.print "\n\n"
235
236 ##### サーバー側のセルの生成 #####
237 # print "###### #{@cell_name_body} ... #{@ct_name_body} #{@@generated_cell[ @ct_name_body ].class} #####\n"
238
239 if @@generated_cell[ @ct_name_body ] then
240 file.print "/* cell #{@ct_name_body} #{@@generated_cell[ @ct_name_body ]}: already generated. */\n"
241 else
242 @@generated_cell[ @ct_name_body ] = @cell_name_body
243 nest = @end_region.gen_region_str_pre file
244 nest_str = " " * nest
245 if @next_cell_port_subscript then
246 subscript = '[' + @next_cell_port_subscript.to_s + ']'
247 else
248 subscript = ""
249 end
250
251 # サーバー側チャンネルの生成
252 # 拡張サービスコール本体
253 file.print <<EOT
254
255/* HRPSVC0004 */
256#{nest_str} // Server Side Channel
257#{nest_str} cell #{@ct_name_body} #{@cell_name_body}{
258#{nest_str} #{@call_port_name} = #{@next_cell.get_namespace_path.get_path_str}.#{@next_cell_port_name}#{subscript};
259#{nest_str} };
260EOT
261
262 @end_region.gen_region_str_post file
263
264 file2 = AppFile.open( "#{$gen}/tecsgen.cfg" )
265 file2.print "\n/* Generated by HRPSVCPlugin */\n\n"
266 file2.print <<EOT
267/* HRPSVC0005 */
268#include "#{@ct_name_body}_factory.h"
269EOT
270 file2.close
271
272 # callee_cell のget_restricted_regions を呼び出しておく
273 # restrict が参照された印をつけるため
274 @callee_cell.get_restricted_regions( :dummy_entry_name, :dummy_func_name )
275 end
276 end
277
278 #=== 受け口関数の本体(C言語)を生成する
279 # 通常であれば、ジェネレータは受け口関数のテンプレートを生成する
280 # プラグインの場合、変更する必要のないセルタイプコードを生成する
281 #file:: FILE 出力先ファイル
282 #b_singleton:: bool true if singleton
283 #ct_name:: Symbol
284 #global_ct_name:: string
285 #sig_name:: string
286 #ep_name:: string
287 #func_name:: string
288 #func_global_name:: string
289 #func_type:: class derived from Type
290 def gen_ep_func_body( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )
291 # puts "generate ep_func for #{ct_name}"
292
293 #
294 # 拡張サービスコール呼出し側の関数生成
295 #
296 # 完成形のイメージ
297 #
298 # ER_UINT
299 # eThroughEntry_write(CELLIDX idx, const char* buffer, uint_t length)
300 # {
301 # ER_UINT retval;
302 # tHRPSVCPlugin_<Sig>SVCCaller_<Cell>_<Entry>_CB *p_cellcb;
303 # if( VALID_IDX( idx ) ){
304 # p_cellcb = tHRPSVCPlugin_<Sig>SVCBody_<Cell>_<Entry>_GET_CELLCB(idx);
305 # }else{
306 # /* エラー処理コードをここに記述 */
307 # }
308 #
309 # retval = (ER_UINT)cal_svc( TFN_TECSGEN_ORIGIN + svcid,
310 # (intptr_t)par1, (intptr_t)par2, 0, 0, 0 );
311 #
312 # return retval;
313 # }
314
315 if ! func_type.get_type.kind_of?( VoidType ) then
316 file.print( " #{func_type.get_type_str} retval;\n" )
317 end
318
319 # p "celltype_name, sig_name, func_name, func_global_name"
320 # p "#{ct_name}, #{sig_name}, #{func_name}, #{func_global_name}"
321
322 delim = ""
323 if ! func_type.get_type.kind_of?( VoidType ) then
324 file.print( " retval = (#{func_type.get_type_str})" )
325 else
326 file.print( " " )
327 end
328
329 #file.print( "#{@call_port_name}_#{func_name}(" )
330 SVCManage.set_func_id( "#{@ct_name_body}_#{func_name}" )
331 svcid = SVCManage.get_func_id( "#{@ct_name_body}_#{func_name}" )
332 #file.print( "cal_svc( #{@ct_name_body}_#{func_name}" )
333 file.print( "cal_svc( TFN_TECSGEN_ORIGIN + #{svcid.to_s}" )
334
335 # if ( ! b_singleton ) then
336 # file.print( " tecs_this" )
337 # delim = ","
338 # end
339
340 i = 0
341 passed_param = {}
342 params.each{ |param|
343 delim = ","
344 file.printf( "#{delim} (intptr_t)#{param.get_name}" )
345 passed_param[i] = param.get_name
346 i += 1
347 }
348
349 while(i < NUM_SVC_ARG_MAX) do
350 delim = ","
351 file.printf( "#{delim} 0" )
352 passed_param[i] = "par#{i+1}"
353 i += 1
354 end
355
356 file.print( " );\n\n" )
357
358 if ! func_type.get_type.kind_of?( VoidType ) then
359 file.print( " return retval;\n" )
360 end
361
362 #
363 # 拡張サービスコール本体側の関数生成
364 #
365 # 完成形のイメージ
366 #
367 # ER_UINT
368 # eThroughEntry_write(CELLIDX idx, const char* buffer, uint_t length)
369 # {
370 # ER_UINT retval;
371 # tHRPSVCPlugin_<Sig>SVCBody_<Cell>_<Entry>_CB *p_cellcb;
372 # if( VALID_IDX( idx ) ){
373 # p_cellcb = tHRPSVCPlugin_<Sig>SVCBody_<Cell>_<Entry>_GET_CELLCB(idx);
374 # }else{
375 # /* エラー処理コードをここに記述 */
376 # }
377 #
378 # retval = (ER_UINT)cal_svc( TFN_TECSGEN_ORIGIN + svcid,
379 # (intptr_t)par1, (intptr_t)par2, 0, 0, 0 );
380 #
381 # return retval;
382 # }
383 file2 = AppFile.open( "#{$gen}/#{@ct_name_body}.c" )
384 if @b_printed_include_stdint == false then
385 file2.print <<EOT
386#ifndef SIZE_MAX
387#define SIZE_MAX (~0UL)
388#endif
389
390EOT
391 @b_printed_include_stdint = true
392 end
393
394 if func_type.get_type.kind_of?( VoidType ) then
395 retval_assign = ""
396 else
397 retval_assign = "retval = (ER_UINT)"
398 end
399
400 file2.print <<EOT
401/* HRPSVC0006 */
402ER_UINT
403#{@ct_name_body}_#{func_name}(intptr_t #{passed_param[0]}, intptr_t #{passed_param[1]}, intptr_t #{passed_param[2]}, intptr_t #{passed_param[3]}, intptr_t #{passed_param[4]}, ID cdmid)
404{
405 ER_UINT retval = E_OK;
406
407EOT
408
409 #
410 # エラーチェック処理の生成
411 #
412
413 #
414 # 呼出し元ドメインのチェック
415 # * private method: gen_caller_check_code参照
416 #
417 generated_check_code = gen_caller_check_code(func_name)
418 check_code = generated_check_code["check_code"]
419 user_cannot_callable = generated_check_code["user_cannot_callable"]
420
421 #
422 # パラメータにポインタが存在する場合,呼出し元タスクに対する
423 # アクセス権のチェック処理を出力する
424 # ※ cdmidがカーネルドメイン(拡張サービスコール呼出し中のユーザ
425 # ドメインを含む)であればprb_memの処理をスキップし,初段の
426 # 拡張サービスコールのみprb_memを呼出し元タスクに発行する
427 #
428 num = 0
429 params.each{ |param|
430 if param.get_declarator.get_ptr_level > 0 then
431 align_check_str = "!ALIGN_TYPE(#{passed_param[num]}, #{param.get_type.get_referto.get_type_str}) || "
432
433 if param.get_type.get_referto.kind_of?(IntType) then
434 case param.get_type.get_referto.get_bit_size
435 when -11, -1, 8 # char, char_t, int8_t (無符号含む)
436 #
437 # charデータの場合,ALIGN_TYPEは必ずTRUE
438 # となるので,エラーチェックを省略
439 # char型の@bit_sizeは-11
440 # tecsgen/tecslib/core/types.rbを参照
441 #
442 align_check_str = ""
443 end
444 end
445 if param.get_direction == :IN then
446 #
447 # 入力([in])のポインタパラメータは,呼出し元タスクに
448 # TPM_READ(読出し可能)のアクセス権が必要
449 #
450 # 二重ポインタが不可のため、size_is と string が同時に設定されることはない
451 prb_func = "prb_mem"
452 if param.get_size then
453 size_str = param.get_size.to_s
454 elsif param.get_string == -1 then
455 size_str = "SIZE_MAX"
456 prb_func = "prb_str"
457 elsif param.get_string then
458 size_str = param.get_string.to_s
459 prb_func = "prb_str"
460 else
461 size_str = "1"
462 end
463 check_code.concat <<EOT
464 /* HRPSVC0007 */
465 if (#{align_check_str}#{prb_func}((void *)#{passed_param[num]}, sizeof(#{param.get_type.get_referto.get_type_str}) * (#{size_str}), TSK_SELF, TPM_READ) != E_OK) {
466 return E_MACV;
467 }
468EOT
469
470 elsif param.get_direction == :OUT || param.get_direction == :INOUT then
471 #
472 # 出力([out])のポインタパラメータは,呼出し元タスクに
473 # TPM_WRITE(書込み可能)のアクセス権が必要
474 #
475 prb_func = "prb_mem"
476 if param.get_size then
477 size_str = param.get_size.to_s
478 elsif param.get_string then # 引数なしの string はない
479 size_str = param.get_string.to_s
480 # prb_func = "prb_str" # out, inout の場合、必ず領域を確保する. prb_mem を用いる
481 else
482 size_str = "1"
483 end
484 check_code.concat <<EOT
485 /* HRPSVC0008 */
486 if (#{align_check_str}#{prb_func}((void *)#{passed_param[num]}, sizeof(#{param.get_type.get_referto.get_type_str}) * (#{size_str}), TSK_SELF, TPM_WRITE) != E_OK) {
487 return E_MACV;
488 }
489EOT
490
491 end
492 end
493 num += 1
494 }
495
496 #
497 # 呼出し元がカーネルドメインのみ許可されている場合,
498 # すべてのユーザドメインからの呼出しに対し,E_OACVを返す
499 #
500 if user_cannot_callable
501 check_code = "\t\treturn E_OACV;"
502 end
503
504 if check_code != ""
505 #
506 # 呼出し元がカーネルドメインの場合,アクセス権のチェック
507 # 処理をスキップさせる
508 #
509 file2.print <<eot
510 if (cdmid != TDOM_KERNEL) {
511#{check_code}
512 }
513eot
514 end
515
516 #
517 # 拡張サービスコール本体(本来の受け口関数)を呼び出す
518 #
519 file2.print" #{retval_assign}#{@call_port_name}_#{func_name}("
520
521 delim = ""
522 num = 0
523 params.each{ |param|
524 file2.print "#{delim}"
525 delim = ", "
526 file2.print "(#{param.get_type.get_type_str})"
527 file2.print passed_param[num]
528 file2.print param.get_type.get_type_str_post
529 num += 1
530 }
531
532 file2.print ");\n"
533
534 file2.print "\n return retval;\n"
535 file2.print "}\n\n"
536
537 file2.close
538
539 #
540 # 拡張サービスコールの登録
541 #
542 file2 = AppFile.open( "#{$gen}/tecsgen.cfg" )
543 file2.print "\n/* Generated by HRPSVCPlugin */\n\n"
544 file2.print <<EOT
545/* HRPSVC0009 */
546KERNEL_DOMAIN{
547 DEF_SVC( TFN_TECSGEN_ORIGIN + #{svcid.to_s}, { TA_NULL, #{@ct_name_body}_#{func_name}, SSZ_#{func_global_name} } );
548}
549EOT
550 file2.close
551
552 #
553 # 拡張サービスコール登録に必要な情報をヘッダに出力
554 # - 拡張サービスコール呼出し時のチェックで使用するスタックサイズを出力
555 # - 拡張サービスコールとして登録する関数名のextern宣言を出力
556 #
557 file2 = AppFile.open( "#{$gen}/#{@ct_name_body}_factory.h" )
558 file2.print "\n/* Generated by HRPSVCPlugin */\n\n"
559 file2.print <<EOT
560/* HRPSVC0010 */
561#ifndef SSZ_#{func_global_name}
562#define SSZ_#{func_global_name} DefaultExtsvcStackSize
563#endif /* SSZ_#{func_global_name} */
564
565/* HRPSVC0011 */
566extern ER_UINT #{@ct_name_body}_#{func_name}(intptr_t par1, intptr_t par2, intptr_t par3, intptr_t par4, intptr_t par5, ID cdmid);
567EOT
568 file2.close
569 end
570
571 def get_callee_cell
572 return @callee_cell
573 end
574
575 def get_caller_cell
576 return @caller_cell
577 end
578
579 def get_callee_ep_name
580 return @join.get_port_name
581 end
582
583 private
584 #
585 # 拡張サービスコール本体における,呼出し元チェックのコードを
586 # 出力する
587 # gen_ep_func_body からのみ呼び出される
588 # 引数: 対象の関数名
589 # 返り値: 下記のハッシュ
590 # {"check_code"=>出力するエラーチェックコード,
591 # "user_cannot_callable"=>ユーザドメインが呼出し不可能かどうかのフラグ}
592 #
593 def gen_caller_check_code(func_name)
594 dbgPrint "gen_caller_check_code(func_name): #{@callee_cell.get_name}\n"
595 #
596 # エラーチェック処理
597 #
598 check_code = ""
599 user_cannot_callable = false
600 all_domain_callable = false
601 caller_unrestricted = false
602
603 #
604 # 呼出し元ドメインのチェック処理
605 # callable_domains: 拡張サービスコールを呼出し可能なドメインのリスト
606 # - 無所属のセルから結合されている場合,すべてのセルに対して,
607 #  callable?をチェックし,呼出し可能なすべてのドメインを返す
608 # - 無所属以外のセルから結合されている場合,そのセルに対して
609 # callable?をチェックし,呼出し可能であれば,そのドメインを返す
610 #
611 callable_domains = []
612 @@generated_celltype[ @ct_name_body ].each { |svcplugin|
613 if svcplugin.get_caller_cell.get_region.get_domain_root.get_domain_type.get_option == "OutOfDomain"
614 # 無所属かつ active な場合も、restrict に従う
615 # if svcplugin.get_caller_cell.get_celltype.is_active?
616 # #
617 # # 無所属かつactiveなセルは、TECSから存在が認識されていないのを
618 # # 含む任意のドメインから呼び出される可能性も存在する
619 # #
620 # caller_unrestricted = true
621 # else
622 # #
623 # # 無所属から接続されている場合は,すべてのセルの
624 # # restrictをチェック
625 # #
626 # Cell.get_cell_list2.each { |cell|
627 # if cell.callable?(svcplugin.get_callee_cell, svcplugin.get_callee_ep_name, func_name)
628 # callable_domains << cell.get_region.get_domain_root
629 # end
630 # }
631 # print "callable_domains: "
632 # callable_domains.each{ |dm| print dm.get_name, " " }
633 # print "\n"
634 # end
635
636 # restrict 指定がある場合には、それに従う。さもなければ、チェックしない
637 callable_domains = @callee_cell.get_restricted_regions( get_callee_ep_name, func_name )
638 if callable_domains == nil then
639 caller_unrestricted = true
640 end
641 # print "restrict_list: "
642 # delim = ""
643 # callable_domains.each{ |domain|
644 # print delim, domain
645 # delim = ", "
646 # }
647 # print "\n"
648
649 elsif svcplugin.get_caller_cell.callable?( svcplugin.get_callee_cell, svcplugin.get_callee_ep_name, func_name )
650 #
651 # 特定のドメインから接続されている場合は,呼出し元セルの
652 # restrictをチェック
653 #
654 callable_domains << svcplugin.get_caller_cell.get_region.get_domain_root
655 else
656 #
657 # 無所属から結合されておらず,特定の呼出し元ドメインにアクセス権
658 # がない場合,callable_domainsは空となる
659 #
660 # pp "#{svcplugin.get_caller_cell.get_name} cannot call #{svcplugin.get_callee_cell.get_name}_#{svcplugin.get_callee_ep_name}_#{func_name}"
661 end
662 }
663
664 if caller_unrestricted
665 # pp "caller_unrestricted: #{@ct_name_body}"
666 return {"check_code"=>"", "user_cannot_callable"=>false}
667 end
668
669 #
670 # 重複を削除
671 #
672 callable_domains.uniq!
673 #
674 # 無所属に対するドメインチェックは実施しない
675 # カーネルドメインに対するドメインチェックは実施しない
676 #
677 callable_domains = callable_domains.select { |domain|
678 ((domain.get_domain_type.get_option != "OutOfDomain") && \
679 (domain.get_domain_type.get_option != "kernel"))
680 }
681 # pp "callable_domains"
682 # pp callable_domains.map{|domain| domain.get_name }
683 #
684 # すべてのユーザドメインから呼出し可能な場合,ドメインチェックは
685 # 実施しない
686 #
687 all_domain_regions = DomainType.get_domain_regions[:HRP].select { |reg|
688 ((reg.get_domain_type.get_option != "OutOfDomain") && \
689 (reg.get_domain_type.get_option != "kernel"))
690
691 }
692 # pp "all domains"
693 # pp all_domain_regions.map {|reg| reg.get_name}
694 if all_domain_regions.all? {|reg| callable_domains.include?(reg)}
695 all_domain_callable = true
696 end
697
698 #
699 # 呼出し元ドメインのチェック処理本体の生成
700 #
701 if callable_domains.length == 0
702 dbgPrint "callable_domain.length = 0\n"
703 #
704 # ユーザドメインから呼出し不可能な場合は
705 # 個別のエラーチェックはせず,問答無用でE_OACVを返す
706 #
707 user_cannot_callable = true
708 elsif callable_domains.length == 1
709 dbgPrint "callable_domain.length = 1\n"
710 #
711 # 呼出し可能なユーザドメインが単一の場合は
712 # cdmid != <domain名> の形式でチェックする
713 #
714 check_code += "\t/* HRPSVC0012.1 */\n"
715 check_code += "\tif (cdmid != #{callable_domains[0].get_name}) {\n"
716 elsif callable_domains.length > 1 && !all_domain_callable
717 dbgPrint "callable_domain.length > 1 && not all_domains \n"
718 #
719 # 呼出し可能なユーザドメインが複数の場合は
720 # TACP(cdmid) & (TACP(<domain名>) | ...) != 0U
721 # の形式でチェックする
722 #
723 check_code += "\t/* HRPSVC0012.2 */\n"
724 check_code += "\tif((TACP(cdmid) & ("
725 check_code += (callable_domains.map { |domain| "TACP(#{domain.get_name})"}).join("|")
726 check_code += ")) != 0U) {\n"
727 else
728 dbgPrint "callable_all_domains\n"
729 end
730 if check_code != ""
731 #
732 # 呼出し可能なユーザドメインのチェックがある場合は
733 # エラーコードを返すためのコードを出力する
734 #
735 check_code += <<EOS
736 /* HRPSVC0013 */
737 return E_OACV;
738 }
739EOS
740 end
741
742 return {"check_code"=>check_code, "user_cannot_callable"=>user_cannot_callable}
743 end
744
745 #---------------------------------------------------------#
746 #=== シグニチャのチェック
747 def check_signature signature
748 signature.get_function_head_array.each{ |fh|
749 type = fh.get_return_type
750 check_return_type signature, fh, type
751 if fh.get_paramlist.get_items.length > NUM_SVC_ARG_MAX then
752 cdl_error( "HSV0005 $1.$2: # of parameter more than #{NUM_SVC_ARG_MAX}", signature.get_name, fh.get_name )
753 end
754 fh.get_paramlist.get_items.each{ |param|
755 check_param signature, fh, param
756 }
757 }
758 end
759 #=== 戻り値の型のチェック
760 # ER, ER_UINT は推奨される型
761 # 整数、ブール、void は可能、他は不可
762 def check_return_type signature, fh, type
763 ot = type.get_original_type
764 if( type.get_type_str == "ER" || type.get_type_str == "ER_UINT" ) then
765 # OK!
766 elsif ot.kind_of?( IntType ) || ot.kind_of?( VoidType ) || ot.kind_of?( BoolType ) then
767 cdl_warning( "HSW0001 $1.$2: $3 return type cannot get access violation error", signature.get_name, fh.get_name, type.get_type_str.downcase )
768 check_intptr "#{signature.get_name}.#{fh.get_name} return type", type
769 else
770 cdl_error( "HSV0001 $1.$2 return type $3 cannot be used", signature.get_name, fh.get_name, type.get_type_str.to_s+type.get_type_str_post.to_s )
771 end
772 end
773 #=== 引数の型のチェック
774 def check_param signature, fh, param
775 type = param.get_type
776 ot = type.get_original_type
777 dir = param.get_direction
778 case dir
779 when :IN
780 if ot.kind_of?( IntType ) || ot.kind_of?( BoolType ) then
781 # OK!
782 check_intptr "#{signature.get_name}.#{fh.get_name}.#{param.get_name}", type
783 elsif ot.kind_of? PtrType then
784 check_ptr signature, fh, param, dir
785 else
786 cdl_error( "HSV0002 $1.$2.$3 $4 param type cannot be used", signature.get_name, fh.get_name, param.get_name, type.get_type_str.to_s+type.get_type_str_post.to_s )
787 end
788 when :OUT, :INOUT
789 if ot.kind_of? PtrType then
790 check_ptr signature, fh, param, dir
791 else
792 # error
793 end
794 when :SEND, :RECEIVE
795 cdl_error( "HSV0008 $1.$2.$3 param direction '$4' cannot be used", signature.get_name, fh.get_name, param.get_name, param.get_direction.to_s.downcase )
796 end
797 end
798 def check_ptr signature, fh, param, dir
799 type = param.get_type.get_referto
800 ot = type.get_original_type
801 if ot.kind_of?( IntType ) || ot.kind_of?( BoolType ) || ot.kind_of?( FloatType ) then
802 # OK!
803 check_intptr "#{signature.get_name}.#{fh.get_name}.#{param.get_name}", type
804 elsif ot.kind_of? PtrType then
805 cdl_error( "HSV0003 $1.$2.$3 multi-pointer type cannot be used", signature.get_name, fh.get_name, param.get_name, type.get_type_str.to_s+type.get_type_str_post.to_s )
806 elsif ot.kind_of? StructType then
807 check_struct signature, fh, param
808 else
809 cdl_error( "HSV0004 $1.$2.$3 $4 type cannot be used", signature.get_name, fh.get_name, param.get_name, type.get_type_str.to_s+type.get_type_str_post.to_s )
810 end
811 if ( dir == :OUT || dir == :INOUT) && param.get_string == -1 then
812 cdl_error( "HSV0009 $1.$2.$3 string argment is necessary for out/inout parameter", signature.get_name, fh.get_name, param.get_name )
813 end
814 end
815 def check_struct signature, fh, param
816 type = param.get_type.get_referto
817 ot = type.get_original_type
818 ot.get_members_decl.get_items.each{ |decl|
819 type = decl.get_type
820 ot = type.get_original_type
821 if ot.kind_of?( IntType ) || ot.kind_of?( BoolType ) || ot.kind_of?( FloatType ) then
822 # OK!
823 check_intptr "#{signature.get_name}.#{fh.get_name}.#{param.get_name}.#{decl.get_name} member", type
824 else
825 dbgPrint "struct member #{decl.get_name} #{type} #{decl.get_type} #{decl.get_type.get_original_type}\n"
826 if( decl.get_type.get_original_type.kind_of? ArrayType ) then
827 dbgPrint "member array type #{decl.get_type.get_original_type.get_type} #{decl.get_type.get_original_type.get_type.get_original_type}\n"
828 check_struct_member_array signature, fh, param, decl
829 else
830 cdl_error( "HSV0006 $1.$2.$3 $4 type cannot be used as struct member", signature.get_name, fh.get_name, param.get_name, type.get_type_str.to_s+type.get_type_str_post.to_s )
831 end
832 end
833 }
834 end
835 def check_struct_member_array signature, fh, param, member_decl
836 # p "check_struct_member_array: #{member_decl.get_type.get_type_str}"
837 type = member_decl.get_type.get_type
838 ot = type.get_original_type
839 if ot.kind_of?( IntType ) || ot.kind_of?( BoolType ) || ot.kind_of?( FloatType ) then
840 # OK!
841 check_intptr "#{signature.get_name}.#{fh.get_name}.#{param.get_name}.#{member_decl.get_name} member", type
842 else
843 cdl_error( "HSV0007 $1.$2.$3 $4 type cannot be used as struct member", signature.get_name, fh.get_name, param.get_name, type.get_type_str.to_s+type.get_type_str_post )
844 end
845 end
846 def check_intptr msg, type
847 dbgPrint "check_intptr IN\n"
848 t = type
849 while( t.kind_of? DefinedType )
850 dbgPrint "check_intptr #{msg} #{t.get_type_str} #{t.get_original_type.get_type_str}\n"
851 tstr = t.get_type_str
852 tstr.sub!( /const /, "" )
853 tstr.sub!( /volatile /, "" )
854 if tstr == "intptr_t" || tstr == "uintptr_t" then
855 cdl_info( "HSI0001 $1 type '$2' not checked by plugin", msg, type.get_type_str )
856 end
857 t = t.get_type
858 end
859 end
860end
861
Note: See TracBrowser for help on using the repository browser.