实现一个 JavaScriptCore的debugger——iOS 篇

JSC 的 debugger 是个神奇的东西,在网上资料甚少,几乎完全搜索不到,尤其是 iOS 上,OC 接口没有暴露任何 debugger 信息。

不过好在 JSC 是开源的,通过分析源代码可以找到 JSC::Debugger 这个抽象类,我们继承这个抽象类,然后实现掉虚函数,创建实例并且把它挂载到 global object 即可开启 debug 能力了。

思路是简单的,在 iOS 设备上,我们要面临的另一个问题是它的 JavaScriptCore 本身是以 Framework 的形式而非源代码形式提供的,所以我们只有公开的 OC 头文件和静态库文件。

所以要想使用 debugger,我们需要:

编译时使用私有的头文件

确保头文件的版本跟 framework 一致

确保编译选项跟 framework 一致

链接时链接 framwork 中的方法

如何解决呢?步骤如下:

查看 framework 中的 JSC 版本

根据 JSC 版本,找到对应的源代码

构建 JSC 获取私有头文件

建立新项目,引入私有 JSC 头文件

调整宏和编译选项

编写代码

查看 framework 中的 JSC 版本

framework 是一个文件夹(在 XCode 中右键即可打开),可以从tbd 文件中找到系统中库的路径(一般是 /System/Library/Frameworks/JavaScriptCore.framework/ ),然后从 version.plist 中找到当前版本。

在我的 XCode9.2中,找到的版本是 604.4.7.1.3。

下载源代码

在 https://svn.webkit.org/repository/webkit/tags 可以找到对应的源代码。

注意一般 opensource.apple.com 中找不到对应版本。

我们并不需要整个 webkit 代码,所以只要下载 source 目录下的 bmalloc, WTF 和 JavaScriptCore 三个项目就够了。

构建 JSC

首先我们需要建立一个 workspace,然后把三个项目文件拖进 workspace。

依次构建 bmalloc、WTF 和 JavaScriptCore 三个项目即可。

如果配置正确,构建 JSC 应该不会遇到什么困难。

我们只需要构建好的头文件,所以不需要选择 iOS 设备,使用默认的 mac 作为目标就好了。

建立新项目

接下来我们要建立一个 Debugger 项目,随便叫什么名字,选择 iOS 项目。

我们需要调整编译选项:

other C++ flags: -std=c++14

enable C++ runtime Types: No

system header search path: $(PRODUCT_NAME)/

Processor Macros:(太多了,建议直接到项目文件源代码里修改)

ENABLE3DTRANSFORMS,ENABLEACCELERATEDOVERFLOWSCROLLING,ENABLEAPPLEPAY,ENABLEAPPLEPAYSESSIONV3,ENABLEATTACHMENTELEMENT,ENABLEAVFCAPTIONS,ENABLECACHEPARTITIONING,ENABLECANVASPATH,ENABLECANVASPROXY,ENABLECHANNELMESSAGING,ENABLECONTENTFILTERING,ENABLECSSANIMATIONSLEVEL2,ENABLECSSBOXDECORATIONBREAK,ENABLECSSCOMPOSITING,ENABLECSSDEVICEADAPTATION,ENABLECSSIMAGEORIENTATION,ENABLECSSIMAGERESOLUTION,ENABLECSSREGIONS,ENABLECSSSCROLLSNAP,ENABLECSSSELECTORSLEVEL4,ENABLECSSTRAILINGWORD,ENABLECSS3TEXT,ENABLECURSORVISIBILITY,ENABLECUSTOMSCHEMEHANDLER,ENABLEDASHBOARDSUPPORT,ENABLEDATAINTERACTION,ENABLEDATATRANSFERITEMS,ENABLEDATACUEVALUE,ENABLEDATALISTELEMENT,ENABLEDEVICEORIENTATION,ENABLEDRAGSUPPORT,ENABLEENCRYPTEDMEDIA,ENABLEFETCHAPI,ENABLEFILTERSLEVEL2,ENABLEFTLJIT,ENABLEFULLSCREENAPI,ENABLEGAMEPADDEPRECATED,ENABLEGAMEPAD,ENABLEGEOLOCATION,ENABLEICONDATABASE,ENABLEINDEXEDDATABASEINWORKERS,ENABLEINDEXEDDATABASE,ENABLEINPUTTYPECOLORPOPOVER,ENABLEINPUTTYPECOLOR,ENABLEINPUTTYPEDATE,ENABLEINPUTTYPEDATETIMEINCOMPLETE,ENABLEINPUTTYPEDATETIMELOCAL,ENABLEINPUTTYPEMONTH,ENABLEINPUTTYPETIME,ENABLEINPUTTYPEWEEK,ENABLEINTERSECTIONOBSERVER,ENABLEINTL,ENABLEIOSGESTUREEVENTS,ENABLEIOSTOUCHEVENTS,ENABLEJIT,ENABLEKEYBOARDKEYATTRIBUTE,ENABLEKEYBOARDCODEATTRIBUTE,ENABLELEGACYCSSVENDORPREFIXES,ENABLELEGACYENCRYPTEDMEDIA,ENABLELEGACYVENDORPREFIXES,ENABLELETTERPRESS,ENABLELINKPREFETCH,ENABLEMACGESTUREEVENTS,ENABLEMATHML,ENABLEMEDIACAPTURE,ENABLEMEDIACONTROLSSCRIPT,ENABLEMEDIASESSION,ENABLEMEDIASOURCE,ENABLEMEDIASTATISTICS,ENABLEMEDIASTREAM,ENABLEMETERELEMENT,ENABLEMHTML,ENABLEMOUSECURSORSCALE,ENABLENAVIGATORCONTENTUTILS,ENABLENAVIGATORSTANDALONE,ENABLENOTIFICATIONS,ENABLEPDFKITPLUGIN,ENABLEPOINTERLOCK,ENABLEPROXIMITYEVENTS,ENABLEPUBLICSUFFIXLIST,ENABLEQUOTA,ENABLEREMOTEINSPECTOR,ENABLEREQUESTAUTOCOMPLETE,ENABLERESOLUTIONMEDIAQUERY,ENABLERESOURCEUSAGE,ENABLERUBBERBANDING,ENABLESERVICECONTROLS,ENABLESPEECHSYNTHESIS,ENABLESTREAMSAPI,ENABLESUBTLECRYPTO,ENABLESVGFONTS,ENABLETELEPHONENUMBERDETECTION,ENABLETEXTAUTOSIZING,ENABLETOUCHEVENTS,ENABLETOUCHICONLOADING,ENABLEUSERSELECTALL,ENABLEVARIATIONFONTS,ENABLEVIDEOPRESENTATIONMODE,ENABLEMACVIDEOTOOLBOX,ENABLEVIDEOTRACK,ENABLEVIDEO,ENABLEVIEWMODECSSMEDIA,ENABLEWEBANIMATIONS,ENABLEWEBAUDIO,ENABLEWEBRTC,ENABLEWEBSOCKETS,ENABLEWEBTIMING,ENABLEWEBGL,ENABLEWEBGL2,ENABLEWEBGPU,ENABLEWIRELESSPLAYBACKTARGET,ENABLEXSLTFASTJITPERMISSIONS

然后我们打开构建好的 JSC 项目目标, 复制其中 PrivateHeaders 目录,到项目目录的 JavaScriptCore 目录。

再打开 WTF 项目目标, 复制目录下 /usr/local/include/wtf

接下来,我们需要对源代码做一下小修改,因为系统的 JSC 是在非 debug 模式下编译的,所以我们强行把头文件中跟 debug 相关的代码改成非 debug 模式:

JavaScriptCore/HandleStack.h

WTF/hashtable.h

编写代码

代码必须使用 .mm 文件。

我们需要在项目的 build phases 中加入 JavaScriptCore.framework。

使用示例:

题图:https://unsplash.com/photos/Sf5Q7Ljjf58 By @Katerina Pavlickova

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180123G0ESY500?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励