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

Linux fority source和__builtin_xxx

这段代码是用于启用和配置 GCC/Clang 的 Fortify Source 安全机制的预处理指令。Fortify Source 主要用于在编译时增强对缓冲区溢出等内存安全问题的检查。以下是对每一部分的详细解释:


1. 最外层条件编译

#  if CONFIG_FORTIFY_SOURCE > 0
  • 目的:检查是否启用了 Fortify Source(通过 CONFIG_FORTIFY_SOURCE 的值判断)。
  • 如果 CONFIG_FORTIFY_SOURCE 的值大于 0,则启用下面的代码逻辑。

2. 检查优化等级

#    if !defined(__OPTIMIZE__) || (__OPTIMIZE__) <= 0
#      warning requires compiling with optimization (-O2 or higher)
#    endif
  • 目的:确保编译时启用了优化(-O2 或更高)。
  • Fortify Source 依赖编译器优化才能生效。如果未启用优化(__OPTIMIZE__ 未定义或值小于等于 0),会发出警告。

3. 处理 CONFIG_FORTIFY_SOURCE == 3

#    if CONFIG_FORTIFY_SOURCE == 3
#      if __GNUC__ < 12 || (defined(__clang__) && __clang_major__ < 12)
#        error compiler version less than 12 does not support dynamic object size
#      endif
  • 目的:当 Fortify Source 配置为 3 时,检查编译器版本是否支持动态对象大小检查。
  • CONFIG_FORTIFY_SOURCE == 3 表示启用动态对象大小检查(更严格的检查)。
  • 需要 GCC ≥12 或 Clang ≥12,否则报错(旧版本不支持 __builtin_dynamic_object_size)。

4. 定义 fortify_size

#      define fortify_size(__o, type) __builtin_dynamic_object_size(__o, type)
#    else
#      define fortize_size(__o, type) __builtin_object_size(__o, type)
#    endif
  • 目的:根据配置选择静态或动态对象大小检查。
    • CONFIG_FORTIFY_SOURCE == 3,使用 __builtin_dynamic_object_size(动态计算对象大小)。
    • 其他情况使用 __builtin_object_size(静态编译时计算对象大小)。
  • 这两个内置函数用于获取缓冲区的大小,帮助检测缓冲区溢出。

5. 定义 fortify_assert

#    define fortify_assert(condition) do { \
        if (!(condition)) { \
          __builtin_trap(); \
        } \
      } while (0)
  • 目的:在条件不满足时触发程序终止。
  • 如果断言失败(condition 为假),调用 __builtin_trap() 立即终止程序(防止安全漏洞被利用)。

6. 定义 fortify_va_arg_pack

#    define fortify_va_arg_pack __builtin_va_arg_pack
  • 目的:处理可变参数函数(如 printf)。
  • __builtin_va_arg_pack 是 GCC 的内置函数,用于获取可变参数列表,用于对可变参数函数进行安全检查。

7. 定义 fortify_real

#    define fortify_real(fn) __typeof__(fn) __real_##fn __asm__(#fn)
  • 目的:声明原始函数的别名。
  • 例如,fortify_real(memcpy) 会生成 __real_memcpy,指向原始的 memcpy 函数。
  • 这是为了在替换标准库函数时保留原始函数的入口。

8. 定义 fortify_function

#    define fortify_function(fn) fortify_real(fn); \
     extern __inline__ no_builtin(#fn) \
     __attribute__((__always_inline__, __gnu_inline__, __artificial__))
  • 目的:定义内联的强化版函数。
  • no_builtin(#fn):禁用编译器对 fn 的内置实现(强制使用自定义实现)。
  • 属性说明:
    • __always_inline__:强制内联展开。
    • __gnu_inline__:兼容 GNU 内联规则。
    • __artificial__:告诉调试器这是“人工”函数(调试时隐藏实现细节)。

总结

这段代码的作用是:

  1. 启用 Fortify Source:通过条件编译和宏定义,替换标准库函数(如 memcpy, strcpy 等)。
  2. 安全检查:在编译时和运行时插入缓冲区大小检查,防止内存安全问题。
  3. 兼容性处理:根据编译器版本和优化等级调整实现方式。

典型应用场景是 Linux 内核或安全敏感项目,用于增强代码的安全性。

---------------------------------------------------------------------------

这个 fortify_real 宏的作用是为原始函数创建一个别名,使得在替换标准库函数(如 memcpy, strcpy 等)时,仍能保留对原始函数的调用入口。这是 Fortify Source 实现安全检查的关键机制。我们逐层解剖它的语法和用途:


宏定义分解

#    define fortify_real(fn) __typeof__(fn) __real_##fn __asm__(#fn)
1. __typeof__(fn)
  • 作用:获取函数 fn 的类型(返回值类型 + 参数类型)。
  • 例如,如果 fnmemcpy(声明为 void* memcpy(void*, const void*, size_t)),则 __typeof__(fn) 会被替换为 void* (*)(void*, const void*, size_t)(即函数指针类型)。

2. __real_##fn
  • 作用:通过 ##(预处理器粘贴符)生成一个名为 __real_函数名 的新标识符。
  • 例如,若 fnmemcpy,则 __real_##fn 会展开为 __real_memcpy
  • 用途:这个新名称将作为原始函数的别名,避免与自定义的强化函数冲突。

3. __asm__(#fn)
  • 作用:通过 __asm__(GCC/Clang 的内联汇编扩展)指定符号的汇编名称。
  • #fn 会将 fn 字符串化(例如,memcpy"memcpy")。
  • 最终效果:将 __real_memcpy 这个符号与原始函数 memcpy 的汇编符号绑定。
    • 相当于告诉编译器:“__real_memcpy 这个变量/函数,在汇编层对应符号 memcpy”。

完整展开示例

假设调用 fortify_real(memcpy),宏会展开为:

__typeof__(memcpy) __real_memcpy __asm__("memcpy");

这相当于:

// 1. 获取 memcpy 的类型(假设为标准库声明)
typedef void* (*memcpy_type)(void*, const void*, size_t);

// 2. 声明一个函数指针变量 __real_memcpy,并绑定到符号 "memcpy"(即原始 memcpy)
memcpy_type __real_memcpy __asm__("memcpy");

实际用途

在 Fortify Source 中,这个宏的典型用法是替换标准库函数,同时保留原始函数的调用方式。例如:

// 1. 声明原始 memcpy 的别名 __real_memcpy
fortify_real(memcpy);

// 2. 定义强化版的 memcpy
void* memcpy(void* dest, const void* src, size_t n) {
  // 检查缓冲区大小是否合法
  if (n > fortify_size(dest, 1)) {
    __builtin_trap(); // 触发崩溃
  }
  // 调用原始 memcpy(通过 __real_memcpy)
  return __real_memcpy(dest, src, n);
}
  • 关键点:用户代码调用 memcpy 时,实际调用的是强化版函数,而强化版内部通过 __real_memcpy 调用原始函数。

为什么需要这种设计?

  1. 安全增强:在调用原始函数前插入安全检查(如缓冲区大小验证)。
  2. 透明替换:用户代码无需修改,所有对 memcpy 的调用自动被重定向到强化版。
  3. 避免递归调用:如果没有 __real_memcpy,强化版 memcpy 内部调用 memcpy 会导致无限递归。

总结

  • fortify_real 宏的本质:通过预处理器和编译器扩展,为原始函数创建一个别名(__real_函数名),使得强化版函数能安全地调用原始实现。
  • 应用场景:安全加固的标准库函数实现(如 Linux 内核、安全敏感项目)。

---------------------------------------------------------------------------

__builtin_dynamic_object_size__builtin_object_size 是 GCC/Clang 提供的两个内置函数(built-in functions),用于在编译时或运行时计算对象(如缓冲区)的大小。它们的主要区别在于计算方式的灵活性适用场景,以下是详细对比:


1. __builtin_object_size静态对象大小计算

  • 功能
    编译时尝试计算对象(如数组或指针指向的缓冲区)的静态已知大小
  • 语法
    size_t __builtin_object_size(const void* ptr, int type);
    
    • ptr:需要计算大小的对象指针。
    • type:取值范围 0123,控制计算逻辑:
      • type & 1:是否假设 ptr 指向的对象是子对象(如结构体成员)。
      • type & 2:是否在无法确定大小时返回安全的最小值(0)或最大值(SIZE_MAX)。
  • 局限性
    • 仅能在编译时确定大小(依赖优化等级 -O1 或更高)。
    • 对于动态分配的内存(如 malloc)或复杂指针运算,可能无法正确计算,返回 SIZE_MAX0
示例
char buf[10];
size_t size = __builtin_object_size(buf, 0); // 返回 10

char* p = malloc(20);
size_t size_p = __builtin_object_size(p, 0); // 可能返回 0 或 SIZE_MAX(取决于优化和代码结构)

2. __builtin_dynamic_object_size动态对象大小计算

  • 功能
    运行时动态计算对象的大小,支持更复杂场景(如动态分配的内存、变量长度数组等)。
  • 语法
    size_t __builtin_dynamic_object_size(const void* ptr, int type);
    
    • 参数 type 的语义与 __builtin_object_size 相同。
  • 优势
    • 可以处理编译时无法确定大小的对象(如通过 alloca、VLA 分配的缓冲区)。
    • 更精确的安全检查(例如检测 strcpy 写入是否超出实际分配的内存)。
示例
void func(size_t n) {
  char buf[n]; // 变量长度数组(VLA)
  size_t size = __builtin_dynamic_object_size(buf, 0); // 返回 n
}

关键区别总结

特性__builtin_object_size__builtin_dynamic_object_size
计算时机编译时(依赖优化等级)运行时(动态计算)
动态内存支持有限(如 malloc 可能失败)支持(如 alloca、VLA)
编译器要求较旧版本(GCC 4.1+)需要较新版本(GCC 12+ 或 Clang 12+)
准确性依赖编译时可分析性更灵活,适用于运行时场景
Fortify Source 应用CONFIG_FORTIFY_SOURCE=1/2CONFIG_FORTIFY_SOURCE=3(更严格模式)

具体应用场景

场景 1:静态数组
char static_buf[100];
size_t s1 = __builtin_object_size(static_buf, 0);    // 返回 100
size_t s2 = __builtin_dynamic_object_size(static_buf, 0); // 同样返回 100
  • 两者结果一致,因为大小在编译时已知。
场景 2:动态分配内存
void foo(size_t n) {
  char* dynamic_buf = malloc(n);
  size_t s1 = __builtin_object_size(dynamic_buf, 0);      // 可能返回 0 或 SIZE_MAX
  size_t s2 = __builtin_dynamic_object_size(dynamic_buf, 0); // 返回实际分配的 n
}
  • __builtin_object_size 无法跟踪 malloc 的运行时参数,而 __builtin_dynamic_object_size 可以。
场景 3:变量长度数组(VLA)
void bar(size_t n) {
  char vla_buf[n];
  size_t s1 = __builtin_object_size(vla_buf, 0);      // 可能返回 0(编译时无法确定)
  size_t s2 = __builtin_dynamic_object_size(vla_buf, 0); // 返回 n
}
  • __builtin_dynamic_object_size 是唯一能正确处理 VLA 的选项。

在 Fortify Source 中的作用

  • CONFIG_FORTIFY_SOURCE=1/2
    使用 __builtin_object_size,在编译时插入静态检查。例如:

    char buf[10];
    strcpy(buf, "overflow!"); // 编译时报错(静态检查到溢出)
    
  • CONFIG_FORTIFY_SOURCE=3
    使用 __builtin_dynamic_object_size,在运行时插入动态检查。例如:

    void func(size_t n) {
      char* buf = malloc(n);
      read(fd, buf, n+1); // 运行时检查:若实际写入超过 n,触发崩溃
    }
    

总结

  • __builtin_object_size:适合简单场景,依赖编译时优化,但对动态内存支持有限。
  • __builtin_dynamic_object_size:更强大灵活,支持运行时计算,但需要新版本编译器。

Fortify Source 通过这两者的组合,实现了从静态到动态的多层次内存安全防护。

---------------------------------------------------------------------------

__builtin_trap 是 GCC 和 Clang 等编译器提供的一个内置函数(built-in function),它的核心作用是立即终止程序执行,并触发一个与平台相关的硬件异常或信号。以下是它的详细行为、用途和与其他类似函数的对比:


1. 核心功能

  • 作用
    当调用 __builtin_trap() 时,编译器会生成一条特定的陷阱指令(如 ud2 在 x86 架构,或 trap 在某些 RISC 架构),导致程序立即终止。
  • 终止方式
    • 在类 Unix 系统(Linux/macOS)中,通常会触发 SIGILL 信号(非法指令)或 SIGTRAP 信号。
    • 在 Windows 中,可能触发结构化异常(SEH)的非法指令异常。
  • 结果
    程序崩溃,生成核心转储(core dump,如果系统允许),不会执行后续代码。

2. 典型使用场景

(1) 不可恢复的错误处理

用于标记代码中的“不可能到达”的分支或未处理的错误条件。例如:

switch (value) {
  case 1: do_something(); break;
  case 2: do_another(); break;
  default: __builtin_trap(); // 如果 value 只能是 1 或 2,此处标记逻辑错误
}
(2) 安全防护(Fortify Source)

在安全敏感代码中,检测到缓冲区溢出等漏洞时立即终止程序,防止攻击者利用漏洞:

if (buffer_overflow_condition) {
  __builtin_trap(); // 主动崩溃,拒绝继续执行危险操作
}
(3) 调试辅助

强制程序在特定位置崩溃,方便通过核心转储或调试器定位问题。


3. 与其他终止函数的对比

函数/机制行为可捕获性适用场景
__builtin_trap()生成陷阱指令,直接触发硬件异常不可捕获(直接硬件异常)安全防护、逻辑错误终止
abort()发送 SIGABRT 信号,默认终止进程可捕获(通过信号处理)一般错误终止
exit()正常退出,执行清理函数(如 atexit 注册的函数)正常退出资源释放后退出
assert()若断言失败,调用 abort()可捕获调试期断言
panic()(内核)内核级错误处理,记录信息后停机系统级崩溃操作系统内核崩溃

4. 关键特性

(1) 不可恢复性
  • 无法通过信号处理函数(如 signal(SIGTRAP, handler))拦截或恢复执行。
  • abort() 不同,SIGABRT 可被捕获并尝试恢复,但 __builtin_trap() 直接触发硬件异常,更“强硬”。
(2) 编译器优化
  • 编译器会将 __builtin_trap() 视为不可达代码(unreachable code),可能优化其后的代码。例如:
    if (error) {
      __builtin_trap();
    }
    safe_code(); // 编译器可能认为此处永远不会被执行,从而优化掉某些检查
    
(3) 跨平台行为
  • Linux/macOS:通常生成 SIGILL(非法指令)信号。
  • Windows:触发 STATUS_ILLEGAL_INSTRUCTION 异常。
  • 嵌入式系统:可能导致硬件复位或进入调试模式。

5. 示例代码

场景:检测缓冲区溢出
#include <string.h>

void fortified_memcpy(void* dest, const void* src, size_t n) {
  // 动态检查目标缓冲区大小
  size_t dest_size = __builtin_dynamic_object_size(dest, 1);
  if (n > dest_size) {
    __builtin_trap(); // 溢出风险,立即终止
  }
  memcpy(dest, src, n);
}

6. 注意事项

  1. 调试友好性
    使用 __builtin_trap() 生成的崩溃会保留完整的调用栈和核心转储,方便事后分析。

  2. unreachable() 的区别
    __builtin_unreachable() 仅提示编译器代码不可达(用于优化),而 __builtin_trap() 会实际生成终止指令。

  3. 不可滥用
    仅在确实需要主动防御安全漏洞或标记逻辑错误时使用,过度使用会降低程序健壮性。


总结

__builtin_trap() 是编译器提供的一种“强硬”终止机制,适合以下场景:

  • 安全敏感代码:检测到漏洞时立即终止,防止攻击者利用。
  • 逻辑完整性检查:标记理论上不应出现的代码分支。
  • 调试辅助:在关键路径上强制崩溃,定位问题。

它的不可捕获性和直接触发硬件异常的特性,使其成为安全加固代码中的重要工具。

---------------------------------------------------------------------------

__builtin_object_sizetype 参数是一个整数,取值范围为 0123,它通过 低两位比特(bit 0 和 bit 1) 的组合控制计算对象大小的行为。以下是每个 type 值的详细解释:


type 参数的定义

type 的低两位比特决定了以下行为:

  1. 最低位(bit 0)
    • 0:假设 ptr 指向一个完整的对象(不考虑子对象)。
    • 1:假设 ptr 可能指向一个子对象(如结构体成员或数组元素)。
  2. 次低位(bit 1)
    • 0:在无法确定对象大小时,返回 安全的最小可能值(保守模式)。
    • 1:在无法确定对象大小时,返回 安全的最大可能值(宽松模式)。

因此,type 的四种组合如下:

typebit 1bit 0行为模式
000保守模式:不考虑子对象,无法确定大小时返回最小值(通常 0)。
101保守模式:考虑子对象,无法确定大小时返回最小值。
210宽松模式:不考虑子对象,无法确定大小时返回最大值(通常 SIZE_MAX)。
311宽松模式:考虑子对象,无法确定大小时返回最大值。

具体行为详解

1. type = 0(保守模式,不考虑子对象)
  • 行为
    尝试计算 ptr 指向的 完整对象 的大小。若无法确定,返回 0
  • 适用场景
    严格的缓冲区溢出检查,例如确保 memcpy 不会溢出目标缓冲区。
  • 示例
    char buf[10];
    size_t size = __builtin_object_size(buf, 0); // 返回 10
    
    struct Example {
      char header[4];
      char data[20];
    } obj;
    size_t size_header = __builtin_object_size(obj.header, 0); // 返回 4(完整对象是 header)
    size_t size_data = __builtin_object_size(obj.data, 0);     // 返回 20(完整对象是 data)
    

2. type = 1(保守模式,考虑子对象)
  • 行为
    尝试计算 ptr 指向的 子对象 所属的父对象的大小。若无法确定,返回 0
  • 适用场景
    ptr 可能指向一个子对象(如结构体成员)时,检查父对象的总大小。
  • 示例
    struct Example {
      char header[4];
      char data[20];
    } obj;
    
    char* p = obj.data;
    size_t size = __builtin_object_size(p, 1); // 返回 20(父对象是 data)
                                               // 若 type=0,则返回 20(完整对象是 data)
    

3. type = 2(宽松模式,不考虑子对象)
  • 行为
    尝试计算 ptr 指向的 完整对象 的大小。若无法确定,返回 SIZE_MAX
  • 适用场景
    允许最大可能的缓冲区大小,避免误报(例如动态内存分配时)。
  • 示例
    char* p = malloc(100);
    size_t size = __builtin_object_size(p, 2); // 可能返回 SIZE_MAX(无法静态确定大小)
    
    char buf[10];
    size = __builtin_object_size(buf, 2);      // 返回 10
    

4. type = 3(宽松模式,考虑子对象)
  • 行为
    尝试计算 ptr 指向的 子对象 所属的父对象的大小。若无法确定,返回 SIZE_MAX
  • 适用场景
    允许动态内存或复杂指针结构的最大可能大小。
  • 示例
    struct Example {
      char header[4];
      char data[20];
    } obj;
    
    char* p = obj.data + 5; // 指向 data 的中间位置
    size_t size = __builtin_object_size(p, 3); // 返回 15(剩余空间:20 - 5 = 15)
    

关键区别总结

type模式子对象处理无法确定时返回值典型场景
0保守模式不考虑子对象0严格检查静态缓冲区溢出
1保守模式考虑子对象0检查结构体成员的父对象大小
2宽松模式不考虑子对象SIZE_MAX避免误报动态内存操作
3宽松模式考虑子对象SIZE_MAX动态内存或复杂指针结构的检查

实际应用示例

场景:安全增强的 memcpy
void safe_memcpy(void* dest, const void* src, size_t n) {
  // 使用 type=0(保守模式,不考虑子对象)
  size_t dest_size = __builtin_object_size(dest, 0);
  if (n > dest_size) {
    __builtin_trap(); // 终止程序
  }
  memcpy(dest, src, n);
}
场景:动态分配的缓冲区
void process_data(size_t len) {
  char* buf = malloc(len);
  // 使用 type=2(宽松模式,不考虑子对象)
  size_t buf_size = __builtin_object_size(buf, 2);
  if (buf_size != SIZE_MAX && buf_size < len) {
    __builtin_trap();
  }
  // 安全操作...
}

注意事项

  1. 编译器依赖
    具体行为可能因编译器版本和优化等级(-O1 或更高)而异。例如,malloc(100) 在编译时可能被推断为固定大小。
  2. 动态内存限制
    malloc/new 分配的动态内存,__builtin_object_size 通常无法准确计算大小(返回 0SIZE_MAX)。
  3. 子对象场景
    ptr 指向子对象(如结构体成员)时,type=13 可以计算父对象的总大小。

总结

  • type=0type=1:用于严格的安全检查(返回最小值)。
  • type=2type=3:用于避免误报(返回最大值)。
  • 根据是否需要考虑子对象和是否容忍不确定性,选择合适的 type 值。

---------------------------------------------------------------------------

你的问题涉及编译器内置函数(Compiler Built-ins)的本质和实现细节,以下是分层次的解答:


1. __builtin_xx 是什么?

  • 官方定义
    这些是 GCC/Clang 等编译器直接提供的内置函数(Built-in Functions),属于编译器的私有扩展,并非标准 C/C++ 的一部分。
  • 作用
    提供底层硬件操作、优化提示或语言无法直接表达的功能(如对象大小计算、陷阱指令生成等)。
  • 命名规则
    __builtin_ 前缀开头,表示它们是编译器“自带”的特殊功能。

2. 与用户自定义函数的区别

特性__builtin_xx用户自定义函数
实现方编译器内部实现用户代码或库文件
编译阶段处理直接翻译为特定指令或优化行为(无函数调用)生成函数调用指令(可能被内联优化)
可见性无源码(编译器魔法)可查看源码
可移植性依赖编译器(GCC/Clang/ICC 等)标准 C/C++ 代码可跨平台
性能零开销(如 __builtin_trap() 生成单条指令)可能有调用开销

3. 为什么需要内置函数?

  • 访问硬件特性
    例如 __builtin_prefetch(缓存预取)、__builtin_ia32_rdtsc(读取时间戳计数器)。
  • 优化控制
    例如 __builtin_expect(分支预测提示)、__builtin_unreachable(标记不可达代码)。
  • 安全增强
    例如 __builtin_object_size(缓冲区检查)、__builtin_trap(快速终止)。
  • 语言扩展
    例如 __builtin_va_arg(可变参数处理)、__builtin_offsetof(结构体成员偏移)。

4. 能否看到实现代码?

  • 不能直接查看
    内置函数的逻辑 直接内置于编译器内部(GCC/Clang 的源代码中),没有用户可见的 C/C++ 实现代码。
  • 间接研究方式
    1. 编译器源码
      例如 GCC 的 gcc/builtins.def 定义了内置函数的行为,但需要熟悉编译器开发。
    2. 反汇编
      通过编译生成的汇编代码观察其行为(例如 gcc -S 输出):
      // 示例:__builtin_trap() 的汇编输出(x86)
      ud2;    // 生成非法指令
      
    3. 文档
      GCC 官方文档 描述了每个内置函数的行为。

5. 常见 __builtin_xx 示例

内置函数作用等效用户代码可能性
__builtin_memcpy优化版内存拷贝可实现,但性能更差
__builtin_expect分支预测优化(如 likely/unlikely无法用 C 代码实现
__builtin_popcount计算整数二进制中 1 的个数可实现,但更慢
__builtin_debugtrap调试断点(不终止程序)依赖平台特定汇编
__builtin_constant_p判断表达式是否为编译时常量无法实现

6. 用户如何模拟内置函数?

某些内置函数的功能可以通过其他方式近似实现,但通常性能或安全性更差:

  • 示例 1:__builtin_trap 的替代

    // 用户模拟版本(不跨平台)
    void my_trap() {
      *((volatile int*)0) = 0; // 触发段错误(SIGSEGV)
    }
    

    缺点:信号可被捕获,不如 __builtin_trap() 直接。

  • 示例 2:__builtin_popcount 的替代

    int my_popcount(unsigned int x) {
      int count = 0;
      while (x) {
        count += x & 1;
        x >>= 1;
      }
      return count;
    }
    

    缺点:编译器无法优化为单条 POPCNT 指令。


7. 为什么编译器不开放实现?

  • 硬件依赖性
    某些内置函数直接映射到特定 CPU 指令(如 __builtin_ia32_rdtsc)。
  • 优化耦合性
    内置函数的行为可能与编译器的中间表示(IR)优化深度绑定。
  • 避免滥用
    这些函数通常用于编译器或标准库开发,普通用户应优先使用标准库接口。

8. 何时应该使用内置函数?

  • 需要极致性能(如加密算法中的 __builtin_aes)。
  • 实现标准库(如 glibcmemcpy__builtin_memcpy 优化)。
  • 系统级开发(如内核中需要触发陷阱或读取寄存器)。
  • 安全关键代码(如 Fortify Source 的缓冲区检查)。

总结

  • __builtin_xx 是编译器的“黑魔法”,没有用户可见的实现代码,但可通过文档和反汇编理解其行为。
  • 与用户函数相比,它们零开销、与硬件/优化深度集成,但牺牲了可移植性。
  • 普通开发中应优先使用标准库,仅在必要时谨慎使用内置函数。

示例代码参考
在这里插入图片描述


http://www.kler.cn/a/613764.html

相关文章:

  • Burp Suite抓包实战:SQL注入漏洞挖掘
  • 无人机宽带自组网机载电台技术详解,50KM超远图数传输系统实现详解
  • Debian ubuntu源
  • 深度求索(DeepSeek):以AI之力重塑医疗未来
  • 机器学习——LightGBM
  • 系统间交互时,怎么校验两个系统所在服务器时间是否一致
  • 【Linux】应用层协议 HTTP
  • CSS3学习教程,从入门到精通,CSS3 媒体查询实现响应式布局语法指南(21)
  • 从dev分支checkout出一个functionA分支开发功能
  • linux》》docker 、containerd 保存镜像、打包tar、加载tar镜像
  • 数据库----单表、多表
  • 基于EFISH-SBC-RK3576的无人机智能飞控与数据存储方案
  • Leetcode 组合总和 III
  • 鸿蒙OS 5.0 服务能力框架深入剖析
  • markdown 文件转 word
  • 原生android实现定位java实现
  • elementUI el-image图片加载失败解决
  • SpringCloud+Mybatis-Plus+Docker+RabbitMQ+Redis+Elasticsearch黑马商城
  • Git 基础入门:从概念到实践的版本控制指南
  • [leetcode]1749. 任意子数组和的绝对值的最大值(dp)