user12527223
user12527223

Reputation:

Jump to a label from inline assembly to C

I have a written piece of code in assembly and at some points of it, I want to jump to a label in C. So I have the following code (shortened version but still, I am having the same problem):

    #include <stdio.h>

    #define JE asm volatile("jmp end");
    int main(){
        printf("hi\n");
        JE
        printf("Invisible\n");
        end:
        printf("Visible\n");
        return 0;
    }

This code compiles, but there is no end label in the disassembled version of the code.

If I change the label name from end to any other thing (let's say l1, both in asm code(jmp l1) and in the C code), the compiler says that

    main.c:(.text+0x6b): undefined reference to `l1'
    collect2: error: ld returned 1 exit status
    Makefile:2: recipe for target 'main' failed
    make: *** [main] Error 1

I have tried different things(different length, different cases, upper, lower, etc.) and I think it only compiles with end label. And with end label, I am receiving segmentation fault because, there is no end label in the disassembled version.

Compiled with: gcc -O0 main.c -o main

Disassembled code:

    000000000000063a <main>:
     63a:   55                      push   %rbp
     63b:   48 89 e5                mov    %rsp,%rbp
     63e:   48 8d 3d af 00 00 00    lea    0xaf(%rip),%rdi        # 6f4 <_IO_stdin_used+0x4>
     645:   e8 c6 fe ff ff          callq  510 <puts@plt>
     64a:   e9 c9 09 20 00          jmpq   201018 <_end> # there is no _end label!
     64f:   48 8d 3d a1 00 00 00    lea    0xa1(%rip),%rdi        # 6f7 <_IO_stdin_used+0x7>
     656:   e8 b5 fe ff ff          callq  510 <puts@plt>
     65b:   48 8d 3d 9f 00 00 00    lea    0x9f(%rip),%rdi        # 701 <_IO_stdin_used+0x11>
     662:   e8 a9 fe ff ff          callq  510 <puts@plt>
     667:   b8 00 00 00 00          mov    $0x0,%eax
     66c:   5d                      pop    %rbp
     66d:   c3                      retq   
     66e:   66 90                   xchg   %ax,%ax

So, the questions are:

  1. Am I doing something wrong? I have seen this kind of jumps (from assembly to C) in codes. I can provide example links.
  2. Why the compiler/linker cannot find l1 but can find end?

Upvotes: 1

Views: 2949

Answers (1)

Peter Cordes
Peter Cordes

Reputation: 364180

This is what asm goto is for. GCC Inline Assembly: Jump to label outside block

Note that defining a label inside another asm statement will sometimes work (e.g. with optimization disabled) but IS NOT SAFE.

    asm("end:");   // BROKEN; NEVER USE 
                   // except for toy experiments to look at compiler output

GNU C does not define the behaviour of jumping from one asm statement to another without asm goto. The compiler is allowed to assume that execution comes out the end of an asm statement and e.g. put a store after it.


The C end: label within a given function won't just have the asm symbol name of end or _end: - that wouldn't make sense because separate C functions are each allowed to have their own end: label. It could be something like main.end but it turns out GCC and clang just use their usual autonumbered labels like .L123.

Then how this code works: https://github.com/IAIK/transientfail/blob/master/pocs/spectre/PHT/sa_oop/main.c

It doesn't; the end label that asm volatile("je end"); references is in the .data section and happens to be defined by the compiler or linker to mark the end of that section.

asm volatile("je end") has no connection to the C label in that function.

I commented out some of the code in other functions to get it to compile without the "cacheutils.h" header but that didn't affect that part of the oop() function; see https://godbolt.org/z/jabYu3 for disassembly of the linked executable with JE_4k changed to JE_16 so it's not huge. It's disassembly of a linked executable so you can see the numeric address of je 6010f0 <_end> while the oop function itself starts at 4006e0 and ends at 400750. (So it doesn't contain the branch target).

If this happens to work for Spectre exploits, that's because apparently the branch is never actually taken.

Upvotes: 4

Related Questions