diff options
Diffstat (limited to 'winsup/cygwin/local_includes/dll_init.h')
-rw-r--r-- | winsup/cygwin/local_includes/dll_init.h | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/winsup/cygwin/local_includes/dll_init.h b/winsup/cygwin/local_includes/dll_init.h new file mode 100644 index 000000000..65f4213db --- /dev/null +++ b/winsup/cygwin/local_includes/dll_init.h @@ -0,0 +1,210 @@ +/* dll_init.h + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +struct per_module +{ + void (**ctors)(void); + void (**dtors)(void); + void *data_start; + void *data_end; + void *bss_start; + void *bss_end; + int (*main)(int, char **, char **); + per_module &operator = (per_process *p) + { + ctors = p->ctors; + dtors = p->dtors; + data_start = p->data_start; + data_end = p->data_end; + bss_start = p->bss_start; + bss_end = p->bss_end; + main = p->main; + return *this; + } + void run_ctors (); + void run_dtors (); +}; + + +typedef enum +{ + DLL_NONE, + DLL_SELF, /* main-program.exe, cygwin1.dll */ + DLL_LINK, + DLL_LOAD, + DLL_ANY +} dll_type; + +struct dll +{ + struct dll *next, *prev; + per_module p; + HMODULE handle; + int count; + bool has_dtors; + dll_type type; + long ndeps; + dll** deps; + DWORD image_size; + void* preferred_base; + PWCHAR modname; + FILE_INTERNAL_INFORMATION fii; + PWCHAR forkable_ntname; + WCHAR ntname[1]; /* must be the last data member */ + + void detach (); + int init (); + bool stat_real_file_once (); + void nominate_forkable (PCWCHAR); + bool create_forkable (); + void run_dtors () + { + if (has_dtors) + { + has_dtors = 0; + p.run_dtors (); + } + } + PWCHAR forkedntname () + { + return forkable_ntname && *forkable_ntname ? forkable_ntname : ntname; + } +}; + +#define MAX_DLL_BEFORE_INIT 100 + +class dll_list +{ + bool forkables_supported () + { + return cygwin_shared->forkable_hardlink_support >= 0; + } + DWORD forkables_dirx_size; + bool forkables_created; + PWCHAR forkables_dirx_ntname; + PWCHAR forkables_mutex_name; + HANDLE forkables_mutex; + void track_self (); + dll *find_by_forkedntname (PCWCHAR ntname); + size_t forkable_ntnamesize (dll_type, PCWCHAR fullntname, PCWCHAR modname); + void prepare_forkables_nomination (); + void update_forkables_needs (); + bool update_forkables (); + bool create_forkables (); + void denominate_forkables (); + bool close_mutex (); + void try_remove_forkables (PWCHAR dirbuf, size_t dirlen, size_t dirbufsize); + void set_forkables_inheritance (bool); + void request_forkables (); + + dll *end; + dll *hold; + dll_type hold_type; + static muto protect; + /* Use this buffer under loader lock conditions only. */ + static WCHAR NO_COPY nt_max_path_buffer[NT_MAX_PATH]; +public: + static HANDLE ntopenfile (PCWCHAR ntname, NTSTATUS *pstatus = NULL, + ULONG openopts = 0, ACCESS_MASK access = 0, + HANDLE rootDir = NULL); + static bool read_fii (HANDLE fh, PFILE_INTERNAL_INFORMATION pfii); + static PWCHAR form_ntname (PWCHAR ntbuf, size_t bufsize, PCWCHAR name); + static PWCHAR form_shortname (PWCHAR shortbuf, size_t bufsize, PCWCHAR name); + static PWCHAR nt_max_path_buf () + { + return nt_max_path_buffer; + } + static PCWCHAR buffered_shortname (PCWCHAR name) + { + form_shortname (nt_max_path_buffer, NT_MAX_PATH, name); + return nt_max_path_buffer; + } + + dll *main_executable; + dll start; + int loaded_dlls; + int reload_on_fork; + dll *operator [] (PCWCHAR ntname); + dll *alloc (HINSTANCE, per_process *, dll_type); + dll *find (void *); + void detach (void *); + void init (); + void load_after_fork (HANDLE); + void reserve_space (); + void load_after_fork_impl (HANDLE, dll* which, int retries); + dll *find_by_modname (PCWCHAR modname); + void populate_deps (dll* d); + void topsort (); + void topsort_visit (dll* d, bool goto_tail); + void append (dll* d); + + void release_forkables (); + void cleanup_forkables (); + bool setup_forkables (bool with_forkables) + { + if (!forkables_supported ()) + return true; /* no need to retry fork */ + if (forkables_created) + /* Once created, use forkables in current + process chain on first fork try already. */ + with_forkables = true; + if (with_forkables) + request_forkables (); + return with_forkables; + } + + dll *inext () + { + while ((hold = hold->next)) + if (hold_type == DLL_ANY || hold->type == hold_type) + break; + return hold; + } + + dll *istart (dll_type t) + { + hold_type = t; + hold = &start; + return inext (); + } + void guard(bool lockit) + { + if (lockit) + protect.acquire (); + else + protect.release (); + } + friend void dll_global_dtors (); + dll_list () { protect.init ("dll_list"); } +}; + +/* References: + http://msdn.microsoft.com/en-us/windows/hardware/gg463125 + http://msdn.microsoft.com/en-us/library/ms809762.aspx +*/ +struct pefile +{ + IMAGE_DOS_HEADER dos_hdr; + + char* rva (ptrdiff_t offset) { return (char*) this + offset; } + PIMAGE_NT_HEADERS pe_hdr () { return (PIMAGE_NT_HEADERS) rva (dos_hdr.e_lfanew); } + PIMAGE_OPTIONAL_HEADER optional_hdr () { return &pe_hdr ()->OptionalHeader; } + PIMAGE_DATA_DIRECTORY idata_dir (DWORD which) + { + PIMAGE_OPTIONAL_HEADER oh = optional_hdr (); + return (which < oh->NumberOfRvaAndSizes)? oh->DataDirectory + which : 0; + } +}; + +extern dll_list dlls; +void dll_global_dtors (); + +/* These probably belong in a newlib header but we can keep them here + for now. */ +extern "C" int __cxa_atexit(void (*)(void*), void*, void*); +extern "C" int __cxa_finalize(void*); |