From e340f717a422917491cebe4b693c6d30416ea0f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 11 Oct 2016 22:26:06 +0200 Subject: [PATCH] runtime_loader: add support for ELF init/term routine arrays. * binutils 2.27 defaults to DT_INIT_ARRAY instead of DT_INIT. --- .../private/runtime_loader/runtime_loader.h | 6 ++++ src/system/runtime_loader/elf.cpp | 24 +++++++++++++++ src/system/runtime_loader/elf_load_image.cpp | 30 +++++++++++++++++-- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h index 6a754f2330..d93f676af2 100644 --- a/headers/private/runtime_loader/runtime_loader.h +++ b/headers/private/runtime_loader/runtime_loader.h @@ -115,6 +115,12 @@ typedef struct image_t { int rela_len; elf_rel *pltrel; int pltrel_len; + addr_t *init_array; + int init_array_len; + addr_t *preinit_array; + int preinit_array_len; + addr_t *term_array; + int term_array_len; unsigned dso_tls_id; diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp index 6d30bbb7f2..03b8bd1c73 100644 --- a/src/system/runtime_loader/elf.cpp +++ b/src/system/runtime_loader/elf.cpp @@ -257,9 +257,21 @@ init_dependencies(image_t *image, bool initHead) TRACE(("%ld: init: %s\n", find_thread(NULL), image->name)); + if (image->preinit_array) { + uint count_preinit = image->preinit_array_len / sizeof(addr_t); + for (uint j = 0; j < count_preinit; j++) + ((init_term_function)image->preinit_array[j])(image->id); + } + if (image->init_routine != 0) ((init_term_function)image->init_routine)(image->id); + if (image->init_array) { + uint count_init = image->init_array_len / sizeof(addr_t); + for (uint j = 0; j < count_init; j++) + ((init_term_function)image->init_array[j])(image->id); + } + image_event(image, IMAGE_EVENT_INITIALIZED); } TRACE(("%ld: init done.\n", find_thread(NULL))); @@ -633,6 +645,12 @@ unload_library(void* handle, image_id imageID, bool addOn) image_event(image, IMAGE_EVENT_UNINITIALIZING); + if (image->term_array) { + uint count_term = image->term_array_len / sizeof(addr_t); + for (uint i = count_term; i-- > 0;) + ((init_term_function)image->term_array[i])(image->id); + } + if (image->term_routine) ((init_term_function)image->term_routine)(image->id); @@ -1017,6 +1035,12 @@ terminate_program(void) image_event(image, IMAGE_EVENT_UNINITIALIZING); + if (image->term_array) { + uint count_term = image->term_array_len / sizeof(addr_t); + for (uint j = count_term; j-- > 0;) + ((init_term_function)image->term_array[j])(image->id); + } + if (image->term_routine) ((init_term_function)image->term_routine)(image->id); diff --git a/src/system/runtime_loader/elf_load_image.cpp b/src/system/runtime_loader/elf_load_image.cpp index 73ffad1453..7181562c66 100644 --- a/src/system/runtime_loader/elf_load_image.cpp +++ b/src/system/runtime_loader/elf_load_image.cpp @@ -339,6 +339,33 @@ parse_dynamic_segment(image_t* image) } break; } + case DT_INIT_ARRAY: + // array of pointers to initialization functions + image->init_array = (addr_t*) + (d[i].d_un.d_ptr + image->regions[0].delta); + break; + case DT_INIT_ARRAYSZ: + // size in bytes of the array of initialization functions + image->init_array_len = d[i].d_un.d_val; + break; + case DT_PREINIT_ARRAY: + // array of pointers to pre-initialization functions + image->preinit_array = (addr_t*) + (d[i].d_un.d_ptr + image->regions[0].delta); + break; + case DT_PREINIT_ARRAYSZ: + // size in bytes of the array of pre-initialization functions + image->preinit_array_len = d[i].d_un.d_val; + break; + case DT_FINI_ARRAY: + // array of pointers to termination functions + image->term_array = (addr_t*) + (d[i].d_un.d_ptr + image->regions[0].delta); + break; + case DT_FINI_ARRAYSZ: + // size in bytes of the array of termination functions + image->term_array_len = d[i].d_un.d_val; + break; default: continue; @@ -348,9 +375,6 @@ parse_dynamic_segment(image_t* image) // DT_SYMENT: The size of a symbol table entry. // DT_PLTREL: The type of the PLT relocation entries (DT_JMPREL). // DT_BIND_NOW/DF_BIND_NOW: No lazy binding allowed. - // DT_INIT_ARRAY[SZ], DT_FINI_ARRAY[SZ]: Initialization/termination - // function arrays. - // DT_PREINIT_ARRAY[SZ]: Preinitialization function array. // DT_RUNPATH: Library search path (supersedes DT_RPATH). // DT_TEXTREL/DF_TEXTREL: Indicates whether text relocations are // required (for optimization purposes only).