X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f X-Recipient: djgpp AT delorie DOT com Message-ID: <56111BF6.8040408@gmx.de> Date: Sun, 04 Oct 2015 14:30:46 +0200 From: "Juan Manuel Guerrero (juan DOT guerrero AT gmx DOT de) [via djgpp AT delorie DOT com]" User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.13) Gecko/20101206 SUSE/3.1.7 Thunderbird/3.1.7 MIME-Version: 1.0 To: djgpp AT delorie DOT com Subject: Re: dlclose not removing dependency dxes References: <952a68b4-223b-4222-b456-35514bb8b7eb AT googlegroups DOT com> <561101C4 DOT 7040701 AT gmx DOT de> In-Reply-To: <561101C4.7040701@gmx.de> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Provags-ID: V03:K0:5q38kQmLdhWMPxtp/wFspnVl58Kccv0Z/9rdllE5R/6WoQJoBcu meXfPlA/mKjixstpBq54w4Pkr/JY0ZiM10z7awbIqSNii92bkxzPrr+ahQ4ahFMHo6u5Aqp b1yDRFiQm/F0CXvyg6pfAqlN6OMTOpa4D5LV1hActXnMaxaSM7A+olHZFoyXqFqXALrcUbu utcDBMkoYqhg5n1CjUejg== X-UI-Out-Filterresults: notjunk:1;V01:K0:oeuHO3tkXa4=:Yj4U5wtIK9ywhYjHsLnqc3 ZePfkGjbfW5kiIQSEnI5EXS24k0Ak3Y63/mlHBbnIZyKdatrq4adJ6ZlB92UfADuacb9wETEk MgLSsR3Ql/o5MF3N3wyj6+HKgeg3WxHNmvul9vXj/07YLU2eq2YsPhsvQLrc1uKakU2likz/H v/b40SGmik2iwRajyaPkqeYv2/aaJdiecNnkImW3iBCS73RdU0YUkUwNlJtZPrSifH636gQtn E9UsGu0GyrhJzVHoyHoUX/mIiFjepoBqKJmLqBu1s0QbjZd5GHo2t5PQx7wYaCw+ZMG3ZNyxN VxL0OGVpyRRhZzuboZL+cyLrpsoIuD0iUdLsH7XU6FLK8r4nBxx5qxQMDa35tefPxo2BfU/vC YO9icSJQQwPlrvdbTcws+sSey6T0z1Aydh8RyqayuQizrasZiN7BVCwJcscp7+dxUYZnUrkyQ xOPTbIjJaHaQ1SWWroALgq3dp4asjIw+LpH3Dd1MnpNMKbD45MekR3tBlHkemaW227ITz5m31 ByRT5Ai+8wPOya39+4Dy4VtY9+ihxaj3jJNGgyzRdD9C6DCcBczCvWfxfPCNSkDcMTlIfMoFH 55Xc1PX8zFignxfFgxuBzfJK9aQsVhr/mJgIEJ4phZoZ1trBBvM3mKKdwpEVwUL/b9e0rqsNw jdrxzB3XqK6G/HG1X9snVuyI6buQLUqGGtEGLV4yS7ISYsODb8V+OliqFoDhx73bNatXDeoQ1 P3jx+0/zxjMtajRCqZlciyD+7YSN6+k6A+T9TBx3nFu2aQEwsbgmXuPfoNj3x64CVylfJWuK9 VuTsoJF Reply-To: djgpp AT delorie DOT com Am 04.10.2015 12:39, schrieb Juan Manuel Guerrero (juan DOT guerrero AT gmx DOT de) [via djgpp AT delorie DOT com]: [snip] > Below is a patch that will implement ref-counting for implicitly loaded modules > by other ones. Please not that this ref-counting only works for dlopen/dlclose. > There may be other loading mechanisms that suffer from the same issue and that > will not be fixed by this modification. > The patch is intended for the main branch but should work on v2_05_1 as well. [snip] There was a typo in the previously posted patch. Please use this one. Regards, Juan M. Guerrero 2015-10-03 Juan Manuel Guerrero * djgpp/src/libc/dxe/dlopen.c: Added reference counting support for implicitly loaded DXE modules by dlopen. diff -aprNU5 djgpp.orig/src/libc/dxe/dlopen.c djgpp/src/libc/dxe/dlopen.c --- djgpp.orig/src/libc/dxe/dlopen.c 2015-10-04 10:27:26 -29907 +++ djgpp/src/libc/dxe/dlopen.c 2015-10-04 13:58:56 -29907 @@ -36,14 +36,16 @@ #ifndef ELOOP #define ELOOP EMLINK #endif +#define __DEBUG_DXE3__ 0 /* Prints struct __dxe_handle members. Always commited as 0. */ + /* private stack */ -typedef struct stk_node { +typedef struct __stk_node { const char *name; - struct stk_node *next; + struct __stk_node *next; } stk_node; /* Exported symbols table entry */ typedef struct { @@ -57,22 +59,29 @@ typedef struct unsigned short n_rel_relocs; unsigned short n_abs_relocs; char name [1]; /* expanded as needed */ } __attribute__((packed)) unres_table_entry; +/* This is a linked list of implicitly loaded dxe modules. */ +typedef struct __linked_list { + struct __dxe_handle *handle; /* Pointer to next implicitly open module by this module */ + struct __linked_list *next; /* Next entry in list */ +} dxe_handle_list; + /* This is the private dxe_h structure */ typedef struct __dxe_handle { - struct __dxe_handle *next; /* Pointer to next module in chain */ - char fname[FILENAME_MAX]; /* Full module pathname */ - int mode; /* Module open mode */ - int inuse; /* In-use counter */ - int n_exp_syms; /* Number of entries in export table */ - exp_table_entry **exp_table; /* Exported symbols table */ - char *header; /* The resident portion of header */ - char *section; /* code+data+bss section */ - long _fini; /* finalization */ + struct __dxe_handle *next; /* Pointer to next module in chain */ + char fname[FILENAME_MAX]; /* Full module pathname */ + int mode; /* Module open mode */ + int in_use; /* In-use counter */ + int n_exp_syms; /* Number of entries in export table */ + exp_table_entry **exp_table; /* Exported symbols table */ + char *header; /* The resident portion of header */ + char *section; /* code+data+bss section */ + long _fini; /* Finalization */ + dxe_handle_list *implicit_handle_list; /* Linked list of implicitly open module by this module or NULL */ } dxe_handle, *dxe_h; /* Last-resort symbol resolver */ void *(*_dlsymresolver) (const char *symname) = NULL; /* Last-error unresolved symbol count */ @@ -110,10 +119,12 @@ void *dlopen(const char *filename, int m char *discardable; stk_node *node; static stk_node *stk_top = NULL; + dxe_handle_list *implicitly_open_handle_list; + #ifndef __GNUC__ static int cleanup = 0; #endif _dl_unresolved_count = 0; @@ -180,11 +191,11 @@ found: /* Look through the loaded modules list */ for (cur = dxe_chain; cur; cur = cur->next) if (!strcmp(realfn, cur->fname)) { - cur->inuse++; + cur->in_use++; return cur; } fh = OPEN(filename, OPENFLAGS); if (fh < 0) return NULL; @@ -202,13 +213,14 @@ found: return NULL; } /* O.k, fill the module handle structure */ strcpy(dxe.fname, realfn); - dxe.inuse = 1; + dxe.in_use = 1; dxe.mode = mode; dxe.n_exp_syms = dxehdr.n_exp_syms; + dxe.implicit_handle_list = NULL; /* Read DXE tables and the data section */ hdrsize = dxehdr.symbol_offset - sizeof(dxehdr); discardsize = dxehdr.dep_size + dxehdr.unres_size + dxehdr.nrelocs * sizeof(long); if ((dxe.header = malloc(hdrsize + dxehdr.sec_size)) == NULL) @@ -240,11 +252,11 @@ found: /* Fill the unfilled portion of code+data+bss segment with zeros */ memset(dxe.section + dxehdr.sec_f_size, 0, dxehdr.sec_size - dxehdr.sec_f_size); /* Load the dependencies */ scan = discardable; - for (i = 0; i < dxehdr.n_deps; i++) + for (implicitly_open_handle_list = NULL, i = 0; i < dxehdr.n_deps; i++) { stk_node tmp; tmp.name = realfn; tmp.next = stk_top; stk_top = &tmp; @@ -252,14 +264,35 @@ found: if (dlopen(scan, RTLD_GLOBAL) == NULL) { stk_top = tmp.next; goto unrecoverable; } + else + { + dxe_handle_list *next_handle_list; + + stk_top = tmp.next; - stk_top = tmp.next; + scan = strchr(scan, 0) + 1; - scan = strchr(scan, 0) + 1; + /* Register all implicitly open modules by this one. */ + if ((next_handle_list = malloc(sizeof(dxe_handle_list))) == NULL) + { + errno = ENOMEM; + goto midwayerror; + } + next_handle_list->handle = dxe_chain; + next_handle_list->next = NULL; + + if (implicitly_open_handle_list) + { + implicitly_open_handle_list->next = next_handle_list; + implicitly_open_handle_list = implicitly_open_handle_list->next; + } + else + dxe.implicit_handle_list = implicitly_open_handle_list = next_handle_list; + } } /* Allright, now we're ready to resolve all unresolved symbols */ _dl_unresolved_count = dxehdr.n_unres_syms; _dl_unresolved_symbol[0] = 0; @@ -325,10 +358,50 @@ found: errno = ENOMEM; goto midwayerror; } memcpy(dxe_chain, &dxe, sizeof(dxe_handle)); +#if defined(__DEBUG_DXE3__) && __DEBUG_DXE3__ == 1 + { + FILE *f = fopen("c:/tmp/dxe_chain.txt", "a"); + + if (f) + { + fprintf(f, "dxe_chain : 0x%p\n" + " next : 0x%p\n" + " fname : %s\n" + " mode : %s\n" + " in_use : %d\n" + " n_exp_syms : %d\n" + " exp_table : 0x%p\n", + dxe_chain, dxe_chain->next, dxe_chain->fname, + dxe_chain->mode == RTLD_LAZY ? "RTLD_LAZY" : + dxe_chain->mode == RTLD_NOW ? "RTLD_NOW" : + dxe_chain->mode == RTLD_LOCAL ? "RTLD_LOCAL" : + dxe_chain->mode == RTLD_GLOBAL ? "RTLD_GLOBAL" : "unknown", + dxe_chain->in_use, dxe_chain->n_exp_syms, dxe_chain->exp_table); + for (i = 0; i < dxe_chain->n_exp_syms; i++) + fprintf(f, " exp_table[%d]->offset : %ld\n" + " exp_table[%d]->name : %s\n", + i, dxe_chain->exp_table[i]->offset, i, dxe_chain->exp_table[i]->name); + fprintf(f, " header : 0x%p\n" + " section : 0x%p\n" + " _fini : %ld\n", + dxe_chain->header, dxe_chain->section, dxe_chain->_fini); + if ((implicitly_open_handle_list = dxe_chain->implicit_handle_list)) + for (; implicitly_open_handle_list; implicitly_open_handle_list = implicitly_open_handle_list->next) + fprintf(f, " implicitly_open_handle_list: 0x%p\n" + " handle : 0x%p\n" + " handle->fname : %s\n\n", + implicitly_open_handle_list, implicitly_open_handle_list->handle, implicitly_open_handle_list->handle->fname); + else + fprintf(f, " implicitly_open_handle_list: 0x00000000\n\n"); + fclose(f); + } + } +#endif + #ifndef __GNUC__ if (!cleanup) { cleanup = !0; atexit(_closeall); @@ -348,11 +421,11 @@ midwayerror: int dlclose(void *dxe) { if (!dxe) return -1; - if (--((dxe_h)dxe)->inuse) + if (--((dxe_h)dxe)->in_use) return 0; /* finalization */ if (((dxe_h)dxe)->_fini != -1) ((void (*) (void))(((dxe_h)dxe)->_fini + (long)((dxe_h)dxe)->section))(); @@ -361,10 +434,21 @@ int dlclose(void *dxe) { dxe_h *cur; for (cur = &dxe_chain; *cur; cur = &(*cur)->next) if (*cur == dxe) { + /* Un-register all implicitly loaded modules by this module. */ + dxe_handle_list *implicitly_open_handle_list = (*cur)->implicit_handle_list; + while (implicitly_open_handle_list) + { + dxe_handle_list *next_handle_list = implicitly_open_handle_list->next; + + dlclose(implicitly_open_handle_list->handle); + free(implicitly_open_handle_list); + implicitly_open_handle_list = next_handle_list; + } + *cur = ((dxe_h)dxe)->next; break; } }