Mercurial > illumos > s390-betelgeuse
changeset 1880:1982c224f2bd onnv_39
6410027 ustack() on x86 doesn't match pstack(1)
6414721 it should be legal to have only is-enabled probes
6414729 USDT probes can't be enabled during fork
6414734 $dtrace... symbols appear for static functions containing USDT probes
6414740 processes without DTrace privileges don't auto-enable their USDT probes
6415612 core section headers can be corrupt
6415617 USDT providers with identical names can cause an assertion failure
author | ahl |
---|---|
date | Mon, 24 Apr 2006 21:11:42 -0700 |
parents | ebbc677f4973 |
children | 91880172d596 |
files | usr/src/lib/libdtrace/common/dt_dof.c usr/src/lib/libproc/common/Psymtab.c usr/src/uts/common/dtrace/dtrace.c usr/src/uts/common/dtrace/fasttrap.c usr/src/uts/common/exec/elf/elf.c usr/src/uts/common/os/dtrace_subr.c usr/src/uts/common/os/fork.c usr/src/uts/common/sys/fasttrap_impl.h usr/src/uts/common/sys/proc.h usr/src/uts/intel/dtrace/dtrace_isa.c |
diffstat | 10 files changed, 153 insertions(+), 95 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/lib/libdtrace/common/dt_dof.c Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/lib/libdtrace/common/dt_dof.c Mon Apr 24 21:11:42 2006 -0700 @@ -440,7 +440,12 @@ dofpr.dofpr_func = dof_add_string(ddo, pip->pi_fname); - assert(pip->pi_noffs > 0); + /* + * There should be one probe offset or is-enabled probe offset + * or else this probe instance won't have been created. The + * kernel will reject DOF which has a probe with no offsets. + */ + assert(pip->pi_noffs + pip->pi_nenoffs > 0); dofpr.dofpr_offidx = dt_buf_len(&ddo->ddo_offs) / sizeof (uint32_t); @@ -487,6 +492,7 @@ dof_relohdr_t dofr; dof_secidx_t *dofs; ulong_t xr, nxr; + size_t sz; id_t i; if (pvp->pv_flags & DT_PROVIDER_IMPL) @@ -529,15 +535,17 @@ dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_args, sizeof (uint8_t)); - assert(dt_buf_len(&ddo->ddo_offs) > 0); - dofpv.dofpv_proffs = dof_add_lsect(ddo, NULL, DOF_SECT_PROFFS, sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_offs)); dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_offs, sizeof (uint_t)); - dofpv.dofpv_prenoffs = dof_add_lsect(ddo, NULL, DOF_SECT_PRENOFFS, - sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_enoffs)); + if ((sz = dt_buf_len(&ddo->ddo_enoffs)) != 0) { + dofpv.dofpv_prenoffs = dof_add_lsect(ddo, NULL, + DOF_SECT_PRENOFFS, sizeof (uint_t), 0, sizeof (uint_t), sz); + } else { + dofpv.dofpv_prenoffs = DOF_SECT_NONE; + } dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_enoffs, sizeof (uint_t));
--- a/usr/src/lib/libproc/common/Psymtab.c Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/lib/libproc/common/Psymtab.c Mon Apr 24 21:11:42 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2003,6 +2003,15 @@ } /* + * Prefer the symbol that doesn't begin with a '$' since compilers and + * other symbol generators often use it as a prefix. + */ + if (*bname == '$') + return (-1); + if (*aname == '$') + return (1); + + /* * Prefer the name with fewer leading underscores in the name. */ while (*aname == '_' && *bname == '_') {
--- a/usr/src/uts/common/dtrace/dtrace.c Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/uts/common/dtrace/dtrace.c Mon Apr 24 21:11:42 2006 -0700 @@ -5537,11 +5537,15 @@ { uint32_t priv; - *uidp = crgetuid(cr); - *zoneidp = crgetzoneid(cr); - if (PRIV_POLICY_ONLY(cr, PRIV_ALL, B_FALSE)) { + if (cr == NULL || PRIV_POLICY_ONLY(cr, PRIV_ALL, B_FALSE)) { + /* + * For DTRACE_PRIV_ALL, the uid and zoneid don't matter. + */ priv = DTRACE_PRIV_ALL; } else { + *uidp = crgetuid(cr); + *zoneidp = crgetzoneid(cr); + priv = 0; if (PRIV_POLICY_ONLY(cr, PRIV_DTRACE_KERNEL, B_FALSE)) priv |= DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER; @@ -6636,7 +6640,8 @@ } dtrace_probekey(desc, &pkey); - dtrace_cred2priv(CRED(), &priv, &uid, &zoneid); + dtrace_cred2priv(enab->dten_vstate->dtvs_state->dts_cred.dcr_cred, + &priv, &uid, &zoneid); return (dtrace_match(&pkey, priv, uid, zoneid, dtrace_ecb_create_enable, enab)); @@ -6707,7 +6712,7 @@ * See dtrace_helper_provider_validate(). */ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 && - provider->dofpv_prenoffs != 0) { + provider->dofpv_prenoffs != DOF_SECT_NONE) { enoff_sec = (dof_sec_t *)(uintptr_t)(daddr + dof->dofh_secoff + provider->dofpv_prenoffs * dof->dofh_secsize); enoff = (uint32_t *)(uintptr_t)(daddr + enoff_sec->dofs_offset); @@ -12581,8 +12586,9 @@ enoff_sec = NULL; if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 && - provider->dofpv_prenoffs != 0 && (enoff_sec = dtrace_dof_sect(dof, - DOF_SECT_PRENOFFS, provider->dofpv_prenoffs)) == NULL) + provider->dofpv_prenoffs != DOF_SECT_NONE && + (enoff_sec = dtrace_dof_sect(dof, DOF_SECT_PRENOFFS, + provider->dofpv_prenoffs)) == NULL) return (-1); strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset); @@ -12647,11 +12653,10 @@ } /* - * The offset count must not wrap the index and there must be - * at least one offset. The offsets must also not overflow the - * section's data. - */ - if (probe->dofpr_offidx + probe->dofpr_noffs <= + * The offset count must not wrap the index, and the offsets + * must also not overflow the section's data. + */ + if (probe->dofpr_offidx + probe->dofpr_noffs < probe->dofpr_offidx || (probe->dofpr_offidx + probe->dofpr_noffs) * off_sec->dofs_entsize > off_sec->dofs_size) { @@ -12664,8 +12669,7 @@ * If there's no is-enabled offset section, make sure * there aren't any is-enabled offsets. Otherwise * perform the same checks as for probe offsets - * (immediately above), except that having zero - * is-enabled offsets is permitted. + * (immediately above). */ if (enoff_sec == NULL) { if (probe->dofpr_enoffidx != 0 || @@ -12682,6 +12686,15 @@ "offset"); return (-1); } + + if (probe->dofpr_noffs + probe->dofpr_nenoffs == 0) { + dtrace_dof_error(dof, "zero probe and " + "is-enabled offsets"); + return (-1); + } + } else if (probe->dofpr_noffs == 0) { + dtrace_dof_error(dof, "zero probe offsets"); + return (-1); } if (probe->dofpr_argidx + probe->dofpr_xargc <
--- a/usr/src/uts/common/dtrace/fasttrap.c Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/uts/common/dtrace/fasttrap.c Mon Apr 24 21:11:42 2006 -0700 @@ -298,7 +298,8 @@ * modified, we can't unregister or even * condense. */ - if (fp->ftp_ccount != 0) { + if (fp->ftp_ccount != 0 || + fp->ftp_mcount != 0) { mutex_exit(&fp->ftp_mtx); fp->ftp_marked = 0; continue; @@ -447,9 +448,6 @@ /* * We clean up the pid provider for this process here; user-land * static probes are handled by the meta-provider remove entry point. - * Note that the consumer count is not artificially elevated on the - * pid provider as it is on USDT providers so there's no need to drop - * it here. */ fasttrap_provider_retire(p->p_pid, FASTTRAP_PID_NAME, 0); @@ -902,14 +900,38 @@ mutex_exit(&probe->ftp_prov->ftp_mtx); /* - * Bail out if we can't find the process for this probe or its - * provider is retired (meaning it was valid in a previously exec'ed - * incarnation of this address space). The provider can't go away - * while we're in this code path. + * If this probe's provider is retired (meaning it was valid in a + * previously exec'ed incarnation of this address space), bail out. The + * provider can't go away while we're in this code path. + */ + if (probe->ftp_prov->ftp_retired) + return; + + /* + * If we can't find the process, it may be that we're in the context of + * a fork in which the traced process is being born and we're copying + * USDT probes. Otherwise, the process is gone so bail. */ - if (probe->ftp_prov->ftp_retired || - (p = sprlock(probe->ftp_pid)) == NULL) - return; + if ((p = sprlock(probe->ftp_pid)) == NULL) { + if ((curproc->p_flag & SFORKING) == 0) + return; + + mutex_enter(&pidlock); + p = prfind(probe->ftp_pid); + + /* + * Confirm that curproc is indeed forking the process in which + * we're trying to enable probes. + */ + ASSERT(p != NULL); + ASSERT(p->p_parent == curproc); + ASSERT(p->p_stat == SIDL); + + mutex_enter(&p->p_lock); + mutex_exit(&pidlock); + + sprlock_proc(p); + } ASSERT(!(p->p_flag & SVFORK)); mutex_exit(&p->p_lock); @@ -1122,8 +1144,7 @@ ASSERT(fasttrap_total >= probe->ftp_ntps); atomic_add_32(&fasttrap_total, -probe->ftp_ntps); - size = sizeof (fasttrap_probe_t) + - sizeof (probe->ftp_tps[0]) * (probe->ftp_ntps - 1); + size = offsetof(fasttrap_probe_t, ftp_tps[probe->ftp_ntps]); if (probe->ftp_gen + 1 >= fasttrap_mod_gen) fasttrap_mod_barrier(probe->ftp_gen); @@ -1424,11 +1445,12 @@ proc_t *p; /* - * There need to be no consumers using this provider and no - * associated enabled probes. + * There need to be no associated enabled probes, no consumers + * creating probes, and no meta providers referencing this provider. */ + ASSERT(provider->ftp_rcount == 0); ASSERT(provider->ftp_ccount == 0); - ASSERT(provider->ftp_rcount == 0); + ASSERT(provider->ftp_mcount == 0); fasttrap_proc_release(provider->ftp_proc); @@ -1455,14 +1477,13 @@ } static void -fasttrap_provider_retire(pid_t pid, const char *name, int ccount) +fasttrap_provider_retire(pid_t pid, const char *name, int mprov) { fasttrap_provider_t *fp; fasttrap_bucket_t *bucket; dtrace_provider_id_t provid; ASSERT(strlen(name) < sizeof (fp->ftp_name)); - ASSERT(ccount == 0 || ccount == 1); bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)]; mutex_enter(&bucket->ftb_mtx); @@ -1478,6 +1499,14 @@ return; } + mutex_enter(&fp->ftp_mtx); + ASSERT(!mprov || fp->ftp_mcount > 0); + if (mprov && --fp->ftp_mcount != 0) { + mutex_exit(&fp->ftp_mtx); + mutex_exit(&bucket->ftb_mtx); + return; + } + /* * Mark the provider to be removed in our post-processing step, * mark it retired, and mark its proc as defunct (though it may @@ -1486,7 +1515,6 @@ * setting the retired flag indicates that we're done with this * provider; setting the proc to be defunct indicates that all * tracepoints associated with the traced process should be ignored. - * We also drop the consumer count here by the amount specified. * * We obviously need to take the bucket lock before the provider lock * to perform the lookup, but we need to drop the provider lock @@ -1495,11 +1523,9 @@ * bucket lock therefore protects the integrity of the provider hash * table. */ - mutex_enter(&fp->ftp_mtx); fp->ftp_proc->ftpc_defunct = 1; fp->ftp_retired = 1; fp->ftp_marked = 1; - fp->ftp_ccount -= ccount; provid = fp->ftp_provid; mutex_exit(&fp->ftp_mtx); @@ -1522,7 +1548,6 @@ fasttrap_probe_t *pp; fasttrap_tracepoint_t *tp; char *name; - size_t size; int i, aframes, whack; switch (pdata->ftps_type) { @@ -1565,10 +1590,8 @@ } ASSERT(pdata->ftps_noffs > 0); - size = sizeof (fasttrap_probe_t) + - sizeof (pp->ftp_tps[0]) * (pdata->ftps_noffs - 1); - - pp = kmem_zalloc(size, KM_SLEEP); + pp = kmem_zalloc(offsetof(fasttrap_probe_t, + ftp_tps[pdata->ftps_noffs]), KM_SLEEP); pp->ftp_prov = provider; pp->ftp_faddr = pdata->ftps_pc; @@ -1719,11 +1742,10 @@ } /* - * We elevate the consumer count here to ensure that this provider - * isn't removed until after the meta provider has been told to - * remove it. + * Up the meta provider count so this provider isn't removed until + * the meta provider has been told to remove it. */ - provider->ftp_ccount++; + provider->ftp_mcount++; mutex_exit(&provider->ftp_mtx); @@ -1738,7 +1760,6 @@ fasttrap_provider_t *provider = parg; fasttrap_probe_t *pp; fasttrap_tracepoint_t *tp; - size_t size; int i, j; uint32_t ntps; @@ -1751,6 +1772,7 @@ } ntps = dhpb->dthpb_noffs + dhpb->dthpb_nenoffs; + ASSERT(ntps > 0); atomic_add_32(&fasttrap_total, ntps); @@ -1760,9 +1782,7 @@ return; } - ASSERT(dhpb->dthpb_noffs > 0); - size = sizeof (fasttrap_probe_t) + sizeof (pp->ftp_tps[0]) * (ntps - 1); - pp = kmem_zalloc(size, KM_SLEEP); + pp = kmem_zalloc(offsetof(fasttrap_probe_t, ftp_tps[ntps]), KM_SLEEP); pp->ftp_prov = provider; pp->ftp_pid = provider->ftp_pid;
--- a/usr/src/uts/common/exec/elf/elf.c Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/uts/common/exec/elf/elf.c Mon Apr 24 21:11:42 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -1193,7 +1193,7 @@ */ static int process_scns(core_content_t content, proc_t *p, cred_t *credp, vnode_t *vp, - Shdr *v, int nshdrs, rlim64_t rlimit, Off *doffsetp, int *nshdrsp) + Shdr *v, int nv, rlim64_t rlimit, Off *doffsetp, int *nshdrsp) { vnode_t *lastvp = NULL; struct seg *seg; @@ -1284,7 +1284,7 @@ shdr->sh_link * ehdr.e_shentsize); } - if (v != NULL && i < nshdrs - 1) { + if (v != NULL && i < nv - 1) { if (shdr->sh_size > datasz && shdr->sh_size <= elf_datasz_max) { if (data != NULL) @@ -1352,7 +1352,7 @@ if (strtab->sh_type != SHT_STRTAB) continue; - if (v != NULL && i < nshdrs - 2) { + if (v != NULL && i < nv - 2) { sz = MAX(symtab->sh_size, strtab->sh_size); if (sz > datasz && @@ -1436,7 +1436,7 @@ goto done; } - if (i != nshdrs - 1) { + if (i != nv - 1) { cmn_err(CE_WARN, "elfcore: core dump failed for " "process %d; address space is changing", p->p_pid); error = EIO;
--- a/usr/src/uts/common/os/dtrace_subr.c Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/uts/common/os/dtrace_subr.c Mon Apr 24 21:11:42 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -319,19 +319,9 @@ void dtrace_fasttrap_fork(proc_t *p, proc_t *cp) { - ASSERT(MUTEX_HELD(&p->p_lock)); ASSERT(p->p_proc_flag & P_PR_LOCK); - mutex_exit(&p->p_lock); + ASSERT(p->p_dtrace_count > 0); + ASSERT(dtrace_fasttrap_fork_ptr != NULL); - /* - * If any tracepoints exist, call into the fasttrap module to remove - * those tracepoints. We can rely on that module being loaded since - * the extant tracepoints can't be removed while we hold P_PR_LOCK. - */ - if (p->p_dtrace_count > 0) { - ASSERT(dtrace_fasttrap_fork_ptr != NULL); - dtrace_fasttrap_fork_ptr(p, cp); - } - - mutex_enter(&p->p_lock); + dtrace_fasttrap_fork_ptr(p, cp); }
--- a/usr/src/uts/common/os/fork.c Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/uts/common/os/fork.c Mon Apr 24 21:11:42 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -232,6 +231,7 @@ */ mutex_enter(&p->p_lock); sprlock_proc(p); + p->p_flag |= SFORKING; mutex_exit(&p->p_lock); error = as_dup(p->p_as, &cp->p_as); @@ -258,6 +258,7 @@ task_rele(tk); mutex_enter(&p->p_lock); + p->p_flag &= ~SFORKING; pool_barrier_exit(); continuelwps(p); sprunlock(p); @@ -272,17 +273,26 @@ if (p->p_segacct) shmfork(p, cp); + /* + * Remove all DTrace tracepoints from the child process. We + * need to do this _before_ duplicating USDT providers since + * any associated probes may be immediately enabled. + */ + if (p->p_dtrace_count > 0) + dtrace_fasttrap_fork(p, cp); + + /* + * Duplicate any helper actions and providers. The SFORKING + * we set above informs the code to enable USDT probes that + * sprlock() may fail because the child is being forked. + */ if (p->p_dtrace_helpers != NULL) { ASSERT(dtrace_helpers_fork != NULL); (*dtrace_helpers_fork)(p, cp); } - /* - * Remove all DTrace tracepoints from the child process. - */ mutex_enter(&p->p_lock); - if (p->p_dtrace_count > 0) - dtrace_fasttrap_fork(p, cp); + p->p_flag &= ~SFORKING; sprunlock(p); }
--- a/usr/src/uts/common/sys/fasttrap_impl.h Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/uts/common/sys/fasttrap_impl.h Mon Apr 24 21:11:42 2006 -0700 @@ -85,6 +85,7 @@ kmutex_t ftp_mtx; /* provider lock */ uint64_t ftp_rcount; /* enabled probes ref count */ uint64_t ftp_ccount; /* consumers creating probes */ + uint64_t ftp_mcount; /* meta provider count */ fasttrap_proc_t *ftp_proc; /* shared proc for all provs */ struct fasttrap_provider *ftp_next; /* next prov in hash chain */ } fasttrap_provider_t;
--- a/usr/src/uts/common/sys/proc.h Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/uts/common/sys/proc.h Mon Apr 24 21:11:42 2006 -0700 @@ -446,6 +446,7 @@ #define SSYS 0x00000001 /* system (resident) process */ #define SEXITING 0x00000002 /* process is exiting */ #define SITBUSY 0x00000004 /* setitimer(ITIMER_REAL) in progress */ +#define SFORKING 0x00000008 /* tells called functions that we're forking */ #define SWATCHOK 0x00000010 /* proc in acceptable state for watchpoints */ #define SKILLED 0x00000100 /* SIGKILL has been posted to the process */ #define SSCONT 0x00000200 /* SIGCONT has been posted to the process */
--- a/usr/src/uts/intel/dtrace/dtrace_isa.c Mon Apr 24 19:31:54 2006 -0700 +++ b/usr/src/uts/intel/dtrace/dtrace_isa.c Mon Apr 24 21:11:42 2006 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -139,7 +139,7 @@ s2 = s1 + sizeof (siginfo32_t); } - while (pc != 0 && sp != 0) { + while (pc != 0) { ret++; if (pcstack != NULL) { *pcstack++ = (uint64_t)pc; @@ -148,6 +148,9 @@ break; } + if (sp == 0) + break; + if (oldcontext == sp + s1 || oldcontext == sp + s2) { if (p->p_model == DATAMODEL_NATIVE) { ucontext_t *ucp = (ucontext_t *)oldcontext; @@ -336,13 +339,16 @@ pc = dtrace_fuword32((void *)rp->r_sp); } - while (pc != 0 && sp != 0) { + while (pc != 0) { *pcstack++ = (uint64_t)pc; *fpstack++ = sp; pcstack_limit--; if (pcstack_limit <= 0) break; + if (sp == 0) + break; + if (oldcontext == sp + s1 || oldcontext == sp + s2) { if (p->p_model == DATAMODEL_NATIVE) { ucontext_t *ucp = (ucontext_t *)oldcontext;