Why does -g force .cfi_* directives?

Fangrui Song i@maskray.me
Fri Feb 26 07:09:05 GMT 2021


On 2021-02-20, Segher Boessenkool wrote:
>Hi!
>
>On Fri, Feb 19, 2021 at 07:53:13PM -0800, Jim Wilson wrote:
>> On Fri, Feb 19, 2021 at 4:36 PM Fangrui Song <i@maskray.me> wrote:
>> > How should we make the following code work with both
>> > -fno-asynchronous-unwind-tables and -fasynchronous-unwind-tables?
>> >
>> >    int main() {
>> >      asm(".cfi_undefined %rip");
>> >    }
>> >
>>
>> I don't think that there is a way currently to make this work.
>>
>> In general, I'd say that if you are doing something non-trivial you should
>> not be using an extended asm.  You should either use a built-in function or
>> just write it in assembly language directly.  Extended asms really only
>> work well for simple stuff.  If you use a built-in function, then the
>> compiler should emit any CFI directives for that built-in if necessary. If
>> writing in assembly language then you can hand write CFI directives for the
>> entire function, or rely on assembler support if the assembler can figure
>> it out from the code.
>
>[ Well, I wouldn't say "non-trivial"...  But "more than a few machine
>instructions", or "something that uses assembler pseudo-ops that aren't
>set up for this (with push/pop for example), I certainly agree with it
>if put that way. ]
>
>An inline asm inserts a piece of text in the middle of the compiler
>output.  You aren't even guaranteed it will be in *this* function, it
>could be inlined, and could be cloned, etc.  Or deleted.
>
>That can be dealt with by using a noipa attribute.  But then you get the
>next problem:
>
>You then know this asm will appear somewhere in the compiler output for
>this function.  But where?  In this example there is likely no other
>code generated for this function (if you have optimisation enabled!),
>but for any useful function, you do not know.
>
>(Btw, this is not an extended asm, this is a basic asm.  If you use at
>least one colon it is en extended asm, and then you need to write
>"%%rip", i.e., two percent signs).
>
>> But if you really want to do this in an extended asm, then we would need to
>> extend the asm syntax so that one can put CFI info in the middle of an
>> asm.
>
>But what would the semantics of that be?  You cannot control where in
>the compiler output the asm will appear, or even if that is only once!
>For example, in this code:
>
>int a, b;
>void f(int x)
>{
>	if (x)
>		a++;
>	else
>		b++;
>	asm("beacon");
>}
>
>the asm is output twice, since in effect the compiler makes this
>
>int a, b;
>void f(int x)
>{
>	if (x) {
>		a++;
>		asm("beacon");
>		return;
>	} else {
>		b++;
>		asm("beacon");
>		return;
>	}
>}
>
>> One way to do that might be a special operator for formatting asm
>> strings that only prints the string if we are emitting unwind info.  We
>> would have to find a free punctuation character that isn't already used by
>> any existing port, and then assuming backquote is free we could do
>
>There are no free characters this way: some code out there might output
>backticks in its inline asm.  Everything not % (or {|} on some targets)
>is emitted as-is (well, almost).
>
>> int main() {
>>      asm("`.cfi_undefined %rip`");
>>    }
>> and the backquotes then only print the string if we are emitting unwind
>> info.  Or alternatively make this a % operator like %`.
>
>Yes, that can work.  But you still have all the other problems with
>abusing asm like this :-/
>
>> Either way, I
>> think this would look funny, so might not be the best approach.  It would
>> likely be difficult for people to use.  I seriously doubt many users can
>> write CFI code and get it right.
>
>It often will depend on choices the compiler made, too, in which case 0
>users can get it right!  They can get lucky, and sometimes it will do
>what the user wanted.

For my .cfi_* in inline asm problem, I have filed

https://sourceware.org/bugzilla/show_bug.cgi?id=27472
   gas: Suppress "CFI instruction used without previous .cfi_startproc" if .cfi_sections is empty

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99282
   Emit .cfi_sections without arguments for -fno-asynchronous-unwind-tables


(I noticed that LLVM integrated assembler did not support
.cfi_sections with an empty section list. I just implemented it.
)


More information about the Gcc-help mailing list