runtime_loader: add support for ELF init/term routine arrays.

* binutils 2.27 defaults to DT_INIT_ARRAY instead of DT_INIT.
This commit is contained in:
Jérôme Duval 2016-10-11 22:26:06 +02:00
parent 1df36f2cee
commit e340f717a4
3 changed files with 57 additions and 3 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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).