Why doesn't gcc support naked functions? - c++

I use naked functions to patch parts of a program while it's running. I can easily do this in VC++ in Windows. I'm trying to do this in Linux and it seems gcc doesn't support naked functions. Compiling code with naked functions gives me this: warning: ‘naked’ attribute directive ignored. Compiled under CentOS 5.5 i386.

The naked attribute is only supported by GCC on certain platforms (ARM, AVR, MCORE, RX and SPU) according to the docs:
naked:
Use this attribute on the ARM, AVR, MCORE, RX and SPU ports to
indicate that the specified function does not need prologue/epilogue
sequences generated by the compiler. It is up to the programmer to
provide these sequences. The only statements that can be safely
included in naked functions are asm statements that do not have
operands. All other statements, including declarations of local
variables, if statements, and so forth, should be avoided. Naked
functions should be used to implement the body of an assembly
function, while allowing the compiler to construct the requisite
function declaration for the assembler.
I'm not sure why.

On x86 you can workaround by using asm at global scope instead:
int write(int fd, const void *buf, int count);
asm
(
".global write \n\t"
"write: \n\t"
" pusha \n\t"
" movl $4, %eax \n\t"
" movl 36(%esp), %ebx \n\t"
" movl 40(%esp), %ecx \n\t"
" movl 44(%esp), %edx \n\t"
" int $0x80 \n\t"
" popa \n\t"
" ret \n\t"
);
void _start()
{
#define w(x) write(1, x, sizeof(x));
w("hello\n");
w("bye\n");
}
Also naked is listed among x86 function attributes, so I suppose it works for newer gcc.

That's an ugly solution. Link against a .asm file for your target architecture.

GCC only supports naked functions on ARM and other embedded platforms. http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Also, what you're doing is inherently unsafe, as you cannot guarantee that the code you're patching isn't executing if the program is running.

Related

Referencing memory operands in .intel_syntax GNU C inline assembly

I'm catching a link error when compiling and linking a source file with inline assembly.
Here are the test files:
via:$ cat test.cxx
extern int libtest();
int main(int argc, char* argv[])
{
return libtest();
}
$ cat lib.cxx
#include <stdint.h>
int libtest()
{
uint32_t rnds_00_15;
__asm__ __volatile__
(
".intel_syntax noprefix ;\n\t"
"mov DWORD PTR [rnds_00_15], 1 ;\n\t"
"cmp DWORD PTR [rnds_00_15], 1 ;\n\t"
"je done ;\n\t"
"done: ;\n\t"
".att_syntax noprefix ;\n\t"
:
: [rnds_00_15] "m" (rnds_00_15)
: "memory", "cc"
);
return 0;
}
Compiling and linking the program results in:
via:$ g++ -fPIC test.cxx lib.cxx -c
via:$ g++ -fPIC lib.o test.o -o test.exe
lib.o: In function `libtest()':
lib.cxx:(.text+0x1d): undefined reference to `rnds_00_15'
lib.cxx:(.text+0x27): undefined reference to `rnds_00_15'
collect2: error: ld returned 1 exit status
The real program is more complex. The routine is out of registers so the flag rnds_00_15 must be a memory operand. Use of rnds_00_15 is local to the asm block. It is declared in the C code to ensure the memory is allocated on the stack and nothing more. We don't read from it or write to it as far as the C code is concerned. We list it as a memory input so GCC knows we use it and wire up the "C variable name" in the extended ASM.
Why am I receiving a link error, and how do I fix it?
Compile with gcc -masm=intel and don't try to switch modes inside the asm template string. AFAIK there's no equivalent before clang14 (Note: MacOS installs clang as gcc / g++ by default.)
Also, of course you need to use valid GNU C inline asm, using operands to tell the compiler which C objects you want to read and write.
Can I use Intel syntax of x86 assembly with GCC? clang14 supports -masm=intel like GCC
How to set gcc to use intel syntax permanently? clang13 and earlier didn't.
I don't believe Intel syntax uses the percent sign. Perhaps I am missing something?
You're getting mixed up between %operand substitutions into the Extended-Asm template (which use a single %), vs. the final asm that the assembler sees.
You need %% to use a literal % in the final asm. You wouldn't use "mov %%eax, 1" in Intel-syntax inline asm, but you do still use "mov %0, 1" or %[named_operand].
See https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html. In Basic asm (no operands), there is no substitution and % isn't special in the template, so you'd write mov $1, %eax in Basic asm vs. mov $1, %%eax in Extended, if for some reason you weren't using an operand like mov $1, %[tmp] or mov $1, %0.
uint32_t rnds_00_15; is a local with automatic storage. Of course it there's no asm symbol with that name.
Use %[rnds_00_15] and compile with -masm=intel (And remove the .att_syntax at the end; that would break the compiler-generate asm that comes after.)
You also need to remove the DWORD PTR, because the operand-expansion already includes that, e.g. DWORD PTR [rsp - 4], and clang errors on DWORD PTR DWORD PTR [rsp - 4]. (GAS accepts it just fine, but the 2nd one takes precendence so it's pointless and potentially misleading.)
And you'll want a "=m" output operand if you want the compiler to reserve you some scratch space on the stack. You must not modify input-only operands, even if it's unused in the C. Maybe the compiler decides it can overlap something else because it's not written and not initialized (i.e. UB). (I'm not sure if your "memory" clobber makes it safe, but there's no reason not to use an early-clobber output operand here.)
And you'll want to avoid label name conflicts by using %= to get a unique number.
Working example (GCC and ICC, but not clang unfortunately), on the Godbolt compiler explorer (which uses -masm=intel depending on options in the dropdown). You can use "binary mode" (the 11010 button) to prove that it actually assembles after compiling to asm without warnings.
int libtest_intel()
{
uint32_t rnds_00_15;
// Intel syntax operand-size can only be overridden with operand modifiers
// because the expansion includes an explicit DWORD PTR
__asm__ __volatile__
( // ".intel_syntax noprefix \n\t"
"mov %[rnds_00_15], 1 \n\t"
"cmp %[rnds_00_15], 1 \n\t"
"je .Ldone%= \n\t"
".Ldone%=: \n\t"
: [rnds_00_15] "=&m" (rnds_00_15)
:
: // no clobbers
);
return 0;
}
Compiles (with gcc -O3 -masm=intel) to this asm. Also works with gcc -m32 -masm=intel of course:
libtest_intel:
mov DWORD PTR [rsp-4], 1
cmp DWORD PTR [rsp-4], 1
je .Ldone8
.Ldone8:
xor eax, eax
ret
I couldn't get this to work with clang: It choked on .intel_syntax noprefix when I left that in explicitly.
Operand-size overrides:
You have to use %b[tmp] to get the compiler to substitute in BYTE PTR [rsp-4] to only access the low byte of a dword input operand. I'd recommend AT&T syntax if you want to do much of this.
Using %[rnds_00_15] results in Error: junk '(%ebp)' after expression.
That's because you switched to Intel syntax without telling the compiler. If you want it to use Intel addressing modes, compile with -masm=intel so the compiler can substitute into the template with the correct syntax.
This is why I avoid that crappy GCC inline assembly at nearly all costs. Man I despise this crappy tool.
You're just using it wrong. It's a bit cumbersome, but makes sense and mostly works well if you understand how it's designed.
Repeat after me: The compiler doesn't parse the asm string at all, except to do text substitutions of %operand. This is why it doesn't notice your .intel_syntax noprefex and keeps substituting AT&T syntax.
It does work better and more easily with AT&T syntax though, e.g. for overriding the operand-size of a memory operand, or adding an offset. (e.g. 4 + %[mem] works in AT&T syntax).
Dialect alternatives:
If you want to write inline asm that doesn't depend on -masm=intel or not, use Dialect alternatives (which makes your code super-ugly; not recommended for anything other than wrapping one or two instructions):
Also demonstrates operand-size overrides
#include <stdint.h>
int libtest_override_operand_size()
{
uint32_t rnds_00_15;
// Intel syntax operand-size can only be overriden with operand modifiers
// because the expansion includes an explicit DWORD PTR
__asm__ __volatile__
(
"{movl $1, %[rnds_00_15] | mov %[rnds_00_15], 1} \n\t"
"{cmpl $1, %[rnds_00_15] | cmp %k[rnds_00_15], 1} \n\t"
"{cmpw $1, %[rnds_00_15] | cmp %w[rnds_00_15], 1} \n\t"
"{cmpb $1, %[rnds_00_15] | cmp %b[rnds_00_15], 1} \n\t"
"je .Ldone%= \n\t"
".Ldone%=: \n\t"
: [rnds_00_15] "=&m" (rnds_00_15)
);
return 0;
}
With Intel syntax, gcc compiles it to:
mov DWORD PTR [rsp-4], 1
cmp DWORD PTR [rsp-4], 1
cmp WORD PTR [rsp-4], 1
cmp BYTE PTR [rsp-4], 1
je .Ldone38
.Ldone38:
xor eax, eax
ret
With AT&T syntax, compiles to:
movl $1, -4(%rsp)
cmpl $1, -4(%rsp)
cmpw $1, -4(%rsp)
cmpb $1, -4(%rsp)
je .Ldone38
.Ldone38:
xorl %eax, %eax
ret

Is it possible to use explicit register variables in GCC with C++17?

I am using explicit register variables to pass parameters to a raw Linux syscall using registers that don't have machine-specific constraints (such as r8, r9, r10 on x86_64) as suggested here.
#include <asm/unistd.h>
#ifdef __i386__
#define _syscallOper "int $0x80"
#define _syscallNumReg "eax"
#define _syscallRetReg "eax"
#define _syscallReg1 "ebx"
#define _syscallReg2 "ecx"
#define _syscallReg3 "edx"
#define _syscallReg4 "esi"
#define _syscallReg5 "edi"
#define _syscallReg6 "ebp"
#define _syscallClob
#else
#define _syscallOper "syscall"
#define _syscallNumReg "rax"
#define _syscallRetReg "rax"
#define _syscallReg1 "rdi"
#define _syscallReg2 "rsi"
#define _syscallReg3 "rdx"
#define _syscallReg4 "r10"
#define _syscallReg5 "r8"
#define _syscallReg6 "r9"
#define _syscallClob "rcx", "r11"
#endif
template <typename Ret = long, typename T1>
Ret syscall(long num, T1 arg1)
{
register long _num __asm__(_syscallNumReg) = num;
register T1 _arg1 __asm__(_syscallReg1) = arg1;
register Ret _ret __asm__(_syscallRetReg);
__asm__ __volatile__(_syscallOper
: "=r"(_ret)
: "r"(_num), "r"(_arg1)
: _syscallClob);
return _ret;
}
extern "C" void _start()
{
syscall(__NR_exit, 0);
}
However this feature requires the use of register keyword which was deprecated in C++11 and removed in C++17. So when I compile this code with GCC 7 (-std=c++17 -nostdlib) it gives me a warning:
ISO C++1z does not allow ‘register’ storage class specifier [-Wregister]
and it seems to ignore the register allocation and the program segfaults because syscall wasn't called properly. This code however compiles and works fine in Clang 6. Note: I actually have 6 syscall functions (up to 6 arguments) but only 1-argument version is shown here for the sake of minimal example.
I realize that register keyword by itself wasn't really useful that's why it was removed, but this specific use case seems like an exception to me so it seems unreasonable to remove compiler support for it as well.
I also realize that this use case is compiler-specific (i.e. non-standard), so my question is about compiler support rather then removal from the standard.
It appears you've found a GCC bug: GNU register-asm local variables don't work inside template functions. (clang compiles your example correctly). Apparently this was already a known bug, thanks for #Florian for finding it.
-Wregister triggering is just a symptom of this first bug: GNU register-asm local variables don't trigger the warning. But in a template, gcc compiles them as they were plain register int foo = bar; without the asm part of the declaration. So GCC thought you were just using plain register variables, not register-asm.
In a regular function, your code compiles fine with no warnings, even with -std=c++17.
#define T1 unsigned long
#define Ret T1
// template <typename Ret = long, typename T1>
... your code unchanged ...
__asm__ __volatile__(_syscallOper " #operands in %0, %1, %2"
...
On Godbolt with gcc7.3 -O3:
_start:
movl $60, %eax
xorl %edx, %edx
syscall #operands in %rax, %rax, %edx
ret
But clang6.0 doesn't have this bug, and we get:
_start: # #_start
movl $60, %eax
xorl %edi, %edi
syscall #operands in %rax, %rax, %edi
retq
Notice the asm comment I appended to your template (with C++ string-literal concatenation). We can just get the compiler to tell us what it thinks it's doing, instead of having to puzzle things out.
(Mostly posting this answer to discuss that debugging technique; Florian's answer already covers the specifics of this actual case.)
Instead of templates, you can use MUSL's existing portable headers:
It's a C library, so it might need a bit of extra casting to keep a C++ compiler happy. Or avoiding use of temporary expressions as lvalues, in the ARM headers.
But it should take care of most of the issues Florian pointed out. It has a permissive license, so you can just copy its syscall wrapper headers into your project. They work without linking against the rest of MUSL, and are truly inline.
http://git.musl-libc.org/cgit/musl/tree/arch/x86_64/syscall_arch.h is the x86-64 version.
This looks like a GCC bug to me. The C++17 warning is a red herring. The code works fine with optimization for me (when compiled with GCC 7), but it breaks at -O0.
According to the documentation for local register variables, this is not expected, so this is likely a GCC bug. According to this bug report, it is not even related to optimization, but ultimately caused by the use of a template.
I suggest to overload only on the number of system call arguments in the ultimate system call wrapper, and use long types for all arguments and the result:
inline long syscall_base(long num, long arg1)
{
register long _num __asm__(_syscallNumReg) = num;
register long _arg1 __asm__(_syscallReg1) = arg1;
register long _ret __asm__(_syscallRetReg);
__asm__ __volatile__(_syscallOper
: "=r"(_ret)
: "r"(_num), "r"(_arg1)
: _syscallClob);
return _ret;
}
template <typename Ret = long, typename T1>
Ret syscall(long num, T1 arg1)
{
return (Ret) (syscall_base(num, (long) arg1));
}
You'll have to use something nicer for the casts (probably type-indexed conversion functions), and of course you still have to deal with the syscall ABI variance in some other way (x32 has long long instead of long, and POWER has two return registers instead of one, etc.), but that's also a problem with your original approach.

segmentation fault with cmpxchg in inline asm

I'm writing my_simple_mutex using inline asm. The part of the code below that is commented out works fine, however, the version with cmpxchg terminates with a segfault. I'm using g++ 4.8.2 in cygwin.
void simple_mutex::spin_lock(){
/*asm ("spin_lock:\n\t"
"rep; nop;\n\t"
"lock; bts $0x00, %0;\n\t"
"jc spin_lock;\n\t"
:"=m"(lock)
:"m"(lock)
:
);
*/
asm ("spin_lock:\n\t"
"rep; nop;\n\t"
"movl $0x00, %%eax\n\t"
"movl $0x01, %%edx\n\t"
"lock; cmpxchg %%edx, %0\n\t"
"jnz spin_lock;\n\t"
:"=m"(lock)
:"m"(lock)
:
);
}
The variable lock is of type int. Any ideas what I'm doing wrong?
Possibly the fault is elsewhere, due to the fact that you have forgotten to tell the compiler you modified eax and edx. The fix is to list them as clobbers (the part after the 3rd colon). Unless you are forced to use inline asm, use the atomic builtins instead.

Issues with SIMD functions in GNU c & c++

Environment Details:
Machine: Core i5 M540 processor running Centos 64 bits in a virtual machine in VMware player.
GCC: 4.8.2 built from source tar.
Issue:
I am trying to learn more about SIMD functions in C/C++ and for that I created the following helloworld program.
#include <iostream>
#include <pmmintrin.h>
int main(void){
__m128i a, b, c;
a = _mm_set_epi32(1, 1, 1, 1);
b = _mm_set_epi32(2, 3, 4, 5);
c = _mm_add_epi32(a,b);
std::cout << "Value of first int: " << c[0];
}
When I look at the assembly output for it using the following command I do not see the SIMD instructions.
g++ -S -I/usr/local/include/c++/4.8.2 -msse3 -O3 hello.cpp
Sample of the assembly generated:
movl $.LC2, %esi
movl $_ZSt4cout, %edi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movabsq $21474836486, %rsi
movq %rax, %rdi
call _ZNSo9_M_insertIxEERSoT_
xorl %eax, %eax
Please advise the correct way of writing or compiling the SIMD code.
Thanks you!!
It looks like your compiler is optimizing away the calls to _mm_foo_epi32, since all the values are known. Try taking all the relevant inputs from the user and see what happens.
Alternately, compile with -O0 instead of -O3 and see what happens.

Assembler code in C++ code

How can I put Intel asm code into my c++ application?
I'm using Dev-C++.
I want to do sth like that:
int temp = 0;
int usernb = 3;
pusha
mov eax, temp
inc eax
xor usernb, usernb
mov eax, usernb
popa
This is only example.
How can I do sth like that?
UPDATE:
How does it look in Visual Studio ?
You can find a complete howto here http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
#include <stdlib.h>
int main()
{
int temp = 0;
int usernb = 3;
__asm__ volatile (
"pusha \n"
"mov eax, %0 \n"
"inc eax \n"
"mov ecx, %1 \n"
"xor ecx, %1 \n"
"mov %1, ecx \n"
"mov eax, %1 \n"
"popa \n"
: // no output
: "m" (temp), "m" (usernb) ); // input
exit(0);
}
After that you need to compile with something like:
gcc -m32 -std=c99 -Wall -Wextra -masm=intel -o casm casmt.c && ./casm && echo $?
output:
0
You need to compile with the -masm=intel flag since you want intel assembly syntax :)
UPDATE: How does it look in Visual Studio ?
If you are building for 64 bit, you cannot use inline assembly in Visual Studio. If you are building for 32 bit, then you use __asm to do the embedding.
Generally, using inline ASM is a bad idea.
You're probably going to produce worse ASM than a compiler.
Using any ASM in a method generally defeats any optimizations which try to touch that method (i.e. inlining).
If you need to access specific features of the processor not obvious in C++ (e.g. SIMD instructions) then you can use much more consistent with the language intrinsics provided by most any compiler vendor. Intrinsics give you all the speed of that "special" instruction but in a way which is compatible with the language semantics and with optimizers.
Here's a simple example to show the syntax for GCC/Dev-C++:
int main(void)
{
int x = 10, y;
asm ("movl %1, %%eax;"
"movl %%eax, %0;"
:"=r"(y) /* y is output operand */
:"r"(x) /* x is input operand */
:"%eax"); /* %eax is clobbered register */
}
It depends on your compiler. But from your tags I guess you use gcc/g++ then you can use gcc inline assembler. But the syntax is quite weird and a bit different from intel syntax, although it achieves the same.
EDIT: With Visual Studio (or the Visual C++ compiler) it get's much easier, as it uses the usual Intel syntax.
If it's for some exercices I'd recommend some real assembler avoiding inlined code as it can get rather messy/confusing.
Some basics using GCC can be found here.
If you're open to trying MSVC (not sure if GCC is a requirement), I'd suggest you have a look at MSVC's interpretation which is (in my opinion) a lot easier to read/understand, especially for learning assembler. An example can be found here.