How I can make alias on external defined function in C? - c

During compiling this C code
extern void Default_Handler(void);
void NMI_Handler(void) __attribute__ ((weak, alias ("Default_Handler")));
I've recive this
error: 'NMI_Handler' aliased to undefined symbol 'Default_Handler'
How I can make alias on external defined function?
Compiler:
gcc version 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204] (GNU Tools for Arm Embedded Processors 7-2017-q4-major)

To alias an external function, you can use objcopy. Here's an example:
Say I have the definition of a function and I alias it, like in the following program (called myimp.c):
// myimp.c
int
myadd(int x, int y)
{
return x+y;
}
int
coolguy (int x, int y) __attribute__((alias("myadd")));
If we compile this (but don't link) we get an object file and we can check out its symbols:
# compile
$ cc -c myimp.c
# look at the symbols
$ nm myimp.o
0000000000000000 T coolguy
0000000000000000 T myadd
So we can see that the __attribute__((alias("myadd")) is simply adding a symbol coolguy with the same value, 0000000000000000, as myadd. If you look in the man page for nm, it will say that T means it is a global symbol in the .text section. This makes sense because the function is not static and comprises instructions (as opposed to data).
So if we have the object file, but not the source, and we want to add a function alias we can do so using objcopy --add-symbol.
Say we have the object file resulting from compiling this source code:
// myimp2.c
int
myadd(int x, int y)
{
return x+y;
}
Compiling as above, we'll get myimp2.o, whose symbol table tools like this:
# look at the symbols
$ nm myimp2.o
0000000000000000 T myadd
So we want to add the coolguy symbol, which we do as follows
# objcopy --add-symbol coolguy=.text:0000000000000000,global myimp2.o myimp2_augmented.o
Look at the documentation on --add-symbol in the objcopy man page. Basically .text specifies the section, after the colon the value, and then global I found by passing a bad type and objcopy failed and told me a list of the valid types, from which I chose global.
Try running nm on myimp2_augmented.o, you'll see that we've added the symbol.
Now you should be able to link with myimp2_augmented.o instead of myimp.o and your program can call coolguy without linking errors.

As suggested here, add the following to your linker command file:
PROVIDE(NMI_Handler = Default_Handler);
(And remove the weak alias declaration from the C code.)

here NMI_Handler has a weak definition attribute means that if NMI_Handler is not defined then definition of Default_Handler will be used for NMI_Handler. generally there are strong definition available for interrupts like NMI_Handler or Default_Handler.you might need to add those file in your compilation to remove error.if you wants to handle NMI_Handler in your own way then you can define it somewhere and that definition will be included instead of weak one.

It's popular to employee weak and alias attribute to implement override mechanism for native C project especially in cases of firmware projects.
Both of declaration and definition can be noted by __attribute__((weak)) and its linking priority rules is related to if any declaration exists in a head file.
It would be good tactic that just to code and compile it. Then see what would happen when linking is look for its definition. I usually check symbols by -Wl,-trace,-trace-symbol=ANY_FUNCTION_NAME_YOU_WANT and nm OBJECT_FILE_NAME.
Usually I just create a weak attribute function definition and let other objects override it.
An example shown as below:
In C file:
//non-exported weak attribute definition
__attribute__((weak)) void startup_handler_dummy(void) {
printf("[%s][%s]Entry (NO OVERRIDE HANLDER COMES HERE)\n", __FILE__, __func__);
}
//weak and alias attribute declaration
void startup_handler_dummy_impl(void) __attribute__((weak, alias("startup_handler_dummy")));
//exported weak attribute definition
__attribute__((weak)) void startup_handler(void) {
startup_handler_dummy_impl();
}
In header file:
#ifndef _BOARD_H_
#define _BOARD_H_
#define STARTUP_HANDLER startup_handler //to export symbol
#endif
Hope my code can help :)
And you can see more details and program screen-shots on MyGitHub.

Related

C Code using Glib library building succesfully on windows gives compiler/linker error on linux

I have a code which makes use of Glib library to create a new type. Now the code is as:
.h file:
G_DECLARE_DERIVABLE_TYPE(NewTypeState, new_type_state, NEW, TYPE_STATE, ParentType)
.c file:
G_DEFINE_TYPE_WITH_PRIVATE(NewTypeState, new_type_state, NEW_TYPE_STATE)
now as per the glib doc for object creation we have to define two static functions as:
static new_type_init()
static new_type_class_init()
But in the code instead of defining static new_type_init() the func. is declared as:
__declspec(dllexport) extern void new_type_init()
and defined as:
void new_type_init()
{}
And the code compiles and links successfully on windows but while trying to build on linux I removed the __declspec(dllexport) but I started getting the error:
static declaration follows non-static declaration
Now I commented out the declaration from .h file and only has non-static definition in the .c file but when trying to build it I get the linker error:
undefined reference new_type_init
I even added the extern to definition but the error stays.
Could someone explain the above behavior?
EDIT:
o/p for objdump -t <file-name> | grep -i <symbol-name> is:
000000000000b440 l F .text 0000000000000023 symbol-name
0000000000000000 *UND* 0000000000000000 symbol-name
Extern indicates the function will be available later (i.e. is not defined here in this translation unit). Static forces the function to be unavailable externally. Add extern to the declaration in the header and remove static from the definition and you may have some success. That being said, I do not know Glib so cannot say for sure.

C library include

I write C library and I don't know how make some functions invisible for user (which are used to implement functionality). There is any way in C? And my second question is: when I include some library in .h or .c file (let's see math.h) is there any problem when user declare the same header in his program (which use my library of course)?
And how about structure? Is there any key word?
how to make some functions invisible ?
do not declare the function in the header file of your library
define the function as static in the source file of your library
Example:
your-lib.h
#ifndef YOUR_LIB_H
#define YOUR_LIB_H
void do_public_stuff(void);
#endif YOUR_LIB_H
your-lib.c
#include "your-lib.h"
// this functions is invisible
static void do_private_stuff(void)
{
// ...
}
// this functions is visible
void do_public_stuff(void)
{
// ...
}
user-code.c
#include "your-lib.h"
int main(void)
{
do_public_stuff();
return 0;
}
A usual way is to make implementation functions static that is to declare them with storage specifier static and place them in modules with code. So neither header will have references to these functions.
You can use the keyword static as the other answers suggested.
But sometimes, the library itself will consist of several source- and object-files, and there might be functions, which have to be used throughout the whole library, but shall not be exported after linking.
Simple example:
Your library has 3 objects: lib1.o lib2.o util.o
Located in util.o are several helper-functions, which are used by lib1.o and lib2.o. You cannot use static here, because the functions would not be visible to them and linking would fail.
What you can do:
Make the helper-functions non-static and provide the linker with a version script, which only exports the needed symbols:
gcc -shared lib1.o lib2.o util.o -o mylib.so -Wl,--version-script=map
The file map could have the following content:
{
global:
bar;
baz;
local: *;
};
This would only export the symbols bar and baz (which are the relevant API-functions for this sample lib), while omitting all other symbols from the symbol table.

How to compile the c code with the same variable name in different libraries (.a)

I build two libraries called templib1.a and templib2.a
And some global variables and function names in templib1.a and templib2.a are the same; when I try to compile my c code with these two libraries, it failed.
Is there any method except namespace for solving this problem? Do I need to re-build the libraries? Thanks.
=======================================================================
I build libraries as following
build templib1.a from aaa.c bbb.c ddd.c aaa.h; there is global variable int var_a, int var b; and functions void func_a(), void func_b() in aaa.c and bbb.c respectively
build templib2.a from aaa.c bbb.c eee.c aaa.h; there is global variable int var_a, int var b; and functions void func_a(), void func_b() in aaa.c and bbb.c respectively
And I my c code like
gcc $(INC) $(TEMPLIB1_DIR)/templib1.a $(TEMPLIB2_DIR)/temp2lib.a -o run
and it shows
"multiple definition of var_a
temp2lib.a : first defined here"
"multiple definition of var_b
temp2lib.a : first defined here"
Judging by the names of your libs, object files and variables, this is only a toy lib. When you write a real lib, you have to think about its design:
Under Unix, it is customary to name your lib libsomething.a. Your libs should therefore be called libtemp1.a and libtemp2.a, so that you can easily link them with -ltemp1 and -ltemp2.
If you export all symbols, you'll probably export too much and therefore clutter the namespace available for link symbols.
Think about which symbols you should export. The user of the lib needs to know which symbols she can use, so there's probably a header file accompanying the lib. This is the lib's interface. You need to export only the symbols in that interface. Start by making as many global variables and functions static, i.e. local to one compilation unit (object file). If you still export too many symbols, consider controlling your exports manually.
C doesn't have packages or namespaces. It is good practice to prefix all exported symbols with a short prefix, e.g. temp1_var_a, temp1_initi and so on.
Choose meaningful names for your symbols. A global variable shouldn't be called var_a. Use this rule of thumb: Small scope, short names. Big scope, longer names.
Don't be shy to rebuild your libs if you are their only user.
If your want your functions and variables accessible from outside your libs, rename them and include prefix.
If those functions and variables are for internal use only, use the static keyword:
What does "static" mean?

Undefined Variable error

I'm a newbie to programming in C, and I'm having trouble understanding the error that is coming up when I attempt to compile my program. I've got the following program, which is fairly simple and which my professor says is correct:
#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define BOOL int
extern int x;
extern BOOL do_exp;
int exp_or_log();
main()
{
x = 10;
do_exp = TRUE;
printf("2^%d = %d\n", x, exp_or_log()); //should print 1024
x = 145;
do_exp = FALSE;
printf("log(%d) = %d\n", x, exp_or_log()); //should print 7
}
But when I try to compile it, I get:
"_x", referenced from:
_x$non_lazy_ptr in ccWdLlxk.o
"_exp_or_log", referenced from:
_main in ccWdLlxk.o
_main in ccWdLlxk.o
"_do_exp", referenced from:
_do_exp$non_lazy_ptr in ccWdLlxk.o
ld: symbol(s) not found
I don't even have enough of an idea of what that means to know where to begin trying to figure out the problem. If anyone has a helpful explanation, or even just a general idea of what I should look at to begin problem shooting, I'd really appreciate it.
x, do_exp, and exp_or_log() are all defined in another file, I'm guessing supplied by your professor. You need to link together with that file. This is usually done by adding its filename along with yours on your compile line.
You've declared to the compiler that these variables and functions are available, but not necessarily defined in this particular source file:
extern int x;
extern BOOL do_exp;
int exp_or_log();
And they are not defined in that source file. However, the linker needs to be able to resolve those names, and the error message you're getting indicates that the linker can't find those names in any of its input files.
You need to wither provide the linker (ld) with a library that has these things, or you need a C file that defines them, and ahave that C file also compiled and linked in.
It's not the compiler that is complaining:
ld: symbol(s) not found
The linker (ld) cannot find the referenced symbols. You haven't provided their definitions.
First, note how you used the extern keyword on two variable definitions.
extern int x;
extern BOOL do_exp;
This means:
These variable are created elsewhere
(extern ally). You should be aware
that they exist, but they exist
somewhere else.
If these variable are intentionally declared in another file, you need to link compile that other file with yours, and link them together.
However, I suspect it is more likely that you just meant to declare them.
int x;
BOOL do_exp;
Report back on this, then we'll begin dealing with your function exp_or_log.
I'm guessing you're using a *nix machine from the output, so you would need to:
cc -c Anna_program.c
This should produce Anna_program.o. In your error the gibberish .o file was the same as this one, but was temporary, so was given a psudo-random name. The -c flag has the effect of only compiling the source file, and leaves off linking, which produces the executable, for later.
Then you can do:
cc Anna_program.o other_file.o -o Anna_program
And produce the executable Anna_program. If you aren't using a *nix style compiler then your sets will be different and you may need to put an extension on the end of the output file name in the last command.
You could do:
cc Anna_program.c other_file.o -o Anna_program
Which would combine the previous two steps.
What you should remember is that cc (or gcc) aren't actually the compiler, but a simple compilation manager. Under the hood they run other programs which do different steps in building your programs. By default cc will try to take what you give it and produce an executable (a.out), running as many of the steps as needed based on what you have given it. You can pass it flags, such as -c to tell it to only go part way (compiling and assembling, in this case).
The steps for C are Preprocessing (done by the program cpp), compiling (done by cc1), assembling (done by as), and linking (done by ld).
The cc or gcc command decides what needs to be done and then runs these other programs to do it.
You're having linker problems.
See the top of your code:
extern int x;
extern BOOL do_exp;
int exp_or_log();
Those three lines are like promises to the compiler. You're saying, trust me, when the time comes you'll be able to find an integer x, a BOOL do_exp, and a function exp_or_log();
The extern makes this promise for variables and the fact that the function doesn't have a body: {...} makes it for the function.
The linker is complaining because you're not following through on your promise. You need an implementation of exp_or_log(), and to have declared x and do_exp.
Is there more code? If you make another file, call is x.h, with the following content:
int x;
int do_exp;
int exp_or_log() {
return 6;
}
and then include this in your .c file:
#include "x.h"
You'll get some output. In this case it's nonsensical but it will compile while you fix the logic problems.
$ ./a.out
2^10 = 6
log(145) = 6

Weak-linking with static libraries

I have declared an external function with a GCC weak attribute in a .c file:
extern int weakFunction( ) __attribute__ ((weak));
Compiled object file has weakFunction defined as a weak symbol.
Output of nm:
1791: w weakFunction
I am calling the weak defined function as follows:
if (weakFunction != NULL)
{
weakFunction();
}
When I link the program by defining the object files as parameters to GCC (gcc main.o weakf.o -o main.exe) weak symbols work fine. If I leave the weakf.o out of linking, the function address is NULL in main.c and the function won't be called.
Problem is, when weakf.o is inside a static library, for some reason the linker doesn't find the function and the function address always ends up being NULL.
Static library is created with ar: ar rcs weaklibrary weakf.o
Anyone had similar problems?
While I don't know the exact workings of weak symbols it looks like you are getting what you ask for: if no one else is forcing the weakFunction() to be present, main() won't either. To me this makes sense: if you are trying to write code which works with facility X present as well as without it, then you don't want your code to force X to be included in your build at all costs. It looks like "weak" is meant to ask if something is present, not to request that something is present.
Maybe you can force inclusion of weak symbols with "-u weakFunction" as linker option in your case.

Resources