我正在使用 a library 在编译时注册一些结构。在这种情况下,它正在注册一个表示我想公开的 JSON-RPC 方法的结构。该库使用 __attribute(section("xautodata_" "somename")) 标记结构,以便将其放在单独的部分中,以便以后检索。生成的内容将如下所示:

static const autodata_json_command_ *__attribute__((__used__)) __attribute__((section("xautodata_" "json_command"))) autodata_json_command_151 = (&help_command);;
static const autodata_json_command_ *__attribute__((__used__)) __attribute__((section("xautodata_" "json_command"))) autodata_json_command_173 = (&stop_command);;

稍后检索命令的代码将获得指向该部分的指针(并计算该部分中的元素数)并对其进行迭代,如下所示:
size_t count;
struct json_command **commands = get_json_commands(&count);
for (size_t i=0; i<count; i++) {
  // Access commands[i];
}

如果我们不使用 -fsanitize=address 编译,这非常好,但是当使用 -fsanitize=address 编译时它会添加填充。

没有地址清理器的命令彼此相邻,即 commands[0]commands[1] 是指向结构的有效指针。对于 sanitizer ,只有每 8 个命令是一个有效指针(可能是由于填充)。

现在真正的问题是:解决这个问题的最干净的方法是什么?我是否应该尝试使步长更大(在这种情况下,需要预处理器指令来区分 sanitizer 的使用)?或者有没有办法为该部分中的内容禁用此填充?

最佳答案

由于您概述的原因(即保持连续性),GCC Asan 故意避免在自定义部分中检测变量:

/* Don't protect if using user section, often vars placed
   into user section from multiple TUs are then assumed
   to be an array of such vars, putting padding in there
   breaks this assumption.  */
  || (DECL_SECTION_NAME (decl) != NULL
  && !symtab_node::get (decl)->implicit_section
  && !section_sanitized_p (DECL_SECTION_NAME (decl)))

(来自 gcc/asan.c )。在这种情况下,可以使用特殊标志 -fsanitize-sections=wildcard1,wildcard2,... 来强制检测。

另一方面,Clang Asan 忽略用户部分注释(请参阅 AddressSanitizer.cpp )。

我建议向 Asan tracker 添加 PR 以使 Clang 表现得像 GCC 或添加一个特殊标志来控制用户部分的检测(在后一种情况下,我们还需要更新 Asan Clang/GCC incompatibility wiki )。

关于c - 地址 sanitizer 和 __attribute(section ("mysection")) 失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53503870/

10-12 00:41