I want to be able to use a char *function_name = "foo" to call foo() from a C program. The foo() routine would be in a shared library. I don't have access to any dlopen, etc, just the load step for a regular executable. Is there any way to resolve this name and load it from the shared library?
No. You either use dlopen and dlsym, or you make your own array of function names and function pointers and look it up that way.
You can't do this unless you have access to the function names and load addresses. You can do this using LoadLibrary() and GetProcAddress() in Windows.
In your case, I don't know exactly what you have available (you didn't mention your platform, compiler, etc.) or if this is feasible. I strongly suspect, however, that it is not.
The common method to call functions by name is to use a table of names and function pointers. A caveat to this technique is that the functions must all have the same signature.
If you know the names functions but the function signatures differ, you will have to use and if-then-else ladder.
Related
The short version:
I'm trying to use a function in a shared library that hasn't been declared in a header file. Is it possible? If so, how?
The long version:
I'm trying to use GNU readline-7.0 as a shared library. Unfortunately it will echo input by default unless you turn it off with an api call. Sadly this api call wasn't declared in their header, because someone forgot. see details here Note: I can't update to a newer readline, so I'm stuck with this library. How do I use this undeclared function?
As noted in the linked bug, there is no external declaration in the header file even though the function exists in the implementation.
The link also shows the fix with the added declaration:
extern int rl_tty_set_echoing PARAMS((int));
So you can add this in your code right after #include <readline.h>
The sort answer is yes!!!
Just use the library -ldl with function dlopen(3), etc. This library allows you to load a shared object and search for identifiers that you know nothing about. Of course, the static typing nature of C forces to declare the interface of those functions with a prototype, so once you get a (void *) to the object you can cast it to something like int (*t)() and jump to it with a t(); call.
In the manual page you will get the details, dlopen allows you to search a shared object for symbols passed as strings. It returns pointers to the places those identifiers have been loaded in memory. You can even do this with your own program.
On the other hand, this is a feature of ELF shared loaded modules. If you are running a.out executables or otherwise, it is now waranteed that you'll have a dlopen(3) library for it, or that it will work that way.
If a library function like e.g. malloc is reimplemented, then there are two symbols with that name, one in a local object file and one in the system library. Which of the two is used when a function from e.g. stdio is used, which calls malloc (and why)?
The link behaviour is, in a general way:
Include all symbols defined in the object files.
Then resolve the undefined ones using the objects in the libs.
So, if malloc is reimplemented and linked as object file, the version in the object file will override the version in the standard libraries. However, if the new malloc is linked as a library, it depends on the libraries linking order.
Another way, considering the gnu binutils as scope, to override library functions is to wrap the function using the --wrap parameter: https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html
By using the --wrap ld option we can get both functions linked and the wrapper function would be able to call the wrapped one.
The linking order also depends on the command line parameters order. So I'm considering here that libs are listed after objects because, in general, doesn't make sense to put libraries before objects as their objective is to supply the missing symbols demanded by those.
One answer is that you are getting yourself in an awful lot of trouble by trying to replace malloc. Don't go there. Don't even think about it. Especially if you need to ask questions on stackoverflow, don't even think about it.
Another answer is that you are invoking undefined behaviour, and the likely result is that the malloc function will be called that will hurt you most. If you are lucky, while developing. If you are less lucky, once your code is in the hand of customers. Don't do it.
Writing wrappers around malloc with new names is bad enough. Trying to replace malloc is madness.
I want to code some libc functions myself (but not all libc!) for increasing performance in my programs . but does GCC use them instead of libc functions in the compiled program or ignores them?
Pretty much all the public symbols in glibc are weak linked, which means you can provide your own implementation which will take precedence over the weak symbols during linking.
So, yes. You can just define your own functions with the same name/arguments and they will get used instead. Be sure to look in the header files to see the real signature of a function, some functions may be a macro expanding to another function.
You can also create a shared library that contains the functions you want to override, and have the dynamic linker pre-load it to override functions in shared libraries. See this question for more information.
I am trying to write a generic library in pure c , just some data structures like stack, queue...
In my stack.h when giving name to those functions. I have questions about that.
Can I use such name, for example "init" as the function name to init a stack. Will there be something wrong?
I know maybe there exist other functions which just do other things and have the same name as "init". Then would the program be confused, especially when i both include the different init's headers.
3.I know my worry may be unnecessary, but i still want to know the principle.
Any help is appreciated, thanks.
Can I use such name, for example "init" as the function name to init a
stack. Will there be something wrong?
Yes, if anyone else wants a function named init.
I know my worry may be unnecessary, but i still want to know the
principle
Your worry is necessary, this (the lack of namespaces) is a serious problem in C.
Export as few functions as possible. Make everything static if you can
Prefix function names with something. For instance, instead of init, try stack_init
You don't have namespaces in C so usually you prefix every identifier with the name or nickname of your library.
init();
becomes
fancy_lib_init();
There might be existing libraries doing what you want (e.g. Glib). At least, study them a little before writing your own.
If you claim to develop a generic reusable C library, I suggest having naming conventions. For instance, have all the identifiers (notably function names, typedef-s, struct names...) share some common prefix.
Be systematic in your naming conventions. For instance, initializers for stacks and for queues should have similar names & signatures, and end with _init. Document your naming conventions.
Define very clearly how should data be allocated and released. Who and when should call free?
init() might be okay (if you're including your library into something else as an actual library, rather than compiling its source in), but it's better practice to use something like stack_init(), and to prefix your library's functions with stack_ or queue_, etc.
A program using your library may get confused, depending on the order the libraries are included, see #1.
As far as the principles go, the linker (on Linux, anyway) will look for symbols, and there's an ordering to how those symbols will be found. For more information, you can check out the man page for dlsym(), and specifically for RTLD_NEXT.
Function names in C are global. If two functions in a program have the same name, the program should fail to compile. (Well, sometimes it fails at link time, but the idea still holds.)
Generally, you get around this problem by using some sort of prefix or suffix on the function names in your library. "apporc_stack_init()" is much less likely to collide with something than "init()" is.
I have written a custom library which implements malloc/calloc/realloc/free using the standard C prototypes, and I figured out how to compile it to an so. I want to test the library by linking a standard application against it? What would be a good way to do this? Once I have a working library I assume I can just load it with LD_PRELOAD, but how do I get my functions to co-exist with but take precedence over the system library ones? My functions need to make a call to malloc in order to get memory to run, so I can't just completely ditch stdlib... Help?
Functions that you are trying to replace are standard C functions, not macros, not system calls. So you have to simply give your functions the same names and compile them into a shared library.
Then, use LD_PRELOAD to pre-load your library before binary starts. Since all addresses are resolved once, linker will figure out addresses of your functions and remember their names and will not look for them in standard library later.
This approach might not work if your program is linked with the standard runtime statically. Also, it will not work on Mac OS X as there is another API for interpolation.
In Linux, for example, in order for your functions to co-exist (i.e. if you want to use system malloc in your own implementation of malloc), you have to open the standard library manually using dlopen, look up functions you need there using dlsym and call them later by address.
Don't write your malloc() in terms of malloc() -- write it using sbrk, which gets memory directly from the OS.
If you have control of the source code that is to use this library, here is one possibility. Use different function names: Rather than malloc, for example, call it newCoolMalloc. This method is sometimes simpler and doesn't depend on special linker options.
Then in your code, use #define to cause the code to call the desired set of functions. You can #define malloc to be something different. For example:
#define malloc newCoolMalloc
#define free newCoolFree
If you do that, though, you have to be very very careful to include that consistently. Otherwise you run the risk of using stdlib malloc in one place and then your own free in another leading to messy bugs. One way to help mitigate that situation is to (if possible) in your own code use custom names for the allocation and free functions. Then it is easier to ensure that the correct one is being called. You can define the various custom names to your own malloc functions or even the original stdlib malloc functions.
For example, you might use mallocPlaceHolder as the actual name in the code:
someThing = mallocPlaceHolder( nbytes );
Then your defines would look more like this:
#define mallocPlaceHolder myCoolMalloc
If no function of the form mallocPlaceHolder (and associated free) actually exist, it avoids mixing different libraries.