How to change libdirs priority in premake? - linker

I have the following lines in my premake4.lua file
platforms { "x32", "x64" }
...
libdirs { "../deps/linux/lib64" }
Then the generated Makefile will contain:
LDFLAGS += -m64 -L/usr/lib64 -L../deps/linux/lib64
Is it possible to prioritize my custom library dir?
I mean I want the following line:
LDFLAGS += -m64 -L../deps/linux/lib64 -L/usr/lib64
I'm using premake4 but I can switch to premake5 if needed.

In Premake4, you can add this to your project file:
premake.gcc.platforms.x64.ldflags = "-L../deps/linux/lib64 -L/usr/lib64"
In Premake5, you can do this:
premake.tools.gcc.libraryDirectories.architecture.x86_64 = { "-L../deps/linux/lib64", "-L/usr/lib64" }
Though it would clearly be better if you didn't have to do that. If you could open an issue ticket and link it to this discussion I can look into swapping those variables around in the code.

Related

GDB Debugger - "malloc" not defined. Trying to assign C array with debugger

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
}

Weak alias to mock

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.

C plugin system: dlopen fails

as a continuation to this post C pluginsystem: symbol lookup error, I am still writing my plugin system and encounter new bugs.
To recap what the plugins are, the program consists of a network application interfaced by a shell, messages has a type and therefore can be use to create applications on the network. For exemple, a possible application would be a chat or a transfert application.
So shell commands can send message of a particular application on the network, when a message is received, if it corresponds to a particular application then an action function is executed with the message content as argument, it could be the application.
A plugin is a shared library with an init function that register it's commands and actions. A command could just be a simple command that doesn't interact with the network, and that's why I achieved at the moment.
The plugin system consists in modules:
plugin_system.c
list.c used by the first module to store plugins
The network part consists in:
protocol.c main part of the protocol
message.c main part for message treatment
application.c main part used to program applications
common.c file with ccommon functions
network.c useful network functions
The modules in protocole are all interdependent, I have split files for conveniency.
All modules are compiled with -fPIC option.
To compile a plugin called plug.c wich doesn't interact with the network, I use:
gcc -Wall -O2 -std=gnu99 -D DEBUG -g -fPIC -c -o plug.o plug.c
gcc -Wall -O2 -std=gnu99 -D DEBUG -g -o plug.so plug.o plugin_system.o list.o -shared
And it works perfectly, the library is loaded with dlopen with no problem, the init function loaded with dlsym and executed correctly so the plugin is registered, I then executed the command and I can see that it work.
Now I wan't to add supports for network communications for the plugins, so I have modified the same test plugin that I used which has just a command to print a message. I have had a call to sendappmessage_all a function that send a message to everyone over the network, defined in message.c.
I can compile the new plugin without adding the network module objects, it compile, the plugin loads correctly, but when it call sendappmessage_all obviously it fails with the message
symbol lookup error: ./plugins/zyva.so: undefined symbol: sendappmessage_all
So to make it work, I should like the plugin with network modules so that's what I have done with
gcc -Wall -O2 -std=gnu99 -D DEBUG -g -o plug.so plug.o plugin_system.o list.o protocol.o message.o thread.o common.o application.o network.o -shared
It compile but when I try to load the plugin, dlopen return NULL.
I have also tried to add just one module, at worst it would only result in an undefined symbol error, but I dlopen still return NULL.
I know it's a lot of informations and on the otherside you probably wan't to see the code but I tried to be the clearer in the most succint way I could be because is way more complex and bigger than the post.
Thank you for your understanding.
The problem is that when you compile the plugin system (i.e. functions called by plugins), and link it to the final executable, the linker does not export the symbols used by the plugins in the dynamic symbol table.
There are two options:
Use -rdynamic when linking the final executable, adding all symbols to the dynamic symbol table.
Use -Wl,-dynamic-list,plugin-system.list when linking the final executable, adding symbols listed in file plugin-system.list to the dynamic symbol table.
The file format is simple:
{
sendappmessage_all;
plugin_*;
};
In other words, you can list either each symbol name (function or data structure), or a glob pattern that matches the desired symbol names. Remember the semicolon after each symbol, and after the closing brace, or you'll get a "syntax error in dynamic list" error at link time.
Note that just marking a function "used" via __attribute__((used)) is not sufficient to make the linker include it in the dynamic symbol table (with GCC 4.8.4 and GNU ld 2.24, at least).
Since the OP thinks what I wrote above is incorrect, here is a fully verifiable proof of the above.
First, a simple main.c that loads plugin files named on the command line, and executes their const char *register_plugin(void); function. Because the function name is shared across all plugins, we need to link them locally (RTLD_LOCAL).
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <stdio.h>
static const char *load_plugin(const char *pathname)
{
const char *errmsg;
void *handle; /* We deliberately leak the handle */
const char * (*initfunc)(void);
if (!pathname || !*pathname)
return "No path specified";
dlerror();
handle = dlopen(pathname, RTLD_NOW | RTLD_LOCAL);
errmsg = dlerror();
if (errmsg)
return errmsg;
initfunc = dlsym(handle, "register_plugin");
errmsg = dlerror();
if (errmsg)
return errmsg;
return initfunc();
}
int main(int argc, char *argv[])
{
const char *errmsg;
int arg;
if (argc < 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s plugin [ plugin ... ]\n", argv[0]);
fprintf(stderr, "\n");
return EXIT_SUCCESS;
}
for (arg = 1; arg < argc; arg++) {
errmsg = load_plugin(argv[arg]);
if (errmsg) {
fflush(stdout);
fprintf(stderr, "%s: %s.\n", argv[arg], errmsg);
return EXIT_FAILURE;
}
}
fflush(stdout);
fprintf(stderr, "All plugins loaded successfully.\n");
return EXIT_SUCCESS;
}
The plugins will have access via certain functions (and/or variables), declared in plugin_system.h:
#ifndef PLUGIN_SYSTEM_H
#define PLUGIN_SYSTEM_H
extern void plugin_message(const char *);
#endif /* PLUGIN_SYSTEM_H */
They are implemented in plugin_system.c:
#include <stdio.h>
void plugin_message(const char *msg)
{
fputs(msg, stderr);
}
and listed as dynamic symbols in plugin_system.list:
{
plugin_message;
};
We'll also need a plugin, plugin_foo.c:
#include <stdlib.h>
#include "plugin_system.h"
const char *register_plugin(void) __attribute__((used));
const char *register_plugin(void)
{
plugin_message("Plugin 'foo' is here.\n");
return NULL;
}
and just to remove any confusion about what effect there is having each plugin a registration function by the same name, another plugin named plugin_bar.c:
#include <stdlib.h>
#include "plugin_system.h"
const char *register_plugin(void) __attribute__((used));
const char *register_plugin(void)
{
plugin_message("Plugin 'bar' is here.\n");
return NULL;
}
To make all of this easy to compile, we'll need a Makefile:
CC := gcc
CFLAGS := -Wall -Wextra -O2
LDFLAGS := -ldl -Wl,-dynamic-list,plugin_system.list
PLUGIN_CFLAGS := $(CFLAGS)
PLUGIN_LDFLAGS := -fPIC
PLUGINS := plugin_foo.so plugin_bar.so
PROGS := example
.phony: all clean progs plugins
all: clean progs plugins
clean:
rm -f *.o $(PLUGINS) $(PROGS)
%.so: %.c
$(CC) $(PLUGIN_CFLAGS) $^ $(PLUGIN_LDFLAGS) -shared -Wl,-soname,$# -o $#
%.o: %.c
$(CC) $(CFLAGS) -c $^
plugins: $(PLUGINS)
progs: $(PROGS)
example: main.o plugin_system.o
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
Note that Makefiles require intendation by tabs, not spaces; listing the file here always converts them to spaces. So, if you paste the above to a file, you'll need to fix the indentation, via e.g.
sed -e 's|^ *|\t|' -i Makefile
It is safe to run that more than once; the worst it can do, is mess up your "human-readable" layout.
Compile the above using e.g.
make
and run it via e.g.
./example ./plugin_bar.so ./plugin_foo.so
which shall output
Plugin 'bar' is here.
Plugin 'foo' is here.
All plugins loaded successfully.
to standard error.
Personally, I prefer to register my plugins via a structure, with a version number, and at least one function pointer (to the initialization function). This lets me load all plugins before initializing them, and resolve e.g. interplugin conflicts or dependencies. (In other words, I use a structure with a fixed name, rather than a function with a fixed name, to identify plugins.)
Now, as to __attribute__((used)). If you modify plugin_system.c into
#include <stdio.h>
void plugin_message(const char *msg) __attribute__((used));
void plugin_message(const char *msg)
{
fputs(msg, stderr);
}
and modify the Makefile to have LDFLAGS := -ldl only, the example program and plugins will compile just fine, but running it will yield
./plugin_bar.so: ./plugin_bar.so: undefined symbol: plugin_message.
In other words, if the API exported to plugins is compiled in a separate compilation unit, you will need to use either -rdynamic or -Wl,-dynamic-list,plugin-system.list to ensure the functions are included in the dynamic symbol table in the final executable; the used attribute does not suffice.
If you want all and only non-static functions and symbols in plugin_system.o included in dynamic symbol table in the final binary, you can e.g. modify the end of the Makefile into
example: main.o plugin_system.o
#rm -f plugin_system.list
./list_globals.sh plugin_system.o > plugin_system.list
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
with list_globals.sh:
#!/bin/sh
[ $# -ge 1 ] || exit 0
export LANG=C LC_ALL=C
IFS=:
IFS="$(printf '\t ')"
printf '{\n'
readelf -s "$#" | while read Num Value Size Type Bind Vis Ndx Name Dummy ; do
[ -n "$Name" ] || continue
if [ "$Bind:$Type" = "GLOBAL:FUNC" ]; then
printf ' %s;\n' "$Name"
elif [ "$Bind:$Type:$Ndx" = "GLOBAL:OBJECT:COM" ]; then
printf ' %s;\n' "$Name"
fi
done
printf '};\n'
Remember to make the script executable, chmod u+x list_globals.sh.

conditional compilation flags in make

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

How do I link object files in C? Fails with "Undefined symbols for architecture x86_64"

So I'm trying trying to use a function defined in another C (file1.c) file in my file (file2.c). I'm including the header of file1 (file1.h) in order to do this.
However, I keep getting the following error whenever I try to compile my file using gcc:
Undefined symbols for architecture x86_64:
"_init_filenames", referenced from:
_run_worker in cc8hoqCM.o
"_read_list", referenced from:
_run_worker in cc8hoqCM.o
ld: symbol(s) not found for architecture x86_64
I've been told I need to "link the object files together" in order to use the functions from file1 in file2, but I have no clue what that means :(
I assume you are using gcc, to simply link object files do:
$ gcc -o output file1.o file2.o
To get the object-files simply compile using
$ gcc -c file1.c
this yields file1.o and so on.
If you want to link your files to an executable do
$ gcc -o output file1.c file2.c
The existing answers already cover the "how", but I just wanted to elaborate on the "what" and "why" for others who might be wondering.
What a compiler (gcc) does: The term "compile" is a bit of an overloaded term because it is used at a high-level to mean "convert source code to a program", but more technically means to "convert source code to object code". A compiler like gcc actually performs two related, but arguably distinct functions to turn your source code into a program: compiling (as in the latter definition of turning source to object code) and linking (the process of combining the necessary object code files together into one complete executable).
The original error that you saw is technically a "linking error", and is thrown by "ld", the linker. Unlike (strict) compile-time errors, there is no reference to source code lines, as the linker is already in object space.
By default, when gcc is given source code as input, it attempts to compile each and then link them all together. As noted in the other responses, it's possible to use flags to instruct gcc to just compile first, then use the object files later to link in a separate step. This two-step process may seem unnecessary (and probably is for very small programs) but it is very important when managing a very large program, where compiling the entire project each time you make a small change would waste a considerable amount of time.
You could compile and link in one command:
gcc file1.c file2.c -o myprogram
And run with:
./myprogram
But to answer the question as asked, simply pass the object files to gcc:
gcc file1.o file2.o -o myprogram
Add foo1.c , foo2.c , foo3.c and makefile in one folder
the type make in bash
if you do not want to use the makefile, you can run the command
gcc -c foo1.c foo2.c foo3.c
then
gcc -o output foo1.o foo2.o foo3.o
foo1.c
#include <stdio.h>
#include <string.h>
void funk1();
void funk1() {
printf ("\nfunk1\n");
}
int main(void) {
char *arg2;
size_t nbytes = 100;
while ( 1 ) {
printf ("\nargv2 = %s\n" , arg2);
printf ("\n:> ");
getline (&arg2 , &nbytes , stdin);
if( strcmp (arg2 , "1\n") == 0 ) {
funk1 ();
} else if( strcmp (arg2 , "2\n") == 0 ) {
funk2 ();
} else if( strcmp (arg2 , "3\n") == 0 ) {
funk3 ();
} else if( strcmp (arg2 , "4\n") == 0 ) {
funk4 ();
} else {
funk5 ();
}
}
}
foo2.c
#include <stdio.h>
void funk2(){
printf("\nfunk2\n");
}
void funk3(){
printf("\nfunk3\n");
}
foo3.c
#include <stdio.h>
void funk4(){
printf("\nfunk4\n");
}
void funk5(){
printf("\nfunk5\n");
}
makefile
outputTest: foo1.o foo2.o foo3.o
gcc -o output foo1.o foo2.o foo3.o
make removeO
outputTest.o: foo1.c foo2.c foo3.c
gcc -c foo1.c foo2.c foo3.c
clean:
rm -f *.o output
removeO:
rm -f *.o
Since there's no mention of how to compile a .c file together with a bunch of .o files, and this comment asks for it:
where's the main.c in this answer? :/ if file1.c is the main, how do
you link it with other already compiled .o files? – Tom Brito Oct 12
'14 at 19:45
$ gcc main.c lib_obj1.o lib_obj2.o lib_objN.o -o x0rbin
Here, main.c is the C file with the main() function and the object files (*.o) are precompiled. GCC knows how to handle these together, and invokes the linker accordingly and results in a final executable, which in our case is x0rbin.
You will be able to use functions not defined in the main.c but using an extern reference to functions defined in the object files (*.o).
You can also link with .obj or other extensions if the object files have the correct format (such as COFF).

Resources