April 27th, 2008 by admin
Today we have a special reader request from an anonymous reader (slightly edited):
Hello,
Can you help me with some link issue which i face?
I need to compile tree of c-sources which produce .so files and exe
files. I want to decrease the sizes of .so by throwing away unused symbols.
I can compile my tree statically and used as compiler flags –static -ffunction-sections -fdata-sections and link with –gc-sections option and it reduces all the unneeded symbols but I want to achieve the same effect in dynamic linking.
Do you know some efficient way to do it?
Thanks,
Anonymous Reader
So the question is: how to make a minimal set of dynamic libraries for a known set of executables that only contain the code for those symbols which the executables actually use, thus saving expensive storage?
The quite simple answer is that there exists a Python utility that does exactly what you want called mklibs - It produces cut-down shared libraries that contain only the routines required by a particular set of executables.
On Debian just go “sudo apt-get install mklibs”, or you can get the source straight from the Buildroot source repository here.
If you don’t like Python (you really should!) you can try an older, shell script based variation on the same theme found here.
Note that you can pass the cross compiler prefix with the “–target” option, which is of course needed for supporting cross compilation.
Hope you found it useful and if you have more questions about Linux development you’d like answered, just let us know.
The Codefidence team.
March 9th, 2008 by admin
Eclipse is an open source development platform comprised of extensible frameworks, tools and run times for building, deploying and managing software across the life cycle.
CDT is the name of the C/C++ development plug-in. It includes a graphical GDB front end.
The following slides are a short visual “how to” demonstrating configuring and using CDT to debug a remote target with GDB.
eclipse_debug.pdf
February 13th, 2008 by admin
Shared libraries, sometime also referred to as DSO (for Dynamic Shared Objects) or DLL (for Dynamically Loadable Modules), offer an easy way to pack together useful functions and data as a code library that can be easily reused, updated separately from all the application making use of it and most important - under certain conditions allows most the code and data of the library to only be loaded once to the machine RAM regardless of the number of applications using it.
A shared library is thus normally comprised of a set of global functions which may be called by applications (or other libraries) that link with the library.
Given the shared nature of shared libraries, it is often useful to provide a constructor for the code library which will run each time the library is loaded by an application. Doing this is very simple, using the GNU specific constructor attribute.
Here is a code example:
/* init_demo.c */
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
static void __attribute__ ((constructor)) \
lib_init(void);
static void lib_init(void) {
printf("Library ready. \n");
return;
}
Then build the the shared library using the following GNU Makefile:
.PHONY: clean
libinitdemo.so.1.0.0: init_demo.c
$(CC) -fPIC init_demo.c -shared \
-Wl,-soname,libinitdemo.so.1 -o \
libinitdemo.so.1.0.0
clean:
$(RM) -f libinitdemo.so.1.0.0
TIP
Combining a shared library constructor as shown above with use of LD_PRELOAD can be a powerful way to add construction code to existing programs without changing their source code and indeed, without requiring access to their source code at all.
December 11th, 2007 by admin
It can sometime be very useful to force an application to force to use a specific network interface for routing traffic, the regular routing tables not withstanding.
An example for such cases is where an embedded Linux system has a management network interface and a separate regular network interface where regular traffic should go:
So long as the two interfaces use two different IP addresses from non overlapping network it is very easy - simply bind the management application socket to the management IP and let the routing table do the rest.
What to do, however, if product definition calls for supporting two different and separate, default gateway settings for management and media traffic? Although we can assign multiple default gateway routing table entries, how to make sure the management applications use one and all other traffic use another?
This is where the SO_BINDTODEVICE socket option comes to our rescue. We will install two default gateway entries: a normal one for the media traffic and another one for the management traffic, for which we will define a high metric so it will normally will not be used.
Then, we will set the SO_BINDTODEVICE socket option on sockets opened in management application, thus forcing the Linux networking stack to disregard any routing table entries not going through the specific device, but only for those specific sockets.
It looks something like this:
#include <sys/socket.h>
#include <net/if.h>
struct ifreq interface;
struct socket sock;
/* Management net interface name */
#define IFNAME "eth3"
/* Acquire socket here ... */
strncpy(interface.ifr_ifrn.ifrn_name, IFNAME, \
IFNAMSIZ);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, \
(char *)&interface, sizeof(interface)) < 0) {
perror("SO_BINDTODEVICE failed");
/* Deal with error... */
}
But wait! this is all well and good when we have the management application source code. This however is not always the case. Fear not! this too can be dealt with by hijacking the socket library call:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#define __USE_GNU // Get RTLD_NEXT definition
#include <dlfcn.h>
/* Management interface */
#define IFNAME "eth3"
int socket(int domain, int type, int protocol) {
int (*origsock)(int domain, int type, int protocol);
char * error;
int sock;
origsock = dlsym(RTLD_NEXT, "socket");
if ((error = dlerror()) != NULL) {
fprintf (stderr, "%s\n", error);
exit(1);
}
sock = origsock(domain, type, protocol);
if(sock != -1) {
struct ifreq interface;
strncpy(interface.ifr_ifrn.ifrn_name, IFNAME, \
IFNAMSIZ);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, \
(char *)&interface, sizeof(interface)) < 0) {
perror("sendpacket: setting SO_BINDTODEVICE");
exit(1);
}
}
return sock;
}
Compile this small library with (or create a proper Makefile)
$ gcc sendto.c -fPIC -o sendto.so -ldl -shared
To use:
LD_PRELOAD=sendto.so ./management_app