“LOS_##_ns” 的意思是什么?

huangapple go评论72阅读模式
英文:

What's the meaning of __asm ("LOS_##_ns")

问题

我正在尝试深入了解苹果的OS Signpost实现方式。我正在使用C API(也有Swift API)。我的最终目标是尝试为它们构建一个RAII风格的C++包装类,尽管这可能比看起来更难。

扩展os_signpost_emit_with_type宏的操作会创建从传递给该宏的字符串文字生成的静态字符串,它们看起来像这样:

__attribute__((section("__TEXT,__oslogstring,cstring_literals"), internal_linkage)) static const char string_name[] __asm (OS_STRINGIFY(OS_CONCAT(LOS_##_ns, __COUNTER__))) = "string literal";

这些字符串稍后将出现在Instruments分析器中的标志点名称中。从阅读该代码中我所了解的,这个字符串被放置在二进制文件的特定部分,以便分析器可以找到它。让我困惑的是赋值之前的__asm语句。显然,通过__COUNTER__宏,它会扩展为类似于__asm ("LOS_##_ns0")__asm ("LOS_##_ns1"),数字对于每个字符串都是唯一的。我对汇编的深入了解很有限,我尝试研究一下该语句的含义,但没有得到有用的结果。

我的尝试和错误测试表明,__COUNTER__宏生成的数字附录的唯一性很重要,如果出现两个重复的值,具有该重复值的字符串将在分析器输出中覆盖另一个。

有了汇编知识的人可以解释一下这里发生了什么,对于像我这样的C++开发人员吗?

额外问题:是否有任何办法可以从C++代码中生成这条指令,其中唯一的数值值是由某个变量提供的,而不是__COUNTER__生成的值?

英文:

I'm trying to gain some insight on how Apples OS signpost implementation works. I'm working with the C API (there is also a Swift API). My ultimate goal is trying to build a RAII style C++ wrapper class for them, which is harder as it might seem.

Expanding the os_signpost_emit_with_type macro reveals that it creates static strings from the string literals passed to that macro that look like this:

__attribute__((section("__TEXT,__oslogstring,cstring_literals"), internal_linkage)) static const char string_name[] __asm (OS_STRINGIFY(OS_CONCAT(LOS_##_ns, __COUNTER__))) = "string literal";

These strings will later appear as names for the signposts in the instruments profiler. What I get from reading that code, is that the string is placed in a specific section of the binary so that the profiler can find it. What's confusing me is the __asm statement before the assignment. Obviously via the __COUNTER__ macro, it expands to something like __asm ("LOS_##_ns0"), __asm ("LOS_##_ns1") with the number being unique for every string. I have very little in depth knowledge when it comes to assembly, I tried to research the meaning of that statement a bit but got no useful results.

My try-and-error testing revealed that the uniqueness of that numerical appendix generated by the __COUNTER__ macro matters, if two duplicated values occur the string with that duplicated value will shadow the other one in the profiler output.

Can anyone with assembly know how explain what's going on here to a C++ developer like me?

Bonus question: Would there be any way to generate that instruction from within C++ code where the unique numerical value here generated by __COUNTER__would be taken from some variable?

答案1

得分: 1

  1. __attribute__((section("foo")) 将变量放置在名为foo的部分中,通过在汇编中发出.section指令,然后将变量的标签放置在该部分。详情请参阅https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes。看起来您已经了解这一点。

  2. 在声明中的asm实际上不是内联汇编;它只是告诉编译器在生成汇编代码时要使用的符号名称。__asm只是asm的变体拼写。请参阅https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Asm-Labels.html#Asm-Labels。因此,int foo asm("bar") = 7; 定义了一个变量,在C源代码中将其称为foo,但其汇编中的标签将命名为bar

  3. __COUNTER__是由gcc/clang预处理器定义的特殊宏,每次扩展时都会递增。请参阅https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros。

英文:

A general note: for information on clang extensions, you generally have to refer to the gcc documentation instead. clang aims to be compatible with gcc and so they didn't bother to write independent docs.

So in your example, a few different extensions are being used. Note that none of them are part of standard C or C++.

  1. __attribute__((section ("foo")) places the variable in the section named foo, by having the compiler emit a .section directive into the assembly before placing the label for the variable. See https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes. It sounds like you already know about this.

  2. asm in a declaration isn't really inline assembly per se; it simply tells the compiler what symbol name to use for this variable when it emits the assembly code. The __asm is just a variant spelling of asm. See https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Asm-Labels.html#Asm-Labels. So int foo asm("bar") = 7; defines a variable which will be referred to as foo in C source, but whose label in assembly will be named bar.

  3. __COUNTER__ is a special macro defined by the gcc/clang preprocessor that simply increments every time it is expanded. See https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros

huangapple
  • 本文由 发表于 2023年2月16日 17:11:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75469986.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定