does dynamic library shared global variable in linux - linux

As we know, linux call ldconfig to load all *.so libraries and then link the applications who use the shared library. However, I am confused how the global variable is working in this case. Since there is only one copy of shared library across all these application, do they share the global variables in the shared library? If yes, then how they synchronize?
Thanks,

No it is not shared - the code/text section of the library is shared - the data portion is unique to each process that uses the library

As I commented:
Levine's book on linkers and loaders is a useful reference.
Linux dynamic linker ld.so is free software, part of GNU libc and you can study and improve its source code
the dynamic linker is ld.so not ldconfig (which just updated cached information used by ld.so).
the ld.so linker is using the mmap(2) system call to project some .so segments into the virtual address space of the process; the "text" segment (for code and read-only constants) uses MAP_SHARED with PROT_READ. The "data" segment (for global or static variables in C or C++) uses MAP_PRIVATE with PROT_WRITE
you would learn a lot by strace-ing your program to get a feeling of the involved system calls.

Related

Grub bootloader with shared library support

I'd like to load a shared library (closed-source binary user-space library) at boot stage with grub boot-loader. Are there any chances for this or I must write a custom-elf-loader (grub module) to do it?
29/08/2014: For more detail, this is a programming problem in which I
want to customize or add some new features to Grub boot-loader
project. Thank you for your all supporting!
So, you don't make it crystal clear what you are trying to do, but:
Loading a userspace (assuming Linux SysV ELF type) shared library straight into GRUB is not possible. GRUB modules are indeed in ELF format, but they contain additional headers. Among the information contained in that header is an explicit license statement - GRUB will refuse to load any modules that are not explicitly GPLv2+, GPLv3 or GPLv3+.
It should be possible to write an ELF loader, but an easier way might be to write a tool to convert a userspace library to a GRUB module. There would of course be several restrictions here:
You would need to ensure the userspace library performed no system calls - GRUB would have nothing in place to handle them.
You would need to abide by the licensing rules (so only above three licenses would be acceptable).
You would need to ensure these libraries were not dependent on a global offset table being set up by glibc for them.
If recompiling is an option, GRUB also provides a POSIX emulation layer - add CPPFLAGS_POSIX to your CPPFLAGS, and use core standard POSIX header files. Have a look at the gcrypt support for an example.

How to build the elf interpreter (ld-linux.so.2/ld-2.17.so) as static library?

I apologize if my question is not precise because I don't have a lot
of Linux related experience. I'm currently building a Linux from
scratch (mostly following the guide at linuxfromscratch.org version
7.3). I ran into the following problem: when I build an executable it
gets a hardcoded path to something called ELF interpreter.
readelf -l program
shows something like
[Requesting program interpreter: /lib/ld-linux.so.2]
I traced this library ld-linux-so.2 to be part of glibc. I am not very
happy with this behaviour because it makes the binary very unportable
- if I change the location of /lib/ld-linux.so.2 the executable no
longer works and the only "fix" I found is to use the patchelf utility
from NixOS to change the hardcoded path to another hardcoded path. For
this reason I would like to link against a static version of the ld
library but such is not produced. And so this is my question, could
you please explain how could I build glibc so that it will produce a
static version of ld-linux.so.2 which I could later link to my
executables. I don't fully understand what this ld library does, but I
assume this is the part that loads other dynamic libraries (or at
least glibc.so). I would like to link my executables dynamically, but
I would like the dynamic linker itself to be statically built into
them, so they would not depend on hardcoded paths. Or alternatively I
would like to be able to set the path to the interpreter with
environment variable similar to LD_LIBRARY_PATH, maybe
LD_INTERPRETER_PATH. The goal is to be able to produce portable
binaries, that would run on any platform with the same ABI no matter
what the directory structure is.
Some background that may be relevant: I'm using Slackware 14 x86 to
build i686 compiler toolchain, so overall it is all x86 host and
target. I am using glibc 2.17 and gcc 4.7.x.
I would like to be able to set the path to the interpreter with environment variable similar to LD_LIBRARY_PATH, maybe LD_INTERPRETER_PATH.
This is simply not possible. Read carefully (and several times) the execve(2), elf(5) & ld.so(8) man pages and the Linux ABI & ELF specifications. And also the kernel code doing execve.
The ELF interpreter is responsible for dynamic linking. It has to be a file (technically a statically linked ELF shared library) at some fixed location in the file hierarchy (often /lib/ld.so.2 or /lib/ld-linux.so.2 or /lib64/ld-linux-x86-64.so.2)
The old a.out format from the 1990s had a builtin dynamic linker, partly implemented in old Linux 1.x kernel. It was much less flexible, and much less powerful.
The kernel enables, by such (in principle) arbitrary dynamic linker path, to have various dynamic linkers. But most systems have only one. This is a good way to parameterize the dynamic linker. If you want to try another one, install it in the file system and generate ELF executables mentioning that path.
With great pain and effort, you might make your own ld.so-like dynamic linker implementing your LD_INTERPRETER_PATH wish, but that linker still has to be an ELF shared library sitting at some fixed location in the file tree.
If you want a system not needing any files (at some predefined, and wired locations, like /lib/ld.so, /dev/null, /sbin/init ...), you'll need to build all its executable binaries statically. You may want (but current Linux distributions usually don't do that) to have a few statically linked executables (like /sbin/init, /bin/sash...) that will enable you to repair a system broken to the point of not having any dynamic linker.
BTW, the /sbin/init -or /bin/sh - path is wired inside the kernel itself. You may pass some argument to the kernel at boot load time -e.g. with GRUB- to overwrite the default. So even the kernel wants some files to be here!
As I commented, you might look into MUSL-Libc for an alternative Libc implementation (providing its own dynamic linker). Read also about VDSO and ASLR and initrd.
In practice, accept the fact that modern Linuxes and Unixes are expecting some non-empty file system ... Notice that dynamic linking and shared libraries are a huge progress (it was much more painful in the 1990s Linux kernels and distributions).
Alternatively, define your own binary format, then make a kernel module or a binfmt_misc entry to handle it.
BTW, most (or all) of Linux is free software, so you can improve it (but this will take months -or many years- of work to you). Please share your improvements by publishing them.
Read also Drepper's Hwo to Write Shared Libraries paper; and this question.
I ran into the same issue. In my case I want to bundle my application with a different GLIBC than comes system installed. Since ld-linux.so must match the GLIBC version I can't simply deploy my application with the according GLIBC. The problem is that I can't run my application on older installations that don't have the required GLIBC version.
The path to the loader interpreter can be modified with --dynamic-linker=/path/to/interp. However, this needs to be set at compile time and therefore would require my application to be installed in that location (or at least I would need to deploy the ld-linux.so that goes with my GLIBC in that location which goes against a simple xcopy deployment.
So what's needed is an $ORIGIN option equivalent to what the -rpath option can handle. That would allow for a fully dynamic deployment.
Given the lack of a dynamic interpreter path (at runtime) leaves two options:
a) Use patchelf to modify the path before the executable gets launched.
b) Invoke the ld-linux.so directly with the executable as an argument.
Both options are not as 'integrated' as a compiled $ORIGIN path in the executable itself.

symbols in kernel module

I built linux kernel module with SSP support for mips architecture. I added -fstack-protector-all to compilation flags. But after loading this module I've got undefined references to __stack_chk_guard and __stack_chk_fail. But I added libssp.so to linker. It looks like I should export those symbols in kernel something like this:
EXPORT_SYMBOL(__stack_chk_guard);
Because my kernel is old and didn't contain them yet. But unfortunately I should use this version.
My question is: why user space can use this symbols from toolchain library, but kernel space don't ?
I think, I missed some linux kernel essentials.
You can't link the kernel to shared libraries. If you have a static library of libssp, it MAY work - but it would require that the library isn't calling something else that would cause problems in the kernel.
In general, stack-checking isn't something that you should be doing on the kernel - I'm pretty sure it serves no particularly good purpose [I'm also pretty sure that the kernel uses a "guard page" for each kernel stack].
You cannot use shared libraries anywhere in kernel space (including as part of kernel modules).
You could think of kernel modules themselves as an equivalent of shared libraries in kernel space but with lot of differences.
Kernel modules can depend on exported symbols from other kernel modules.
My question is: why user space can use this symbols from toolchain
library, but kernel space don't ?
Nothing in kernel space has access to the libc C library. Kernel has its own set of builtin standard string manipulation functions, etc. that you could use instead. The toolchain libraries are built on top of libc.
+1 on Mats's answer. You could use a static library as long as it does not depend on standard C libraries like libc

Loading ELF shared library and custom binfmt executable into same Linux address space

I am working on a project to load and run a custom binary format executable (PE, in my case) on a Linux platform. I've done this pretty successfully so far by first loading the executable and then loading a small ELF shared library that calls the start address of the executable and then exits safely.
I would really like not doing the ELF loading myself for a few reasons, though. First, the shared library I use is written in assembly (I can't use anything else because I'm not linking to libc, etc.), which will be very platform-specific, and I'd like to move away from that and use C so I can compile for any platform. Also, it will be easier and safer to use Linux's native ELF loader instead of my own simplified version.
I'm wondering if there is a way to use my binfmt handler, an installed kernel module, to load my executable and then ask Linux to load my shared library (and its dependencies) into the same address space without overwriting my executable code. I first thought that the uselib syscall might be useful, but the description on the man page is unclear about whether or not this will serve my purposes:
From libc 4.4.4 on only the library "/lib/ld.so" is loaded, so that
this dynamic library can load the remaining libraries needed (again
using this call). This is also the state of affairs in libc5.
glibc2 does not use this call.
I've also never seen an example of its use, and I'm always wary of using syscalls that I don't understand.
Is there a good way to achieve what I've described? Can I use Linux's existing capabilities to load a shared library (written in C) into an address space already containing executable code, and, if so, how can I use that library without knowing where it has been loaded?
there is already a project like this called binfmt_pe (by me!) which is a kernel module and will have it's own linker (similar to /lib/ld). check it out here.
As for your question about making modules and the loader/linker, there are links below. I also included links with info about ELF and PE executables.
I hope this helps. :)
Useful information for making a Linux Kernel Module
The Linux Kernel Module Programming Guide
Writing Your Own Loadable Kernel Module
Linux Data Structures
The Linux kernel: The kernel source
Kernel Support for miscellaneous Binary Formats
binfmt_elf.c
binfmt_misc.c
Information About Dynamnic Loading/Linking
Understanding ld-linux.so.2
ld.so : Dynamic-Link Library support
How To Write Shared Libraries - PDF
ld-linux(8) - Linux man page
rpath
Listing Shared Library Dependencies
Information About ELF and PE Formats
OSRC: Executable File Formats
EXE Format
How Windows NT Recognizes MS-DOS - Based Applications
Common Object File Format (COFF)
Peering Inside the PE: A Tour of the Win32 Portable Executable File Format
Executable and Linkable Format
An In-Depth Look into the Win32 Portable Executable File Format
An In-Depth Look into the Win32 Portable Executable File Format, Part 2
Injective Code Inside an Import Table
The PE Format | Hackers Library
IMAGE_NT_HEADERS structure (Windows)
x86 Disassembly/Windows Executable Files
the Portable Executable Format on Windows

How tcamalloc gets linked to the main program

I want to know how malloc gets linked to the main program.Basically I have a program which uses several static and dynamic libraries.I am including all these in my makefile using option "-llibName1 -llibName2".
The documentation of TCmalloc says that we can override our malloc simply by calling "LD_PRELOAD=/usr/lib64/libtcmalloc.so".I am not able to understand how tcamlloc gets called to the all these static and dynamic libraries.Also how does tcmalloc also gets linked to STL libraries and new/delete operations of C++?
can anyone please give any insights on this.
"LD_PRELOAD=/usr/lib64/libtcmalloc.so" directs the loader to use libtcmalloc.so before any other shared library when resolving symbols external to your program, and because libtcmalloc.so defines a symbol named "malloc", that is the verison your program will use.
If you omit the LD_PRELOAD line, glibc.so (or whatever C library you have on your system) will be the first shared library to define a symbol named "malloc".
Note also that if you link against a static library which defines a symbol named "malloc" (and uses proper arguments, etc), or another shared library is loaded that defines a symbol named "malloc", your program will attempt to use that version of malloc.
That's the general idea anyway; the actual goings-on is quite interesting and I will have to direct to you http://en.wikipedia.org/wiki/Dynamic_linker as a starting point for more information.

Resources