Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting GCC to compile without inserting call to memcpy

I'm currently using GCC 4.5.3, compiled for PowerPC 440, and am compiling some code that doesn't require libc. I don't have any direct calls to memcpy(), but the compiler seems to be inserting one during the build.

There are linker options like -nostdlib, -nostartfiles, -nodefaultlibs but I'm unable to use them as I'm not doing the linking phase. I'm only compiling. With something like this:

$ powerpc-440-eabi-gcc -O2 -g -c -o output.o input.c

If I check the output.o with nm, I see a reference to memcpy:

$ powerpc-440-eabi-nm output.o | grep memcpy
     U memcpy
$ 

The GCC man page makes it clear how to remove calls to memcpy and other libc calls with the linker, but I don't want the compiler to insert them in the first place, as I'm using a completely different linker (not GNU's ld, and it doesn't know about libc).

Thanks for any help you can provide.

like image 638
Brian Avatar asked Jun 20 '11 11:06

Brian


2 Answers

There is no need to -fno-builtins or -ffreestanding as they will unnecessarily disable many important optimizations

This is actually "optimized" by gcc's tree-loop-distribute-patterns, so to disable the unwanted behavior while keeping the useful builtin capabilities, you can just use:

-fno-tree-loop-distribute-patterns

Musl-libc uses this flag for its build and has the following note in their configure script (I looked through the source and didn't find any macros, so this should be enough)

# Check for options that may be needed to prevent the compiler from
# generating self-referential versions of memcpy,, memmove, memcmp,
# and memset. Really, we should add a check to determine if this
# option is sufficient, and if not, add a macro to cripple these
# functions with volatile...
# tryflag CFLAGS_MEMOPS -fno-tree-loop-distribute-patterns

You can also add this as an attribute to individual functions in gcc using its optimize attribute, so that other functions can benefit from calling mem*()

like image 183
technosaurus Avatar answered Sep 25 '22 07:09

technosaurus


You can also make your binary a "freestanding" one:

The ISO C standard defines (in clause 4) two classes of conforming implementation. A conforming hosted implementation supports the whole standard [...]; a conforming freestanding implementation is only required to provide certain library facilities: those in , , , and ; since AMD1, also those in ; and in C99, also those in and . [...].

The standard also defines two environments for programs, a freestanding environment, required of all implementations and which may not have library facilities beyond those required of freestanding implementations, where the handling of program startup and termination are implementation-defined, and a hosted environment, which is not required, in which all the library facilities are provided and startup is through a function int main (void) or int main (int, char *[]).

An OS kernel would be a freestanding environment; a program using the facilities of an operating system would normally be in a hosted implementation.

(paragraph added by me)

More here. And the corresponding gcc option/s (keywords -ffreestanding or -fno-builtin) can be found here.

like image 43
Sebastian Mach Avatar answered Sep 23 '22 07:09

Sebastian Mach