2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. 2N/A * Private structures. 2N/A * This is the name of the variable in libc that contains 2N/A * the uberdata address that we will need. 2N/A * This is the actual name of uberdata, used in the event 2N/A * that tdb_bootstrap has not yet been initialized. 2N/A * The library name should end with ".so.1", but older versions of 2N/A * dbx expect the unadorned name and malfunction if ".1" is specified. 2N/A * Unfortunately, if ".1" is not specified, mdb malfunctions when it 2N/A * is applied to another instance of itself (due to the presence of 2N/A * Initialize threads debugging interface. 2N/A * This function does nothing, and never did. 2N/A * But the symbol is in the ABI, so we can't delete it. 2N/A * Short-cut to read just the hash table size from the process, 2N/A * to avoid repeatedly reading the full uberdata structure when 2N/A * dealing with a single-threaded process. 2N/A default:
/* uninitialized */ 2N/A case 1:
/* partially initialized */ 2N/A case 2:
/* fully initialized */ 2N/A }
else {
/* single-threaded */ 2N/A * It may not be ulwp_one if this is a child of fork1(). 2N/A case 2:
/* fully initialized */ 2N/A case 1:
/* partially initialized */ 2N/A * Uninitialized -- do the startup work. 2N/A * We set ta_p->initialized to -1 to cut off recursive calls 2N/A * into libc_db by code in the provider of ps_pglobal_lookup(). 2N/A * Read the uberdata address into the thread agent structure. 2N/A /* primary linkmap in the tgt is not initialized */ 2N/A /* primary linkmap in the tgt is not initialized */ 2N/A#
endif /* _SYSCALL32 */ 2N/A * Allocate a new agent process handle ("thread agent"). 2N/A * ps_pdmodel might not be defined if this is an older client. 2N/A * Make it a weak symbol and test if it exists before calling. 2N/A * Initialize the agent process handle. 2N/A * Pick up the symbol value we need from the target process. 2N/A * Because the old libthread_db enabled lock tracking by default, 2N/A * we must also do it. However, we do it only if the application 2N/A * provides the ps_kill() and ps_lrolltoaddr() interfaces. 2N/A * (dbx provides the ps_kill() and ps_lrolltoaddr() interfaces.) 2N/A * Lock tracking was already enabled or we 2N/A * failed to enable it, probably because we 2N/A * are examining a core file. In either case 2N/A * set the sync_tracking flag non-zero to 2N/A * indicate that we should not attempt to 2N/A * disable lock tracking when we delete the 2N/A * agent process handle in td_ta_delete(). 2N/A * Utility function to grab the readers lock and return the prochandle, 2N/A * given an agent process handle. Performs standard error checking. 2N/A * Returns non-NULL with the lock held, or NULL with the lock not held. 2N/A * Utility function to grab the readers lock and return the prochandle, 2N/A * given an agent thread handle. Performs standard error checking. 2N/A * Returns non-NULL with the lock held, or NULL with the lock not held. 2N/A * Utility function to grab the readers lock and return the prochandle, 2N/A * given a synchronization object handle. Performs standard error checking. 2N/A * Returns non-NULL with the lock held, or NULL with the lock not held. 2N/A * Unlock the agent process handle obtained from ph_lock_*(). 2N/A * De-allocate an agent process handle, 2N/A * releasing all related resources. 2N/A * XXX -- This is hopelessly broken --- 2N/A * Storage for thread agent is not deallocated. The prochandle 2N/A * in the thread agent is set to NULL so that future uses of 2N/A * the thread agent can be detected and an error value returned. 2N/A * All functions in the external user interface that make 2N/A * use of the thread agent are expected 2N/A * to check for a NULL prochandle in the thread agent. 2N/A * All such functions are also expected to obtain a 2N/A * reader lock on the thread agent while it is using it. 2N/A * This is the only place we grab the writer lock. 2N/A * We are going to NULL out the prochandle. 2N/A * If synch. tracking was disabled when td_ta_new() was called and 2N/A * if td_ta_sync_tracking_enable() was never called, then disable 2N/A * synch. tracking (it was enabled by default in td_ta_new()). 2N/A * Map an agent process handle to a client prochandle. 2N/A * Currently unused by dbx. 2N/A * Set the process's suggested concurrency level. 2N/A * This is a no-op in a one-level model. 2N/A * Currently unused by dbx. 2N/A * Get the number of threads in the process. 2N/A#
endif /* _SYSCALL32 */ 2N/A * Check the value in data against the thread id. 2N/A * If it matches, return 1 to terminate iterations. 2N/A * This function is used by td_ta_map_id2thr() to map a tid to a thread handle. 2N/A * Given a thread identifier, return the corresponding thread handle. 2N/A * LOCKING EXCEPTION - Locking is not required here because 2N/A * the locking and checking will be done in __td_ta_thr_iter. 2N/A * Map the address of a synchronization object to a sync. object handle. 2N/A * Check the magic number of the sync. object to make sure it's valid. 2N/A * The magic number is at the same offset for all sync. objects. 2N/A * Just fill in the appropriate fields of the sync. handle. 2N/A * Iterate over the set of global TSD keys. 2N/A * The call back function is called with three arguments, 2N/A * a key, a pointer to the destructor function, and the cbdata pointer. 2N/A * Currently unused by dbx. 2N/A#
endif /* _SYSCALL32 */ 2N/A#
endif /* _SYSCALL32 */ 2N/A * Iterate over all threads. For each thread call 2N/A * the function pointed to by "cb" with a pointer 2N/A * to a thread handle, and a pointer to data which 2N/A * can be NULL. Only call td_thr_iter_f() on threads 2N/A * which match the properties of state, ti_pri, 2N/A * ti_sigmask_p, and ti_user_flags. If cb returns 2N/A * a non-zero value, terminate iterations. 2N/A * *ta_p - thread agent 2N/A * *cb - call back function defined by user. 2N/A * td_thr_iter_f() takes a thread handle and 2N/A * cbdata_p as a parameter. 2N/A * cbdata_p - parameter for td_thr_iter_f(). 2N/A * state - state of threads of interest. A value of 2N/A * TD_THR_ANY_STATE from enum td_thr_state_e 2N/A * does not restrict iterations by state. 2N/A * ti_pri - lower bound of priorities of threads of 2N/A * interest. A value of TD_THR_LOWEST_PRIORITY 2N/A * iterations by priority. A thread with priority 2N/A * less than ti_pri will NOT be passed to the callback 2N/A * ti_sigmask_p - signal mask of threads of interest. 2N/A * does not restrict iterations by signal mask. 2N/A * ti_user_flags - user flags of threads of interest. A 2N/A * does not restrict iterations by user flags. 2N/A * If state is not within bound, short circuit. 2N/A * For each ulwp_t in the circular linked lists pointed 2N/A * to by "all_lwps" and "all_zombies": 2N/A * (1) Filter each thread. 2N/A * (2) Create the thread_object for each thread that passes. 2N/A * (3) Call the call back function on each thread. 2N/A#
else /* _SYSCALL32 */ 2N/A#
endif /* _SYSCALL32 */ 2N/A * If first_lwp_addr and first_zombie_addr are both NULL, 2N/A * libc must not yet be initialized or all threads have 2N/A * exited. Return TD_NOTHR and all will be well. 2N/A * Run down the lists of all living and dead lwps. 2N/A * Read the ulwp struct. 2N/A#
else /* _SYSCALL32 */ 2N/A#
endif /* _SYSCALL32 */ 2N/A * Filter on state, priority, sigmask, and user flags. 2N/A * Call back - break if the return 2N/A * from the call back is non-zero. 2N/A * Switch to the zombie list, unless it is NULL 2N/A * or we have already been doing the zombie list, 2N/A * in which case terminate the loop. 2N/A * Enable or disable process synchronization object tracking. 2N/A * Currently unused by dbx. 2N/A * Values of tdb_register_sync in the victim process: 2N/A * REGISTER_SYNC_ENABLE enables registration of synch objects 2N/A * REGISTER_SYNC_DISABLE disables registration of synch objects 2N/A * These cause the table to be cleared and tdb_register_sync set to: 2N/A * REGISTER_SYNC_ON registration in effect 2N/A * REGISTER_SYNC_OFF registration not in effect 2N/A * Remember that this interface was called (see td_ta_delete()). 2N/A * Iterate over all known synchronization variables. 2N/A * It is very possible that the list generated is incomplete, 2N/A * because the iterator can only find synchronization variables 2N/A * that have been registered by the process since synchronization 2N/A * object registration was enabled. 2N/A * The call back function cb is called for each synchronization 2N/A * variable with two arguments: a pointer to the synchronization 2N/A * handle and the passed-in argument cbdata. 2N/A * If cb returns a non-zero value, iterations are terminated. 2N/A * First read the hash table. 2N/A * The hash table is large; allocate with mmap(). 2N/A#
endif /* _SYSCALL32 */ 2N/A * Now scan the hash table. 2N/A /* not registered since registration enabled */ 2N/A * Enable process statistics collection. 2N/A * Reset process statistics. 2N/A * Read process statistics. 2N/A * Transfer information from lwp struct to thread information struct. 2N/A * XXX -- lots of this needs cleaning up. 2N/A * The bloody fools got this backwards! 2N/A * The bloody fools got this backwards! 2N/A#
endif /* _SYSCALL32 */ 2N/A * Get thread information. 2N/A * Read the ulwp struct from the process. 2N/A * Transfer the ulwp struct to the thread information struct. 2N/A#
endif /* _SYSCALL32 */ 2N/A * Given a process and an event number, return information about 2N/A * an address in the process or at which a breakpoint can be set 2N/A * to monitor the event. 2N/A * Add the events in eventset 2 to eventset 1. 2N/A * Delete the events in eventset 2 from eventset 1. 2N/A * Either add or delete the given event set from a thread's event mask. 2N/A#
endif /* _SYSCALL32 */ 2N/A * Enable or disable tracing for a given thread. Tracing 2N/A * is filtered based on the event mask of each thread. Tracing 2N/A * can be turned on/off for the thread without changing thread 2N/A * Currently unused by dbx. 2N/A * Set event mask to enable event. event is turned on in 2N/A * event mask for thread. If a thread encounters an event 2N/A * for which its event mask is on, notification will be sent 2N/A * Addresses for each event are provided to the 2N/A * debugger. It is assumed that a breakpoint of some type will 2N/A * be placed at that address. If the event mask for the thread 2N/A * is on, the instruction at the address will be executed. 2N/A * Otherwise, the instruction will be skipped. 2N/A * Enable or disable a set of events in the process-global event mask, 2N/A * depending on the value of onoff. 2N/A * Enable a set of events in the process-global event mask. 2N/A * Set event mask to disable the given event set; these events are cleared 2N/A * from the event mask of the thread. Events that occur for a thread 2N/A * with the event masked off will not cause notification to be 2N/A * sent to the debugger (see td_thr_set_event for fuller description). 2N/A * Disable a set of events in the process-global event mask. 2N/A * This function returns the most recent event message, if any, 2N/A * associated with a thread. Given a thread handle, return the message 2N/A * corresponding to the event encountered by the thread. Only one 2N/A * message per thread is saved. Messages from earlier events are lost 2N/A * when later events occur. 2N/A /* "Consume" the message */ 2N/A /* "Consume" the message */ 2N/A#
endif /* _SYSCALL32 */ 2N/A * The callback function td_ta_event_getmsg uses when looking for 2N/A * a thread with an event. A thin wrapper around td_thr_event_getmsg. 2N/A * Got an event, stop iterating. 2N/A * Because of past mistakes in interface definition, 2N/A * we are forced to pass back a static local variable 2N/A * for the thread handle because th_p is a pointer 2N/A * to a local variable in __td_ta_thr_iter(). 2N/A * This function is just like td_thr_event_getmsg, except that it is 2N/A * passed a process handle rather than a thread handle, and returns 2N/A * an event message for some thread in the process that has an event 2N/A * message pending. If no thread has an event message pending, this 2N/A * routine returns TD_NOEVENT. Thus, all pending event messages may 2N/A * be collected from a process by repeatedly calling this routine 2N/A * until it returns TD_NOEVENT. 2N/A * The caller holds the prochandle lock 2N/A * and has already verfied everything. 2N/A#
endif /* _SYSCALL32 */ 2N/A * XXX: What does this mean in a one-level model? 2N/A * Resume a suspended thread. 2N/A * XXX: What does this mean in a one-level model? 2N/A * Set a thread's signal mask. 2N/A * Currently unused by dbx. 2N/A * Set a thread's "signals-pending" set. 2N/A * Currently unused by dbx. 2N/A * Get a thread's general register set. 2N/A * Set a thread's general register set. 2N/A * Get a thread's floating-point register set. 2N/A * Set a thread's floating-point register set. 2N/A * Get the size of the extra state register set for this architecture. 2N/A * Currently unused by dbx. 2N/A * Get a thread's extra state register set. 2N/A * Set a thread's extra state register set. 2N/A * Get the size of the extra state register set for this processor. 2N/A * Currently unused by dbx. 2N/A * ps_lgetcxregsize might not be defined if this is an older client. 2N/A * Make it a weak symbol and test if it exists before calling. 2N/A * Get a thread's extra state register set. 2N/A * ps_lgetcxregs might not be defined if this is an older client. 2N/A * Make it a weak symbol and test if it exists before calling. 2N/A * Set a thread's extra state register set. 2N/A * ps_lsetcxregs might not be defined if this is an older client. 2N/A * Make it a weak symbol and test if it exists before calling. 2N/A * Check the struct thread address in *th_p again first 2N/A * value in "data". If value in data is found, set second value 2N/A * in "data" to 1 and return 1 to terminate iterations. 2N/A * This function is used by td_thr_validate() to verify that 2N/A * a thread handle is valid. 2N/A * Validate the thread handle. Check that 2N/A * corresponds to thread with handle *th_p. 2N/A * Currently unused by dbx. 2N/A * LOCKING EXCEPTION - Locking is not required 2N/A * here because no use of the thread agent is made (other 2N/A * than the sanity check) and checking of the thread 2N/A * agent will be done in __td_ta_thr_iter. 2N/A * Get a thread's private binding to a given thread specific 2N/A * data(TSD) key(see thr_getspecific(3T). If the thread doesn't 2N/A * have a binding for a particular key, then NULL is returned. 2N/A#
endif /* _SYSCALL32 */ 2N/A /* NULL has already been stored in data_pp */ 2N/A * Read the value from the thread's tsd array. 2N/A#
endif /* _SYSCALL32 */ 2N/A * Get the base address of a thread's thread local storage (TLS) block 2N/A * for the module (executable or shared object) identified by 'moduleid'. 2N/A#
endif /* _SYSCALL32 */ 2N/A * Change a thread's priority to the value specified by ti_pri. 2N/A * Currently unused by dbx. 2N/A * This structure links td_thr_lockowner and the lowner_cb callback function. 2N/A * Iterate over the set of locks owned by a specified thread. 2N/A * If cb returns a non-zero value, terminate iterations. 2N/A * Just sanity checks. 2N/A * If a thread is asleep on a synchronization variable, 2N/A * then get the synchronization handle. 2N/A * No need to stop the process for a simple read. 2N/A#
endif /* _SYSCALL32 */ 2N/A * Which thread is running on an lwp? 2N/A * Common code for td_sync_get_info() and td_sync_get_stats() 2N/A * Determine the sync. object type; a little type fudgery here. 2N/A * First attempt to read the whole union. If that fails, attempt 2N/A * to read just the condvar. A condvar is the smallest sync. object. 2N/A /* this is useless but the old interface provided it */ 2N/A /* this is useless but the old interface provided it */ 2N/A * Given a synchronization handle, fill in the 2N/A * information for the synchronization variable into *si_p. 2N/A * Compute the hash table index from the synch object's address. 2N/A * Get the address of the first element in the linked list. 2N/A * Search the linked list for an entry for the synch object.. 2N/A * Given a synchronization handle, fill in the 2N/A * statistics for the synchronization variable into *ss_p. 2N/A /* we can correct TD_BADSH */ 2N/A /* we correct si_type and si_size below */ 2N/A * Get the address of the hash table in the target process. 2N/A#
endif /* _SYSCALL32 */ 2N/A * We have the hash table entry. Transfer the data to 2N/A * the td_syncstats_t structure provided by the caller. 2N/A * Change the state of a synchronization variable. 2N/A * 1) mutex lock state set to value 2N/A * 2) semaphore's count set to value 2N/A * 3) writer's lock set by value < 0 2N/A * 4) reader's lock number of readers set to value >= 0 2N/A * Currently unused by dbx. 2N/A * Read the synch. variable information. 2N/A * First attempt to read the whole union and if that fails 2N/A * fall back to reading only the smallest member, the condvar. 2N/A * Set the new value in the sync. variable, read the synch. variable 2N/A * information. from the process, reset its value and write it back. 2N/A /* Operation not supported on a condition variable */ 2N/A /* Bad sync. object type */ 2N/A#
endif /* _SYSCALL32 */ 2N/A * For a given synchronization variable, iterate over the 2N/A * set of waiting threads. The call back function is passed 2N/A * two parameters, a pointer to a thread handle and a pointer 2N/A * to extra call back data.