diff --git a/.gitbook/assets/harmonyOS (1).png b/.gitbook/assets/harmonyOS (4) (1).png similarity index 100% rename from .gitbook/assets/harmonyOS (1).png rename to .gitbook/assets/harmonyOS (4) (1).png diff --git a/.gitbook/assets/harmonyOS.png b/.gitbook/assets/harmonyOS (4) (2).png similarity index 100% rename from .gitbook/assets/harmonyOS.png rename to .gitbook/assets/harmonyOS (4) (2).png diff --git a/.gitbook/assets/harmonyOS (4) (3).png b/.gitbook/assets/harmonyOS (4) (3).png new file mode 100644 index 0000000..885b3a2 Binary files /dev/null and b/.gitbook/assets/harmonyOS (4) (3).png differ diff --git a/.gitbook/assets/harmonyOS (4) (4).png b/.gitbook/assets/harmonyOS (4) (4).png new file mode 100644 index 0000000..885b3a2 Binary files /dev/null and b/.gitbook/assets/harmonyOS (4) (4).png differ diff --git a/.gitbook/assets/harmonyOS (4).png b/.gitbook/assets/harmonyOS (4).png new file mode 100644 index 0000000..885b3a2 Binary files /dev/null and b/.gitbook/assets/harmonyOS (4).png differ diff --git a/.gitbook/assets/image-20201210134143907.png b/.gitbook/assets/image-20201210134143907.png new file mode 100644 index 0000000..74be335 Binary files /dev/null and b/.gitbook/assets/image-20201210134143907.png differ diff --git a/.gitbook/assets/image-20201210134328575.png b/.gitbook/assets/image-20201210134328575.png new file mode 100644 index 0000000..ea65209 Binary files /dev/null and b/.gitbook/assets/image-20201210134328575.png differ diff --git a/.gitbook/assets/image-20201210135019104.png b/.gitbook/assets/image-20201210135019104.png new file mode 100644 index 0000000..126b73e Binary files /dev/null and b/.gitbook/assets/image-20201210135019104.png differ diff --git a/.gitbook/assets/image-20201210135047052.png b/.gitbook/assets/image-20201210135047052.png new file mode 100644 index 0000000..eaf6714 Binary files /dev/null and b/.gitbook/assets/image-20201210135047052.png differ diff --git a/.gitbook/assets/image-20201210145819255.png b/.gitbook/assets/image-20201210145819255.png new file mode 100644 index 0000000..4d52e92 Binary files /dev/null and b/.gitbook/assets/image-20201210145819255.png differ diff --git a/.gitbook/assets/image-20201210151627827.png b/.gitbook/assets/image-20201210151627827.png new file mode 100644 index 0000000..b9a8f9b Binary files /dev/null and b/.gitbook/assets/image-20201210151627827.png differ diff --git a/.gitbook/assets/image-20201210165334864.png b/.gitbook/assets/image-20201210165334864.png new file mode 100644 index 0000000..04f4f01 Binary files /dev/null and b/.gitbook/assets/image-20201210165334864.png differ diff --git a/.gitbook/assets/image-20201210183358390.png b/.gitbook/assets/image-20201210183358390.png new file mode 100644 index 0000000..4e65935 Binary files /dev/null and b/.gitbook/assets/image-20201210183358390.png differ diff --git a/.gitbook/assets/image-20201210183700963.png b/.gitbook/assets/image-20201210183700963.png new file mode 100644 index 0000000..d395056 Binary files /dev/null and b/.gitbook/assets/image-20201210183700963.png differ diff --git a/.gitbook/assets/image-20201210184448955.png b/.gitbook/assets/image-20201210184448955.png new file mode 100644 index 0000000..619ac1c Binary files /dev/null and b/.gitbook/assets/image-20201210184448955.png differ diff --git a/.gitbook/assets/image-20201210184527645.png b/.gitbook/assets/image-20201210184527645.png new file mode 100644 index 0000000..39f02f4 Binary files /dev/null and b/.gitbook/assets/image-20201210184527645.png differ diff --git a/.gitbook/assets/image-20201210184850528.png b/.gitbook/assets/image-20201210184850528.png new file mode 100644 index 0000000..4c4ea8e Binary files /dev/null and b/.gitbook/assets/image-20201210184850528.png differ diff --git a/.gitbook/assets/image-20201210191310040.png b/.gitbook/assets/image-20201210191310040.png new file mode 100644 index 0000000..a32d885 Binary files /dev/null and b/.gitbook/assets/image-20201210191310040.png differ diff --git a/.gitbook/assets/image-20201210192001954.png b/.gitbook/assets/image-20201210192001954.png new file mode 100644 index 0000000..4076d86 Binary files /dev/null and b/.gitbook/assets/image-20201210192001954.png differ diff --git a/.gitbook/assets/image-20201210193321202.png b/.gitbook/assets/image-20201210193321202.png new file mode 100644 index 0000000..1f8ce15 Binary files /dev/null and b/.gitbook/assets/image-20201210193321202.png differ diff --git a/.gitbook/assets/image-20201210193735607.png b/.gitbook/assets/image-20201210193735607.png new file mode 100644 index 0000000..d80033f Binary files /dev/null and b/.gitbook/assets/image-20201210193735607.png differ diff --git a/.gitbook/assets/image-20201210195519912.png b/.gitbook/assets/image-20201210195519912.png new file mode 100644 index 0000000..25fb594 Binary files /dev/null and b/.gitbook/assets/image-20201210195519912.png differ diff --git a/.gitbook/assets/image-20201210200518022.png b/.gitbook/assets/image-20201210200518022.png new file mode 100644 index 0000000..ea5abee Binary files /dev/null and b/.gitbook/assets/image-20201210200518022.png differ diff --git a/.gitbook/assets/image-20201210200637330.png b/.gitbook/assets/image-20201210200637330.png new file mode 100644 index 0000000..d6fa71f Binary files /dev/null and b/.gitbook/assets/image-20201210200637330.png differ diff --git a/.gitbook/assets/image-20201210201540194.png b/.gitbook/assets/image-20201210201540194.png new file mode 100644 index 0000000..552016a Binary files /dev/null and b/.gitbook/assets/image-20201210201540194.png differ diff --git a/.gitbook/assets/image-20201216173124146.png b/.gitbook/assets/image-20201216173124146.png new file mode 100644 index 0000000..2bddf83 Binary files /dev/null and b/.gitbook/assets/image-20201216173124146.png differ diff --git a/.gitbook/assets/image-20201216175534756.png b/.gitbook/assets/image-20201216175534756.png new file mode 100644 index 0000000..6b6727d Binary files /dev/null and b/.gitbook/assets/image-20201216175534756.png differ diff --git a/.gitbook/assets/image-20201216175748133.png b/.gitbook/assets/image-20201216175748133.png new file mode 100644 index 0000000..42be157 Binary files /dev/null and b/.gitbook/assets/image-20201216175748133.png differ diff --git a/.gitbook/assets/image-20201216180114246.png b/.gitbook/assets/image-20201216180114246.png new file mode 100644 index 0000000..3bf26c9 Binary files /dev/null and b/.gitbook/assets/image-20201216180114246.png differ diff --git a/.gitbook/assets/image-20201216180216650.png b/.gitbook/assets/image-20201216180216650.png new file mode 100644 index 0000000..170ed56 Binary files /dev/null and b/.gitbook/assets/image-20201216180216650.png differ diff --git a/.gitbook/assets/image-20201216180422745.png b/.gitbook/assets/image-20201216180422745.png new file mode 100644 index 0000000..fd0e97a Binary files /dev/null and b/.gitbook/assets/image-20201216180422745.png differ diff --git a/.gitbook/assets/image-20201216180523896.png b/.gitbook/assets/image-20201216180523896.png new file mode 100644 index 0000000..6c5f10e Binary files /dev/null and b/.gitbook/assets/image-20201216180523896.png differ diff --git a/.gitbook/assets/image-20201216202538515.png b/.gitbook/assets/image-20201216202538515.png new file mode 100644 index 0000000..b8bfbda Binary files /dev/null and b/.gitbook/assets/image-20201216202538515.png differ diff --git a/.gitbook/assets/image-20201216204823876.png b/.gitbook/assets/image-20201216204823876.png new file mode 100644 index 0000000..06e6730 Binary files /dev/null and b/.gitbook/assets/image-20201216204823876.png differ diff --git a/.gitbook/assets/image-20201216205125278.png b/.gitbook/assets/image-20201216205125278.png new file mode 100644 index 0000000..0328b62 Binary files /dev/null and b/.gitbook/assets/image-20201216205125278.png differ diff --git a/.gitbook/assets/image-20201216210158092.png b/.gitbook/assets/image-20201216210158092.png new file mode 100644 index 0000000..8befdf7 Binary files /dev/null and b/.gitbook/assets/image-20201216210158092.png differ diff --git a/.gitbook/assets/image-20201216210347469.png b/.gitbook/assets/image-20201216210347469.png new file mode 100644 index 0000000..afc0a38 Binary files /dev/null and b/.gitbook/assets/image-20201216210347469.png differ diff --git a/README.md b/README.md index fb361e6..1aff0f8 100644 --- a/README.md +++ b/README.md @@ -6,31 +6,31 @@ Getting started with static program analysis. Read this and start writing your f > ❓ How to automatically and efficiently guarantee software quality -静态程序分析入门。阅读此书并着手编写你的第一个静态程序分析器吧!本仓库关注一个非常重要的问题: +静态程序分析入门。阅读此书并着手编写你的第一个静态程序分析器吧!本仓库关注一个非常重要的问题: > ❓ 如何自动化地高效保障软件质量 * [《静态程序分析》Gitbook在线阅读地址](https://ranger-nju.gitbook.io/static-program-analysis-book/) + * 有时gitbook需要科学上网才能访问,没法科学上网的小伙伴可以试试访问[这里](https://spa-book.pblo.gq/)。 * [《静态程序分析》GitHub项目地址](https://github.com/RangerNJU/Static-Program-Analysis-Book) * 离线阅读方式 1. 将本仓库**下载**到本地(安装Git后,在命令行中执行命令`git clone https://github.com/RangerNJU/Static-Program-Analysis-Book.git`) 2. 周期性地**更新**,在仓库目录下执行`git pull` 3. 使用[Typora](https://typora.io/)等本地Markdown阅读器**阅读** -### 表达你的声音 👂 +### 表达你的声音 👂 * **批评的意见很有价值。** 这是我第一次书写教程,一定有很多做得不好的地方。如果你觉得有值得修改或值得讨论的地方(包括但不仅限于行文风格,内容准确性,图例与解释的易读性等等),可以选择: - -1. 加入QQ群(951182704)匿名或实名表达你的意见与看法 -2. 提issue -3. 通过邮箱联系我(ranger.nju\#gmail.com\) - * 如果你觉得我写得不错,可以到GitHub仓库中给我一个Star,也可以在自己的社交圈子中宣传,让更多的人了解这个项目。 - +* 加入QQ群(951182704)匿名或实名表达你的意见与看法 +* 提issue +* 通过邮箱联系我(ranger.nju\#gmail.com\) + * 如果你觉得我写得不错,可以到GitHub仓库中给我一个Star,也可以在自己的社交圈子中宣传,让更多的人了解这个项目。 ### 更新记录与里程碑事件 -1. Oct, 2020. 设立Repo,一个月内获得Star、Fork和PR 🥳 +1. Oct, 2020. 设立Repo,一个月内解锁Star、Fork和PR。 2. Nov. 将IR与Data Flow Analysis的相关内容暂时移出仓库,更新七至十课——Interprocedural Analysis、Pointer Analysis-Introduction and Foundations。 +3. Dec. 更新十一和十二两课——Context Sensitive Pointer Analysis,指针分析大结局。🥳 ## 这一《静态程序分析》教程对谁有用? @@ -58,7 +58,7 @@ Getting started with static program analysis. Read this and start writing your f #### 编程语言的分类 -当今的计算机世界,面对这样一条恶龙: 👇 +当今的计算机世界,面对这样一条恶龙: 👇 > 数十年来语言的核心没有变化,但软件的规模和复杂性增长迅速,如何保证程序的可靠性? @@ -126,7 +126,7 @@ Getting started with static program analysis. Read this and start writing your f 1. 学术门槛较高,学习者必须有良好的数学基础才能入门。 2. 验证代价较高,一般来说非常重要的项目会使用这一方式保证程序质量。甚至在操作系统这样重要的软件中,也并不一定会使用。\(截图来自鸿蒙OS直播发布会\) -![](.gitbook/assets/harmonyOS%20%281%29.png) +![](.gitbook/assets/harmonyOS%20%284%29%20%284%29.png) ## 加入项目/How to contribute @@ -134,6 +134,8 @@ Getting started with static program analysis. Read this and start writing your f 欢迎希望添加更好的讲解资料或对教程内容进行扩充的小伙伴 `fork, modify, PR` 三连。 +**提醒:引用图片时请使用相对路径。** + ## 本地化/Localization We'd love help translating this book! Open a new issue to start working on a new language. Feel free to start :\) diff --git a/SUMMARY.md b/SUMMARY.md index adeb5cc..021450d 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,13 +1,28 @@ # Table of contents * [简介](README.md) + +## 前言 + * [写在前面](ch0/README.md) * [为什么是这本书?](ch0/00-01-why-this-book.md) * [资料来源与版权信息](ch0/00-02-sources-and-license.md) -* [静态程序分析简介与数据流分析](ch1.md) -* [过程间分析](ch2/README.md) - * [过程间分析简介](ch2/02-01-inter-analysis-spa.md) - * [指针分析简介](ch2/02-02-pointer-analysis-spa.md) - * [指针分析理论一](ch2/02-03-pointer2-analysis-spa.md) - * [指针分析理论二](ch2/02-04-pointer3-analysis-spa.md) + +## 数据流分析 + +* [静态程序分析简介与数据流分析](ch1/ch1.md) + +## 过程间分析 + +* [过程间分析简介](ch2/ch2.md) + +## 指针分析 + +* [指针分析简介](ch3/pointer-analysis/README.md) + * [指针分析简介](ch3/pointer-analysis/03-01-pointer-analysis-spa.md) + * [指针分析理论(上)](ch3/pointer-analysis/03-02-pointer2-analysis-spa.md) + * [指针分析理论(下)](ch3/pointer-analysis/03-03-pointer3-analysis-spa.md) +* [指针分析进阶](ch3/context-sensitivity/README.md) + * [上下文敏感分析(上)](ch3/context-sensitivity/03-04-context-sensitivity.md) + * [上下文敏感分析(下)](ch3/context-sensitivity/03-05-cs2.md) diff --git a/ch1.md b/ch1/ch1.md similarity index 100% rename from ch1.md rename to ch1/ch1.md diff --git a/ch2/README.md b/ch2/README.md deleted file mode 100644 index 04d22ec..0000000 --- a/ch2/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# 过程间分析 - -**阅读提示:使用屏幕较大的设备能够看到自带的Sticky Table of Contents,更有利于理清阅读思路。** - -对应视频在: - -* [第七课-过程间分析](https://www.bilibili.com/video/BV1GQ4y1T7zm) -* [第八课-指针分析](https://www.bilibili.com/video/BV1gg4y1z78p) - diff --git a/ch2/02-01-inter-analysis-spa.md b/ch2/ch2.md similarity index 96% rename from ch2/02-01-inter-analysis-spa.md rename to ch2/ch2.md index c918e7f..60a2861 100644 --- a/ch2/02-01-inter-analysis-spa.md +++ b/ch2/ch2.md @@ -1,5 +1,12 @@ # 过程间分析简介 +**阅读提示:使用屏幕较大的设备能够看到自带的Sticky Table of Contents,更有利于理清阅读思路。** + +对应视频在: + +* [第七课-过程间分析](https://www.bilibili.com/video/BV1GQ4y1T7zm) +* [第八课-指针分析](https://www.bilibili.com/video/BV1gg4y1z78p) + ## 过程间分析简介 本小节通过四个部分介绍过程间分析。 @@ -178,15 +185,15 @@ A:分别调用A和C中定义的foo方法。 ![](../.gitbook/assets/image-20201029230504891.png) -2. 处理main后向WL中加入A.foo\(\) +1. 处理main后向WL中加入A.foo\(\) ![](../.gitbook/assets/image-20201029230535984.png) -3. 中间省略一些步骤,这里面对C.bar\(\)时,虽然会调用A.foo\(\),但由于A.foo\(\)之前已经处理过(在集合RM中),之后不会再进行处理 +1. 中间省略一些步骤,这里面对C.bar\(\)时,虽然会调用A.foo\(\),但由于A.foo\(\)之前已经处理过(在集合RM中),之后不会再进行处理 ![](../.gitbook/assets/image-20201029230622120.png) -4. 这里C.m\(\)是不可达的死代码 +1. 这里C.m\(\)是不可达的死代码 ![](../.gitbook/assets/image-20201029230909895.png) @@ -260,8 +267,6 @@ Edge transfer处理引入的call & return edge。为此,我们需要**在之 ## Key points -**The X You Need To Understand in This Lecture** - 1. How to build call graph via class hierarchy analysis * 如何利用CHA构建调用关系图\(call graph\) 2. Concept of interprocedural control-flow graph diff --git a/ch3/context-sensitivity/03-04-context-sensitivity.md b/ch3/context-sensitivity/03-04-context-sensitivity.md new file mode 100644 index 0000000..2a858d8 --- /dev/null +++ b/ch3/context-sensitivity/03-04-context-sensitivity.md @@ -0,0 +1,153 @@ +# 上下文敏感分析(上) + +> 上下文敏感分析是提高指针分析精度最有效的技术,没有之一。 + +本课分为以下五个部分: + +1. Introduction\(Example\) +2. Introduction\(Theory\) +3. Context Sensitive Pointer Analysis: Rules +4. Context Sensitive Pointer Analysis: Algorithms +5. Context Sensitivity Variants + +在上半篇中我们讲解前三个部分,下半篇会继续讲最后的两个部分。 + +## Introduction\(example\) + +首先用一个例子直观地说明上下文不敏感分析的问题所在。 + +```java +void main() { +Number n1, n2, x, y; + n1 = new One(); // 𝑜1 + n2 = new Two(); // 𝑜2 + x = id(n1); + y = id(n2); + int i = x.get(); + //假设使用我们之前所讲述的上下文不敏感分析 + //这里i的常量分析结果是什么? +} +Number id(Number n) { + return n; +} +interface Number { + int get(); +} +class One implements Number { + public int get() { return 1; } +} +class Two implements Number { + public int get() { return 2; } +} +``` + +使用我们之前描述的算法,由于不考虑调用的顺序,会得到这样的PFG。 + +![](../../.gitbook/assets/image-20201210134143907.png) + +也就因此造成了分析结果的低精度,即在动态运行时i一定是1,而分析的结果认为i为NAC\(Not a constant\): + +![](../../.gitbook/assets/image-20201210134328575.png) + +如果我们使用上下文敏感的分析方式,区分不同时间对的id调用,则会得到这样的PFG: + +![](../../.gitbook/assets/image-20201210135019104.png) + +对应地也就能得到更为精确的分析结果: + +![](../../.gitbook/assets/image-20201210135047052.png) + +## Introduction\(Theory\) + +### C.I.\(Context Insensitive\) + +是什么原因导致了上下文不敏感分析的低精度? + +1. 在动态执行时,对同一个函数的不同调用,往往有着不同的调用上下文(calling contexts),如上一小节的例子中两次对id的调用。 +2. 不同的调用上下文会被混合并传播,进而形成假的数据流。如上一小节的例子中指针x和y指向两个目标。 + +### C.S.\(Context Sensitive\) + +上下文敏感分析通过区分不同调用上下文的数据流,对调用上下文建模。举个例子,在这一段代码中,对id调用的上下文就是两行call-site,记为\[1\]和\[2\]: + +```java +x = id(n1); //context 1 for id() +y = id(n2); //context 2 for id() +int i = x.get(); + +Number id(Number n) { + return n; +} +``` + +进而,我们可以**通过对同一函数的不同调用添加标号进行区分**,而得到更精确的PFG: + +![](../../.gitbook/assets/image-20201210145819255.png) + +### C.S. heap + +**对于Java中被动态分配到heap上的对象,我们也需要对他们做相应的标记以提高分析精度。**例子:~~(或许真的需要录视频了?)~~ + +* 不做标记时,第八行new出来的对象无法区分,只能同一记作 $$o_8$$ +* 做标记后,可以分别记为$$ 3:o_8$$和$$ 4:o_8$$ + +![](../../.gitbook/assets/image-20201210151627827.png) + +不过,采取C.I.+ C.S. heap进行分析时,C.S. heap就不能提高精度了。 + +![](../../.gitbook/assets/image-20201210165334864.png) + +## Context Sensitive Pointer Analysis: Rules + +### Domains and Notations + +接下来我们用介绍适用于上下文敏感分析的规则。 + +首先我们讨论的Domain中,methods/variables/objects都升级为带有上下文标识的。 + +![](../../.gitbook/assets/image-20201216173124146.png) + +新引入符号说明:引入C表示所有的上下文组成的集合,c表示具体的某个上下文。 + +值得一提的是,fields不需要带有上下文标记,因为field总是依赖于某一个object。只要object被标记进而通过上下文可被区分了,fields自然也可以被区分。一个不太准确但是可以帮助理解的例子是,如果你能区分一对双胞胎,那么他/她们口袋里的东西也是可以被区分的。 + +### Rules + +首先我们考虑不包含调用(Call)语句的四类语句所对应的规则。 + +![](../../.gitbook/assets/image-20201216175534756.png) + +对比一下上下文不敏感指针分析的规则: + +![](../../.gitbook/assets/image-20201216175748133.png) + +**唯一的区别在于,对象被加上了上下文标识。** + +然后我们来看看调用如何处理。在上下文敏感的指针分析中,规则如下: + +![](../../.gitbook/assets/image-20201216180216650.png) + +再次对比一下上下文不敏感指针分析的规则: + +![](../../.gitbook/assets/image-20201216180114246.png) + +**这次我们添加了一个Select函数,它的作用是为object添加上下文标识,例如:** + +* 为参数添加上下文标识 + +![](../../.gitbook/assets/image-20201216180422745.png) + +* 为返回值添加上下文标识 + +![](../../.gitbook/assets/image-20201216180523896.png) + +**也就是说,上下文的信息是在处理调用时添加的。** + +## Key points + +* Concept of context sensitivity \(**C.S.**\) +* Concept of context-sensitive heap \(**C.S. heap**\) +* **Why** C.S. **and** C.S. heap improve **precision** + * 单独使用C.S.或C.S. heap依然会损失精度 +* Context-sensitive pointer analysis **rules** + diff --git a/ch3/context-sensitivity/03-05-cs2.md b/ch3/context-sensitivity/03-05-cs2.md new file mode 100644 index 0000000..771671b --- /dev/null +++ b/ch3/context-sensitivity/03-05-cs2.md @@ -0,0 +1,264 @@ +# 上下文敏感分析(下) + +> 上下文敏感分析是提高指针分析精度最有效的技术,没有之一。 + +本课分为以下五个部分: + +1. Introduction\(Example\) +2. Introduction\(Theory\) +3. Context Sensitive Pointer Analysis: Rules +4. Context Sensitive Pointer Analysis: Algorithms +5. Context Sensitivity Variants + +在上半篇中我们讲解了前三个部分,下半篇来继续讲最后的两个部分。 + +~~挖个坑——本文所有的例子其实都更适合视频讲解。~~ + +## Context Sensitive Pointer Analysis: Algorithms + +### Idea + +除了PFG做了相应改进之外,算法的总体思路没有改变。 + +![](../../.gitbook/assets/image-20201210183358390.png) + +具体来说,带有上下文信息的Node和Edge的构成带有上下文信息的PFG: + +![](../../.gitbook/assets/image-20201210183700963.png) + +### Algorithm + +![](../../.gitbook/assets/image-20201210184448955.png) + +乍一看挺吓人的,对吧?不过你应该对上下文敏感\(C.S.\)指针分析算法的小伙伴上下文不敏感\(C.I.\)指针分析算法很熟悉了(下图中所有上下文标记都用色块遮挡了): + +![](../../.gitbook/assets/image-20201210184527645.png) + +因此,在接下来的内容中我们更关注和上下文相关的部分,而不像之前一样详细地关注所有细节。 + +值得一提的差异是,RM和CG两个集合在本节所述的上下文敏感算法中都是带有上下文信息的。举个例子,在C.S.的分析中,caller和callee都带有上下文信息($$c^t$$ 代表callee的上下文标记,c:2->$$c^t:\dots$$表示第二行的caller调用了带有$$c^t$$标记的callee): + +![](../../.gitbook/assets/image-20201210184850528.png) + +### Select in ProcessCall + +![](../../.gitbook/assets/image-20201216202538515.png) + +在这一部分,我们只需要理解Select的作用(对于Select的具体实现,会在后面讲解): + +* ProcessCall接收两个参数,意义是:带有上下文标记的x新增一个带有上下文标记指向目标o。 +* Select接收参数(这里虽然有4个参数,但并非每种实现方式都需要用到所有的4个参数) + * c。x的上下文标记 + * l。调用点本身(call site),在例子中以行号标识调用点 + * $$c' : o_i $$。receiver object + * m。 目标method +* Select返回callee的context $$ c^t$$ + +## Context Sensitivity Variants + +> 那,讲讲Select吧? + +Select函数实现时的具体差异,产生了不同的上下文敏感分析的变种方法,它们有不同的优缺点。具体来说,就是 + +![](../../.gitbook/assets/image-20201210191310040.png) + +### C.I. + +* 可以视为**C.S. 的一种特殊情况**,无论传递给Select的参数是什么,总是返回同样的上下文。即: + +```java +Select(*,*,*) = [] +``` + +### Call-Site Sensitivity + +* 用一系列的**调用链\(call chain/call stream\)作为上下文标识**。 +* Also called **call-string sensitivity**, or **k-CFA** + +```java +Select(c,l,*) = [𝑙`, 𝑙``, 𝑙] +// where 𝑐 = [𝑙`, … , 𝑙``] +// 即:只根据caller已有的上下文和 +// call-site的新增上下文 +// 计算callee的上下文 +``` + +举个例子直观地展示Call-Site Sensitivity: + +![](../../.gitbook/assets/image-20201210192001954.png) + +当然,如果bar是递归的,分析出来的context可能会包含非常多的内容…… + +![](../../.gitbook/assets/image-20201210193321202.png) + +#### k-Limiting Context Abstraction + +为了避免上面所说的递归导致的算法无法终止的情况,我们可以给contexts的长度设一个上界k。 + +* 1-call-site/1-CFA + + ```java + Select(*,l,*) = [l] + // 即:不继承caller已经带有的上下文 + // 只考虑call-site新引入的上下文 + // "只记得最近一次经过的路口是哪一个" + ``` + + ![](../../.gitbook/assets/image-20201210193735607.png) + +* 2-call-site/2-CFA + + ```java + Select(c,l,*) = [l``,l] + // where c = [l`,l``] + // 即:"只记得最后两次经过的路口是哪两个" + ``` + +### Call-Site Example + +分析以下代码,给出指针流图PFG和调用关系图CG作为结果。(不需要关注heap上的变量和this变量,因为它们在这个例子中不是重点) + +```java +class C { + static void main() { + C c = new C(); + c.m(); + } + + Number id(Number n) { + return n; + } + void m() { + Number n1,n2,x,y; + n1 = new One(); + n2 = new Two(); + x = this.id(n1); + y = this.id(n2); + x.get(); + // 先想想动态执行的时候上一行调用的结果是什么? + } +} +``` + +答案如下: + +![](../../.gitbook/assets/image-20201216204823876.png) + +和C.I.对比,我们可以发现对于16行处的分析,C.S.\(1-Call-Site\)更加精确。 + +![](../../.gitbook/assets/image-20201216205125278.png) + +### Object Sensitivity + +* **以receiver object作为上下文标识** +* Each context consists of a list of abstract objects \(represented by their allocation sites\) + * At a method call, use the receiver object with its heap + + context as callee context + + * Distinguish the operations of data flow on different objects +* ![](../../.gitbook/assets/image-20201210195519912.png) + +### Object Example & Comparison + +分别用1-Call-Site和1-Object的方式分析以下代码,给出所有指针(包括Variable和Field)所指向的对象。 + +```java +a1 = new A(); +a2 = new A(); +b1 = new B(); +b2 = new B(); +a1.set(b1); +a2.set(b2); +x = a1.get(); + +class A { + B f; + void set(B b) { + this.doSet(b); + } + void doSet(B p) { + this.f = p; + } + B get() { + return this.f; + } +} +``` + +![](../../.gitbook/assets/image-20201210200518022.png) + +在12行,1-call-site的分析方法产生了不精确分析结果。在Call Graph中我们能够更好地看到这一点: + +![](../../.gitbook/assets/image-20201210200637330.png) + +更加通俗地说,1-call-site只能记得自己是从哪个路口走到当前位置的,而1-object能够记得自己是谁。 + +然而并不能说明1-object的精度一定比1-call-site高。比如在分析以下代码时: + +```java +class C { + static void main() { + C c = new C(); + c.m(); + } + + Number id(Number n) { + return n; + } + + void m() { + Number n1,n2,x,y; + n1 = new One(); + n2 = new Two(); + x = this.id(n1); + y = this.id(n2); + // 1-object无法区分以上两条调用 + // 但是1-call-site可以区分 + x.get(); + } +} +``` + +因此,在**理论上**,两种方法不可比。而在针对OO语言\(如Java\)的**实践中**,object方法的表现(无论是精度还是速度)**通常**更好,因为这更符合OO语言的特性。 + +### Type Sensitivity + +* 和Object Sensitivity类似,但是粒度更粗而效率更高——这种方法只关注Object是在哪一个Class中被声明的。 +* Each context consists of a list of types + * At a method call, use the type containing the allocation site of the receiver object with its heap context as callee context + +![](../../.gitbook/assets/image-20201210201540194.png) + +例如(如果你发现这个例子不太好理解,请先往下看看下一个例子): + +![](../../.gitbook/assets/image-20201216210158092.png) + +### Comparison\(Type vs. Object Sensitivity\) + +阅读顺序建议:绿框->蓝框->无框。在Object-sensitivity中我们记录下每一个object被声明出来的行数。在Type-sensitivity中我们只记录它们都是在Class X中声明的。 + +![](../../.gitbook/assets/image-20201216210347469.png) + +### Sum up + +In general: + +* Precision: object > type > call-site +* Efficiency: type > object > call-site + +## Key points + +* **Algorithm** for context-sensitive pointer analysis + * 和C.I.几乎一致 +* 3 Common context sensitivity **variants** + * Call-Site Sensitivity + * Object Sensitivity + * Type Sensitivity +* **Differences and relationship** among common + + context sensitivity variants + + * 在面向对象语言(如Java)中,Object Sensitivity通常比Call-Site Sensitivity表现更好 + * 如果追求速度,可以进而选用Type Sensitivity + diff --git a/ch3/context-sensitivity/README.md b/ch3/context-sensitivity/README.md new file mode 100644 index 0000000..ceed470 --- /dev/null +++ b/ch3/context-sensitivity/README.md @@ -0,0 +1,3 @@ +# 指针分析进阶 + +这一部分介绍精度更高的上下文敏感指针分析。 \ No newline at end of file diff --git a/ch2/02-02-pointer-analysis-spa.md b/ch3/pointer-analysis/03-01-pointer-analysis-spa.md similarity index 83% rename from ch2/02-02-pointer-analysis-spa.md rename to ch3/pointer-analysis/03-01-pointer-analysis-spa.md index b83a437..06eeaec 100644 --- a/ch2/02-02-pointer-analysis-spa.md +++ b/ch3/pointer-analysis/03-01-pointer-analysis-spa.md @@ -15,23 +15,23 @@ 接下来我们对比基于CHA的分析方法和指针分析的分析方法。首先,回想一下CHA的构造过程。在这个程序中对`get()`的调用,在CHA分析下,应该调用哪几个方法? -![](../.gitbook/assets/image-20201105183618529.png) +![](../../.gitbook/assets/image-20201105183618529.png) ### 使用CHA分析 -![](../.gitbook/assets/image-20201109140057119.png) +![](../../.gitbook/assets/image-20201109140057119.png) 可以看出,由于只关心类的层次结构,分析结果的三个箭头中有两个是false positive。也因此导致了分析结果的不精确。 -![](../.gitbook/assets/image-20201109140605829.png) +![](../../.gitbook/assets/image-20201109140605829.png) ### 使用指针分析 利用指针分析,我们能知道n指向的对象就是new One\(\)语句所新建出来的对象。所以能精确地知道x一定会取1。 -![](../.gitbook/assets/image-20201109154728420.png) +![](../../.gitbook/assets/image-20201109154728420.png) -![](../.gitbook/assets/image-20201109154844509.png) +![](../../.gitbook/assets/image-20201109154844509.png) **比较两种分析,可以看出CHA速度快而精度低,接下来我们学习高精度的指针分析。** @@ -44,7 +44,7 @@ 什么是指针分析呢?举个例子(省略中间过程): -![](../.gitbook/assets/image-20201105184327763.png) +![](../../.gitbook/assets/image-20201105184327763.png) ### 区分指针分析与别名分析 @@ -71,7 +71,7 @@ y = new Y(); > 业界大佬们说它很重要。 -![](../.gitbook/assets/image-20201105184919660.png) +![](../../.gitbook/assets/image-20201105184919660.png) ## Key Factors of Pointer Analysis @@ -80,7 +80,7 @@ y = new Y(); * Pointer analysis is a complex system * Multiple factors affect the precision and efficiency of the system -![](../.gitbook/assets/image-20201105185230667.png) +![](../../.gitbook/assets/image-20201105185230667.png) ### Heap Abstraction @@ -94,17 +94,17 @@ for (…) { 解决方法也很简单,学校里同学太多了就分成班级来管理,我们也可以对堆上的对象进行抽象: -![](../.gitbook/assets/image-20201105185431196.png) +![](../../.gitbook/assets/image-20201105185431196.png) 相关的技术有很多,这里只讲一个最常用的分支Allocation-Site Abstraction。而Storeless的方法本课程不涉及。 -![](../.gitbook/assets/image-20201105185630758.png) +![](../../.gitbook/assets/image-20201105185630758.png) #### Allocation-Site Abstraction 虽然动态时对象的个数可能是无限的,但是new语句的个数一定是有限的。我们可以按照new语句来进行抽象。 -![](../.gitbook/assets/image-20201105185806532.png) +![](../../.gitbook/assets/image-20201105185806532.png) ### Context Sensitivity @@ -112,11 +112,11 @@ for (…) { 如果将上下文做区分(进行额外的标记,如记录下图中p指向的目标),对参数不同时的调用做不同的分析,则称为**上下文敏感分析**。 -![](../.gitbook/assets/image-20201105190333596.png) +![](../../.gitbook/assets/image-20201105190333596.png) 反之,如果不区分上下文,则称为**上下文不敏感分析**。由于忽略了一部分信息,可能会损失分析的精度。 -![](../.gitbook/assets/image-20201105190439805.png) +![](../../.gitbook/assets/image-20201105190439805.png) 我们首先学习不敏感的分析方法,在之后的课程中介绍上下文敏感分析。 @@ -135,11 +135,11 @@ c.f = "y"; 对于流敏感的分析,会得到如下的mapping。`o1`代表在第一行动态分配的对象。 -![](../.gitbook/assets/image-20201105191248594.png) +![](../../.gitbook/assets/image-20201105191248594.png) 如果使用流不敏感的分析,会得到如下的mapping。 -![](../.gitbook/assets/image-20201105191705757.png) +![](../../.gitbook/assets/image-20201105191705757.png) ### Analysis Scope @@ -162,7 +162,7 @@ Java中的Pointers有以下几类: * Array element: array\[i\] * 涉及数组的分析中,我们**忽略下标**,代之以一个域(a single field)。例如,在下图中我们用arr表示。 * 原因之一:数组下标是变量时难以计算具体值 - * 在之后介绍的算法中,**可作为Instance field处理**![](../.gitbook/assets/image-20201105194030384.png) + * 在之后介绍的算法中,**可作为Instance field处理**![](../../.gitbook/assets/image-20201105194030384.png) ### 关注的语句类型 @@ -187,12 +187,11 @@ r = x.k(a, …) 复杂的Store和Load指令可以解构成简单的,所以我们可以只考虑对上述五种基本类型语句的分析: -![](../.gitbook/assets/image-20201105194707507.png) +![](../../.gitbook/assets/image-20201105194707507.png) ## Key points -**The X You Need To Understand in This Lecture** +* **What is pointer analysis?** +* Understand **the key factors** of pointer analysis +* Understand **what we analyze** in pointer analysis -- **What is pointer analysis?** -- Understand **the key factors** of pointer analysis -- Understand **what we analyze** in pointer analysis \ No newline at end of file diff --git a/ch2/02-03-pointer2-analysis-spa.md b/ch3/pointer-analysis/03-02-pointer2-analysis-spa.md similarity index 79% rename from ch2/02-03-pointer2-analysis-spa.md rename to ch3/pointer-analysis/03-02-pointer2-analysis-spa.md index dc212ac..d07fb98 100644 --- a/ch2/02-03-pointer2-analysis-spa.md +++ b/ch3/pointer-analysis/03-02-pointer2-analysis-spa.md @@ -1,4 +1,4 @@ -# 指针分析理论基础一 +# 指针分析理论(上) 接下来两篇文章将主要介绍以下四点内容。前三点对应线下课程第九课,最后一点对应第十课。 @@ -11,11 +11,11 @@ ## Notations -![](../.gitbook/assets/image-20201105195029800.png) +![](../../.gitbook/assets/image-20201105195029800.png) 首先介绍常用数学符号,不会的同学可以复习一下离散数学。 -![](../.gitbook/assets/image-20201105195154527.png) +![](../../.gitbook/assets/image-20201105195154527.png) 分别定义变量,域,对象(用下标标识是在第几行创建的对象),实例域和指针(是变量和实例对象的并),和指向关系。`X`表示笛卡尔积。 @@ -33,29 +33,29 @@ if(...){ _前排提示:与《数理逻辑》/《形式化语义》梦幻联动。没学过的同学也不要着急。_ -![](../.gitbook/assets/image-20201105195524932.png) +![](../../.gitbook/assets/image-20201105195524932.png) 主要解释Rule一列中的内容。**横线上的内容是前提\(Premises\),横线下的内容是结论\(Conclusion\)。** 用简单易懂的语言描述,看到new语句,我们就将新建的对象加入`pt(x)`。 -![](../.gitbook/assets/image-20201105195943007.png) +![](../../.gitbook/assets/image-20201105195943007.png) 对于Assign语句,我们将x指向y指向的对象。 -![](../.gitbook/assets/image-20201105235312349.png) +![](../../.gitbook/assets/image-20201105235312349.png) 对于Store和Load亦然。 -![](../.gitbook/assets/image-20201105200112512.png) +![](../../.gitbook/assets/image-20201105200112512.png) -![](../.gitbook/assets/image-20201105200123601.png) +![](../../.gitbook/assets/image-20201105200123601.png) ### Summary 最后用一图总结。**第一条规则添加指向,而后三条规则传递指向关系。** -![](../.gitbook/assets/image-20201105200412145.png) +![](../../.gitbook/assets/image-20201105200412145.png) ## How to Implement Pointer Analysis @@ -63,7 +63,7 @@ _别处的资料都没有全家桶,只介绍某些特殊情况下的分析算 本质上来说,指针分析是在指针间**传递**指向关系。 -![](../.gitbook/assets/image-20201105200815104.png) +![](../../.gitbook/assets/image-20201105200815104.png) inclusion constraints的具体解释:在上述表示的结论部分中可以写作两个集合间的包含关系。如Load应该表示为: @@ -72,7 +72,7 @@ inclusion constraints的具体解释:在上述表示的结论部分中可以 > Key to implementation: when 𝑝𝑡\(𝑥\)is **changed**, **propagate** the **changed par**t to the **related pointers** of 𝑥 -![](../.gitbook/assets/image-20201105201018655.png) +![](../../.gitbook/assets/image-20201105201018655.png) ### Pointer Flow Graph @@ -88,21 +88,21 @@ inclusion constraints的具体解释:在上述表示的结论部分中可以 * `Edges: Pointer × Pointer` * **An edge 𝑥 -> 𝑦** means that the objects pointed by pointer 𝑥 **may flow to \(and also be pointed to by\)** pointer 𝑦 -![](../.gitbook/assets/image-20201105201421501.png) +![](../../.gitbook/assets/image-20201105201421501.png) ### Example 假设c和d一开始都指向 $$o_i$$,根据上述规则,我们能够从左侧的程序语句从上到下构建出右侧的指针流图。 -![](../.gitbook/assets/image-20201105201746860.png) +![](../../.gitbook/assets/image-20201105201746860.png) 因此,所有b所指向的对象更新时,都要传递到e中。这是一个求传递闭包\(transitive closure\)的过程。假如我们考虑j位置的一条新语句`b = new T();` -![](../.gitbook/assets/image-20201105201939088.png) +![](../../.gitbook/assets/image-20201105201939088.png) PFG的整个构造过程,需要在构建PFG和在已有的PFG上传递指向关系这两个步骤间循环往复。这两个步骤是相互依赖的,所以需要精心设计算法来实现分析。 -![](../.gitbook/assets/image-20201105202101633.png) +![](../../.gitbook/assets/image-20201105202101633.png) ## Pointer Analysis: Algorithms @@ -115,28 +115,28 @@ PFG的整个构造过程,需要在构建PFG和在已有的PFG上传递指向 首先,四个红框部分对应之前提到的四种基本语句——New、Assign、Store和Load。接下来做详细讲解。 -![](../.gitbook/assets/image-20201127170432941.png) +![](../../.gitbook/assets/image-20201127170432941.png) ### Handling of New and Assign #### Init and adding edges -![](../.gitbook/assets/image-20201112191544354.png) +![](../../.gitbook/assets/image-20201112191544354.png) 首先考虑两种简单的语句:New和Assign。 -* 前三行代码做初始化的工作,并针对所有的**New**语句,将所有的初始指向关系加入WorkList。注意pt(n)初始化后为空集{},随着算法的迭代会增加元素。 +* 前三行代码做初始化的工作,并针对所有的**New**语句,将所有的初始指向关系加入WorkList。注意pt\(n\)初始化后为空集{},随着算法的迭代会增加元素。 * 之后的两行代码处理**Assign**语句,添加`y->x`的边到PFG中。添加边的具体算法如下 -![](../.gitbook/assets/image-20201112191630283.png) +![](../../.gitbook/assets/image-20201112191630283.png) #### Propagate -![](../.gitbook/assets/image-20201112193329365.png) +![](../../.gitbook/assets/image-20201112193329365.png) 传播的具体算法如下,标号为2的语句是整个算法中唯一执行后改变指向关系的语句。 -![](../.gitbook/assets/image-20201112193357268.png) +![](../../.gitbook/assets/image-20201112193357268.png) #### Detial-Differential Propagation @@ -153,22 +153,22 @@ Solve(𝑆) 首先我们考虑不使用Differential Propagation的情况,首先是a->c->d的传递路线。 -![](../.gitbook/assets/image-20201112194234928.png) +![](../../.gitbook/assets/image-20201112194234928.png) 然后是b->c->d的传递路线,虽然 $$\{o_1, o_3\}$$之前已经在c所指向的集合中了,但依然需要参与传播,这是冗余的。 -![](../.gitbook/assets/image-20201112194358502.png) +![](../../.gitbook/assets/image-20201112194358502.png) 我们再来看使用Differential Propagation的情况,只需要传播$$\{o_5\}$$一项即可。在实际应用中这能够大大减小开销。 -![](../.gitbook/assets/image-20201112194555582.png) +![](../../.gitbook/assets/image-20201112194555582.png) * In practice, Δ is usually small compared with the original set, so propagating only the new points-to information \(Δ\) * Besides, Δ is also important for efficiency when handling stores, loads, and method calls, as explained later ### Handling Store and Load -![](../.gitbook/assets/image-20201112195502575.png) +![](../../.gitbook/assets/image-20201112195502575.png) 对于AddEdge函数中第二个if的说明:仅在第一次添加s->t到PFG时添加pt\(s\)的信息到t,是因为Propagate中的语句能够处理后续的pt\(s\)变化。 @@ -176,7 +176,7 @@ Solve(𝑆) 至此,我们完整地介绍了为了教学目的设计的指针分析算法。 -![](../.gitbook/assets/image-20201123205009821.png) +![](../../.gitbook/assets/image-20201123205009821.png) ### Example @@ -194,12 +194,11 @@ e = d.f; 这一例子动态内容很多,所以计划录制一小段视频讲解。先放个答案,能自己推导对的同学就可以跳过视频了。 -![](../.gitbook/assets/image-20201126221950557.png) +![](../../.gitbook/assets/image-20201126221950557.png) ## Key points -**The X You Need To Understand in This Lecture** - * **Rules** for pointer analysis * **PFG**\(Pointer flow graph\) -* **Algorithm** for pointer analysis \ No newline at end of file +* **Algorithm** for pointer analysis + diff --git a/ch2/02-04-pointer3-analysis-spa.md b/ch3/pointer-analysis/03-03-pointer3-analysis-spa.md similarity index 78% rename from ch2/02-04-pointer3-analysis-spa.md rename to ch3/pointer-analysis/03-03-pointer3-analysis-spa.md index d935b28..946063f 100644 --- a/ch2/02-04-pointer3-analysis-spa.md +++ b/ch3/pointer-analysis/03-03-pointer3-analysis-spa.md @@ -1,4 +1,4 @@ -# 指针分析理论基础二 +# 指针分析理论(下) 首先回顾一下在上一篇文章中列出的大纲。 @@ -36,30 +36,30 @@ void foo(A a) { 各个符号的定义为: - +![](../../.gitbook/assets/image-20201201151956869.png) -![](../.gitbook/assets/image-20201126230831572.png) +![](../../.gitbook/assets/image-20201126230831572.png) -> 一个参考答案:保存现场,构造调用栈帧,传递参数,跳转到目标函数开始执行……目标函数执行完毕跳转回来,后从预定的位置取返回值(若需要),恢复现场,继续往下执行…… +> 一个参考答案:保存现场,构造调用栈帧,传递参数,跳转到目标函数开始执行……目标函数执行完毕跳转回来,后从预定的位置取返回值(若需要),恢复现场,继续往下执行…… 在静态分析中,我们更多地关心数据流,而非控制流。而针对Java,处理函数调用的数据流可以分为以下四个部分: 1. 确定目标方法。用第7课介绍过的Dispatch函数完成。 2. 传receiver object -![](../.gitbook/assets/image-20201126184745576.png) +![](../../.gitbook/assets/image-20201126184745576.png) -3. 传参数 +1. 传参数 -![](../.gitbook/assets/image-20201126185008506.png) +![](../../.gitbook/assets/image-20201126185008506.png) -4. 传返回值 +1. 传返回值 -![](../.gitbook/assets/image-20201126185233403.png) +![](../../.gitbook/assets/image-20201126185233403.png) 因此,我们可以对应规则,在PFG上添加Edge实现过程间信息的传递。完整的规则如下: -![](../.gitbook/assets/image-20201126231116221.png) +![](../../.gitbook/assets/image-20201126231116221.png) #### Detail-1 @@ -67,9 +67,9 @@ void foo(A a) { 通过这两个图可以直观地说明原因: -![](../.gitbook/assets/image-20201126231403264.png) +![](../../.gitbook/assets/image-20201126231403264.png) -![](../.gitbook/assets/image-20201126231437769.png) +![](../../.gitbook/assets/image-20201126231437769.png) _在每次算法执行时,_$$o_i$$_是确定的某个(只有一个)对象,然后针对这个对象做Dispatch,能够找到对应的唯一的receiver object._ @@ -77,20 +77,20 @@ _在每次算法执行时,_$$o_i$$_是确定的某个(只有一个)对象 像之前用CHA做过程间分析时一样,我们需要将分析的过程和Call graph构建的过程结合起来。 -![](../.gitbook/assets/image-20201126231722298.png) +![](../../.gitbook/assets/image-20201126231722298.png) 不同的是,这次我们只分析从main方法(或者一般性地说,程序入口)开始可达的部分。原因有二: 1. 提升分析速度。因为我们能够避免分析不会被执行到的死代码。 2. 提升分析精度。避免了unreachable部分的代码调用reachable部分方法时可能引起的精度下降。 -![](../.gitbook/assets/image-20201126191225969.png) +![](../../.gitbook/assets/image-20201126191225969.png) ## Algorithm: PA with Method Calls 接下来介绍一个具体的、易于理解和实现的算法。由于指针分析是静态程序分析的基础,理解了这个看起来枯燥的算法后,更容易在静态程序分析领域触类旁通。~~而且据说后面两节课会学得更加轻松~~ -![](../.gitbook/assets/image-20201126191650221.png) +![](../../.gitbook/assets/image-20201126191650221.png) 算法整体上来说和上一节课所介绍的大框架相似,黄色标记的部分是这次新加入的部分。绿色部分是对新的全局变量的说明: @@ -104,7 +104,7 @@ AddReachable的作用是: * **输入参数**m是最新的可达方法。 * 函数修改维护全局的RM、S和$$S_m$$,并处理新的方法m中的New和Assign语句。 -![](../.gitbook/assets/image-20201126194125039.png) +![](../../.gitbook/assets/image-20201126194125039.png) #### Detail-3 @@ -121,9 +121,9 @@ ProcessCall的作用是: * 输入的$$o_i$$是x新指向的目标。 * 函数在可达的语句集合S中,选择所有与x有关的过程调用,做之前提到的数据流相关四步处理(确定被调用方法、传对象、传参数,传返回值)。 -![](../.gitbook/assets/image-20201126195311513.png) +![](../../.gitbook/assets/image-20201126195311513.png) -![](../.gitbook/assets/image-20201126195425756.png) +![](../../.gitbook/assets/image-20201126195425756.png) ## Example @@ -148,14 +148,13 @@ class B extends A { 答案如下: -![](../.gitbook/assets/image-20201126201000426.png) +![](../../.gitbook/assets/image-20201126201000426.png) 这个流不敏感的分析算法在分析精度上仍然可以改进。我们将在接下来的课程中学习精度更高的流敏感分析。 ## Key points -**The X You Need To Understand in This Lecture** - * Pointer analysis **rule for method call** * **Algorithm** for inter-procedural pointer analysis * **On-the-fly call graph construction** + diff --git a/ch3/pointer-analysis/README.md b/ch3/pointer-analysis/README.md new file mode 100644 index 0000000..0a0364a --- /dev/null +++ b/ch3/pointer-analysis/README.md @@ -0,0 +1,3 @@ +# 指针分析简介 + +这一部分介绍比CHA分析精度更高的指针分析技术(上下文不敏感版本)。 \ No newline at end of file