Short Version: It is possible to go over all ELF "section" headers during runtime and get relocated address of every "section" header for every loaded shared library.
Long Version:
I'm trying to implement the same mechanism for dynamic debug in userspace as it exists in kernel (dyn_debug). The way it works that every LOG macro instance creates static variable in specific "section" in the program
__attribute__((section("__verbose")))
This forces compiler to put the variable not in ".data" section but in "__verbose" section. Later start and stop address of this section can be accessed through variables
__start___verbose, __stop___verbose. This way some central routine can go over all registered "log" entries and change attributes on demand.
This works find for statically linked executable, but when using shared libraries there are several "__verbose" sections (one per each shared library) and one in the executable itself. (I am using -fPIC flag of course in order to be included in the library)
Also everything in linked with "-export-dynamic" in order to ensure all symbols are exported.
Each shared library and main executable has attribute(constructor) method for init.
I had observed two different behaviors in 2 cases.
case1: For first case libraries are not loaded with ldopen but by the "libc loader"
referencing __start___verbose always returns same address (that of the main executable), where only "main" executable logging entries are present.
dlsym(RTLD_NEXT, __start___verbose), returns address of the symbol of the "next" resolvable library, so in fact i get all addresses.
case 2: Loading library with ldopen
- referencing __start___verbose always returns same address (that of the main executable)
- dlsym(RTLD_NEXT, __start___verbose) return NULL.
- dlsym(RTLD_DEFAULT, __start___verbose) return "main" process table.
- dlsym(handle, __start___verbose) - returns correct section address
Question: Is there any way for library opened with ldopen to obtain that symbol, besides 4, as 4 requires explicit call from the "loader"
Code:
/* Main" */
void func1()
{
static int attribute__((section("__verbose"))) var = 1;
}
/* Shared library */
void func2()
{
static int attribute__((section("__verbose"))) var = 2;
}
/* Both in main and shared library
* Prints same address !!! BAD !! */
void __attribute__((constructor)) initializer()
{
struct int *iter;
for (iter = __start___verbose; iter != __stop___verbose; ++iter) {
printf("Value is %d", *iter)
}
}
/* Works for libraries opened by libc runtime.
* Does not work for libraries opened with LDOPEN*/
void __attribute__((constructor)) initializer()
{
struct int *iter = ;
for (iter = dlsym(RTLD_NEXT, "__start___verbose"); iter != __stop___verbose; ++iter) {
printf("Value is %d", *iter)
}
}
/* Snippet for main doing dynamic loading */
handle = ldopen('path', RTLD_NOW)
iter = dlsym(handle, "__start___verbose")
for (; iter != __stop___verbose; ++iter) {
printf("Value is %d", *iter)
}
__start___verboseand__stop___verbosevariables because I don't have them. - ysdx