C / LLVM: вызов функции с недопустимыми символами в ее имени

#c #llvm

#c #llvm

Вопрос:

У меня есть следующий код LLVM:

 define i64 @main() {
entry:
  call void @some.function()
  ret i64 0
}

declare void @some.function()
  

some.function . в нем есть a, что означает, что если я сделаю что-то подобное на C:

 #include <stdio.h>
void some.function(void) {
    puts("this will not work");
}
  

Случаются плохие вещи:

 $ cc tmp.c -S
tmp.c:3:10: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token
 void some.function(void) {
          ^
  

Если я изменю some.function на some_function , я получу следующую сборку:

     .file   "tmp.c"
    .text
    .section    .rodata
.LC0:
    .string "this will not work"
    .text
    .globl  some_function
    .type   some_function, @function
some_function:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    leaq    .LC0(%rip), %rdi
    call    puts@PLT
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   some_function, .-some_function
    .ident  "GCC: (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0"
    .section    .note.GNU-stack,"",@progbits
  

Я могу вручную изменить все экземпляры some_function to some.function и скомпилировать его:

 $ cc tmp.s main.s  # main.s is the LLVM code
$ ./a.out
this will not work
  

Как я могу сделать это из самого C? То, что я хотел бы сделать, это что-то вроде этого:

 void "some.function"(void) {}

//or

void __some_special_macro((some.function))(void) {}
  

Есть мысли?

Ответ №1:

Если вы используете GCC или Clang, есть возможность указать, что имя в сборке отличается от имени в C:

 extern void foo(void) __asm__("some.function");
  

Затем, когда вы вызываете функцию foo , компилятор сгенерирует ассемблерный код, такой как callq some.function .