强制某些编译器生成的变量进入特定的 ELF 部分(使用 gcc)

2024-01-11

我将从最终的问题开始:在带有 gcc 的 C 中,是否有可能获得以下值__func__(或同等地,__FUNCTION__)存储在除.rodata(或任何地方-mrodata=点)或其小节?

完整解释:

假设我有一个日志记录宏:

#define LOG(fmt, ...) log_internal(__FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__)

(字符串连接运算符##在该一元上下文中使用时会消耗前面的逗号当且仅当__VA_ARGS__列表为空,因此允许使用带或不带参数的格式字符串。)

然后我就可以正常使用宏了:

void my_function(void) {
    LOG("foo!");
    LOG("bar: %p", &bar);
}

可能会打印(显然取决于log_internal):

foo.c:201(my_function) foo!
foo.c:202(my_function) bar: 0x12345678

在这种情况下,格式字符串 ("foo" and "bar: %p") 和预处理器字符串 ("foo.c" and "my_function")是匿名只读数据,它们被放入.rodata自动部分。

但是假设我希望它们去一个不同的地方(我在一个嵌入式平台上运行几乎所有来自 RAM 的东西以提高速度,但内存限制正在推动将一些东西移动到 ROM 中)。移动起来很“容易”__FILE__和格式字符串:

#define ROM_STR(str) (__extension__({static const __attribute__((__section__(".rom_data"))) char __c[] = (str); (const char *)&__c;}))
#define LOG(fmt, ...) log_internal(ROM_STR(__FILE__), __LINE__, __func__, ROM_STR(fmt), ##__VA_ARGS__)

你不能把__attribute__在匿名字符串上,所以ROM_STR宏给它一个临时名称,将其附加到特定部分,然后计算起始地址,以便它可以干净地替换。如果您尝试通过char *变量为LOG作为您的格式字符串,但我愿意排除该用例。

通常,恰好相同的匿名字符串会被编译器组合到单个存储位置中,因此每个实例__FILE__在一个文件中将共享相同的运行时地址。通过显式命名ROM_STR,每个实例都会有自己的存储位置,因此使用它实际上可能没有意义__FILE__.

不过,我想用它__func__。问题是__func__与魔法不同__FILE__。来自 gcc 手册,“函数名称作为字符串”:

标识符__func__由翻译器隐式声明,就好像紧跟在每个函数定义的左大括号之后,声明

static const char __func__[] = "function-name";

出现,其中 function-name 是词法封闭函数的名称。该名称是函数的原始名称。 ... 这些标识符不是预处理器宏。在 GCC 3.3 及更早版本中,并且仅在 C 中,__FUNCTION__ and __PRETTY_FUNCTION__被视为字符串文字;它们可以用来初始化 char 数组,并且可以与其他字符串文字连接。 GCC 3.4 及更高版本将它们视为变量,例如__func__.

因此,如果你包装__func__ with ROM_STR, 你得到

error: invalid initializer

如果您尝试在使用之前或之后放置一个节属性__func__, 你得到

error: expected expression before ‘__attribute__’

or

error: expected ‘)’ before ‘__attribute__’

因此我们回到开头的问题:是否有可能得到__func__存储在我选择的部分中?也许我可以用-fdata-sections并执行一些链接器脚本魔法来获得.rodata.__func__.*排除在其余的之外.rodata?如果是这样,链接描述文件中排除通配符的语法是什么?换句话说,在某处你有一个*(.rodata*)- 我可以放一个*(.rodata.__func__*)其他地方,但我需要修改原始的 glob 以排除它,这样我就不会得到两个副本。


一种方法可能比您想要的更黑客,是插入一个脚本来更改编译和汇编之间的节名称。例如:

gcc -fdata-sections -S -o test.s test.c
sed 's/^\t.section\t\.rodata\.__func__\.[0-9]*/\t.section .rom_data/' -i test.s
gcc -c test.s

您还可以尝试编写一个 clang 转换传递来放置__func__在您选择的部分中进行声明,或者使用以下命令编写目标文件操作程序libbfd http://en.wikipedia.org/wiki/Binary_File_Descriptor_library.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

强制某些编译器生成的变量进入特定的 ELF 部分(使用 gcc) 的相关文章

  • Asp.net core默认路由

    简化版Startup code public void ConfigureServices IServiceCollection services services AddMvc public void Configure IApplica
  • EventHandler 应该始终用于事件吗?

    我一直在愉快地使用自定义委托类型和通用编写事件Action委托类型 没有真正考虑我在做什么 我有一些很好的扩展助手Action and EventHandler这使我倾向于使用那些预定义的委托类型而不是我自己的委托类型 但除此之外 除了惯例
  • 通过 SOAP 的 Gmt php 或 UTC C# 等效项

    is C DateTime UtcNow和 PHPdate c 是等价的 我怀疑 因为当我肥皂时 我得到了 C
  • libtool 在 Ubuntu 13.04 上构建 thrift 0.9.1 时出错

    在 Ubuntu 13 04 上构建 thrift 0 9 1 支持 C C java C perl python 时出现此错误 configure 不带任何选项运行 make 不带任何选项运行 Making all in test mak
  • 如何调整 Windows 窗体以适应任何屏幕分辨率?

    我知道这是重复的问题 但我检查了所有其他相关问题 他们的答案没有帮助 结果仍然与屏幕截图 2 中所示相同 我是 C Windows 窗体新手 如截图1所示 我有Form1有一些控件 每组控件都放在一个面板中 我在 PC1 中设计了应用程序
  • DataGridView 列中的数字文本框

    我有一个DataGridView 我想要它的第一列或任何所需的列 其中有textboxes在其中 成为NUMERIC ONLY 我目前正在使用这段代码 private void dataGridViewItems EditingContro
  • C 类型命名约定,_t 或 ALLCAPS

    我一直想知道是否有任何命名约定 例如何时对类型使用全部大写以及何时追加 t 什么时候不使用任何东西 我知道当时 K R 发布了各种有关如何使用 C 的文档 但我找不到任何相关内容 在 C 标准库类型中 t看起来漂亮占主导地位 time t
  • “没有合适的默认构造函数可用”——为什么会调用默认构造函数?

    我已经查看了与此相关的其他一些问题 但我不明白为什么在我的情况下甚至应该调用默认构造函数 我可以只提供一个默认构造函数 但我想了解它为什么这样做以及它会产生什么影响 error C2512 CubeGeometry no appropria
  • 是否可以在Linux上将C转换为asm而不链接libc?

    测试平台为Linux 32位 但也欢迎 Windows 32 位上的某些解决方案 这是一个c代码片段 int a 0 printf d n a 如果我使用 gcc 生成汇编代码 gcc S test c 然后我会得到 movl 0 28 e
  • C 与 C++ 中的 JNI 调用不同?

    所以我有以下使用 Java 本机接口的 C 代码 但是我想将其转换为 C 但不知道如何转换 include
  • 如何对STL向量进行排序?

    我想排序一个vector vector
  • 选择 asp.net CheckBoxList 中的所有项目

    ASP NET 和 C 我想要一个带有 全选 项目的复选框列表 当这个特定项目是 已选择 所有其他都将被选择 也 当选择被删除时 这个项目 也将来自所有人 其他物品 选中 取消选中 任何其他项目只会有一个 对特定项目的影响 无论选择状态如何
  • 使用 Unity 在 C# 中发送 http 请求

    如何使用 Unity 在 C 中发送 HTTP GET 和 POST 请求 我想要的是 在post请求中发送json数据 我使用Unity序列化器 所以不需要 新的 我只想在发布数据中传递一个字符串并且能够 将 ContentType 设置
  • 在 Qt 中播放通知(频率 x)声音 - 最简单的方法?

    Qt 5 1 或更高版本 我需要播放频率为 x 的通知声音 n 毫秒 如果我能像这样组合音调那就太好了 1000Hz 持续 2 秒 然后 3000Hz 持续 1 秒 最简单的方法是使用文件 WAV MP3 例如如此处所述 如何用Qt播放声音
  • 如何调用与现有方法同名的扩展方法? [复制]

    这个问题在这里已经有答案了 我有这样的代码 public class TestA public string ColA get set public string ColB get set public string ColC get se
  • 时间:2019-03-17 标签:c#TimerStopConfusion

    我想通过单击按钮时更改文本颜色来将文本框文本设置为 闪烁 我可以让文本按照我想要的方式闪烁 但我希望它在闪烁几次后停止 我不知道如何在计时器触发几次后让它停止 这是我的代码 public Form1 InitializeComponent
  • 值和类型的简洁双向静态 1:1 映射

    我将从我想象如何使用我想要创建的代码开始 它不必完全像这样 但它是我在标题中所说的 简洁 的一个很好的例子 就我而言 它是将类型映射到相关的枚举值 struct bar foo
  • 使用 boost 异步发送和接收自定义数据包?

    我正在尝试使用 boost 异步发送和接收自定义数据包 根据我当前的实现 我有一些问题 tcpclient cpp include tcpclient h include
  • 在 C 中使用 #define 没有任何价值

    If a define没有任何价值地使用 例如 define COMMAND SPI 默认值是0吗 不 它的评估结果为零 从字面上看 该符号被替换为空 然而 一旦你有了 define FOO 预处理器条件 ifdef FOO现在将是真的 另
  • 如何在c中断言两个类型相等?

    在 C 中如何断言两种类型相等 在 C 中 我会使用 std is same 但搜索 StackOverflow 和其他地方似乎只能给出 C 和 C 的结果 在C中没有办法做到这一点吗 请注意 这不是询问变量是否具有某种类型 而是询问两个类

随机推荐

  • 将静态 IP 地址与 Amazon EC2 结合使用

    我想将 Amazon Web Service 免费微实例用于我的不同项目以进行测试和个人目的 但我需要一些静态公共 IP 来运行我的服务器 那可能吗 我可以从哪里购买 IP 并将其与我的 AWS 一起使用 EC2 弹性 IP 地址 http
  • ActiveAdmin不会保存有很多并且属于很多字段

    我有 2 个型号 类别和帖子 它们使用 has many and belongs to many 关系进行连接 我检查了 Rails 控制台 关系正常 我在 activeadmin 中创建了复选框来使用此表单字段设置帖子类别 f input
  • 为什么 %prec 在此 bison 语法中不起作用?

    考虑以下 Bison 语法 这是从我正在研究的一个更大的语法中剥离出来的 token ident left left CALLPREC start add expr ident call add call expr prec CALLPRE
  • 在 Mono 上使用自定义 SSL 客户端证书 System.Net.HttpClient

    我在用着Microsoft HTTP 客户端库 https www nuget org packages Microsoft Net Http来自 NuGet 我基本上尝试使用 X509Certificate2 证书在 HttpClient
  • lambda 内隐含的匿名类型

    In 这个问题 https stackoverflow com q 43973776 1876620 用户 Holger 提供一个答案 https stackoverflow com a 43983558 1876620这显示了我不知道的匿
  • 无法将导出用作类型,因为导出是一个值

    运行时出现此错误flow check 但我不确定这意味着什么 无法将导出用作类型 因为导出是一个值 要获取值的类型 请使用 typeof 错误位置是0 1 在 flow注释处 这是代码 flow import Chunk from mode
  • svn commit 不带-m

    我尝试过输入svn commit它将弹出一个屏幕 其中显示正在添加 更改 等的文件列表 以及在消息中输入的位置 但按 Enter 会在消息中添加换行符 而不是启动提交 是否有热键或某些组合键来启动提交 看起来底部有某种类似 emacs 的控
  • 如何以及在何处使用 AsyncStorage 保存整个 redux 存储

    我想知道是否必须执行类似的操作 才能在反应本机应用程序中使用 AsyncStorage 保存应用程序的整个存储 并在应用程序启动时检查它是否存在 var store loadInitialState async gt try var val
  • Vuetify 构建为 Web 组件样式未显示

    我正在使用 Vue 和 Vuetify 以及 Web 组件构建一个应用程序 当我将 Vuetify 添加为 Web 组件时 CSS 样式 Vuetify 消失了 我尝试将以下内容添加到 demo html 文件中但这没有帮助 我的仓库是vu
  • android listview半透明选择行的颜色

    我需要在列表视图中实现半透明的行选择 以及 按下 状态 如果我应用纯色 那么一切都会按预期进行 但如果我应用半透明颜色 44444444 那么我会看到默认选择颜色 在我的 2 3 android 上为橙色 在它的顶部是我的颜色 它使橙色稍微
  • 在 XML 中应如何解释带有 CDATA 和空格的文本节点?

    System Xml 解析功能给我带来了一些惊喜 我想知道以下内容如何should被解释 或者如果这是 取决于实现 版本1
  • NuGet - RID 和 TFM 示例

    我一直在 GitHub 上查看 NuGet3 的代码 并且在以下位置看到了几种文件夹模式https github com NuGet NuGet3 blob a5bc907d36ddaa8d4fa6c499e50d7ebf8993ed39
  • 如何在Python中用空格替换所有这些特殊字符?

    如何在 python 中用空格替换所有这些特殊字符 我有一份公司名称清单 例如 myfiles txt 我的公司 INC 老酒私人有限公司 大师头脑有限公司 顶点实验室有限公司 印度新公司 印美私人有限公司 这里 按照上面的例子 我需要文件
  • 如何从 Java 运行 cygwin?

    我想从 Java 开始 如何从 Java 程序启动 cygwin 首先 您必须将 bash exe 设置为环境变量 以便此行将启动 bash Runtime rt Runtime getRuntime execute bash
  • 使用 Firebase Auth 登录 iOS 应用是否满足“导出合规信息”加密要求

    在使用 App Store Connect 上传应用程序时 我看到过有关导出合规性信息加密问题的类似问题 但我仍在寻找问题的直接答案 我正在上传 iOS 应用程序 必须回答以下问题 出口合规信息 您的应用程序使用加密吗 即使您的应用程序仅使
  • Sharepoint 2013 计算字段作为超链接呈现为文本

    I have a column in Sharepoint 2013 and set the type to Calculated I have set the data return type to integer pic attache
  • 如何在中间件中使用“this”上下文

    我出于我的目的编写了自己的中间件作为模块 如下所示 myMiddleware js module exports fn1 function req res next console log fn1 next fn2 function req
  • 错误:无法加载 libphutil

    我们已经安装运行Phabricator在我们的一台服务器中 今天 我按照 中给出的标准步骤对其进行了升级 https secure phabricator com book phabricator article upgrading htt
  • 在 Linq EF 查询中使用 SQRT

    我需要使用 SQRT 函数作为 Linq EF 查询中 where 子句的一部分 我想我可以这样做 var qry context MyTable Where sqrt it field gt 1 但它返回一个错误 指出 sqrt 无法解析
  • 强制某些编译器生成的变量进入特定的 ELF 部分(使用 gcc)

    我将从最终的问题开始 在带有 gcc 的 C 中 是否有可能获得以下值 func 或同等地 FUNCTION 存储在除 rodata 或任何地方 mrodata 点 或其小节 完整解释 假设我有一个日志记录宏 define LOG fmt