Showing posts with label linux_dso. Show all posts
Showing posts with label linux_dso. Show all posts

Jun 20, 2022

[C++] ODR notes

ODR:
https://eel.is/c++draft/basic.def.odr


All definition across the program should be the same.

It's hard.


e.g.

// size of Person might be different inside the program.
class Person{
    std::string first_;
    std::string last_;
# if HAS_MIDDLE_NAME(VAR)
    std::string middle_;
#endif
};

ODRV can be embedded anywhere(DSO, static library, or executable)

  1. Multiple, conflicting definitions of the same symbol in more than one TU.
  2. Compiling a given header/source file with different compiler settings or #defines
    Debug/Release, (no-)RTTI, mismatched preprocessor values, etc.
  3. Overriding operator new/delete in a DSO, but hiding it from the rest of the program.
    The passing C++ objects across that DSO boundary.
  4. Multple varying copies of a dependency(e.g. Boost, JPEG, zlib, etc.)


ODRV Behaviors

  1. Hard to debug
  2. Hard to reproduce
  3. Exceptions failing to get caught
  4. Crashing in the destructor after passing an object across a DSO boundary.

Jun 5, 2022

[C++][CPPCON 2021] s.t about Dynamically Loaded Libraries

Reference:
https://youtu.be/-dxCaM4GOqs

Definition:
Dynamic linking, opposed to static linking form a physical aspect of a program relocation is done at load time.


Dynamic loading ask for additional functionalities often involve library discovery relocation is done at run time maybe capable of 'unloading'.


in C++, object do not relocate but functions do.
Or to be precise, C/Assembly function kind do relocate, thus Golang could have dynamic growing stack size which relocate function at runtime.


After dlopen, unloading is often avoided due to this makes function having a 'lifetime'.
e.g. musl's dlcose is a noop. (complicating thread-local storage(TLS) implementation if library may unload)


Can objects from a library outlive the library?


Library lifetime realized in C++
- When loading a library, init. objects with static storage duration at namespace scope.
- When unloading a library, destruct objects with static storage duration.
- Loaded libraries are reference counted.


Interaction with thread_local
- When a thread starts, init. objects with thread storage duration at namespace scope.
- When a thread exits, destruct objects with thread storage duration.
- What happens if the library is unloaded before all threads exit?


glibc:
Do not unload the shared object during dlclose().
Consequently, the object's static and global variables are not reinitialized if the object is reloaded with dlopen() at a later time.


DF_1_NODELETE (elf.h)
- Set flag on the DSO until all thread_local objects defined in the DSO are destroyed
- After the flag being cleared, a subsequent dlclose() unloads the DSO
- i.e. dlclose() in the middle of destructing thread_local objects is a no-op


Unloading summary:
- Functions may have lifetime
- Implementations need to prevent objects with thread storage duration from outliving their destructors