/* 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*);