上回书说道,如何在tamarin项目的shell中加入定制AS3代码,下面我们接着上回的说。这次,我们将要设计并使用本地代码。
1、修改shell子项目
这次让我们关注tamarin-tracing/shell这个目录。
上次简单地说道tamarin-tracing/shell/shell.py可以构建shell编译的相关C++和abc文件,这次我们来深入看看shell这个项目。
打开tamarin-tracing/shell/shell.py,我们看fullas3这个方法
- def fullas3():
- print "Building Full AS3"
- # compile builtins
- os.system(asc+fullconfig+" -d -abcfuture -import ../core/builtin_full.abc -builtin -out shell main.as shell.as fib.as ../extensions/Dictionary.as Endian.as "+zlibfiles+" Domain.as ByteArray.as")
- # run optimizer
- os.system(abcopt+" ../core/builtin_full.abc shell.abc >shell_full.out")
- os.system("tail -3 shell_full.out")
- mv("shell.abc", "shell_full_orig.abc")
- mv("shell.abc2", "shell_full.abc")
- mv("shell.cpp2", "shell_full.cpp")
- mv("shell.h2", "shell_full.h")
- rm("shell.cpp")
- rm("shell.h")
一般我们编译都是用full这个配置来编译,比如builtin_full和shell_full,因为full包含了更全的内容。关于full的配置,从变量fullconfig="-config CONFIG::Full=true"来区分编译内容,具体内容全部放在as文件中, 写法如下:
- CONFIG::Full
- private static function _join(o, sep):String {
- var s:String = (sep === undefined) ? "," : String(sep);
- var out:String = "";
- for (var i:uint = 0, n:uint=o.length; i < n; i++){
- var x = o[i];
- if (x != null)
- out += x;
- if (i+1 < n)
- out += s;
- }
- return out;
- }
这样编译通过-config CONFIG::Full=true或false来决定这个_join是否要参与AS3编译成c++或abc代码,这些代码的头定义最终织入到shell_full.h和builtin_full.h或shell_min.h和builtin_min.h中。
从shell文件夹和core文件夹中的文件可以看出,文件命名规则是这样的:
以Number类为例,则有Number.as、NumberClass.cpp、NumberClass.h。
然后,让我们看看make编译shell的关键操作流程:
1、shell.py脚本会利用asc.jar中的macromedia.asc.embedding.ScriptCompiler先来编译这些as,然后生成的头全部放入shell_full.h或shell_min.h中(编译core项目生成builtin_full.h道理与之相同)
2、然后根据生成的h和cpp文件在shell文件夹的manifest.mk中编译(.net是在avmplus_9.vcproj项目文件中)
这跟之前提到的一样,先shell.py再make项目的做法相吻合。
2、制作native method
为了便于诠释,我们跟《Implementing Native Methods in Tamarin 》文章一样,采用以斐波那契数列为例。关于这篇文章,感兴趣的朋友请看http://www.bluishcoder.co.nz/2008/02/implementing-native-methods-in-tamarin.html
我们首先建立一个fib.as:
- package testing {
- public function fib(n) {
- if(n <= 1)
- return 1;
- else
- return fib(n-1) + fib(n-2);
- }
- public native function fib2(n:int):int;
- }
我们一口气建立了两个fib函数,一个是as3实现,另一个使用了native method,转入本地代码实现。这样便于我们去对比参考。
然后我们去修改shell.py,在fullas3方法中加入我们要实现的这个fib.as让其参与编译:
os.system(asc+fullconfig+" -d -abcfuture -import ../core/builtin_full.abc -builtin -out shell main.as shell.as fib.as ../extensions/Dictionary.as Endian.as "+zlibfiles+" Domain.as ByteArray.as")
然后系统生成了shell_full.h,我们可以看到已经有fib2方法的头产生:
- struct null_fib2_args {
- public: ScriptObjectp /**//*global0*/ self;
- private: int32_t self_pad;
- public: int32_t n;
- private: int32_t n_pad;
- public: StatusOut* status_out;
- };
- AVMPLUS_NATIVE_METHOD_DECL(int32_t, null_fib2)
分别为一个结构体和一个宏。
然后我们实现这个fib2,fibimpl.cpp:
- #include "avmshell.h"
- #include <stdlib.h>
- namespace avmshell {
- int32_t native_fib(int32_t n) {
- if(n <= 1)
- return 1;
- else
- return native_fib(n-1)+native_fib(n-2);
- }
- AVMPLUS_NATIVE_METHOD(int32_t, null_fib2) {
- return native_fib(args->n);
- }
- }
我们的实现中的宏定义为:
- #define AVMPLUS_NATIVE_METHOD(ret, name)
- ret FASTCALL name (const name##_args* args) /**//* no semi */
在fibimpl.cpp中也就相当于:
- int32_t FASTCALL null_fib2 (const null_fib2_args* args) /**//**//**//* no semi */
- {
- return native_fib(args->n);
- }
这样shell调用fib2就相当于调用null_fib2,null_fib2又相当于调用native_fib(args->n),args就是结构体指针null_fib2_args。
这种调用在tamarin里很常见,他们也具有一定的命名规则,如上一章在shell.as内有一个exit方法:
- package avmplus {
- public class System {
- public native static function exit(status:int):void
- ………………
对应的SystemClass.cpp中就有:
- AVMPLUS_NATIVE_METHOD(void, avmplus_System_exit) {
- ::exit(args->status);
- }
命名规则是:包_类_方法。因为是public的所以没有表示范围
在这个System类内还有_exec方法,那么它的宏是:
命名规则是:包_类_作用域_方法名。
注意,我们并没有准寻[foo].as、[foo]Class.cpp、[foo]Class.h这一命名规则,这说明这规则是编码规范而已。
然后,我们修改shell文件夹下的manifest.mk,在编译路径中加入这个fibimpl.cpp:
- shell_CXXSRCS := $(shell_CXXSRCS)
- $(curdir)/avmshell.cpp
- $(curdir)/ByteArrayGlue.cpp
- $(curdir)/ConsoleOutputStream.cpp
- $(curdir)/DataIO.cpp
- $(curdir)/DebugCLI.cpp
- $(curdir)/DomainClass.cpp
- $(curdir)/FileClass.cpp
- $(curdir)/FileInputStream.cpp
- $(curdir)/SystemClass.cpp
- $(curdir)/fibimpl.cpp
- $(curdir)/../extensions/DictionaryGlue.cpp
- $(NULL)
然后我们make编译项目,注意上一篇提到的Atom BUG问题,这里不再赘述。
假设新的build的shell叫build2,区别与之前的build。在build2/shell目录下,制作fibtest.as和fibtest2.as:
- $ cat fibtest.as
- import testing.*;
- print("fib 30 = " + fib(30));
- $ cat fibtest2.as
- import testing.*;
- print("fib 30 = " + fib2(30));
分别测试基于as3的fib和基于native method的fib2:
- $ ./shell/avmshell -lifespan fibtest.abc
- fib 30 = 1346269
- Run time was 2390 msec = 2.39 sec
- $ ./shell/avmshell -lifespan fibtest2.abc
- fib 30 = 1346269
- Run time was 443 msec = 0.44 sec
- $ ./shell/avmshell -lifespan -interp fibtest.abc
- fib 30 = 1346269
- Run time was 129007 msec = 129.01 sec
- $ ./shell/avmshell -lifespan -interp fibtest2.abc
- fib 30 = 1346269
- Run time was 329 msec = 0.33 sec
发现native method明显快于as3 mathod(这是当然的,呵呵)
好了,我们诠释了《Implementing Native Methods in Tamarin 》一文,实践了fib2这个方法的从无到有的过程。
2、关于Atom的BUG
这两章一直有提到这个AVMPLUS_NATIVE_METHOD_DECL(Atom, ……)出错的问题。我们就在这节由这个问题引出更深层次的东西。
首先我们看AVMPLUS_NATIVE_METHOD_DECL的定义:
- #define AVMPLUS_NATIVE_METHOD_DECL(ret, name)
- enum { k_NativeRetType_##name = NativeRetType_##ret } ;
- extern ret FASTCALL name (const name##_args* args); /**//* semi required here */
可以看到这个宏做两件事情,一件是用来做enum返回类型的定义,另一个是做extern方法定义,如:
AVMPLUS_NATIVE_METHOD_DECL(bool, avmplus_File_private__write),解析成:
enum { k_NativeRetType_avmplus_File_private__write = NativeRetType_bool }
extern bool FASTCALL avmplus_File_private__write(const avmplus_File_private__write_args* args)
而native method的返回类型如下:
- typedef uint64_t BoxReturnType;
- // a little syntactic sugar for mapping C++ ret types into a useful enum
- enum NativeRetType {
- NativeRetType_ScriptObjectp,
- NativeRetType_bool,
- NativeRetType_int32_t,
- NativeRetType_uint32_t,
- NativeRetType_Namespacep,
- NativeRetType_double,
- NativeRetType_BoxReturnType,
- NativeRetType_Stringp,
- NativeRetType_void
- };
而且,对应的shell_full.h里就有对应的结构体:
- struct avmplus_File_private__write_args {
- public: ScriptObjectp /**//*File$*/ classself;
- private: int32_t classself_pad;
- public: Stringp filename;
- private: int32_t filename_pad;
- public: Stringp data;
- private: int32_t data_pad;
- public: StatusOut* status_out;
- };
这个结构体是是对应的as文件用shell.py生成的,就像刚才我们生成null_fib2_args一样。
这样,这一个PY脚本工具生成的宏就把整个的native method定义流程和结构串在了一起。
Atom的产生原因是定义as文件时返回了不明确的类型,比如Object类型或*类型。Atom的定义如下:
- // NOTE, for the new native-method glue to work properly,
- // Atom must be a unique type, NOT an alias onto int, intptr_t, etc.
- // Please use the atomPtr, atomKind, etc functions in AtomConstants.h to
- // operate on them.
- typedef struct Atom_* Atom;
说明单是Atom是个抽象的不能使用的类型,而且,建议使用的是atomPtr和atomKind,而atomPtr又是#define atomPtr(a) ((void*)(uintptr_t(a) & ~7)),7为atomKind的enum数量,uintptr_t返回的是uint64_t。
为什么要用NativeRetType_BoxReturnType来替换呢,因为在解释器Interpreter.cpp里,处理NativeRetType_BoxReturnType为:
- case NativeRetType_BoxReturnType:
- // remember: plain object and any-typed values are handled as Box, not SO*
- result.q = (*NativeMethodProc_BoxReturnType(f))(argv);
- break;
可以看出,BoxReturnType为plain object(即Object基类型)和任何被类型化的值。所以换为BoxReturnType就不会出问题了。
今天详细地介绍了如何制作本地方法,并深入了解本地方法的来龙去脉和核心宏方法。
下面,我们将深入到源代码内部去看看tamarin的运作机制,并且将介绍其他子项目的功能和内容。精彩不容错过呦
============================================================================
最近特别忙,就没空出时间继续研究。不过以后会补上进度的。
相关推荐
Tamarin Prover是一款强大的工具,专门用于形式化分析和验证安全协议的安全性。它由Simon Meier、...在阅读Tamarin的用户手册之前,先通过入门级介绍文档了解其基本概念和操作方法,将为后续的学习打下坚实基础。
**PyPI 官网下载 | tamarin-utils-0.14.5.tar.gz** 这个压缩包文件`tamarin-utils-0.14.5.tar.gz`来源于Python的官方软件仓库PyPI(Python Package Index),它是一个包含众多Python库的地方,方便开发者下载和分享...
2. **安装方式**:手册详细介绍了在macOS、Linux和Windows 10上的安装步骤,同时也提到了从源代码编译以及在远程机器上运行Tamarin的方法。 3. **编辑器支持**:Tamarin支持多种代码编辑器,以方便用户编写和编辑...
基于 Tamarin 的 5G AKA 协议形式化分析及其改进方法 本文主要介绍了基于 Tamarin 的 5G AKA 协议形式化分析及其改进方法。在 5G 移动通信网络中,3GPP 组织标准化了 5G AKA 协议,用以身份认证和密钥协商。文章...
Tamarin证明者资料库 本自述文件描述了Tamarin证明者用于安全协议验证的存储库的组织。 它的目标受众是Tamarin证明者的感兴趣的用户和将来的开发人员。 有关Tamarin证明器的安装和使用说明,请参见手册的第2章: : ...
`tamarin-utils`正是针对这样的需求而设计的,它提供了一系列与Zookeeper交互的Python接口,使得开发者可以更方便地在Python代码中使用Zookeeper的服务。这包括但不限于创建、删除、更新Zookeeper节点,以及监视节点...
《PyPI上的tamarin-utils-0.15.1.tar.gz:Python库解析与应用》 在Python的世界里,PyPI(Python Package Index)是最重要的软件仓库,它为开发者提供了无数的工具和库,便于他们构建和分享自己的项目。本文将深入...
5. **时间日期处理**:对Python的datetime模块进行了封装,提供了更加直观和便捷的时间日期操作方法,如时间间隔计算、格式化输出等。 6. **并发编程**:包含线程池、异步I/O等多线程、多进程工具,能够充分利用...
gem 'tamarin' 然后执行: $ bundle 或者自己安装: $ gem install tamarin 用法 运行服务器: bundle exec ruby lib / tamarin 然后,在其他终端运行: curl http : //localhost :3030 贡献 分叉它( )...
EM验证 这是EMV标准的模型,是我们IEEE S&P 2021论文EMV标准:Break,Fix,Verify的补充材料。 有关这项工作的详细信息,请访问 。... :GNU脚本,用于生成目标模型并对其进行Tamarin分析。 *.oracle
是GNU脚本,用于生成目标模型并对其进行Tamarin分析。 *.oracle是证明支持的*.oracle 。 包含自动生成的目标模型( .spthy )及其证明( .proof )。 以HTML格式显示分析结果。 包含有用的脚本: 是一个Python...
我们将感谢您为我们提供5星级的评级! 如果您有任何问题或反馈支持,可以在info@newtabgallery.com上达到 通过我们的扩展,您获得: 1:高分辨率新标签体验 2:简单,清洁视图 - 没有瓷砖! 3:没有广告或恼人的弹...
2. **SSL/TLS协议**:这是Internet上最常用的安全协议之一,用于保护Web通信的安全。SSL/TLS协议位于应用层和传输层之间,主要由两部分组成: - 上层协议:包括TLS握手协议、TLS密码变化协议和TLS警告协议。 - ...
Thane 是 Tamarin ( ) 的一个轻微修改版本,具有部分 Flash Player 兼容层,主要用 ActionScript 编写,并带有一点原生胶水。 引擎本身被修改为在 x86_64 架构下的 Unix 平台上运行。 现有的 Windows/64 支持已扩展...
5. **特征工程**:从原始数据中创建新的特征,这可能包括计算统计指标、提取文本的关键词、处理时间序列数据等。特征工程有助于提升模型的预测能力。 6. **数据存储**:处理过的数据应以结构化和易于访问的形式存储...
- **本地资源访问与离线存储**:AIR程序可以访问本地资源并进行离线存储,打破了浏览器的限制,模糊了浏览器与桌面应用之间的界限。 - **RIA的第二次革命**:AIR被视为RIA领域的第二次革命,其前瞻性的视角和技术...
在压缩包文件`tamarin-central-fbecf6c8a86f`中,包含了AVM2的源代码,Tamarin是AVM2的一个实现,由Mozilla基金会开发。这个版本可能包含最新的改进和修复,是学习和研究AVM2的好起点。下载并分析这个源码,你将能...
形式化分析工具是实现协议验证的关键,以下是一些常用工具: - **ProVerif**:一种基于符号执行的协议验证工具,支持线性时间和分支时间逻辑。 - **Tamarin**:基于模型检查的协议验证工具,特别适用于公钥密码学...