Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 73 additions & 87 deletions winsup/cygwin/autoload.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,44 +64,34 @@ bool NO_COPY wsock_started;
* DLL name (n bytes) asciz string containing the name of the DLL.
*/

/* LoadDLLprime is used to prime the DLL info information, providing an
additional initialization routine to call prior to calling the first
function. */
#if defined(__x86_64__)
#define LoadDLLprime(dllname, init_also, no_resolve_on_fork) __asm__ (" \n\
.ifndef " #dllname "_primed \n\
.section .data_cygwin_nocopy,\"w\" \n\
.align 8 \n\
."#dllname "_info: \n\
.quad _std_dll_init \n\
.quad " #no_resolve_on_fork " \n\
.long -1 \n\
.align 8 \n\
.quad " #init_also " \n\
.string16 \"" #dllname ".dll\" \n\
.text \n\
.set " #dllname "_primed, 1 \n\
.endif \n\
");
# define WORD64 ".quad"
#elif defined(__aarch64__)
#define LoadDLLprime(dllname, init_also, no_resolve_on_fork) __asm__ ( "\n\
# define WORD64 ".xword"
#else
# error unimplemented for this target
#endif

/* LoadDLLprime is used to prime the DLL info information, providing an
additional initialization routine to call prior to calling the first
function. WORD64 stands in for .quad/.xword, and .balign (which means
"align to N bytes" on both targets - "x64" and "arm64) is used for
alignment. */
#define LoadDLLprime(dllname, init_also, no_resolve_on_fork) __asm__ ("\n\
.ifndef " #dllname "_primed \n\
.section .data_cygwin_nocopy,\"w\" \n\
.balign 8 \n\
." #dllname "_info: \n\
.xword _std_dll_init \n\
.xword " #no_resolve_on_fork " \n\
.long -1 \n\
.balign 8 \n\
.xword " #init_also " \n\
.balign 8 \n\
." #dllname "_info: \n\
" WORD64 " _std_dll_init \n\
" WORD64 " " #no_resolve_on_fork " \n\
.long -1 \n\
.balign 8 \n\
" WORD64 " " #init_also " \n\
.string16 \"" #dllname ".dll\" \n\
.text \n\
.text \n\
.set " #dllname "_primed, 1 \n\
.endif \n\
.endif \n\
");
#else
#error unimplemented for this target
#endif

/* Standard DLL load macro. May invoke a fatal error if the function isn't
found. */
Expand Down Expand Up @@ -149,28 +139,28 @@ _win32_" #name ": \n\
.p2align 4 \n\
" #name ": \n\
_win32_" #name ": \n\
adr x16, 3f \n\
ldr x16, [x16] \n\
br x16 \n\
adr x16, 3f // x16 = &func_addr slot (label 3 == func_info+12)\n\
ldr x16, [x16] // x16 = *(&func_addr) = 1b first time, real addr later\n\
br x16 // fast-path branch into the resolved DLL func\n\
1: \n\
sub sp, sp, #80 \n\
sub sp, sp, #80 // reserve 80B frame for caller's arg regs + LR\n\
stp x0, x1, [sp, #0] \n\
stp x2, x3, [sp, #16] \n\
stp x4, x5, [sp, #32] \n\
stp x6, x7, [sp, #48] \n\
stp x8, x30, [sp, #64] \n\
adr x16, 2f \n\
ldur x17, [x16] \n\
ldr x17, [x17] \n\
blr x17 \n\
stp x8, x30, [sp, #64] // x30 here == label 2 == &func_info\n\
adr x16, 2f // x16 = &func_info\n\
ldr x17, [x16] // x17 = func_info->dll (= dll_info*)\n\
ldr x17, [x17] // x17 = dll_info->load_state (e.g. _std_dll_init)\n\
blr x17 // call thunk; LR = label 2 = arg to std_dll_init\n\
2: \n\
.xword ." #dllname "_info \n\
.hword " #notimp " \n\
.hword ((" #err ") & 0xffff) \n\
3: \n\
.xword 1b \n\
.asciz \"" #name "\" \n\
.text \n\
.xword ." #dllname "_info // +0 func_info.dll\n\
.hword " #notimp " // +8 func_info.decoration[lo]\n\
.hword ((" #err ") & 0xffff) // +10 func_info.decoration[hi]\n\
3: \n\
.xword 1b // +12 func_info.func_addr (patched by dll_func_load)\n\
.asciz \"" #name "\" // +20 func_info.name (asciz)\n\
.text \n\
");
#else
#error unimplemented for this target
Expand Down Expand Up @@ -261,55 +251,51 @@ msg1: \n\
\n\
.text \n\
.p2align 2 \n\
noload: \n\
ldr x2, [sp] // func_info* \n\
ldr w3, [x2, #8] // decoration \n\
tbz w3, #0, 1f \n\
\n\
asr w4, w3, #16 \n\
str w4, [sp, #8] \n\
mov w0, #127 // ERROR_PROC_NOT_FOUND \n\
noload: \n\
ldr x2, [sp] // x2 = func_info* (pushed by dll_chain)\n\
ldr w3, [x2, #8] // w3 = func_info.decoration\n\
tbz w3, #0, 1f // notimp bit clear -> fatal\n\
asr w4, w3, #16 // w4 = err (sign-extend high half)\n\
str w4, [sp, #8] // spill into dll_chain's xzr slot\n\
mov w0, #127 // ERROR_PROC_NOT_FOUND\n\
bl SetLastError \n\
ldr w0, [sp, #8] \n\
ldr x30, [sp, #88] \n\
add sp, sp, #96 \n\
ret \n\
1: \n\
add x1, x2, #20 \n\
ldur x3, [x2] \n\
ldr x2, [x3, #8] \n\
adrp x0, msg1 \n\
add x0, x0, #:lo12:msg1 \n\
bl api_fatal \n\
ldr w0, [sp, #8] // reload err as return value\n\
ldr x30, [sp, #88] // restore caller LR (16 + 72)\n\
add sp, sp, #96 // drop dll_chain (16) + trampoline (80) frames\n\
ret \n\
1: \n\
add x1, x2, #20 // x1 = &func_info.name\n\
ldr x3, [x2] // x3 = dll_info*\n\
ldr x2, [x3, #8] // x2 = dll_info->handle\n\
adrp x0, msg1 \n\
add x0, x0, #:lo12:msg1\n\
bl api_fatal // never returns \n\
\n\
.globl dll_func_load \n\
dll_func_load: \n\
ldr x2, [sp] \n\
ldur x3, [x2] \n\
ldr x0, [x3, #8] \n\
add x1, x2, #20 \n\
dll_func_load: \n\
ldr x2, [sp] // x2 = func_info* (pushed by dll_chain)\n\
ldr x3, [x2] // x3 = dll_info*\n\
ldr x0, [x3, #8] // x0 = dll handle (arg1 to GetProcAddress)\n\
add x1, x2, #20 // x1 = &func_info.name (arg2)\n\
bl GetProcAddress \n\
cbz x0, noload \n\
\n\
ldr x2, [sp] \n\
add x3, x2, #12 \n\
str x0, [x3] \n\
\n\
sub x16, x2, #52 \n\
\n\
add sp, sp, #16 \n\
ldp x0, x1, [sp, #0] \n\
cbz x0, noload // 0 -> not found, jump to error path\n\
ldr x2, [sp] // reload func_info*\n\
str x0, [x2, #12] // patch func_addr slot (label 3)\n\
sub x16, x2, #52 // x16 = trampoline entry; '#52' = 12B prologue\n\
// + 40B slow path; sync with LoadDLLfuncEx3\n\
add sp, sp, #16 // drop dll_chain frame\n\
ldp x0, x1, [sp, #0] // restore caller's arg regs\n\
ldp x2, x3, [sp, #16] \n\
ldp x4, x5, [sp, #32] \n\
ldp x6, x7, [sp, #48] \n\
ldp x8, x30, [sp, #64] \n\
add sp, sp, #80 \n\
br x16 \n\
ldp x8, x30, [sp, #64]\n\
add sp, sp, #80 // drop trampoline frame\n\
br x16 // re-enter trampoline; fast path now hits real func\n\
\n\
.global dll_chain \n\
dll_chain: \n\
stp x0, xzr, [sp, #-16]! \n\
br x1 \n\
stp x0, xzr, [sp, #-16]! // x0 = func_info* (= ret.high); push for dll_func_load\n\
br x1 // x1 = dll->init (= ret.low); tail-call resolver\n\
");
#else
#error unimplemented for this target
Expand Down Expand Up @@ -781,4 +767,4 @@ LoadDLLfunc (PdhAddEnglishCounterW, pdh)
LoadDLLfunc (PdhCollectQueryData, pdh)
LoadDLLfunc (PdhGetFormattedCounterValue, pdh)
LoadDLLfunc (PdhOpenQueryW, pdh)
}
}