Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22273

System function overloading in nested shared library

$
0
0

Simple scenario

  1. Application uses write function from libc and links to shared library.
  2. Shared library defines write function.
  3. Original write function from libc will be overloaded by its version from the shared library.

Nested scenario

  1. Application uses write function from libc.
  2. Shared library 1 does not defines its own write but depends on shared library 2.
  3. Shared library 2 defines write function.
  4. No. write function will NOT be replaced with a version from the second shared library.

I do want to understand Why so ? How to make it work with nested shared library dependencies.

Here is exact code examples:

main.c

#include <unistd.h>int main() {    write(1,"Hello\n",6);    return 0;}

shared-lib-1.c

#include <unistd.h>__attribute__((constructor))void shared_lib_1_constructor(void) {    char str[] = "shared-lib-1-constructor\n";    write(1, str, sizeof(str)); }

shared-lib-2.c

#include <stdlib.h>#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count) {    exit(1);    return 0;}__attribute__((constructor))void shared_lib_2_constructor(void) {    char str[] = "shared-lib-2-constructor\n";    write(1, str, sizeof(str)); }

build.sh

#!/usr/bin/env shset -vset -egcc -g -fPIC -shared shared-lib-2.c -o libshared-lib-2.sogcc -g -fPIC -shared -Wl,-rpath . -L`pwd` -lshared-lib-2 shared-lib-1.c -o libshared-lib-1.sogcc -g -L`pwd` -Wl,-rpath . -lshared-lib-1 main.c

Execution of the a.out gives:

[smirnov@localhost tmp]$ ./a.out shared-lib-2-constructorshared-lib-1-constructorHello

write was not overwritten by shared-lib-2. It was completely ignored even from shared-lib-2 code.

How does it work with nested libraries ? Moving write definition to shared-lib-1 does work, it overloads glibc version and exits from application.

Running application with LD_DEBUG=all shows order of resolving:

   36441:     Initial object scopes   36441:     object=./a.out [0]   36441:      scope 0: ./a.out ./libshared-lib-1.so /lib64/libc.so.6 ./libshared-lib-2.so /lib64/ld-linux-x86-64.so.2...   36441:     calling init: ./libshared-lib-2.so   36441:        36441:     symbol=write;  lookup in file=./a.out [0]   36441:     symbol=write;  lookup in file=./libshared-lib-1.so [0]   36441:     symbol=write;  lookup in file=/lib64/libc.so.6 [0]   36441:     binding file ./libshared-lib-2.so [0] to /lib64/libc.so.6 [0]: normal symbol `write'

Why libc placed in between shared-lib-1 and shared-lib-2 ?It seems that ld resolves in the following order:

  • all dependencies of a.out, but not recursivelly, only first level
  • all subdependencies, but not recursivelly
  • so on...

The only solution I've found is to use

LD_DYNAMIC_WEAK=1 ./a.out

Is there a way to fix behavior in advance ?


Viewing all articles
Browse latest Browse all 22273

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>