Backgrounds:
I need to get the register value in the c code, so I found this in gcc usage. I get the ebp value using the following code.
register int ebp asm("ebp");
printf("currently ebp is %08x\n", ebp);
// then some code use the value
Everything seems okay until I changed my program's compiler to clang. In gcc, it usually print something similar as 0x7f1284978, definitely a pointer like value.
But when use clang, output became weird, it print out a value like 0x9. Ebp must can't have a value like this.
Qs:
Why it didn't complain warning or error if it doesn't support this feature(using the following code to compile)?
#include <stdio.h>
static size_t vfp = 0x233;
int main(void) {
register int ebp asm("ebp");
vfp = (size_t) ebp;
printf("vfp value is 0x%lx\n", vfp);
return 0;
}
Clang reduces the single-thread compilation time by 5% to 10% compared with GCC. Therefore, Clang offers more advantages for the construction of large projects.
GCC is slower to compile than clang, so I spend a lot of time compiling, but my final system is (usually) faster with GCC, so I have set GCC as my system compiler.
GCC and C99 allow an array's size to be determined at run time. This extension is not permitted in standard C++. However, Clang supports such variable length arrays for compatibility with GNU C and C99 programs. If you would prefer not to use this extension, you can disable it with -Werror=vla.
Clang supports use of either LLVM's libc++ or GCC's libstdc++ implementation of the C++ standard library.
TL;DR:
Clang does not support explicit register variable as for now.
Details:
See clang documentation
clang only supports global register variables when the register specified is non-allocatable (e.g. the stack pointer). Support for general global register variables is unlikely to be implemented soon because it requires additional LLVM backend support.
On my machine (x86_64 ubuntu 16.04), if I compile with Clang-5.0, the assembly I get is:
08048410 <main>:
8048410: 55 push %ebp
8048411: 89 e5 mov %esp,%ebp
8048413: 83 ec 18 sub $0x18,%esp
8048416: 8d 05 c0 84 04 08 lea 0x80484c0,%eax
804841c: 8b 4d fc mov -0x4(%ebp),%ecx ;this line is wrong, the behavior is meaningless
804841f: 89 0d 1c a0 04 08 mov %ecx,0x804a01c
8048425: 8b 0d 1c a0 04 08 mov 0x804a01c,%ecx
804842b: 89 04 24 mov %eax,(%esp)
804842e: 89 4c 24 04 mov %ecx,0x4(%esp)
8048432: e8 89 fe ff ff call 80482c0 <printf@plt>
8048437: 89 45 f8 mov %eax,-0x8(%ebp)
804843a: 83 c4 18 add $0x18,%esp
804843d: 5d pop %ebp
804843e: c3 ret
804843f: 90 nop
If I compile with GCC-5.5.0, this is the assembly I got:
0000051d <main>:
51d: 8d 4c 24 04 lea 0x4(%esp),%ecx
521: 83 e4 f0 and $0xfffffff0,%esp
524: ff 71 fc pushl -0x4(%ecx)
527: 55 push %ebp
528: 89 e5 mov %esp,%ebp
52a: 53 push %ebx
52b: 51 push %ecx
52c: e8 33 00 00 00 call 564 <__x86.get_pc_thunk.ax>
531: 05 a7 1a 00 00 add $0x1aa7,%eax
536: 89 ea mov %ebp,%edx ; this is the correct location to get the value of ebp
538: 89 90 30 00 00 00 mov %edx,0x30(%eax)
53e: 8b 90 30 00 00 00 mov 0x30(%eax),%edx
544: 83 ec 08 sub $0x8,%esp
547: 52 push %edx
548: 8d 90 18 e6 ff ff lea -0x19e8(%eax),%edx
54e: 52 push %edx
54f: 89 c3 mov %eax,%ebx
551: e8 5a fe ff ff call 3b0 <printf@plt>
556: 83 c4 10 add $0x10,%esp
559: 90 nop
55a: 8d 65 f8 lea -0x8(%ebp),%esp
55d: 59 pop %ecx
55e: 5b pop %ebx
55f: 5d pop %ebp
560: 8d 61 fc lea -0x4(%ecx),%esp
563: c3 ret
We can see that GCC generally supports explicit register value access while Clang does not.
Solution:
If you wish to use Clang to access ebp value, you can use inline assembly, like this: asm("\t movl %%ebp,%0" : "=r"(vfp));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With