当前位置: 首页 > news >正文

[领域]javascript hacking guide part 4

孙向晖 sunshineormer at hotmail.com

在正式开始之前,先说点关于RHG的话题,我的JHG系列,基本是在仿照着RHG的风格在写作。RHG的述事风格很有条理性,并且会指导你跳过跳过再跳过一些无关痛痒的程序片段。这是对的,在一大堆程序中,能够快速准确的定位,不是件很容易的事情。

从今天开始,我将讲述我对蜘蛛猴源代码的查找过程:

在js.c 找到main里面的调用过程,注意,下面的函数都是精简过的,而且是平级的关系:

rt = JS_NewRuntime(...

cx = JS_NewContext(rt,...

glob = JS_NewObject(cx, &global_class, NULL, NULL);

JS_InitStandardClasses(cx, glob)

JS_DefineFunctions(cx, glob, shell_functions)

ok,现在来看一下,运行时和上下文环境是解释引擎的初始化,可以先跳过,哈,我们真正关心的肯定是从glob开始的那3句了:globECMA262中要求的内置全局对象,这里有我们比较感兴趣的NewObject方法;紧接其后的,将是对其他内置对象的创建过程(JS_InitStandardClasses;最后,我们可以看看全局对象global都有哪些方法。

JS_NewObject的函数声明,被定义在jsobj.h中,函数定义在jsobj.c中:

extern JSObject *

js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);

记住,因为是要初始化glob对象,我们在传递参数是,protoparent都传递了NULL。这样,有效传递到函数体中的,就只有刚刚创建的上下文环境(cx)和clasp了。clasp的值被赋予了global_class,这是个全局变量,定义在js.c

JSClass global_class = {

"global", JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS,

JS_PropertyStub, JS_PropertyStub,

JS_PropertyStub, JS_PropertyStub,

global_enumerate, (JSResolveOp) global_resolve,

JS_ConvertStub, JS_FinalizeStub,

JSCLASS_NO_OPTIONAL_MEMBERS

};

在这个变量中,我们发现了“global”这个单词,结合JSClass这名字,再根据MFC等框架的经验,很容易的我们就可以联想到,这是用来做动态生成和RTTI的类名。

要想看懂这个结构体,一点也不难,只需到jsapi.h中找JSClass的定义即可。里面也没有什么太多的玩意,只是有一堆的函数指针,我们只需简单留言其中的强制非空部分即可。

struct JSClass {

const char *name;

uint32 flags;

/* Mandatory non-null function pointer members. */

JSPropertyOp addProperty;

JSPropertyOp delProperty;

JSPropertyOp getProperty;

JSPropertyOp setProperty;

JSEnumerateOp enumerate;

JSResolveOp resolve;

JSConvertOp convert;

JSFinalizeOp finalize;

/* Optionally non-null members start here. */

JSGetObjectOps getObjectOps;

JSCheckAccessOp checkAccess;

JSNative call;

JSNative construct;

JSXDRObjectOp xdrObject;

JSHasInstanceOp hasInstance;

JSMarkOp mark;

JSReserveSlotsOp reserveSlots;

};

放眼望去,偶的老天,原来类的属性操作(增加属性,删除属性,查询和设置属性都是在这定义的啊)。要知道,在javascript中,所有的attributes和方法都是属性啊。按下不表。

还是跳回到newObject

/* Bootstrap the ur-object, and make it the default prototype object. */

if (!proto) {

if (!js_GetClassId(cx, clasp, &id))

return NULL;

if (!js_GetClassPrototype(cx, parent, id, &proto))

return NULL;

if (!proto &&

!js_GetClassPrototype(cx, parent, INT_TO_JSID(JSProto_Object),

&proto)) {

return NULL;

}

}

先看这段代码,简而言之,想做的事情是,找到要创建对象的原型,如果实在找不到,就使用缺省的原型对象。跳过。

接下来的代码,

/* Always call the class's getObjectOps hook if it has one. */

ops = clasp->getObjectOps

? clasp->getObjectOps(cx, clasp)

: &js_ObjectOps;

只是想找一个对象的操作方法集,因为我们在定义global_class全局对象时,使用了JSCLASS_NO_OPTIONAL_MEMBERS宏,可以很轻松的判定这个表达式如同:

ops = &js_ObjectOps;

继续向后:

/*

* Allocate a zeroed object from the GC heap. Do this *after* any other

* GC-thing allocations under js_GetClassPrototype or clasp->getObjectOps,

* to avoid displacing the newborn root for obj.

*/

obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));

if (!obj)

return NULL;

从注释中,我们可以轻松的看出,按照ECMAScript的说法,对象被分配到heap中,已经得到了实现了。

被定义在了jsgc.c中,我们不想太多的去看堆的alloc分配,只要知道这里生成了一个空的JSObject对象即可。

void *

js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)

再接着,是一大段的判断条件,想法很简单,既而是已经在heap中创建了对象,就要给对象的mapslot进行赋值了:一种做法是判断了若干条件后,用原型的map;另一种可能,是创建新的map

你会问map里面都存放了什么?呵呵。好问题。且听下回分解吧。

相关文章:

  • 导入csv 0的问题_解决:MySQL workbench8.0 无法导入csv
  • 多态性——vptr和vtable
  • mysql建删改查_mysql 操作数据库创建,增删改查
  • python中wraps_python装饰器函数wraps
  • 什么是期货
  • mysql-sandbox_mysql-sandbox 安装
  • 常用股市术语
  • MySQL创建视图yggl_yggl数据库的创建
  • Linux中设定让Firefox可以运行Java程序,然后老爸就可以在家与“小白”决象棋了!...
  • python3 value counts函数_(python3)pandas做数据分析:统计相关函数
  • SP版本Windows Mobile Crossbow简短体验
  • python画三维几何图形拼成的图案_The discovery of oil _______ in an era of employment and prosperity....
  • MySQL安装目录分类_linux 下mysqllinux下mysql安装、目录结构、配置
  • yale cas 配置谈
  • 天线3db波束宽度_天线尺寸与频率,口径与波宽的关系
  • [译] React v16.8: 含有Hooks的版本
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • Angular 4.x 动态创建组件
  • Octave 入门
  • OSS Web直传 (文件图片)
  • Python十分钟制作属于你自己的个性logo
  • vuex 笔记整理
  • webgl (原生)基础入门指南【一】
  • 对象引论
  • 如何选择开源的机器学习框架?
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 通过git安装npm私有模块
  • 微信开源mars源码分析1—上层samples分析
  • 详解NodeJs流之一
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (1)(1.13) SiK无线电高级配置(五)
  • (C语言)fread与fwrite详解
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (转)可以带来幸福的一本书
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .NET Core跨平台微服务学习资源
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET 回调、接口回调、 委托
  • .net 托管代码与非托管代码
  • .NET基础篇——反射的奥妙
  • .NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数
  • .Net组件程序设计之线程、并发管理(一)
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @configuration注解_2w字长文给你讲透了配置类为什么要添加 @Configuration注解
  • @Data注解的作用
  • @Responsebody与@RequestBody
  • @Valid和@NotNull字段校验使用
  • [Android]How to use FFmpeg to decode Android f...
  • [BZOJ] 2006: [NOI2010]超级钢琴
  • [DAX] MAX函数 | MAXX函数
  • [LaTex]arXiv投稿攻略——jpg/png转pdf
  • [MySQL]日期和时间函数
  • [NOI2005]聪聪与可可(期望)
  • [NOIP2018 PJ T4]对称二叉树