5
votes

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

2

2 Answers

2
votes

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:

  1. Explicitly invoke the dynamic linker to run a program, as in:

    ./ld-linux.so.2 a.out args ...
    
  2. 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
    
2
votes

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.