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

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

Related

Removing symbols from `.a`s

I'm compiling a C++ static library using g++ via Cmake. I want to remove symbols relating to the internal implementation so they don't show up in nm. (See here and here for the same with shared libraries.)
This answer tells you how to do it on iOS, and I'm trying to understand what happens under the hood so I can replicate on Linux. They invoke ld with:
-r/--relocatable to Generate relocatable output---i.e., generate an output file that can in turn serve as input to ld.
-x/--discard-all: Delete all local symbols.
AFAICS the -r glues all the modules into one module, and then the -x removes symbols only used inside that module. Is that right?
It's not clear how the linker 'knows' which symbols will be exported externally? Does it rely on __attribute__((visibility("hidden/default"))) as in the .so case?
Edit: clearly I'm confused... I thought cmake invoked ld to link the .os into .a. Googled + clarified above.
Question still stands: how do I modify the build process to exclude most symbols?

NASM: How to resolve these unresolved externals?

I'm trying to get started learning basic assembly with Paul A. Carter's book "PC Assembly Language." However I'm unable to run the first example Carter provides, so I'm kind of stuck until I figure this out.
I assembled the example "first.asm" without any problem, but I can't figure out how to link these files: first.obj, driver.c, asm_io.obj into an executable. In the comment section of first.asm Carter gives these instructions for creating an executable (I'm using Windows 10, VS community 2015 developer command prompt):
; Using MS C/C++
; nasm -f win32 first.asm
; cl first.obj driver.c asm_io.obj
I'm doing exactly that but I'm getting a fatal error 2 unresolved externals, _printf and _scanf. I have every necessary file that I can think of in the same directory, and I'm compiling in that directory.
Driver.c calls the function defined in and it uses a header file called "CDECL.h"; I have this file in my directory, but I don't understand much about this header file. I wonder if the problem is here. I haven't altered it or anything. I assembled asm_io.asm according to Dr. Carter's instructions.
Not too far into asm_io.asm is see this:
extern _scanf, _printf, _getchar, _putchar, _fputs
So here are the unresolved externals. Shouldn't they be defined in stdio.h? Driver.c includes stdio.h, shouldn't the linker be able to resolve these symbols be looking at stdio.h? What might I be missing?
ps. I'm new to programming in general, and this is my first stack overflow question. I'm open to any and all criticism/feedback. I'll provide more information if you need it, I just didn't want to post a massive wall of text and code if not necessary.
Welcome to SO. You need to understand:-
The difference between a header file, e.g.
foo.h // C or maybe C++ header file)
and a library, e.g.
foo.lib foo.dll // Windows
libfoo.a, libfoo.so // Unix/Linux
that implements the calling interface that is (merely) described in a header file.
The difference between compiling or assembling a source file, e.g.
bar.c // C source file
bar.asm // Assembly source, Windows
bar.s // Assembly source, Unix/Linux
to make an object file. e.g.
bar.obj // Windows
bar.o // Unix/Linux
and linking object files and libraries together make a complete executable.
Linking can succeed only if the linker is supplied with (or knows by default)
the names and locations of object files and/or libraries that provide
implementations of all the functions that are called in the program - including
functions whose calling interfaces are described in header files. Otherwise
unresolved symbol errors ensue.
Research these points and you'll quickly get yourself unstuck. See this
pretty good introductory tutorial, which although it is about getting
started with the GNU Compiler Collection rather
than with assembly language programming, will clarify the principles
and distinctions you need to grasp.

arm toolchain does not seem to have C libraries

I am trying to cross compile a simple program with the arm toolchain. And stdio library points to another library, which results in the following error:
/home/sansari/tools/arm-eabi-4.7/bin/arm-eabi-gcc hello.c -o hello
In file included from hello.c:3:0:
/home/sansari/tools/arm-eabi-4.7/bin/../lib/gcc/arm-eabi/4.7/include-fixed/stdio.h:50:23: fatal error: sys/cdefs.h: No such file or directory
compilation terminated.
make: *** [hello] Error 1
At first, I thought this file is in some subdirectory of the toolchain, and I need to include the folder for this library in my makefile. But a quick tree output says that it is not. So given that I have used this toolchain successfully for a larger project, I know it is copied from somewhere. So my question is how do I add it to this project please? And what is the appropriate place to copy it from? I am trying to understand why it is not in the toolchain folders that I have, and how I should add it to my project please.
#Olaf - You have been very helpful; I however have a little more learning curve. But I do understand what you are instructing. I know I have the libraries in my build system since have built for this platform successfully. I even know that it is in my WORKING_DIRECTORY. What I do not know is if I can copy a folder and address the issue entirely or do I need to keep compiling and see what errors I get. That is do it incrementally. For example, one of the files, which was missing was cdefs.h. And I was able to find it in the folder:
/home/sansari/ndk/android-ndk-r10d/platforms/android-19/arch-arm/usr/include/sys/cdefs_elf.h
So I copied it over and the build process proceeded to the next stage. I do like to know if I should perhaps have copied the entire /sys or /include directory or compared the /include directory of my source and make sure all the files are also in the destination directory also. And that way I can avoid having to compile a number of times.
But nevertheless, I proceeded with copying one file at a time. The last error I got is:
/home/sansari/tbt/tools/arm-eabi-4.7/bin/../lib/gcc/arm-eabi/4.7/include/stdint.h:3:26: fatal error: stdint.h: No such file or directory
And I look in the include directory; I see a file call stdint.h
What do you make of that? Does that make sense to you? I am confused by this error. How can I get this error when the file is in the directory. Basically it seems make is saying this file does not exist when it does.
I did find This post also, which seems to say what you are saying. I just need to know what is the best way to address it.
#Olaf - I really appreciate all your help. I was able to get through all the library errors by putting an include statement in my makefile. Now the linker is giving me errors as follows:
/home/sansari/tbt/tools/arm-eabi-4.7/bin/arm-eabi-gcc -I../../ndk/android-ndk-r10d/platforms/android-19/arch-arm/usr/include hello.c -o hello
/home/sansari/tbt/tools/arm-eabi-4.7/bin/../lib/gcc/arm-eabi/4.7/../../../../arm-eabi/bin/ld: cannot find crt0.o: No such file or directory
/home/sansari/tbt/tools/arm-eabi-4.7/bin/../lib/gcc/arm-eabi/4.7/../../../../arm-eabi/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
make: *** [hello] Error 1
update - I searched for a solution for the above errors. The first error is discussed here and -nostartfiles switch seems to work for me for now. I found this link that talks about libc.a being the fix for the error about not finding -lc. So I found an appropriate copy of libc.a and passed the location to the linker. The program compiles, but I get one last warning as follows:
warning: cannot find entry symbol _start; defaulting to 00000000000080dc
For which this link suggested using --entery-main switch. So now I have an executable. I want to thank you again. If you do see any problem in what I have done, please post something for me. it is gonna take a while for me to get this executable on my device.

ld error while building GD library for Haskell on Windows

When installing the Haskell GD package through cabal, on Windows (using MinGW), I get the following warnings:
Warning: resolving _gdImagePtrDestroyIfNotNull by linking to _gdImagePtrDestroyIfNotNull#4
Warning: resolving _gdImageCopyRotated90 by linking to _gdImageCopyRotated#36
Use --enable-stdcall-fixup to disable these warnings
Use --disable-stdcall-fixup to disable these fixups
Note that these are precisely the functions defined in gd-extras.
Then, when actually compiling a Haskell program which uses gd, I get the following errors:
Linking Main.exe ...
[...]\cabal\gd-3000.7.3\ghc-7.4.1/libHSgd-3000.7.3.a(Internal.o):fake:(.text+0x2211):undefined reference to 'gdImageCopyRotated90'
[...]\cabal\gd-3000.7.3\ghc-7.4.1/libHSgd-3000.7.3.a(Internal.o):fake:(.text+0x500a):undefined reference to 'gdImagePtrDestroyIfNotNull'
[...]
collect2: ld returned 1 exit status
I'm unable to figure out how to fix this — it's already taken me ages to get to this point, as I've had many more issues trying to get it working, but this seems like the final hurdle. I have tried enabling/disabling stdcall fixup, and also changing in which file these functions are defined (as gd-extras seemed to be a potential issue), but that hasn't adressed the issues.
Thanks for any help.
You need to pass explicit linker flags to ghc, pointing to the library. The Haskell GD library is automatically linked, but the dll will not be linked as well unless you tell ghc about it. The stdcall-fixup errors are a red herring here.

Do I need an "so" file or what's wrong?

(I'm on Windows.)
I try to build pysox. Therefore I built libsox (part of SoX). It is said, that pysox needs "libsox.so and libsox.a in your link path." When building libsox I got "libsox.a", "libsox-1.dll", "libsox.dll.a", "libsox.la", "libsox.lai" and many other strange files. When I placed "libsox.a" in my link path, the previously shown error disappeared. But now the build script has an error when it calls mingw32-gcc which says:
C:\Programme\MinGW\bin\mingw32-gcc.exe -shared -s build\temp.win32-2.7\Release\pysox\sox.o build\temp.win32-2.7\Release\pysox\sox.def -LC:\Programme\Python\libs -LC:\Programme\Python\PCbuild -lsox -lpython27 -lmsvcr90 -o build\lib.win32-2.7\pysox\sox.pyd
build\temp.win32-2.7\Release\pysox\sox.o:sox.c:(.text+0x3a96): undefined reference to `sox_get_encodings_info'
build\temp.win32-2.7\Release\pysox\sox.o:sox.c:(.text+0x5035): undefined reference to `sox_get_encodings_info'
build\temp.win32-2.7\Release\pysox\sox.o:sox.c:(.text+0x795d): undefined reference to `bcopy'
build\temp.win32-2.7\Release\pysox\sox.o:sox.c:(.text+0xa8b3): undefined reference to `bcopy'
collect2: ld returned 1 exit status
error: command 'mingw32-gcc' failed with exit status 1
The following attempts didn't work:
Placing "libsox-1.dll" in link path
Renaming it to "libsox.dll"
Renaming it to "libsox.so"
Placing all files generated along with "libsox.a" in link path
Do I really need an "so" file on Windows (how do I get it)? Or what has to be changed?
MinGW uses a static interface library for each dynamic link library (DLL). The libsox.dll.a library is the one you need at link time, i.e. that needs to be copied into the link path. libsox-1.dll is required in the PATH at runtime, but not needed at link time.
You don't need a .so file on Windows platforms. It seems that some symbols are missing from the static library libsox.a, or that a library is missing from the link line. Windows platforms do not allow unresolved symbols in DLLs, contrary to UNIX-like .so platforms. You might have to give the library containing sox_get_encodings_info and friends explicitly on the command line, remembering precedence on the linker line.

Resources