diff options
author | David 'Digit' Turner <digit@google.com> | 2010-10-21 04:16:50 +0200 |
---|---|---|
committer | David 'Digit' Turner <digit@google.com> | 2010-10-21 04:16:50 +0200 |
commit | 1df986c21ee52c6756846b4a5e45cb316f772112 (patch) | |
tree | da7effa96dd8e57e1cd718e69b79827d9011038e /libc/bionic/libc_init_common.c | |
parent | d3f0638aeec0b1daf4d3347386a5e441d5a4bcc4 (diff) | |
download | bionic-1df986c21ee52c6756846b4a5e45cb316f772112.zip bionic-1df986c21ee52c6756846b4a5e45cb316f772112.tar.gz bionic-1df986c21ee52c6756846b4a5e45cb316f772112.tar.bz2 |
libc: fix executable destruction support.
This change allows an executable to call its destructor functions
(declared with __attribute__((destructor))) to be properly called
when it normally exits.
Note that this is different from calling the destructors of a shared
library when it is unloaded with dlclose() or through program exit,
which are already supported.
Bug: 3106500
Change-Id: I1412ef5407f13b613fc6cb6103e0a691dbee4b1a
Diffstat (limited to 'libc/bionic/libc_init_common.c')
-rw-r--r-- | libc/bionic/libc_init_common.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/libc/bionic/libc_init_common.c b/libc/bionic/libc_init_common.c index d78d673..f7579bd 100644 --- a/libc/bionic/libc_init_common.c +++ b/libc/bionic/libc_init_common.c @@ -84,3 +84,39 @@ void __libc_init_common(uintptr_t *elfdata) /* setup system properties - requires environment */ __system_properties_init(); } + +/* This function will be called during normal program termination + * to run the destructors that are listed in the .fini_array section + * of the executable, if any. + * + * 'fini_array' points to a list of function addresses. The first + * entry in the list has value -1, the last one has value 0. + */ +void __libc_fini(void* array) +{ + int count; + void** fini_array = array; + const size_t minus1 = ~(size_t)0; /* ensure proper sign extension */ + + /* Sanity check - first entry must be -1 */ + if (array == NULL || (size_t)fini_array[0] != minus1) { + return; + } + + /* skip over it */ + fini_array += 1; + + /* Count the number of destructors. */ + for (count = 0; fini_array[count] != NULL; count++); + + /* Now call each destructor in reverse order. */ + while (count > 0) { + void (*func)() = (void (*)) fini_array[--count]; + + /* Sanity check, any -1 in the list is ignored */ + if ((size_t)func == minus1) + continue; + + func(); + } +} |