简体   繁体   中英

Link time running of code? (specifically, issues raised by Valgrind seemingly at linktime)

I suspect this is an issue with my understanding of how the linking of shared objects takes place on Linux.

Using Valgrind with OpenCL (which, from various other posts, I understand to be problematic in its own right), I'm encountering errors from a module that is part of the shared object but is never actually run.

Specifically, I have an OpenCL helper module that has a series of functions for performing OpenCL actions. I have removed all references to the functions within this module from the executing code. I would naively assume, therefore, that this module cannot raise any problems with Valgrind.

However, I am seeing issues that are raised through _dl_init.c (lots of them, showing how broken OpenCL is with Valgrind). This suggests to me that code within the OpenCL runtime is being executed at link time.

Can someone clarify (or point me to suitable clarification material) how _dl_init.c is involved in the linker process?

Is it universally true that the .so files execute some initialisation code, or is it a library option?

Is this something that is easily accessible to library writers, or does it involved nefarious hacks?

Shared objects ( .so files) are permitted to have code that is executed as soon as the library is loaded, regardless of the use of any of the code in the library.

This is used, for example, to perform static initialization of C++ objects.

If you don't want to have valgrind complaining about things that are being done in the library behind your back, then you can run valgrind so that it generates output that can be used as a suppression file by passing in --gen-suppressions=all . You use the suppression output in a suppression file of your own when running against the library and it should mask out these issues.

Cases when it appears:

  • If you're using C++ code and have globally scoped objects, then their constructors are called when the library is loaded
  • If you add the gcc specific attribute ((constructor)) to a function definition it gets called when the library is loaded

eg (C++) at a global scope:

#include <iostream>

class demo {
    demo() { std::cout << "Hello World" << std::endl; }
    ~demo() {}
};

demo ademo;

eg (C)

#include <stdio.h>
static void __attribute__((constructor)) my_init() {
    printf("Hello World\n");
}

There is a corresponding event for object destruction or __attribute__((destructor)) on library unloading.

The ELF spec defines the presence of an .init and .fini section, which are, for libraries, the mechanism that is used to run constructor-type and destructor-type code when the library is loaded/unloaded. For a standard executable it's this, plus the getting you to main with the appropriate parameters.

You can explicitly change these entry points, but that's a little bit dangerous and can lead to crashes and unknown bugs. It makes more sense to hook into the mentioned supported mechanisms.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM