[WebKit]遭遇Mac OS私有API

简介: WebKit并不是完全开源的, Apple封装了一部代码在一个静态库(libWebKitSystemInterfaceXXXX.a)中,并没有提供源代码。

WebKit并不是完全开源的, Apple封装了一部代码在一个静态库(libWebKitSystemInterfaceXXXX.a)中,并没有提供源代码。而且不同版本的OS (包括iOS),会有特定的版本。

这就是我今天从分析中了解到的, 觉得过程比较有趣,记录一下。

1. 在WebKit中有这样一段源代码 (Laguage.mm):

static String httpStyleLanguageCode(NSString *languageCode)
{
    ASSERT(isMainThread());

    // Look up the language code using CFBundle.
    RetainPtr<CFStringRef> preferredLanguageCode(AdoptCF, wkCopyCFLocalizationPreferredName((CFStringRef)languageCode));

其中wkCopyCFLocalizationPreferredName只有如下的定义,找不到实现代码:
extern CFStringRef (*wkCopyCFLocalizationPreferredName)(CFStringRef);

2. 在运行时,查询wkCopyCFLocalizationPreferredName的地址信息:
(lldb) p wkCopyCFLocalizationPreferredName
(CFStringRef (*)(CFStringRef)) $0 = 0x0000000100478a49 
(WebKit2`WKCopyCFLocalizationPreferredName)


(lldb) image lookup -s WKCopyCFLocalizationPreferredName
1 symbols match 'WKCopyCFLocalizationPreferredName' in /Volumes/Data/Project/Webkit/webkitSvn/Build/Products/Debug/WebKit2.framework/Versions/A/WebKit2:
        Address: WebKit2[0x0000000000464a49] (WebKit2.__TEXT.__text + 4600745)
        Summary: WebKit2`WKCopyCFLocalizationPreferredName
1 symbols match 'WKCopyCFLocalizationPreferredName' in /Volumes/Data/Project/Webkit/webkitSvn/Build/Products/Debug/WebKit.framework/Versions/A/WebKit:
        Address: WebKit[0x00000000001b8275] (WebKit.__TEXT.__text + 1795141)
        Summary: WebKit`WKCopyCFLocalizationPreferredName

可以看到代码是位于WebKit2.framework中的, 但没有源代码信息,所以必然是link了一个静态库进来。


3. 查看项目的编译设置,可以发现要链接进来的库:


还可以在WEBKIT_SYSTEM_INTERFACE_LIBRARY的定义中发现有不同系统的版本。

可以找到一个正在使用的库看看:
  

4. 用IDA(试用版)打开找找里面有没有WKCopyCFLocalizationPreferredName:


也可以使用nm看看源文件,显然WebKitSystemInterface.o找不到对应的源代码:
nm -a libWebKitSystemInterfaceLion.a
/XXXXXX/Build/Products/Debug/libWebKitSystemInterfaceLion.a(WebKitSystemInterface.o):
0000000000002591 t -[NSWindowGraphicsContext(WebKitSystemInterface) _WebKitSystemInterface_setGraphicsPort:]
0000000000008d98 s -[NSWindowGraphicsContext(WebKitSystemInterface) _WebKitSystemInterface_setGraphicsPort:].eh
00000000000090a8 S _WKCopyBundleURLForExecutableURL.eh
00000000000006c7 T _WKCopyCFLocalizationPreferredName
0000000000008200 S _WKCopyCFLocalizationPreferredName.eh

反汇编可以看到如下的代码:
function _WKCopyCFLocalizationPreferredName {
    CFBundleGetLocalizationInfoForLocalization(arg_0, &var_32, &var_28, &var_24, &var_20);
    rax = CFBundleCopyLocalizationForLocalizationInfo(var_32, var_28, var_24, var_20);
    return rax;
}

很简单,就是涉及到两个函数调用。问题是,这两个函数并没有在开发文档里。


5 继续查找libWebKitSystemInterfaceXXX.a的来历。WebKit的工程都是通过gyp来生成的,打开果然里面提到了这样一段描述:
WebCore.gyp
 ['OS == "mac"', {
      'targets': [
        {
          # On the Mac, libWebKitSystemInterface*.a is used to help WebCore
          # interface with the system.  This library is supplied as a static
          # library in binary format.  At present, it contains many global
          # symbols not marked private_extern.  It should be considered an
          # implementation detail of WebCore, and does not need these symbols
          # to be exposed so widely.
          #
          # This target contains an action that cracks open the existing
          # static library and rebuilds it with these global symbols
          # transformed to private_extern.
          'target_name': 'webkit_system_interface',

它只以二进制形式提供。没问题,有反汇编的结果,写出一个一样的函数也不是问题。


6. 找到两个私有API的来历。
使用 image lookup -s可以很容易确定两个函数是在CoreFundation.framework中的。在Apple Open Source中也可以查得到声明(class-dump对C接口就不灵光了):
   CFBundlePriv.h on opensource.apple.com
    CFBundleGetLocalizationInfoForLocalization
    CFBundleCopyLocalizationForLocalizationInfo

最后添加如下的声明就可以使用了:
extern "C" {
CF_EXPORT Boolean CFBundleGetLocalizationInfoForLocalization(CFStringRef localizationName, SInt32 *languageCode, SInt32 *regionCode, SInt32 *scriptCode, CFStringEncoding *stringEncoding);
CF_EXPORT CFStringRef CFBundleCopyLocalizationForLocalizationInfo(SInt32 languageCode, SInt32 regionCode, SInt32 scriptCode, CFStringEncoding stringEncoding);
}


目录
相关文章
|
5月前
|
iOS开发 MacOS
MAC OS更新系统后IDEA中的SVN报错无法使用
MAC OS更新系统后IDEA中的SVN报错无法使用
|
3天前
|
Unix Shell Linux
史上最全:MAC OS X 命令行汇总
史上最全:MAC OS X 命令行汇总
10 0
|
3天前
|
安全 Java iOS开发
MAC OS X 硬盘安装详细分解教程
MAC OS X 硬盘安装详细分解教程
12 1
|
3天前
|
IDE 5G 开发工具
HP4230s笔记本安装mac os总结(原创)
HP4230s笔记本安装mac os总结(原创)
|
3天前
|
编解码 Oracle iOS开发
VirtualBox虚拟机安装Mac OS X Lion系统详解
VirtualBox虚拟机安装Mac OS X Lion系统详解
|
消息中间件 Dubbo 中间件
在 Docker 中运行 Mac OS 是什么样的体验?
在 Docker 中运行 Mac OS 是什么样的体验?
|
8月前
|
前端开发 安全 Go
在Mac OS X上运行Go语言的GUI程序
在Mac OS X上运行Go语言的GUI程序
216 3
|
12月前
|
iOS开发 MacOS
MAC OS更新系统后IDEA中的SVN报错无法使用
IntelliJ IDEA无法正常使用SVN 报Cannot run program “svn” (in directory “/XXXX/XXXX/XXXX/XXX”): error=2错误! 解决方法来了!
1042 0
|
Shell API Python
OS库常用API讲解
OS库常用API讲解
250 0
|
Oracle Java 关系型数据库
珠联壁合地设天造|M1 Mac os(Apple Silicon)基于vscode(arm64)配置搭建Java开发环境(集成web框架Springboot)
也许有人从未听说过Python,但是不会有人没听说过Java,它作为一个拥有悠久历史的老牌编程语言,常年雄踞TIOBE编程语言榜首,其顶尖的霸主地位不可撼动,而M1 mac业已发布了一段时间,作为跨时代的顶级芯片系统,这两大巨头能否珠联璧合,让开发者们猛虎添翼、更上层楼?本次我们尝试在M1 mac系统中搭建Java开发环境,并且集成目前Web开发领域红的发紫的Springboot框架,另外,谁说玩儿Java就必须得用Eclipse或者IntelliJ IDEA?我们就骄傲地使用Vscode。
珠联壁合地设天造|M1 Mac os(Apple Silicon)基于vscode(arm64)配置搭建Java开发环境(集成web框架Springboot)