Glibc link difference causing segmentation fault - c

Something about the server I build on is broken (I am not the only one who uses it...). It is SLES 11 (no SP). I have tried uninstalling and reinstalling gcc, glibc etc with no success.
The problem is my built program seg-faults as soon as it hits a library function such as memset or strlen (note it is the calling of this function and not the function itself, the parameters are fine). I think it is definitely linking wrong and I can prove it is different to how it was with readelf. eg:
# readelf -s myprog | grep memset
247: 081461d0 52 <OS specific>: 10 GLOBAL DEFAULT 27 memset#GLIBC_2.0 (3)
3530: 081461d0 52 <OS specific>: 10 GLOBAL DEFAULT 27 memset##GLIBC_2.0
vs a previous working version that says:
69: 00000000 0 FUNC GLOBAL DEFAULT UND memset#GLIBC_2.0 (2)
2035: 00000000 0 FUNC GLOBAL DEFAULT UND memset##GLIBC_2.0
Its a fairly standard makefile and nothing has changed. The linker flags are:
LDFLAGS = -L$(companylibrarypath) -lourcompanylibrary -L$(mysql_lib_path) -lmysqlclient -L/usr/tls/ -lpthread -pthread -lz -L$(curl_lib_path) -lcurl -lxslt

Your programs by some bad way redefines functions like memset (instead of using the std library provided versions). It is likely caused by some headers, which may be "standard"... Also may be your compiler (gcc?) by some way generates (elf) code not for your platform...
Also you say the link process is failing, did you mean the linker is failing and cannot produce an executable?

The functions you say fail (memset, printf) are extensively used, if your glibc was really that broken you wouldn't ever reach a shell when booting. And definitely you would't be able to compile anything. I'd first look at the libraries it is picking up via the -L... flags. Check if a LD_PRELOAD=... snuck in somehow. See what ldd and nm tell you. Perhaps a strace myprog 2> /tmp/log or running it under a debugger clear up the mistery...

Related

Re-export Shared Library Symbols from Other Library (OS X / POSIX)

My question is fairly OS X on x86-64 specific but a universal solution that works on other POSIX OSes is even more appreciated.
Given a list of symbol names of some shared library (called original library in the following) and I want my shared library to re-export these symbols. Re-export as in if someone tries to resolve the symbol against my library I either provide my version of this symbol or (if my library doesn't have this symbol) forward to the original library's symbol.
I don't know the types of the symbols, I only know whether they are functions (type T in nm output) or other symbols (type S in nm output).
For functions, I already have a solution: For every function I want to re-export I generate an assembly stub that does dynamically resolve the symbol (using dlsym()) and then jumps into the resolved function with the very same environment (registers rdi, rsi, rdx, rcx, r8, r9, stack pointer, ...). I'm basically generating universal proxy functions. Using some macro trickery that can be generated fairly easy without writing code for each and every symbol.
For non-function symbols the problem seems to be harder because I cannot generate this universal proxy function, because the resolving party does never call a function.
Using a constructor function static void init(void) __attribute__((constructor)); I can execute code whenever someone loads my library, that would be a good point to resolve and re-export all non-function symbols if that's possible.
In other words, I'd like to write the symbol table of my library to point to the respective symbols of another shared library. Doing the rewriting at compile or run time is okay (run time preferred). Or put yet another way, the behaviour of DYLD_INSERT_LIBRARIES (LD_PRELOAD) is exactly what I need but I don't want to insert a new library, I want to replace one (in the file system). EDIT: The reason I don't want/can't use DYLD_INSERT_LIBRARIES or any other environment variable of the DYLD_* family is that they are ignored for code signed, restricted, ... binaries.
I'm aware of the -reexport-l, -reexport_library and -reexported_symbols_list linker flags but I could not get them to work, especially when my library is a "replacement" for frameworks that are part of umbrella frameworks (example: /System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/SearchKit) because ld forbids to link directly against parts of umbrella frameworks.
EDIT: Because I explained it somewhat ambiguously: I can't change the way the actual program is linked. The goal is to produce a shared library that is a replacement for the original library. (Apparently called filter library.)
Found it out now (OS X specific): clang -o replacement-lib.dylib ... -Xlinker -reexport_library PATH_TO_ORIGINAL_LIB does the trick. PATH_TO_ORIGINAL_LIB could for example be /System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/Versions/Current/SearchKit.
If PATH_TO_ORIGINAL_LIB is a library that is part of an umbrella framework (as in the example above), then replace PATH_TO_ORIGINAL_LIB by the path of some other lib (I created a lib empty.dylib for that) and as a second step do
install_name_tool -change /usr/local/lib/empty.dylib PATH_TO_ORIGINAL_LIB replacement-lib.dylib
To see if the actual reexporting worked use:
otool -l replacement-lib.dylib | grep -A2 LC_REEXPORT_DYLIB
The output should look like
cmd LC_REEXPORT_DYLIB
cmdsize XX
name empty.dylib (offset YY)
After launching the install_name_tool it could be
cmd LC_REEXPORT_DYLIB
cmdsize XX
name /System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/Versions/Current/SearchKit (offset YY)
You could link against both libraries and use the link order to make sure to link against the right symbols. This works on both OS X and Linux:
cc -o executable -lmylib -loriglib
Where origlib is the original library and mylib contains symbols that are supposed to overwrite symbols in origlib. Then the executable will be linked against your symbols from mylib first and all unresolved symbols will be linked against origlib.
This works in the same way when linking against OS X frameworks. Just link against your library that replaces symbols first and against the framework after.
cc -o executable -lmylib -framework SomeFramework
Edit: If you just want to replace symbols at runtime then you can use LD_PRELOAD in the same way:
cc -o executable -framework SomeFramework
LD_PRELOAD=libmylib.dylib ./executable

Can I modify the dynamic linker and use without recompiling the glibc?

I am trying to modify the dynamic linker provided in the libc6(2.15-0ubuntu20.2) on a 64 bit Ubuntu machine.
So currently my code is using the same version of the glibc library. (I have downloaded the source code for the same and working on it). My question is that is it possible to modify and build only the linker source code which is present in glibc\elf\ directory without building the entire glibc library.
And if it is possible how can I make my test program to switch using the new version of dynamic linker that I have build myself instead of using the default unmodified linker.
Any pointers or suggestions are highly appreciated.
(If any more information is needed please let me know)
EDIT::
#constantius
I followed the steps in the post linked by you to build ld.so.
But I am getting following error on the make and I checked ld.so is not there in the elf.
The error is::
/var/services/homes/abhi/test/ld/eglibc-build/elf/librtld.os: In function `generic_getcwd':
/var/services/homes/abhi/test/ld/eglibc-2.15/elf/../sysdeps/posix/getcwd.c:356: undefined reference to `__closedir'
/var/services/homes/abhi/test/ld/eglibc-2.15/elf/../sysdeps/posix/getcwd.c:368: undefined reference to `__fdopendir'
/var/services/homes/abhi/test/ld/eglibc-2.15/elf/../sysdeps/posix/getcwd.c:384: undefined reference to `__readdir'
/var/services/homes/abhi/test/ld/eglibc-2.15/elf/../sysdeps/posix/getcwd.c:397: undefined reference to `rewinddir'
/var/services/homes/abhi/test/ld/eglibc-2.15/elf/../sysdeps/posix/getcwd.c:528: undefined reference to `__closedir'
/var/services/homes/abhi/test/ld/eglibc-2.15/elf/../sysdeps/posix/getcwd.c:490: undefined reference to `__closedir'
collect2: error: ld returned 1 exit status
make[2]: *** [/var/services/homes/abhi/test/ld/eglibc-build/elf/ld.so] Error 1
make[2]: Leaving directory `/var/services/homes/abhi/test/ld/eglibc-2.15/elf'
make[1]: *** [elf/subdir_lib] Error 2
make[1]: Leaving directory `/var/services/homes/abhi/test/ld/eglibc-2.15'
make: *** [all] Error 2
NOTE With the same infrastructure I can build and install the full GLIBC so I dont think there is an error with the infrastructure.
-- I guess the error is some where related to editing Makeconfig to all-subdirs = csu elf gmon io misc posix setjmp signal stdlib string time.
--Any suggestions on this..
SOLVED
Need to add dirent in the all-subdirs list in addition to what we edited before
Thanks
Citing this page. In case you don't get something, comment please — I'll try to explain.
Building
To compile Glibc (ld.so cannot be compiled independently) download and unpack Glibc source tarball.
1 Make sure the version of Glibc you downloaded is the same as the system's current one.
2 Make sure the environmental variable LD_RUN_PATH is not set.
3 Read the INSTALL and make sure all necessary tool chains (Make, Binutils, etc) are up-to-date.
4 Make sure the file system you are doing the compilation is case sensitive, or you will see weird errors like
/scratch/elf/librtld.os: In function `process_envvars':
/tmp/glibc-2.x.y/elf/rtld.c:2718: undefined reference to `__open'
...
5 ld.so should be compiled with the optimization flag on (-O2 is the default). Failing to do so will end up with weird errors (see Question 1.23 in FAQ)
6 Suppose Glibc is unpacked at
/tmp/glibc-2.x.y/
Then edit /tmp/glibc-2.x.y/Makefile.in: Un-comment the line
# PARALLELMFLAGS = -j 4
and change 4 to an appropriate number.
7 Since we are only interested in ld.so and not the whole Glibc, we only want to build the essential source files needed by ld.so. To do so, edit /tmp/glibc-2.x.y/Makeconfig: Find the line started with
all-subdirs = csu assert ctype locale intl catgets math setjmp signal \
...
and change it to
all-subdirs = csu elf gmon io misc posix setjmp signal stdlib string time
8 Find a scratch directory, say /scratch. Then
$ cd /scratch
$ /tmp/glibc-2.x.y/configure --prefix=/scratch --disable-profile
$ gmake
Since we are not building the entire Glibc, when the gmake stops (probably with some errors), check if /scratch/elf/ld.so exists or not.
ld.so is a static binary, which means it has its own implementation of standard C routines (e.g. memcpy, strcmp, etc) It has its own printf-like routine called _dl_debug_printf.
Testing
You can run the ld-linux.so directly. It will complain that this is probably not what you want (but you want exactly this) and offer you list of options with which you can run it. See also man ld-linux.so for debugging flags, i.e. there's LD_DEBUG environment variable you can define to see ld-linux.so debugging output.
While I'm not clear on whether the build system for glibc makes doing this easy, there's no fundamental reason why you can't build and use the glibc dynamic linker without building libc.so. I would peruse the top-level Makefile for ways to make this work.
As for testing it, there are two methods:
Explicitly invoke the dynamic linker to run a program, as in:
./ld-linux.so.2 a.out args ...
When linking your program, specify an alternate dynamic linker pathname (which will get stored in its PT_INTERP program header) by passing this option to the compiler driver:
-Wl,-dynamic-linker,/path/to/alternate/ld-linux.so.2

gsoap client compile/link error

Now I am writing a program to call a web service. I write testMain.c. The others are generated by wsdl2h and soapcpp2.
My compiling command is like this:
gcc -Wall -g -c -L. soapC.c soapClient.c stdsoap2.c testMain.c
gcc -o testMain -L/usr/lib -lgsoap -lgsoapck -lgsoapssl soapC.o soapClient.o stdsoap2.o testMain.o
And I get these errors. Please help me.
stdsoap2.o: In function `soap_print_fault':
/test/stdsoap2.c:16279: undefined reference to `soap_check_faultsubcode'
/test/stdsoap2.c:16281: undefined reference to `soap_check_faultdetail'
stdsoap2.o: In function `soap_sprint_fault':
/test/stdsoap2.c:16341: undefined reference to `soap_check_faultdetail'
collect2: ld returned 1 exit status
Recent versions of GCC/ld/the GNU toolchain require that the object and library files be specified in a certain order, so that symbols can be found by the linker in the same order they depend on each other. This means that libraries should go to the end of the command line; your second line (when you're linking) should be
gcc -o testMain -L/usr/lib soapC.o soapClient.o stdsoap2.o testMain.o -lgsoap -lgsoapck -lgsoapssl
instead.
I search the web, and found a post which is very similar with my problem. I use this solution and have solved the problem. http://www.mail-archive.com/gsoap#yahoogroups.com/msg01022.html
You should not need to link stdsoap2.o to your project because it's already included in libgsoap (given through the gcc linker option -lgsoap). Try to exclude stdsoap2.c from your project. From the gSOAP FAQ:
I get a link error with gcc/g++ (GNU GCC). What should I do? For C
apps: use soapcpp2 option -c to generate C code, use only the
package's .c files, link with libgsoap.a (-lgsoap) or use the lib's
source stdsoap2.c (and dom.c when applicable).
I had the same problem with gsoap-2.8.16 compiled from source. (That version was shipped with CentOS 6.)
First I checked for a missing library. According to nm used on all static libraries provided by gsoap-2.8.16:
for X in /usr/local/lib/libgsoap*.a ; do echo $X; nm $X | grep soap_check_faultdetail; done`
it turned out that none of the libraries provided the missing symbols.
A brief look at the source code revealed that the expected return type of both methods soap_check_faultdetail and soap_check_faultsubcode was const char*, and that these were used to generate error messages.
It looked to me as if these are meant to be callbacks that the client must provide. Maybe their implementation is WSDL-dependent and would be supplied by the gsoap code generation utilities - that I don't know, see the answer from #ChristianAmmer above or below.
Anyway, since I knew the symbols were nowhere supplied, and that null-terminated strings were probably acceptable here, I just supplied my own no-op implementation:
// gsoap-missing-symbols.cpp
extern "C" {
const char* soap_check_faultdetail() { return 0; }
const char* soap_check_faultsubcode() { return 0; }
}
This is a brute-force solution. If you follow this solution, you should maybe check for linker warnings in the future; maybe some mechanism (eg. from the gsoap code generator) will supply conflicting implementations later during development.
For later versions of gsoap, I believe these symbols are no longer used and can be dropped (or renamed), see soap_check_faultX in https://www.genivia.com/changelog.html.

how do I always include symbols from a static library?

Suppose I have a static library libx.a. How to I make some symbols (not all) from this library to be always present in any binary I link with my library? Reason is that I need these symbols to be available via dlopen+dlsym. I'm aware of --whole-archive linker switch, but it forces all object files from library archive to linked into resulting binary, and that is not what I want...
Observations so far (CentOS 5.4, 32bit) (upd: this paragraph is wrong; I could not reproduce this behaviour)
ld main.o libx.a
will happily strip all non-referenced symbols, while
ld main.o -L. -lx
will link whole library in. I guess this depends on version of binutils used, however, and newer linkers will be able to cherry-pick individual objects from a static library.
Another question is how can I achieve the same effect under Windows?
Thanks in advance. Any hints will be greatly appreciated.
Imagine you have a project which consists of the following three C files in the same folder;
// ---- jam.h
int jam_badger(int);
// ---- jam.c
#include "jam.h"
int jam_badger(int a)
{
return a + 1;
}
// ---- main.c
#include "jam.h"
int main()
{
return jam_badger(2);
}
And you build it with a boost-build bjam file like this;
lib jam : jam.c <link>static ;
lib jam_badger : jam ;
exe demo : jam_badger main.c ;
You will get an error like this.
undefined reference to `jam_badger'
(I have used bjam here because the file is easier to read, but you could use anything you want)
Removing the 'static' produces a working binary, as does adding static to the other library, or just using the one library (rather than the silly wrapping on inside the other)
The reason this happens is because ld is clever enough to only select the parts of the archive which are actually used, which in this case is none of them.
The solution is to surround the static archives with -Wl,--whole-archive and -Wl,--no-whole-archive, like so;
g++ -o "libjam_candle_badger.so" -Wl,--whole-archive libjam_badger.a Wl,--no-whole-archive
Not quite sure how to get boost-build to do this for you, but you get the idea.
First things first: ld main.o libx.a does not build a valid executable. In general, you should never use ld to link anything directly; always use proper compiler driver (gcc in this case) instead.
Also, "ld main.o libx.a" and "ld main.o -L. -lx" should be exactly equivalent. I am very doubtful you actually got different results from these two commands.
Now to answer your question: if you want foo, bar and baz to be exported from your a.out, do this:
gcc -Wl,-u,foo,-u,bar,-u,baz main.o -L. -lx -rdynamic
Update:
your statement: "symbols I want to include are used by library internally only" doesn't make much sense: if the symbols are internal to the library, why do you want to export them? And if something else uses them (via dlsym), then they are not internal to the library -- they are part of the library public API.
You should clarify your question and explain what you really are trying to achieve. Providing sample code will not hurt either.
I would start with splitting off those symbols you always need into a seperate library, retaining only the optional ones in libx.a.
Take an address of the symbol you need to include.
If gcc's optimiser anyway eliminates it, do something with this address - should be enough.

Is there a way to know which compiler generated a static library?

A third party provided me a static lib (.a) to link with on solaris station.
I tried to compile with sunpro, and failed at link step.
I suppose the issue is coming from the compiler I use (gcc instead?) or simply its version (as the std lib provided by the compiler could change from the version expected by the library AFAIK it could leads to errors at link step).
How could I know which compiler was used to generate this lib? Is there some tools doing that? Some option in sunpro/gcc or whatever?
As an hint: I've read some time ago that compilers use different mangling conventions when generating object files (true?). Still, "nm --demangle" command line prints me well all function names from debug symbols in this static lib. How does it work ? If my assumption is ok, nm does have a way to resolve which convention is in use in a static library, isn't it? Or is it simply meaning that lib was generated by GNU gcc, as nm is a part of GNU binutils?
I am not close to my workstation so I can't copy & paste error output from the linker (not for the moment but I could copy them in a further edit)
Extract the object files from the archive then run the strings command on some of them (first on the smaller ones since there'd be less noise to sift through). Many compilers insert ASCII signatures in the object files.
For example, the following meaningless source file, foo.c:
extern void blah();
when compiled on my Fedora 10 machine into foo.o via gcc -c -o foo.o foo.c results in a 647 byte foo.o object file. Running strings on foo.o results in
GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)
.symtab
.strtab
.shstrtab
.text
.data
.bss
.comment
.note.GNU-stack
foo.c
which makes it clear the compiler was GCC. Even if I'd compiled it with -fno-ident, the .GNU-stack note ELF section would have still been present.
You can extract the object files using the ar utility, or using Midnight Commander (which integrates ar), or you can simply run strings on the archive (which might give you more noise and be less relevant, but would still help.)
I tend to use the strings program (with the '-a' option, or my own variant where the '-a' behaviour is standard) and look for the tell-tale signs. For example, in one of my own libraries, I find:
/work1/gcc/v4.2.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.2.3/include
/work1/gcc/v4.3.0/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.0/include
/work1/gcc/v4.3.1/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.1/include
/work1/gcc/v4.3.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.3/include
That suggests that the code in the library has been compiled with a variety of versions of GCC over a period of years (actually, I'm quite startled to find so many versions in a single library).
Another library contains:
cg: Sun Compiler Common 11 Patch 120760-06 2006/05/26
acomp: Sun C 5.8 Patch 121015-02 2006/03/29
iropt: Sun Compiler Common 11 Patch 120760-06 2006/05/26
/compilers/v11/SUNWspro/prod/bin/cc -O -v -Xa -xarch=v9 ...
So, there are usually fingerprints in the object files indicating which compiler was used. But you have to know how to look for them.
Is the library supposed to be a C or C++ library?
If it is a C library then name mangling can not be the problem, as there is none in C. It could be however in a wrong format. Unices used to have libraries in the a.out format but almost all newer versions switched to more powerful formats like ELF.
If it is a C++ library then name mangling can be an issue. Most compilers embed some symbols that are compiler specific into the code, so if you have a tool like nm to list the symbols you can hopefully deduce from what compiler it came.
For example g++ creates a symbol
__gxx_personality_v0
in it's libraries
You can try the unix utility file:
file foo.a

Resources