I kinda liked the idea of having my own sprintf function without the string.h or stdio.h bloatware.
#define sprintf(x) my_sprintf(x)
void my_sprintf(const char * string);
int main(void)
{
sprintf("abc");
}
These are my LD flags:
LDFLAGS += -lgcc
LDFLAGS += --specs=nano.specs
LDFLAGS += -mthumb
LDFLAGS += -mcpu=cortex-m4
# LDFLAGS += --gc-sections
# LDFLAGS += -nostartfiles
# LDFLAGS += -nodefaultlibs
# LDFLAGS += -gc-sections
As you see, I have the nostartfiles and nodefaultlibs options unset. So, even if I had the idea of including string.h or stdio.h, The compiler might find a definition/reference of the sprintf function.
So I'd like to know what if the #define will still refer to the "redefinition" if it is the same than an existing function name.
Any help is warmly welcome.
Yes, but an easier way would be to use a freestanding environment:
gcc -ffreestanding ...
If you want to know if your approach will take effect across files (i.e. #define function(x) y in file1.c and function(z) in file2.c), then no, it won't.
Related
I've got some software compiled to run on an embedded NRF24 target, using a gcc-arm-none-eabi toolchain from here (a custom one that provides gdb with support for python3) . I'm trying essentially, malloc an array from the GDB debugger console at runtime, then fill it with elements that I provide.
I have a pointer defined in a .c file like: static float32_t *array;.
I want to then call a cmd like: call (void*) malloc(num_of_elements*sizeof(float32_t)) from inside the GDB console to allocate an array at runtime, and then fill it with elements with something like maybe: call (void*) memcpy(array, {var1, var2... var n}, n)
My issue is the GDB debugger cannot find the malloc stdlib function. If I do something like:
break malloc
Function "malloc" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
It can't find this function, although it is fine with finding <string.h> fns, like memcpy for example and I can't quite work out why this is.
I have a feeling it could be something to do with linking, the program is built with a Makefile, the flags towards the end may be of interest:
LIB_FILES += \
$(SDK_ROOT)/components/toolchain/cmsis/dsp/GCC/libarm_cortexM4lf_math.a \
# Optimization flags
OPT = -O0 -g3
# Uncomment the line below to enable link time optimization
#OPT += -flto
# C flags common to all targets
CFLAGS += $(OPT)
CFLAGS += -DBOARD_PCA10056
CFLAGS += -DARM_MATH_CM4
CFLAGS += -DBSP_DEFINES_ONLY
CFLAGS += -DCONFIG_GPIO_AS_PINRESET
CFLAGS += -DFLOAT_ABI_HARD
CFLAGS += -DNRF52840_XXAA
CFLAGS += -mcpu=cortex-m4
CFLAGS += -mthumb -mabi=aapcs
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
# keep every function in a separate section, this allows linker to discard unused ones
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
CFLAGS += -fno-builtin -fshort-enums
CFLAGS += -DDEV8_PINOUT
CFLAGS += -DNUM_FLASH_BLOCKS=128
CFLAGS += -DDEBUG
CFLAGS += -DNRF_LOG_ENABLED=1
CFLAGS += -DNRF_LOG_BACKEND_UART_ENABLED=1
# C++ flags common to all targets
CXXFLAGS += $(OPT)
# Assembler flags common to all targets
ASMFLAGS += $(OPT)
ASMFLAGS += -mcpu=cortex-m4
ASMFLAGS += -mthumb -mabi=aapcs
ASMFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
ASMFLAGS += -DBOARD_PCA10056
ASMFLAGS += -DBSP_DEFINES_ONLY
ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET
ASMFLAGS += -DFLOAT_ABI_HARD
ASMFLAGS += -DNRF52840_XXAA
ASMFLAGS += -DARM_MATH_CM4
# Linker flags
LDFLAGS += $(OPT)
LDFLAGS += -mthumb -mabi=aapcs -L$(SDK_ROOT)/modules/nrfx/mdk -T$(LINKER_SCRIPT)
LDFLAGS += -mcpu=cortex-m4
LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
# let linker dump unused sections
LDFLAGS += -Wl,--gc-sections
# use newlib in nano version
LDFLAGS += --specs=nano.specs
LDFLAGS += -Wl,--print-memory-usage
nrf52840_xxaa: CFLAGS += -D__HEAP_SIZE=8192
nrf52840_xxaa: CFLAGS += -D__STACK_SIZE=8192
nrf52840_xxaa: ASMFLAGS += -D__HEAP_SIZE=8192
nrf52840_xxaa: ASMFLAGS += -D__STACK_SIZE=8192
# Add standard libraries at the very end of the linker input, after all objects
# that may need symbols provided by these libraries.
LIB_FILES += -lc -lnosys -lm
To debug I'm using GDB with a Jlink server type setup.
Your code needs to explicitly reference the symbol to force it to link, and you need to prevent link optimisation from removing unused references. Rather then doing a dummy call with potential unwanted side effects, you can simply refer to the symbol via a function pointer instantiation thus:
void* (*volatile force_malloc_link)(size_t) = &malloc ;
Or more simply since you will not actually invoke the function through the pointer:
volatile void* force_link_malloc = &malloc ;
You could make it generic with a macro for any symbol you wish to link:
#define FORCE_LINK( sym ) volatile void* force_link_ ## sym = &sym
You can also force the entire library to be linked (if you have the space) - How to force gcc to link an unused static library. One of the answers there explains how you can also unpack the static library and link individual object files.
It can't find this function
The function may not be linked into your binary.
Does your binary call malloc elsewhere?
Do you link against libc.so or libc.a?
Does nm a.out | grep ' malloc' find it?
it is fine with finding <string.h> fns, like memcpy
If your binary calls memcpy and you link against libc.a, then memcpy implementation will be linked in. Using the same nm command from above will show that the memcpy symbol is present and malloc is not.
If you want to call malloc at runtime, you need to make sure it's linked in. One way to achieve this is to add:
const char *argv0;
int main(int argc, char *argv[])
{
argv0 = strdup(argv[0]); // This should guarantee that malloc is linked in.
// rest of the program
}
In the openwrt package that I'm working on, I defined a new config flag by adding following bloc to the Config.in file:
config VENDOR_PREFIX
string "Vendor Prefix"
default "X_Custom_SE_"
The flag is well added in the menuconfig:
I want that the value of this config flag is viewed in my C code as a macro. So I defined a macro CUSTOM_PREFIX in the Makefile of the package and assigned to it the value of the defined flag with this way:
TARGET_CFLAGS += -DCUSTOM_PREFIX=\"$(CONFIG_VENDOR_PREFIX)\"
and then I tried to use my macro in my C code by calling it in a structure variable initiation like that:
struct parameter_struct param1= {CUSTOM_PREFIX"param1", 4};
After that I tried to compile it. But I got this compilation error:
/home/user/openwrt//staging_dir/toolchain-mips_mips32_gcc-5.5.0_musl/usr/include -I/home/user/openwrt/staging_dir/toolchain-mips_mips32_gcc-5.5.0_musl/include/fortify -I/home/user/openwrt/staging_dir/toolchain-mips_mips32_gcc-5.5.0_musl/include -I/home/user/openwrt/staging_dir/target-mips_mips32_musl/usr/include -I/home/user/openwrt/staging_dir/target-mips_mips32_musl/usr/include -I/home/user/openwrt/staging_dir/target-mips_mips32_musl/usr/include -DCWMP_VERSION=\"3.0.0\" -I../inc/ -I../dm/ -I../dm/dmtree/ -I../dm/dmtree/common -I../dm/dmtree/tr098 -I../dm/dmtree/tr181 -I../dm/dmtree/upnp -Os -pipe -mips32 -mtune=mips32 -fno-caller-saves -DCONFIG_TARGET_iopsys_brcm63xx_mips -g3 -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -iremap/home/user/openwrt/build_dir/target-mips_mips32_musl/icwmp-curl/icwmp-4.0-2018-03-21:icwmp-4.0-2018-03-21 -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -DCUSTOM_PREFIX=X_CUSTOM1_SE_ -D_GNU_SOURCE -D_AADJ -MT ../dm/dmtree/common/libdatamodel_la-deviceinfo.lo -MD -MP -MF ../dm/dmtree/common/.deps/libdatamodel_la-deviceinfo.Tpo -c ../dm/dmtree/common/deviceinfo.c -fPIC -DPIC -o ../dm/dmtree/common/.libs/libdatamodel_la-deviceinfo.o
^
../dm/dmtree/common/deviceinfo.c: At top level:
<command-line>:0:15: error: 'X_CUSTOM1_SE_' undeclared here (not in a function)
../dm/dmtree/common/deviceinfo.c:28:2: note: in expansion of macro 'CUSTOM_PREFIX'
{CUSTOM_PREFIX"param1", 4}
struct parameter_struct param1= {CUSTOM_PREFIX"param1", 4};
seems like that the c program doesn't accept it as a string.
Is there something wrong in my macro definition?
As I expected and I noted in the my post title the mistake is in the definition of the macro in the Makefile. In Openwrt Makefile the definition of the Macro should be like that:
TARGET_CFLAGS += -DCUSTOM_PREFIX=\\\"$(CONFIG_VENDOR_PREFIX)\\\"
I'm trying to mock a fn say foo using
#ifdef UT_TEST
void foo(void) __attribute__ ((weak, alias ("foo_impl")));
#else
void foo(void);
#endif
However, is there a way to do this # runtime instead of compile time? I cannot use C++, for historical reasons.
In the past I've mostly seen this problem solved at the build system level instead, which I feel is a cleaner solution. Doing it this way allows to avoid most ifdefs and instead work with full files. In make, it might look something like this:
OBJS += file1.o file2.o
ifeq ($(UNIT_TEST),y)
OBJS += dummy_implementation.o
else
OBJS += real_implementation.o
endif
myprog: $(OBJS)
or in more classic make idiom:
OBJS-y += file1.o file2.o
OBJS-$(UNIT_TEST) += dummy_implementation.o
OBJS-$(REAL_BUILD) += real_implementation.o
OBJS = $(OBJS-y)
myprog: $(OBJS)
dummy_implementation.c and real_implementation.c would share a header file in this case.
How to solve the following problem with make?
SRCS1 = a.c b,c
SRCS2 = d.c e.c
SRCS= $(SRCS1) $(SRCS2)
OBJS1 = $(subst .c,.o,$(SRCS1))
OBJS2 = $(subst .c,.o,$(SRCS2))
OBJS = $(OBJS1) $(OBJS2)
include ../Makeconf
(which contains CPPFLAGS=-Dfoo) (the main Makefile is also in ../)
Now I want to compile SRCS1 with foo defined and SRCS2 with foo not defined.
I tried
ifneq (,$(findstring $(OBJS2),$(OBJS)))
CPPFLAGS += -Ufoo
endif
but that adds -Ufoo to all files when compiled. Any ideas?
You haven't shown us enough of the makefile(s) to give a complete answer, but I think this is what you're looking for:
$(OBJS2): CPPFLAGS += -Ufoo
Context :
Trying to understand how lto (link time compilation) works
Code:
I have those files :
julia.h:
#ifndef JULIA_H
#define JULIA_H
#include <stdio.h>
int julian();
#endif // JULIA_H
julia.c :
#include "julia.h"
int julian()
{
printf("Hello Worldu!\n");
return 0;
}
compiled as a shared library like so :
gcc -O3 -fPIC -shared julia.c -o libjulia.so -L$PWD -I$PWD -flto
and my main program :
main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "julia.h"
int main()
{
julian();
return 0;
}
compiled with :
gcc -O3 main.c -I/path/to/inc -L/path/to/lib -Wl,-rpath=/path/to/lib -ljulia -flto
It compiles fines.
Question :
So, this is a hello world program but am I doing it right with LTO ?
Is is all it takes to optimize the linkage ?
Thanks
As keltar saied, LTO doesn't affect shared libraries. But...
LTO works with static libraries
Just replace ar by gcc-ar and add the option --plugin gccpath/liblto_plugin.so. This LTO plugin will copy the declarations, types, callgraph and GIMPLE representation from LTO-compiled objects into the static lib. (same for ranlib to be replaced by gcc-ranlib)
In your example
# First retrieve the GCC path
gccpath=$(gcc -print-search-dirs | awk '/install/{print $2}')
# Compile the static library
gcc julia.c -o julia.o -flto -ffat-lto-objects
gcc-ar rcs libjulia.a julia.o --plugin $gccpath/liblto_plugin.so
# Compile & link the executable
gcc main.c libjulia.a -flto -Ofast -march=native
Note: -Ofast introduced in GCC-4.6 [ref] (else use -03)
Update Makefile
GCCPATH = $(shell gcc -print-search-dirs | awk '/install/{print $$2}')
AR = gcc-ar
RANLIB = gcc-ranlib
ARFLAGS += --plugin $(GCCPATH)/liblto_plugin.so
RANLIBFLAGS += --plugin $(GCCPATH)/liblto_plugin.so
CFLAGS += -flto -ffat-lto-objects
CXXFLAGS += -flto -ffat-lto-objects
LDFLAGS += -flto=8 # 8 -> compiles using 8 threads
Do not forget, the real compilation will be done at link time. Therefore, move your optimization flags from CFLAGS (and CXXFLAGS) to LDFLAGS ;-) One more thing, debugging info and LTO is still experimental in GCC-4.9. GCC-5.0 should improve this point...
LTO doesn't affect shared libraries; they're being linked with by dynamic linker, which is not aware of LTO and can't modify code at runtime.
Moreover, LTO doesn't even work with static libraries, but some day it presumably will (it is TODO on gcc wiki).
But yes, what it takes to enable is using -flto on both compilation and linking phases.