error on using libblkid - c

when i compile and link this code to get disk uuid:
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <blkid/blkid.h>
int main (int argc, char *argv[]) {
blkid_probe pr;
const char *uuid;
if (argc != 2) {
fprintf(stderr, "Usage: %s devname\n", argv[0]);
exit(1);
}
pr = blkid_new_probe_from_filename(argv[1]);
if (!pr) {
err(2, "Failed to open %s", argv[1]);
}
blkid_do_probe(pr);
blkid_probe_lookup_value(pr, "UUID", &uuid, NULL);
printf("UUID=%s\n", uuid);
blkid_free_probe(pr);
return 0;
}
it errors out:
/home/usr/blkid/blkid.c:15: undefined reference to `blkid_new_probe_from_filename'
make[2]: Leaving directory `/home/usr/blkid'
make[1]: Leaving directory `/home/usr/blkid'
/home/usr/blkid/blkid.c:20: undefined reference to `blkid_do_probe'
/home/usr/blkid/blkid.c:21: undefined reference to `blkid_probe_lookup_value'
/home/usr/blkid/blkid.c:25: undefined reference to `blkid_free_probe'
when i compile the code by the following command, the code compiles with no error
gcc -c -g -MMD -MP -MF build/Debug/GNU-Linux-x86/blkid.o.d -o build/Debug/GNU-Linux-x86/blkid.o blkid.c

Try to put -lblkid into your gcc command so the linker will know that you need to link your code to that library. Be sure to put this option at the end of the command. The order of options somehow matters. From here:
It makes a difference where in the command you write this option; the
linker searches and processes libraries and object files in the order
they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after
file foo.o but before bar.o. If bar.o refers to functions in ‘z’,
those functions may not be loaded.
This command should automatically both compile and link your source code:
gcc -o test -g -MMD -MP -MF build/Debug/GNU-Linux-x86/blkid.o.d blkid.c -lblkid

The error you show comes from the linker.
If you compile one single file to a .o file without linking, no external references will be tried to fulfill.
But if you want to compile into an executable, all needed requirements must be fulfilled. If the program requires the presence of a blkid_do_probe(), you should provide it somehow. Probably this will be done by linking with the appropriate library. As someone mentionned in a comment, this is to be done with -lblkid.

Related

Why is my code not throwing a duplicate symbol conflict

Why is my following code not throwing duplicate symbol conflict?
I referred to name mangling, but that seems only when there is difference in parameters. But, here there is not difference in parameters. But, still it does not throw conflict. Why?
good.c
#include <stdio.h>
void printGood() {
printf("I am good");
}
perfect.c
#include <stdio.h>
void printGood() {
printf("I am perfect");
}
A.c
extern void printGood();
void bringGood() {
printGood();
}
B.c
extern void printGood();
void bringPerfect() {
printGood();
}
orchestrator.c
#include <stdio.h>
void bringGood();
void bringPerfect();
int main() {
printf("bringing good");
bringGood();
printf("bringing perfect");
bringPerfect();
return 1;
}
compile line:
gcc -g -c good.c
gcc -g -c perfect.c
gcc -g -c A.c
gcc -g -c B.c
gcc -g -c orchestrator.c
ar rcs libA.a perfect.o A.o
ar rcs libB.a good.o B.o
gcc -o orchestrator orchestrator.o -L. -lA -lB
Why is my following code not throwing duplicate symbol conflict?
The linker looks for undefined symbols in the libraries in the order in which they are specified in the linker line. When it finds a symbol in a library, it uses that definition and stops. It does not check whether that symbol is defined in any of the other libraries specified in the linker line.
In your case, if the linker finds a symbol in A.lib, it stops there. It does not look for the symbol in B.lib.
With your commands, the linker will find function printGood() in object perfect.o in library A. It will not use the function of the same name in good.o from library B. So you effectively link orchestrator.o, A.o, B.o and perfect.o. That's why the executable program prints I am perfect twice and not I am good.
Multiple definition errors are reported only when the object files used in the linker line contain multiple definitions.
You will see the error if you use:
gcc -o orchestrator orchestrator.o a.o b.o perfect.o good.o

Undefined reference to `getaddrinfo_a'

I get linker error while compiling a minimal program that uses getaddrinfo_a on Linux. The program in question
#define _GNU_SOURCE
#include <stdio.h>
#include <netdb.h>
int main(int argc, char **argv) {
int err;
err = getaddrinfo_a(0, NULL, 0, NULL);
}
Compiler output:
$ cc -lanl minimal.c
/tmp/cc89BuFU.o: In function `main':
minimal.c:(.text+0x24): undefined reference to `getaddrinfo_a'
collect2: error: ld returned 1 exit status
$ cc --version
cc (Ubuntu 4.9.2-10ubuntu13) 4.9.2
You are using command in wrong way. Use
cc minimal.c -lanl
-lanl should come after not before file name.
gcc [options] [source files] [object files] [-Ldir] -llibname [-o outfile]
https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
-l  It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.
According to standard also, order of library matters. Linker didn't check for symbol from previously specified libraries. Ref
The library to link must be put after the object (and source files in your case):
$ cc minimal.c -lanl

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.

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).

What's wrong in creating/using a shared library with gcc here?

In libname.h:
int add_libname(int, int);
In libname.c:
#include "libname.h"
int add_libname(int a, int b)
{
return a+b;
}
I can build the shared library this way:
gcc -shared -fPIC libname.c -o libname.so
But I can't use it in another programe test.c:
#include <stdio.h>
#include "libname.h"
int main(int argc, char* argv[])
{
printf("%d\n", add_libname(1,5));
}
Reporting undefined reference to add_libname when I try to build it..
What's wrong here?
Because add_libname takes (int, int) you're giving it (1+5 = 6) or just (int)
I think you meant
add_libname(1, 5);
Also to compile it correctly you must use gcc like so
gcc -o myapp test.c -L. -lname
the lib part of libname is ignored as it is implicit
To create a shared library use these
gcc -fPIC -c libname.c
it gives warning: position independent code and libname.o file is generated.
and now type these command,
gcc -shared libname.so libname.o
libname.so ( the shared library is created with .so extension). To use the shared library
gcc -I/give the path of libname.h sourcefile.c /give the path of your .so file
example if your c file is file.c and the header file libname.h is in c:\folder1\project and your libname.so (shared library) is in c:\folder\project2
then
gcc -I/cygdrive/c/folder1/project file.c /cygdrive/c/folder/project/libname.so
this is the gcc command to be used while using the shared library.
Thank you.

Resources