diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f7c6b9690..c8f68a39e 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,39 @@ +2005-12-02 Christopher Faylor + + * cygtls.h (_cygtls::el): New field. + (_cygtls::handle_exceptions): New function declaration. + (_cygtls::handle_threadlist_exception): Ditto. + (_cygtls::init_exception_handler): Ditto. + (_cygtls::init_threadlist_exceptions): Remove arg from declaration. + * cygtls.cc (_cygtls::call2): Don't initialize exceptions here. + (_cygtls::init_thread): Do it here instead and use member function. + (_cygtls::handle_threadlist_exception): Move into _cygtls class. + (_cygtls::init_exception_handler): Ditto. Rely on existence of 'el' + memmber in _cygtls. + (_cygtls::init_threadlist_exceptions): Ditto. + * dcrt0.cc (dll_crt0_1): Remove exception_list definition and setting + since it now commonly resides in the tls. + * exceptions.cc (init_exception_handler): Move to cygtls.cc. + (init_exceptions): Ditto. + (rtl_unwind): New, safe wrapper function for RtlUnwind. + (_cygtls::handle_exceptions): Move to _cygtls. Call rtl_unwind to + unwind frames and eliminate copying of structures. Put address of + failing instruction in si_addr, not the address on the stack. Return 0 + to indicate that we've handled this exception. + * external.cc (cygwin_internal): Make CW_INIT_EXCEPTIONS a no-op. + * sigproc.cc (wait_sig): Accommodate argument change to + _cygtls::init_threadlist_exceptions. + * tlsoffsets.h: Regenerate. + * include/exceptions.h (exception_list): Add more stuff to the + exception list. Apparently windows needs this? + (init_exceptions): Remove bogus declaration. + + * include/cygwin/signal.h (SI_USER): Redefine as zero as per SUSv3. + + * thread.cc (pthread_kill): Set si_pid and si_uid. + + * timer.cc (timer_thread): Set si_code to SI_KERNEL. + 2005-12-01 Christopher Faylor * dcrt0.cc (getstack): Try harder to modify memory. diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index da72fc2ec..1e6ff4dd0 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -88,10 +88,6 @@ _cygtls::call (DWORD (*func) (void *, void *), void *arg) void _cygtls::call2 (DWORD (*func) (void *, void *), void *arg, void *buf) { - exception_list except_entry; - /* Initialize this thread's ability to respond to things like - SIGSEGV or SIGFPE. */ - init_exceptions (&except_entry); _my_tls.init_thread (buf, func); DWORD res = func (arg, buf); _my_tls.remove (INFINITE); @@ -117,6 +113,9 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *)) } local_clib._current_locale = "C"; locals.process_logmask = LOG_UPTO (LOG_DEBUG); + /* Initialize this thread's ability to respond to things like + SIGSEGV or SIGFPE. */ + init_exception_handler (handle_exceptions); } locals.exitsock = INVALID_SOCKET; @@ -240,8 +239,8 @@ _cygtls::set_siginfo (sigpacket *pack) } extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); -static int -handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *c, void *) +int +_cygtls::handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *c, void *) { if (e->ExceptionCode != STATUS_ACCESS_VIOLATION) { @@ -269,9 +268,24 @@ handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *c, void return 0; } +/* Set up the exception handler for the current thread. The PowerPC & Mips + use compiler generated tables to set up the exception handlers for each + region of code, and the kernel walks the call list until it finds a region + of code that handles exceptions. The x86 on the other hand uses segment + register fs, offset 0 to point to the current exception handler. */ + +extern exception_list *_except_list asm ("%fs:0"); + void -_cygtls::init_threadlist_exceptions (exception_list *el) +_cygtls::init_exception_handler (exception_handler *eh) { - extern void init_exception_handler (exception_list *, exception_handler *); - init_exception_handler (el, handle_threadlist_exception); + el.handler = eh; + el.prev = _except_list; + _except_list = ⪙ +} + +void +_cygtls::init_threadlist_exceptions () +{ + init_exception_handler (handle_threadlist_exception); } diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index 008de05bb..901d58a9b 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -17,6 +17,7 @@ details. */ #include #undef _NOMNTENT_FUNCS #include +#include #ifndef _WINSOCK_H /* Stupid hack: Including winsock.h explicitly causes too many problems. */ @@ -182,6 +183,7 @@ struct _cygtls }; struct _local_storage locals; class cygthread *_ctinfo; + exception_list el; san andreas; waitq wq; struct _cygtls *prev, *next; @@ -212,7 +214,13 @@ struct _cygtls void __stdcall interrupt_setup (int sig, void *handler, struct sigaction& siga) __attribute__((regparm(3))); - void init_threadlist_exceptions (struct _exception_list *); + + /* exception handling */ + static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *); + static int handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *c, void *); + void init_exception_handler (int (*) (EXCEPTION_RECORD *, void *, CONTEXT *, void*)); + void init_threadlist_exceptions (); + #ifdef _THREAD_H operator HANDLE () const {return tid->win32_obj_id;} #endif diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index dd5731a3e..8df5e6e4f 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -730,11 +730,6 @@ dll_crt0_0 () static void dll_crt0_1 (char *) { - /* According to onno@stack.urc.tue.nl, the exception handler record must - be on the stack. */ - /* FIXME: Verify forked children get their exception handler set up ok. */ - exception_list cygwin_except_entry; - check_sanity_and_sync (user_data); malloc_init (); #ifdef CGF @@ -744,9 +739,6 @@ dll_crt0_1 (char *) small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n)); #endif - /* Initialize SIGSEGV handling, etc. */ - init_exceptions (&cygwin_except_entry); - user_data->resourcelocks->Init (); user_data->threadinterface->Init (); ProtectHandle (hMainProc); diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index bc0ea739a..9851183fc 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -36,7 +36,6 @@ details. */ char debugger_command[2 * CYG_MAX_PATH + 20]; extern "C" { -static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *); extern void sigdelayed (); }; @@ -94,28 +93,6 @@ NO_COPY static struct /* Initialization code. */ -// Set up the exception handler for the current thread. The PowerPC & Mips -// use compiler generated tables to set up the exception handlers for each -// region of code, and the kernel walks the call list until it finds a region -// of code that handles exceptions. The x86 on the other hand uses segment -// register fs, offset 0 to point to the current exception handler. - -extern exception_list *_except_list asm ("%fs:0"); - -void -init_exception_handler (exception_list *el, exception_handler *eh) -{ - el->handler = eh; - el->prev = _except_list; - _except_list = el; -} - -extern "C" void -init_exceptions (exception_list *el) -{ - init_exception_handler (el, handle_exceptions); -} - BOOL WINAPI dummy_ctrl_c_handler (DWORD dwCtrlType) { @@ -403,11 +380,31 @@ try_to_debug (bool waitloop) return dbg; } +extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); +static void __stdcall rtl_unwind (void *, PEXCEPTION_RECORD) __attribute__ ((noinline, regparm (3))); +void __stdcall +rtl_unwind (void *frame, PEXCEPTION_RECORD e) +{ + __asm__ ("\n\ + pushl %%ebx \n\ + pushl %%edi \n\ + pushl %%esi \n\ + pushl $0 \n\ + pushl %1 \n\ + pushl $1f \n\ + pushl %0 \n\ + call _RtlUnwind@16 \n\ +1: \n\ + popl %%esi \n\ + popl %%edi \n\ + popl %%ebx \n\ +": : "r" (frame), "r" (e)); +} + /* Main exception handler. */ -extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); -static int -handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) +int +_cygtls::handle_exceptions (EXCEPTION_RECORD *e, void *frame, CONTEXT *in, void *) { static bool NO_COPY debugging; static int NO_COPY recursed; @@ -421,16 +418,13 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) /* If we've already exited, don't do anything here. Returning 1 tells Windows to keep looking for an exception handler. */ - if (exit_already) + if (exit_already || e->ExceptionFlags) return 1; - EXCEPTION_RECORD e = *e0; - CONTEXT in = *in0; - siginfo_t si; si.si_code = SI_KERNEL; /* Coerce win32 value to posix value. */ - switch (e.ExceptionCode) + switch (e->ExceptionCode) { case STATUS_FLOAT_DENORMAL_OPERAND: case STATUS_FLOAT_DIVIDE_BY_ZERO: @@ -514,8 +508,9 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) return 1; } - debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e.ExceptionCode, in.Eip, in.Esp); - debug_printf ("In cygwin_except_handler sig %d at %p", si.si_signo, in.Eip); + rtl_unwind (frame, e); + debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp); + debug_printf ("In cygwin_except_handler sig %d at %p", si.si_signo, in->Eip); if (global_sigs[si.si_signo].sa_mask & SIGTOMASK (si.si_signo)) syscall_printf ("signal %d, masked %p", si.si_signo, @@ -524,9 +519,9 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) debug_printf ("In cygwin_except_handler calling %p", global_sigs[si.si_signo].sa_handler); - DWORD *ebp = (DWORD *)in.Esp; + DWORD *ebp = (DWORD *) in->Esp; for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--) - if (*ebp == in.SegCs && ebp[-1] == in.Eip) + if (*ebp == in->SegCs && ebp[-1] == in->Eip) { ebp -= 2; break; @@ -534,7 +529,7 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) if (!me.fault_guarded () && (!cygwin_finished_initializing - || &_my_tls == _sig_tls + || &me == _sig_tls || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)) @@ -542,7 +537,7 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) /* Print the exception to the console */ if (!myself->cygstarted) for (int i = 0; status_info[i].name; i++) - if (status_info[i].code == e.ExceptionCode) + if (status_info[i].code == e->ExceptionCode) { system_printf ("Exception: %s", status_info[i].name); break; @@ -561,25 +556,22 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) } open_stackdumpfile (); - exception (&e, &in); + exception (e, in); stackdump ((DWORD) ebp, 0, 1); } signal_exit (0x80 | si.si_signo); // Flag signal + core dump } - extern DWORD ret_here[]; - RtlUnwind (frame, ret_here, e0, 0); - __asm__ volatile (".equ _ret_here,."); - if (me.fault_guarded ()) me.return_from_fault (); - si.si_addr = ebp; + si.si_addr = (void *) in->Eip; si.si_errno = si.si_pid = si.si_uid = 0; me.push ((__stack_t) ebp, true); sig_send (NULL, si, &me); // Signal myself - return 1; + e->ExceptionFlags = 0; + return 0; } /* Utilities to call a user supplied exception handler. */ diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index d9686401a..2a6badad2 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -184,7 +184,7 @@ cygwin_internal (cygwin_getinfo_types t, ...) return (DWORD) fillout_pinfo (va_arg (arg, pid_t), 1); case CW_INIT_EXCEPTIONS: - init_exceptions (va_arg (arg, exception_list *)); + /* noop */ /* init_exceptions (va_arg (arg, exception_list *)); */ return 0; case CW_GET_CYGDRIVE_INFO: diff --git a/winsup/cygwin/include/cygwin/signal.h b/winsup/cygwin/include/cygwin/signal.h index 477903ac5..0ccdbc03f 100644 --- a/winsup/cygwin/include/cygwin/signal.h +++ b/winsup/cygwin/include/cygwin/signal.h @@ -102,8 +102,8 @@ typedef struct enum { - SI_USER = 1, /* sent by kill, raise, pthread_kill */ - SI_ASYNCIO, /* sent by AIO completion (currently + SI_USER = 0, /* sent by kill, raise, pthread_kill */ + SI_ASYNCIO = 2, /* sent by AIO completion (currently unimplemented) */ SI_MESGQ, /* sent by real time mesq state change (currently unimplemented) */ diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 7ea34fe2c..9511d925a 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -283,12 +283,14 @@ details. */ 143: Export clock_getres, clock_setres 144: Export timelocal, timegm. 145: Add MAP_NORESERVE flag to mmap. + 146: Change SI_USER definition. FIXME: Need to develop compatibility macro + for this? */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 145 +#define CYGWIN_VERSION_API_MINOR 146 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/exceptions.h b/winsup/cygwin/include/exceptions.h index 462000d61..5311e1f9e 100644 --- a/winsup/cygwin/include/exceptions.h +++ b/winsup/cygwin/include/exceptions.h @@ -106,13 +106,9 @@ typedef struct _exception_list { struct _exception_list *prev; exception_handler *handler; - - /* We're apparently free to add more stuff here. - At present we don't need any. */ + unsigned long stuff[8]; } exception_list; -void init_exceptions (exception_list *); - #ifdef __cplusplus }; #endif /* __cplusplus */ diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index a4a0dafc3..2c3652c6f 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -1067,8 +1067,7 @@ wait_sig (VOID *) sigproc_printf ("myself->dwProcessId %u", myself->dwProcessId); SetEvent (wait_sig_inited); - exception_list el; - _sig_tls->init_threadlist_exceptions (&el); + _sig_tls->init_threadlist_exceptions (); debug_printf ("entering ReadFile loop, readsig %p, myself->sendsig %p", readsig, myself->sendsig); diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 11d60fc0e..8ad16c3c8 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -2873,7 +2873,9 @@ pthread_kill (pthread_t thread, int sig) siginfo_t si; si.si_signo = sig; si.si_code = SI_USER; - si.si_pid = si.si_uid = si.si_errno = 0; + si.si_pid = myself->pid; + si.si_uid = myself->uid; + si.si_errno = 0; thread->cygtls->set_threadkill (); int rval = sig ? sig_send (NULL, si, thread->cygtls) : 0; diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/timer.cc index 74319ea87..30164207d 100644 --- a/winsup/cygwin/timer.cc +++ b/winsup/cygwin/timer.cc @@ -168,6 +168,7 @@ timer_thread (VOID *x) memset (&si, 0, sizeof (si)); si.si_signo = tt->evp.sigev_signo; si.si_sigval.sival_ptr = tt->evp.sigev_value.sival_ptr; + si.si_code = SI_TIMER; debug_printf ("%p sending sig %d", x, tt->evp.sigev_signo); sig_send (myself_nowait, si); break; diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h index 824e02ca3..0b1d4cd94 100644 --- a/winsup/cygwin/tlsoffsets.h +++ b/winsup/cygwin/tlsoffsets.h @@ -1,121 +1,125 @@ //;# autogenerated: Do not edit. -//; $tls::sizeof__cygtls = 3988; -//; $tls::func = -3988; +//; $tls::sizeof__cygtls = 4028; +//; $tls::func = -4028; //; $tls::pfunc = 0; -//; $tls::saved_errno = -3984; +//; $tls::saved_errno = -4024; //; $tls::psaved_errno = 4; -//; $tls::sa_flags = -3980; +//; $tls::sa_flags = -4020; //; $tls::psa_flags = 8; -//; $tls::oldmask = -3976; +//; $tls::oldmask = -4016; //; $tls::poldmask = 12; -//; $tls::deltamask = -3972; +//; $tls::deltamask = -4012; //; $tls::pdeltamask = 16; -//; $tls::event = -3968; +//; $tls::event = -4008; //; $tls::pevent = 20; -//; $tls::errno_addr = -3964; +//; $tls::errno_addr = -4004; //; $tls::perrno_addr = 24; -//; $tls::initialized = -3960; +//; $tls::initialized = -4000; //; $tls::pinitialized = 28; -//; $tls::sigmask = -3956; +//; $tls::sigmask = -3996; //; $tls::psigmask = 32; -//; $tls::sigwait_mask = -3952; +//; $tls::sigwait_mask = -3992; //; $tls::psigwait_mask = 36; -//; $tls::sigwait_info = -3948; +//; $tls::sigwait_info = -3988; //; $tls::psigwait_info = 40; -//; $tls::threadkill = -3944; +//; $tls::threadkill = -3984; //; $tls::pthreadkill = 44; -//; $tls::infodata = -3940; +//; $tls::infodata = -3980; //; $tls::pinfodata = 48; -//; $tls::tid = -3792; +//; $tls::tid = -3832; //; $tls::ptid = 196; -//; $tls::local_clib = -3788; +//; $tls::local_clib = -3828; //; $tls::plocal_clib = 200; -//; $tls::__dontuse = -3788; +//; $tls::__dontuse = -3828; //; $tls::p__dontuse = 200; -//; $tls::locals = -2724; +//; $tls::locals = -2764; //; $tls::plocals = 1264; -//; $tls::_ctinfo = -1092; +//; $tls::_ctinfo = -1132; //; $tls::p_ctinfo = 2896; +//; $tls::el = -1128; +//; $tls::pel = 2900; //; $tls::andreas = -1088; -//; $tls::pandreas = 2900; +//; $tls::pandreas = 2940; //; $tls::wq = -1080; -//; $tls::pwq = 2908; +//; $tls::pwq = 2948; //; $tls::prev = -1052; -//; $tls::pprev = 2936; +//; $tls::pprev = 2976; //; $tls::next = -1048; -//; $tls::pnext = 2940; +//; $tls::pnext = 2980; //; $tls::stackptr = -1044; -//; $tls::pstackptr = 2944; +//; $tls::pstackptr = 2984; //; $tls::sig = -1040; -//; $tls::psig = 2948; +//; $tls::psig = 2988; //; $tls::incyg = -1036; -//; $tls::pincyg = 2952; +//; $tls::pincyg = 2992; //; $tls::spinning = -1032; -//; $tls::pspinning = 2956; +//; $tls::pspinning = 2996; //; $tls::stacklock = -1028; -//; $tls::pstacklock = 2960; +//; $tls::pstacklock = 3000; //; $tls::stack = -1024; -//; $tls::pstack = 2964; +//; $tls::pstack = 3004; //; $tls::padding = 0; -//; $tls::ppadding = 3988; +//; $tls::ppadding = 4028; //; __DATA__ -#define tls_func (-3988) +#define tls_func (-4028) #define tls_pfunc (0) -#define tls_saved_errno (-3984) +#define tls_saved_errno (-4024) #define tls_psaved_errno (4) -#define tls_sa_flags (-3980) +#define tls_sa_flags (-4020) #define tls_psa_flags (8) -#define tls_oldmask (-3976) +#define tls_oldmask (-4016) #define tls_poldmask (12) -#define tls_deltamask (-3972) +#define tls_deltamask (-4012) #define tls_pdeltamask (16) -#define tls_event (-3968) +#define tls_event (-4008) #define tls_pevent (20) -#define tls_errno_addr (-3964) +#define tls_errno_addr (-4004) #define tls_perrno_addr (24) -#define tls_initialized (-3960) +#define tls_initialized (-4000) #define tls_pinitialized (28) -#define tls_sigmask (-3956) +#define tls_sigmask (-3996) #define tls_psigmask (32) -#define tls_sigwait_mask (-3952) +#define tls_sigwait_mask (-3992) #define tls_psigwait_mask (36) -#define tls_sigwait_info (-3948) +#define tls_sigwait_info (-3988) #define tls_psigwait_info (40) -#define tls_threadkill (-3944) +#define tls_threadkill (-3984) #define tls_pthreadkill (44) -#define tls_infodata (-3940) +#define tls_infodata (-3980) #define tls_pinfodata (48) -#define tls_tid (-3792) +#define tls_tid (-3832) #define tls_ptid (196) -#define tls_local_clib (-3788) +#define tls_local_clib (-3828) #define tls_plocal_clib (200) -#define tls___dontuse (-3788) +#define tls___dontuse (-3828) #define tls_p__dontuse (200) -#define tls_locals (-2724) +#define tls_locals (-2764) #define tls_plocals (1264) -#define tls__ctinfo (-1092) +#define tls__ctinfo (-1132) #define tls_p_ctinfo (2896) +#define tls_el (-1128) +#define tls_pel (2900) #define tls_andreas (-1088) -#define tls_pandreas (2900) +#define tls_pandreas (2940) #define tls_wq (-1080) -#define tls_pwq (2908) +#define tls_pwq (2948) #define tls_prev (-1052) -#define tls_pprev (2936) +#define tls_pprev (2976) #define tls_next (-1048) -#define tls_pnext (2940) +#define tls_pnext (2980) #define tls_stackptr (-1044) -#define tls_pstackptr (2944) +#define tls_pstackptr (2984) #define tls_sig (-1040) -#define tls_psig (2948) +#define tls_psig (2988) #define tls_incyg (-1036) -#define tls_pincyg (2952) +#define tls_pincyg (2992) #define tls_spinning (-1032) -#define tls_pspinning (2956) +#define tls_pspinning (2996) #define tls_stacklock (-1028) -#define tls_pstacklock (2960) +#define tls_pstacklock (3000) #define tls_stack (-1024) -#define tls_pstack (2964) +#define tls_pstack (3004) #define tls_padding (0) -#define tls_ppadding (3988) +#define tls_ppadding (4028)