下载本文的PDF版本 PDF

OCCAM-v2:结合静态和动态分析以实现有效且高效的程序整体特化

利用可扩展的指针分析、值分析和动态分析

Jorge A. Navas 和 Ashish Gehani

软件已经发展到支持各种各样的功能集。敏捷软件工程实践,例如为可重用性设计的代码,引入了冗余代码。在一个常见的模式中,整个库被链接进来,但只需要少量函数。不必要的代码积累会对只需要访问这些功能子集的用户产生负面影响。

在一系列关注点的一端,嵌入式系统通常配置的内存量有限。不必要的代码占用空间的存在会增加成本并对性能产生不利影响。在另一端,配置了臃肿代码的云计算平台可能会遭受相应增加的内部攻击面,通过诸如面向返回18、面向跳转3、面向调用17和面向数据10编程等机制。

随着配置参数数量的增加,应用程序跟踪的空间呈指数级增长。这使得全面测试的成本成比例地增加,从而推动了对程序整体特化的需求,它可以将程序分析集中在将要部署的特定变体上。

由于一系列源语言可以编译成 LLVM12 中间表示,因此已经开发了几种工具来特化 LLVM 位代码。这些工具包括 OCCAM13、LLPE20 和 Trimmer19。然而,所有这些工具都仅使用编译器转换来完成任务。相比之下,我们的工具 OCCAM-v2 结合了使用抽象解释框架的更深层次的静态分析以及动态分析。这种组合提供了明显更好的结果。

OCCAM-v216 是作为我们早期工具 OCCAM13 的扩展而开发的。用于自动化复杂位代码构建的功能被分解成一个单独的工具 gllvm8。本文首先提供关于 OCCAM 的相关背景知识,然后描述其静态分析扩展,这些扩展提供与 OCCAM 相同的可靠性保证。接下来,它解释了使用动态分析的可选的激进特化,最后报告了在应用程序套件上评估该工具的结果。

 

背景

自动化软件精简13 应用部分求值来修剪大型应用程序及其依赖项,如图 1 所示。(虚线框中包含的组件是 OCCAM-v2 中的新组件。)特别是,OCCAM 允许使用包含特定环境详细信息的特化清单,将静态信息传递到目标程序的入口点。该工具在 LLVM 位代码上运行。

OCCAM-v2 Combining Static and Dynamic Analysis for Effective and Efficient Whole-program Specialization

每个模块中的函数和调用点被计算并存储在外部接口定义中。使用这个定义,OCCAM 然后搜索带有具体参数的跨模块调用。如果找到任何跨模块调用,则会查阅策略以确定是否构建函数的特化版本。当这种情况发生时,将构造新函数的代码并将其添加到相关的 LLVM 位代码模块;更新相应的接口以反映新函数的可用性;更新具有相同签名的其他调用点以使用新特化版本的函数。

OCCAM 从程序入口点开始,并使用应用程序的随附清单中可能提供的任何静态信息。然后对包含在 main() 模块的调用点中标识的函数的模块进行操作。此过程持续进行,直到所有可到达的模块都被识别出来。在每个步骤中,都会调用 LLVM 的内部优化过程。特别是,全局优化器被用于常量折叠和传播,而死代码消除则会修剪未使用的分支和不可到达的代码。后几个步骤实现了 OCCAM 的模块内特化。

由于此过程可能会发现新的特化机会,无论是在单个模块内还是跨多个模块,因此整个序列会重复执行,直到达到全局不动点。通过这种方式,OCCAM 能够扩展程序整体特化。在最后一步,OCCAM 调用 LLVM 的编译器将位代码转换为本机对象,并调用链接器以生成特化的本机应用程序。

 

扩展的静态分析

OCCAM-v2 的静态分析改进源于其结合了自定义指针分析和值分析。两者都基于抽象解释5

 

精确的调用图构建

LLVM 的 PoolAlloc DSA(数据结构分析)可以用于解析间接函数调用以及其他指针。OCCAM-v2 使用由 DSA 的改进变体计算的调用图:开源的类型敏感指针分析 SeaDSA11

 

改进的跨模块接口

为了支持扩展到大型代码库,OCCAM 一次在一个模块上操作(除了后不动点处理,包括最终链接)。然而,为了方便程序整体分析,对一个模块进行的更改必须意识到与其他代码的交互。这是通过为每个模块构建接口来实现的,该接口可以在更新其他模块的过程中使用。特别是,该接口提供了对模块内使用的外部符号和调用的描述。过去,接口生成一直使用由 LLVM 计算的调用图。

OCCAM-v2 使用由 SeaDSA 计算的调用图。此调用图比来自 LLVM 的调用图更精确。这反过来提高了模块接口的特异性,从而更好地优化了跨模块特化。当计算模块的接口时,它最初包括所有具有非内部链接的调用点(因此可以从另一个模块调用)。此外,还识别了可以通过来自其他模块的调用到达的函数中的所有调用点。在间接调用的情况下,目标可以是任何函数(在没有更多信息的情况下)。使用解析的调用图,OCCAM-v2 减少了可能性的集合。

 

处理函数指针参数

当调用模块外部的函数时,其签名将在包含调用者的模块的接口中报告。当调用点包含常量参数时,原则上可以特化调用。如果参数是函数指针,则 OCCAM 以前仅限于使用空值的情况。这不足以处理通过引用传递函数作为参数的情况。OCCAM-v2 支持特化带有函数指针参数的外部调用。如果函数在被调用者的上下文中接受一个或多个常量参数,则现在也可以特化该函数。这一点尤其值得注意,因为它涵盖了常见的编程模式,例如回调函数的使用。

 

基于签名的候选调用消除

DSA 的使用导致了对实际程序调用图的过度近似,因为 DSA 忽略了函数调用参数的类型。因此,签名与调用点的签名不匹配的函数可能会被错误地视为有效的候选函数。为了解决这个问题,利用 SeaDSA 的指针分析将间接调用替换为 switch 语句,其中每个 case 对应于一个候选地址。在此之后,生成的调用图将不再具有间接调用。然而,在某些情况下,调用点和候选地址的函数签名可能不匹配。分析会根据参数类型正确地过滤掉此类情况。

 

基于类层次结构分析的候选调用消除

当间接调用被解析为一组候选地址时,生成的调用图的精度低于原始程序的调用图。可以通过减少候选者的集合来提高后续执行的静态分析的精度。如果 LLVM 位代码的实例源自用 C++ 编写的程序,则可以利用 CHG(类层次结构图)来提高分析精度。

OCCAM-v2 构建了一个 CHG,其中节点是 C++ 类,类 c1 和 c2 之间的边表示 c1 是 c2 的子类。CHG 用于解析源自 C++ 虚函数的间接调用。(我们的指针分析支持 C++ 虚调用。然而,CHG 通常可以通过分析可以从 LLVM 位代码中提取的虚函数表来改进 SeaDSA 推断的信息。)

给定一个源自 C++ 程序中虚函数调用的调用点,执行以下步骤

1. 识别与包含被调用方法的对象关联的类 C。

2. 计算 C 的所有直接和间接派生子类。(一旦 CHG 可用,就可以以低成本计算出来。)

3. 使用每个子类的虚函数表来收集类型签名与步骤 1 中提到的被调用方法匹配的所有方法。(可以通过检查位代码来构造类的虚函数表。)

此时,已知给定间接调用(源自虚函数调用)的所有可能的被调用者集合。这允许使用这组被调用者来解析间接调用。

 

基于别名分析的优化

LLVM 框架提供了一个 AliasAnalysis 基础设施。此 API 的客户端可以查询两个 LLVM 值是否可能互为别名。这对于可以利用两个值在优化目标代码时不能指向同一位置的知识的转换非常有用。实现必须对内存建模并提供支持来回答这些查询。AliasAnalysis API 实现已经开发出来,它使用 SeaDSA。这允许 OCCAM-v2 使用的整套 LLVM 过程利用指向信息的更高精度。改进的别名分析支持其他相关的优化,例如死存储消除,这有助于识别其他静态变量。

 

值分析的使用

OCCAM 在精简软件时使用死代码消除。修剪算法的核心依赖于构建从变量到常量的映射。这意味着对于所有可能的程序执行,变量都将具有已识别的常量值。为了创建更多的特化机会,OCCAM-v2 构建了从变量到区间的映射。这允许对依赖于可以识别区间的变量的分支进行推理。

抽象解释5 是一种常见的技术,用于正式地推理程序。它被用作静态分析设计中的数学基础。该技术的一个经典用途是推断每个程序变量可以取的可能值。这些可能的值可以通过不同的方式(称为抽象域)来近似:区间表示最小值和最大值;两个变量之间的差值14;八边形约束15;以及变量之间的线性不等式6

尽管功能强大,但 LLVM 中没有这种分析。一个可能的原因是大多数现有实现都假设数学整数,而忽略了在 LLVM 中整数必须使用机器算术表示来建模的事实。为机器算术调整这种分析是具有挑战性的,因为它很难在精度和效率之间找到良好的平衡。

 

推断不变量

C++ 库 Crab7 支持使用抽象解释对程序进行静态分析。它的结构是一个库,因此工具可以以编程方式使用其功能。Crab 在目标程序 CFG(控制流图)的语言无关形式上运行。Clam4 前端将 LLVM 位代码转换为 Crab 的表示形式。在此之后,Crab 的分析用于推断目标程序中的不变量。然后实现常量传播和死代码消除(使用与之前使用的相同的 LLVM 优化器过程)。已识别的不变量的存在允许这些过程做出更强的假设。在某些情况下,这使得可以执行更多的优化。

 

字段敏感的常量传播

OCCAM 的模块内特化依赖于 LLVM 的 SCCP(稀疏条件常量传播)。此过程在其可以执行的分析中受到限制,因为它旨在提高效率并用于编译器的日常工作流程中。特别是,如果常量存储在 C 数组或结构的字段中,则 SCCP 无法识别和使用此静态数据。

Clam 依赖于 SeaDSA 的字段敏感推理来维护内存的抽象表示。SeaDSA 将内存划分为有限数量的区域,每个区域都映射到一个逻辑数组。在这种形式中,区域由逻辑表达式建模,该表达式描述了受内存访问操作影响的位置。这允许使用 SeaDSA 处理别名分析来有效地推理内存。

当 LLVM 位代码被转换为 Crab 的 CFG 表示形式时,内存存储被建模为弱更新(其中受影响的区域是已知的,但确切的位置是未知的)。Clam 为弱更新定义了一个抽象域。Crab 使用它来对 CFG 进行推断。虽然在此域中推理是有效的,但它是不精确的。为了提高精度,特别是在结构字段的情况下,开发了一种新的抽象域9。它提供了一种混合抽象,其中内存存储可以在特定情况下被建模为强更新(用新值替换旧值)。

函数内部分析的优化

不变量的知识有助于编译器优化,从而提高 OCCAM-v2 在目标应用程序及其依赖项中特化和消除代码片段的能力。为此开发了上下文敏感的过程间分析,与基线相比,它提供了更高的精度。为了提高性能,添加了对函数内部分析的记忆化支持。然而,这在实践中可能导致内存耗尽。这通过将记忆化限制为循环头来解决。

 

结合动态分析

作为在线部分求值器,OCCAM 依赖于已知的具体值来进行代码简化和消除。此类信息的重要来源是用户指定的一组参数。在实践中,这些参数通常由 getopt() 或程序入口点附近的类似功能处理。此类代码通常在循环中执行复杂的字符串操作。此外,循环边界可能不是静态的。这种组合对静态分析技术提出了挑战。

OCCAM-v2 的 DCA(部署上下文分析)将特化分为两个阶段。从概念上讲,目标程序的执行跟踪被分解为单个前缀,该前缀在第一阶段使用(条件)动态分析计算,以及一组后缀,这些后缀表示程序中未在第一阶段执行的任何剩余部分。动态分析从程序入口点开始,并持续进行,只要关键的混合条件成立。具体来说,遇到的任何分支都必须仅依赖于已知值。内存快照是前缀执行结束时程序的状态。它用于使用静态分析简化后缀。

此功能通过修改 LLVM 的解释器 lli 来实现。新的过程在三个方面与 lli 不同

• 即使在执行期间,虚拟寄存器或已在堆栈或堆上分配的内存位置的值也可能是未知的。例如,程序可能使用第一个参数的值(在 C 中称为 argv[1]),但在运行时,用户可能在调用程序时没有提供任何参数。在这种情况下,LLVM 解释器将中止执行。相比之下,新的过程将移动到下一个位代码指令并继续解释。

• 当遇到值未知的寄存器或内存位置时,新的过程将跟踪此事实。当后续指令依赖于未知值时,其结果也将被跟踪为未知。通过这种方式,新功能提供了一个轻量级的绑定时间分析,该分析从动态值向前传播污点。

• 在被解释的位代码指令是依赖于未知值的条件这种特殊情况下,执行将暂停。这允许程序即使在存在分支的情况下也能继续运行,只要可以评估它们。定义暂停执行的条件是为了避免不得不探索潜在的指数级状态空间,如果必须遵循以未知值为条件的分支,则会发生这种情况。

 

选项处理

操作系统的 Posix 接口为应用程序提供了一种处理命令行参数的标准机制。这与 DCA 之间的交互需要仔细处理。为了实现所需的动态分析,OCCAM-v2 改编了 LLVM 的 ExecutionEngine 类,该类构成了 lli 的核心。当程序在 DCA 期间调用 getopt() 时,某些参数可能未知。这可能会发生,因为 OCCAM 支持(通过目标的清单)指定在特化期间不会具体化的剩余参数。

为了适应这种情况,自定义的 getopt() 处理已纳入 DCA。由于清单要求具体参数首先出现,因此可以推断出剩余参数将开始的位置。当解释器到达动态参数时,DCA 会转换到使用静态分析来特化剩余位代码的阶段,使用该点的程序状态。这允许特化程序保留对处理剩余参数的支持。

 

多模块动态分析

目标应用程序的动态分析从程序入口点开始。当遇到以未知值为条件的谓词分支时,将使用该点的程序状态子集生成应用程序的特化版本。为了能够确定值是否已知,实现会跟踪内存,因为它是在包含程序 main() 函数的 LLVM 模块中分配的。最初,只有这些内存区域被视为已知。如果从未分配的内存中读取值,则将其视为未知。这种方法足以应对整个程序都在单个模块中的情况。

在实践中,应用程序可能依赖于多个模块(例如,库)中的代码。DCA 可以使用 LLVM ExecutionEngine 的 FFI(外部函数接口)支持外部调用来处理这种情况。在这种情况下,内存可能由未被分析的代码分配。为了适应这一点,开发了一种补充方法。通过关注程序整体分析,可以假定内存默认情况下是已知的。相反,从(动态)程序入口点参数派生的值在特化期间被视为未知。

 

保守排除

回调。 当解释作为对外部函数的调用的指令时,参数可能是用于提供回调的函数指针。ExecutionEngine 然而,不提供一种机制来公开正在解释的位代码函数给通过 FFI 调用的本机代码。因此,执行检查。如果使用 FFI 的调用的参数是函数指针,则 DCA 会暂停并将程序的状态转移到特化版本。已经添加了对检查被调用函数是否可能具有副作用的支持。如果它不能,DCA 可以继续。

共享资源。 同样,特定的外部调用需要特殊处理。出现这种情况的一个类别是当目标程序和特化工具之间共享资源时。考虑被特化的程序关闭与标准输出关联的文件描述符的情况。由于 LLVM 的 ExecutionEngine 假定只有被解释的代码正在执行,因此没有提供特殊的处理。结果,执行这样的指令也会关闭部分求值器的描述符。其他此类类别包括对 exit()vfprintf()pthread_() 系列的调用。当出现这种情况时,DCA 会保守地暂停并继续使用其当前状态创建特化程序。

外部全局变量。 ExecutionEngine 执行的全局变量跟踪范围仅限于程序中的变量。如果在库依赖项中分配了全局变量,则这可能导致无法解析的值。为了适应这种情况,DCA 在这种情况下继续进行。

 

可变参数函数

LLVM 的 ExecutionEngine 不处理可变参数函数。通过扩展实现来正确处理目标应用程序位代码中存在此类函数来解决此问题。

可变参数函数的主体可以通过 va_startva_arg 宏访问其参数。这些宏的扩展可以在位代码中使用相应的 LLVM 内在函数 VAStartInstVAArgInst 表示。如果是这种情况,ExecutionEngine 可以解释这些指令。然而,对于许多应用程序,va_arg 是使用 LLVM 的 GetElementPtr 指令(用于访问数组中的元素)实现的。开发了对处理此类情况下的 va_start 对应的位代码的支持。

 

处理算术内在函数

LLVM 的中间表示包括算术内在函数。可以通过利用目标硬件架构的指令集知识将此类指令编译为高性能的本机代码。然而,生成的代码对于解释器的分析是不透明的。相反,现在将这些指令转换为相应的位代码版本。由于这随后可以在修改后的 ExecutionEngine 中评估,因此直接跟踪副作用。

 

公开包装的 libc 调用

glibc (GNU C 库) 是与 Linux 内核交互的最广泛使用的接口。内部函数(名称以 '__' 开头)通过包装器间接访问。在这种情况下,dlopen() 将无法将包装器的名称解析为底层函数。但是,当使用解释器的 FFI 时,必须传入被调用函数的地址。通过包含声明特定包装器函数的头文件,可以识别后备函数的地址。当遇到 stat()fstat()lstat()(在修改后的解释器的运行期间)时,此方法用于允许解析它们。

 

评估

为了评估 OCCAM-v2 在软件精简方面的有效性,我们在 20 个应用程序的集合上运行了它。用于此目的的程序是选择用于研究 Trimmer1(另一个 LLVM 部分求值器)的程序。在他们使用 Trimmer 的工作中,作者解释了为什么选择这些应用程序中的每一个。此外,他们指定了用于特化每个应用程序的程序参数集。OCCAM-v2 在 Ubuntu 18.04 上使用 LLVM 10,使用相同的参数集在这些程序上运行。

 

有效性

图 2 显示了应用以下两种方法的结果:(1)仅启用增强的静态分析功能的 OCCAM-v2;以及(2)在每个程序的确定性前缀上使用动态分析,并在每个程序的剩余后缀上应用增强的静态分析的 OCCAM-v2。首先将每个程序编译成 LLVM 的中间表示。计算位代码中的指令数。然后,应用(1)仅使用静态分析的 OCCAM-v2;和(2)应用动态和静态分析的 OCCAM-v2。计算每种情况下删除的指令百分比,并在图中报告。在每种情况下,特化上下文与 Trimmer 评估中使用的上下文相同1。从数据中可以看出,OCCAM-v2 的动态分析与增强的静态分析相结合始终比仅使用静态分析的情况删除更多指令。平均而言,OCCAM-v2 的混合分析能够删除原始程序 LLVM IR(中间表示)指令的 40.6%。

OCCAM-v2 Combining Static and Dynamic Analysis for Effective and Efficient Whole-program Specialization

 

效率

OCCAM-v2 的静态分析经过选择,以保持可扩展性和效率。在必要时,牺牲精度以确保性能。更具体地说,使用的指针分析基于 Bjarne Steensgard 的算法21。此外,抽象解释框架被配置为仅使用计算效率高的推理域,包括布尔值、区间和步幅。因此,当使用静态分析模式时,平均特化时间为 6.7 秒。

为了了解 OCCAM-v2 方法的效率,我们可以将其与 Trimmer 使用的方法进行比较。后者通过使用基于 Lars Andersen 算法2 的指针分析(在 SVF(静态值流)框架22 中实现)来选择精度而不是可扩展性。效果可以在配置注释过程1 的成本中看到。Trimmer 分析耗时最长的三个程序是 objdumpyicesgprof,分别使用了 41.4 分钟、23.6 分钟和 16.3 分钟。相比之下,OCCAM-v2 对这三个程序的整个基于静态分析的特化分别在 34 秒、34 秒和 27 秒完成。

图 3 报告了在评估中特化 20 个程序中的每一个程序所花费的时间。以两种方式测量在每个目标程序上运行 OCCAM-v2 的端到端时间:仅使用静态分析以及结合动态和静态分析。请注意,时间以对数刻度报告。提供了静态分析和混合分析方法所需的时间。对于大多数程序,时间相似。bzip2 是一个例外,因为特化配置为利用目标文件的内容,这需要解释器逐步完成整个运行。请注意,这种较高的特化时间产生了 78% 的指令计数减少。即使有这个异常值,平均混合分析特化时间为 22.4 秒。

OCCAM-v2 Combining Static and Dynamic Analysis for Effective and Efficient Whole-program Specialization

 

限制和缓解措施

本节描述了实践中遇到的限制以及缓解这些限制的方法。

 

程序整体假设

OCCAM 假设它可以访问“程序整体”——即,目标应用程序及其依赖的所有代码——在特化时。这允许它推理出任何无法从程序整体调用的代码都是消除的候选代码。这种方法适用于许多程序,但并非所有程序都适用。

这种担忧的出现有多种原因。当必须链接到程序中的对象的源仅在汇编中可用时,就会出现一个重要的情况。OCCAM 的分析将不会意识到此类对象中的任何函数调用或对外部全局变量的访问,因为汇编无法构建到 LLVM 位代码中。因此,OCCAM 可能会修剪掉所需的符号和函数。我们在 musl libc 和 Linux 内核中都遇到了这种情况。

在没有汇编的情况下也可能发生类似的情况——例如,Apache 根据其配置文件动态加载模块。这些模块可能会引入反向依赖——也就是说,假设主程序包含特定的函数,这些函数可能之前已根据缺少对它们的调用而被修剪掉。为了解决这些情况,我们为 OCCAM-v2 添加了支持,用于指定一组不应内部化的函数和全局变量。这可以防止死代码消除修剪这些元素。

 

链接时符号冲突解决

OCCAM 迭代地在模块内执行常量传播和死代码消除,以及跨模块的函数特化。当达到不动点时,特化模块链接在一起。在此阶段,模块中的符号可能会冲突。

如果应用程序及其库之一中使用了相同的符号,或者如果在多个库中定义了该符号,则可能会发生符号冲突。特化函数的命名方案最大限度地减少了出现新冲突的机会。OCCAM-v2 通过一个中间步骤解决了这个问题。链接在内部进行分阶段处理,以允许在参数中指定的位代码文件中的符号覆盖后续重复项。使用 llvm-link 构建中间链接的位代码文件。然后使用 clang++ 将其与清单中指定的本机库链接。

 

未来方向

后缀简化。 在第一阶段完成后,内存快照包含两种类型的状态。第一种包含寄存器中的值,这些值可以安全地用于简化后缀。这种简化包括使用 LLVM 的内部优化以及 Crab 的基于配置域的抽象解释所实现的优化。第二种包含内存中的值。要使用这些值,有两种选择。一种方法是识别特殊情况,在这些情况下,通常可能很安全。第二种方法包括采用指针分析以确保后缀简化的可靠性。由于这会产生大量的计算成本,因此尚未纳入其中。将来,可以添加对此的支持。用户将需要在他们愿意在特化期间承担开销的情况下显式激活它。

减少过度特化。 DCA 依赖于这样的事实,即给定一组特定的输入,前缀是目标应用程序将始终执行的路径。这种方法的吸引力在于它承诺了一种用于捕获外部输入的通用机制。当前的实现探索了一种策略,该策略默认假设此类值独立于后缀中从外部输入获得的值。然后,它会根据需要添加约束来处理违反假设的特定情况。

例如,考虑快照中的一个变量,它是指向内存位置的指针。假设在动态分析期间已为其分配了一个具体值。如果它在程序中的后缀之一中出现,则不会将其替换为常量。这是因为在运行时,该指针可能会采用不同的值。在没有此类排除项的情况下,发出的二进制文件将包含过度特化的实例——即,误报具体化。另一种策略是实施互补方法:默认情况下假定值不能被具体化,除非它们源自指定的输入。

 

结论

OCCAM-v2 利用可扩展的指针分析、值分析和动态分析来创建一个有效且高效的工具,用于特化 LLVM 位代码。实现的减小代码大小的程度取决于特定的部署配置。每个要特化的应用程序都附带一个清单,该清单指定先验已知的具体参数,以及运行时将提供的剩余参数的计数。部分求值的最佳情况发生在参数完全具体指定时。

OCCAM-v2 使用指针分析来反虚函数化调用,从而允许它消除任何直接调用都无法到达的函数的整个主体。混合分析功能可以处理静态分析具有挑战性的情况,例如输入循环、字符串处理和外部数据(例如,在文件中)。在评估的程序套件中,OCCAM-v2 平均能够将指令计数减少 40.6%,中位时间为 2.4 秒。

 

致谢

这项工作部分由 NSF(国家科学基金会)在 ACI-1440800 拨款下以及部分由 ONR(海军研究办公室)在 N68335-17-C-0558 合同下支持。本文中表达的任何意见、发现和结论或建议均为作者的观点,不一定反映 NSF 或 ONR 的观点。

 

参考文献

1. Ahmad, A., Noor, R., Sharif, H., Hameed, U., Asif, S., Anwar, M., Gehani, A., Zaffar, F., Siddiqui, J. 2022. Trimmer:一种基于配置的自动化软件去臃肿系统。IEEE Transactions on Software Engineering 48(9), 3485-3505; https://ieeexplore.ieee.org/document/9478582.

2. Andersen, L. 1994. C 编程语言的程序分析和特化。博士论文,哥本哈根大学计算机科学系。

3. Bletsch, T., Jiang, X., Freeh, V., Liang, Z. 2011. 面向跳转编程:一种新型代码重用攻击。在第 6 届 信息、计算机和通信安全研讨会论文集, 30-40; https://dl.acm.org/doi/10.1145/1966913.1966919.

4. Clam:Crab 的 LLVM 前端。GitHub; https://github.com/seahorn/clam.

5. Cousot, P., Cousot, R. 1977. 抽象解释:一种统一的格模型,用于通过构造或近似不动点对程序进行静态分析。在第 4 届 编程语言原理研讨会论文集, 238-252; https://dl.acm.org/doi/10.1145/512950.512973.

6. Cousot, P., Halbwachs, N. 1978. Automatic discovery of linear restraints among variables of a program. 出自第5届 编程语言原理研讨会论文集, 84-96; https://dl.acm.org/doi/10.1145/512760.512770.

7. Crab: 用于构建程序静态分析的 C++ 库。GitHub; https://github.com/seahorn/crab.

8. Gelle, L., Saidi, H., Gehani, A. 2018. Wholly!: 现代软件堆栈的构建系统。第23届工业关键系统形式化方法国际会议, 242-257; https://link.springer.com/chapter/10.1007/978-3-030-00244-2_16.

9. Gurfinkel, A., Navas, J. 2021. 基于区域内存模型的 LLVM 抽象解释。出自第13届验证软件国际会议:理论、工具和实验, 122-144; https://dl.acm.org/doi/abs/10.1007/978-3-030-95561-8_8.

10. Hu, H., Shinde, S., Adrian, S., Chua, Z. L., Saxena, P., Liang, Z. 2016. 面向数据的编程:关于非控制数据攻击的表达性。出自第37届 IEEE 安全与隐私研讨会, 969-986; https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=7546545.

11. Kuderski, J., Navas, J., Gurfinkel, A. 2019. 没有过度共享的基于统一的指针分析。出自第19届计算机辅助设计形式化方法会议论文集; https://ieeexplore.ieee.org/document/8894275.

12. LLVM 编译器基础设施; https://llvm.net.cn.

13. Malecha, G., Gehani, A., Shankar, N. 2015. 自动化软件筛选。出自第30届 应用计算专题研讨会论文集, 1504-1511; https://dl.acm.org/doi/10.1145/2695664.2695751.

14. Miné, A. 2001. 基于差分界矩阵的新数值抽象域。出自第二届程序即数据对象研讨会论文集, 155-172; https://dl.acm.org/doi/10.5555/645774.668110.

15. Miné, A. 2006. 八边形抽象域。Higher Order Symbolic Computation 19(1), 31-100; https://link.springer.com/article/10.1007/s10990-006-8609-1.

16. OCCAM: 用于保证最大化的对象剔除和具体化。GitHub; https://github.com/SRI-CSL/OCCAM.

17. Sadeghi, A., Niksefat, S., Rostamipour, M. 2018. 纯调用导向编程:使用调用指令链接 gadgets。Journal of Computer Virology and Hacking Techniques 14(2), 139-156; https://link.springer.com/article/10.1007/s11416-017-0299-1.

18. Shacham, H. 2007. 骨肉几何学:无需函数调用的返回到 libc (在 x86 上)。出自第14届 计算机与通信安全会议论文集, 552-561; https://dl.acm.org/doi/10.1145/1315245.1315313.

19. Sharif, H., Abubakar, M., Gehani, A., Zaffar, F. 2018. Trimmer:用于代码精简的应用程序专用化。出自第33届 /IEEE 国际自动化软件工程大会论文集, 329-339; https://dl.acm.org/doi/10.1145/3238147.3238160.

20. Smowton, C. 2015. 通过部分求值的 I/O 优化和消除。博士论文,剑桥大学。

21. Steensgaard, B. 1996. 几乎线性时间的指针分析。出自第23届 编程语言原理研讨会论文集, 32-41; https://dl.acm.org/doi/10.1145/237721.237727.

22. Sui, Y., Xue, J. 2016. SVF: LLVM 中的过程间静态值流分析。出自第25届 编译器构造会议论文集, 265-266; https://dl.acm.org/doi/10.1145/2892208.2892235.

 

Jorge Navas 是 Certora 的一名静态分析研究员。他的重点是设计和实现自动工具,这些工具可以提高程序员的生产力,使代码更可靠和安全。他拥有新墨西哥大学计算机科学博士学位和马德里理工大学计算机科学学士学位。

Ashish Gehani 是位于加利福尼亚州门洛帕克的 SRI 的高级首席计算机科学家。他的研究兴趣是数据出处、可重复性和安全性。他拥有杜克大学计算机科学博士学位和芝加哥大学数学学士学位。

版权 © 2022 由所有者/作者持有。出版权已授权给 。

acmqueue

最初发表于 Queue vol. 20, no. 5
数字图书馆 中评论本文





更多相关文章

Catherine Hayes, David Malone - 质疑评估非加密哈希函数的标准
虽然加密和非加密哈希函数无处不在,但在它们的设计方式上似乎存在差距。出于各种安全需求,加密哈希存在许多标准,但在非加密方面,存在一定的民间知识,尽管哈希函数历史悠久,但尚未得到充分探索。虽然针对真实世界数据集的均匀分布很有意义,但当面对具有特定模式的数据集时,这可能是一个挑战。


Nicole Forsgren, Eirini Kalliamvakou, Abi Noda, Michaela Greiler, Brian Houck, Margaret-Anne Storey - DevEx 在行动
随着领导者寻求在财政紧缩和 AI 等变革性技术的背景下优化软件交付,DevEx(开发者体验)在许多软件组织中越来越受到关注。技术领导者直观地接受了良好的开发者体验能够实现更有效的软件交付和开发者幸福感。然而,在许多组织中,旨在改善 DevEx 的拟议举措和投资难以获得支持,因为业务利益相关者质疑改进的价值主张。


João Varajão, António Trigo, Miguel Almeida - 低代码开发效率
本文旨在通过展示使用基于代码、低代码和极限低代码技术进行的实验室实验结果来研究生产力差异,从而为该主题提供新的见解。低代码技术已清楚地显示出更高的生产力水平,为低代码在短期/中期内主导软件开发主流提供了强有力的论据。本文报告了程序和协议、结果、局限性和未来研究的机会。


Ivar Jacobson, Alistair Cockburn - 用例至关重要
虽然软件行业是一个快节奏且令人兴奋的世界,其中不断开发新的工具、技术和技巧来为商业和社会服务,但它也很健忘。在其快速前进的步伐中,它容易受到时尚的摆布,并且可能会忘记或忽略针对它面临的一些永恒问题的成熟解决方案。用例最早于 1986 年引入,并在后来普及,是这些成熟的解决方案之一。





© 保留所有权利。

© . All rights reserved.