open-src/xserver/xorg/sun-src/os/solaris/mdb/modules/Xserver_clients.c
changeset 908 ee1047befc15
parent 907 3c35d611cdaa
child 919 425233ae7236
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/xserver/xorg/sun-src/os/solaris/mdb/modules/Xserver_clients.c	Sat Feb 20 16:30:16 2010 -0800
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ */
+
+
+#include <sys/mdb_modapi.h>
+
+#include "xorg-server.h"
+#include "dixstruct.h"
+#include "misc.h"
+#include "os/osdep.h"
+#include "IA/interactive_srv.h"
+#include "Xserver_mdb.h"
+
+struct client_walk_data {
+    uintptr_t client_next;
+    uintptr_t clients_end;
+    ClientRec client_data;
+};
+
+/* Copied from dix/privates.c in Xorg 1.6 */
+struct _Private {
+    int state;
+    pointer value;
+};
+
+/*
+ * Initialize the client walker by either using the given starting address,
+ * or reading the value of the server's "clients" pointer.  We also allocate
+ * a  for storage, and save this using the walk_data pointer.
+ */
+_X_HIDDEN int
+client_walk_init(mdb_walk_state_t *wsp)
+{
+    struct client_walk_data *cwda;
+    short max_clients = MAXCLIENTS;
+
+# define CUR_MAX_CLIENTS "currentMaxClients"
+
+    if (wsp->walk_addr == NULL) {
+       /* Xorg 1.6 - clients is the array itself */
+       GElf_Sym clients_sym;
+       if (mdb_lookup_by_name("clients", &clients_sym) == -1) {
+	   mdb_warn("failed to lookup 'clients'");
+	   return (WALK_ERR);
+       }
+       wsp->walk_addr = clients_sym.st_value;
+       if (mdb_readvar(&max_clients, CUR_MAX_CLIENTS) == -1) {
+	   mdb_warn("failed to read '%s'", CUR_MAX_CLIENTS);
+	   return (WALK_ERR);
+       } else {
+	   mdb_printf("%s = %d\n", CUR_MAX_CLIENTS, max_clients);
+       }
+    }
+
+    wsp->walk_data = mdb_alloc(sizeof (struct client_walk_data), UM_SLEEP);
+    cwda = (struct client_walk_data *) wsp->walk_data;
+    cwda->clients_end = wsp->walk_addr + (max_clients * (sizeof(void *)));
+    return (WALK_NEXT);
+}
+
+/*
+ * At each step, read a client struct into our private storage, and then invoke
+ * the callback function.  We terminate when we reach the end of the clients
+ * array.
+ */
+_X_HIDDEN int
+client_walk_step(mdb_walk_state_t *wsp)
+{
+	int status;
+	uintptr_t clientPtr;
+	struct client_walk_data *cwda =
+	  (struct client_walk_data *) wsp->walk_data;
+
+	if (wsp->walk_addr == NULL)
+		return (WALK_DONE);
+
+	do {
+	    if (mdb_vread(&clientPtr, sizeof (void *), wsp->walk_addr) == -1) {
+		mdb_warn("failed to read client table entry at %p", wsp->walk_addr);
+		return (WALK_DONE);
+	    }
+	    if (clientPtr == NULL) {
+#ifdef DEBUG
+		mdb_printf("NULL entry at %p", wsp->walk_addr);
+#endif
+		wsp->walk_addr += sizeof(void *);
+	    }
+	    if (wsp->walk_addr >= cwda->clients_end) {
+#ifdef DEBUG
+		mdb_printf("End of client list at %p", cwda->clients_end);
+#endif
+		return (WALK_DONE);
+	    }
+	} while (clientPtr == NULL);
+
+	if (clientPtr == NULL) {
+	    return (WALK_DONE);
+	}
+
+	if (mdb_vread(&(cwda->client_data), sizeof (ClientRec), (uintptr_t) clientPtr) == -1) {
+		mdb_warn("failed to read client data at %p", wsp->walk_addr);
+		return (WALK_DONE);
+	}
+
+	status = wsp->walk_callback(wsp->walk_addr, &(cwda->client_data),
+	  wsp->walk_cbdata);
+
+	wsp->walk_addr = wsp->walk_addr + sizeof(void *);
+	return (status);
+}
+
+/*
+ * The walker's fini function is invoked at the end of each walk.  Since we
+ * dynamically allocated a proc_t in client_walk_init, we must free it now.
+ */
+_X_HIDDEN void
+client_walk_fini(mdb_walk_state_t *wsp)
+{
+	mdb_free(wsp->walk_data, sizeof (ClientRec));
+}
+
+_X_HIDDEN int
+client_pids(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+    uintptr_t clientP;
+    ClientRec client_data;
+
+	if (argc != 0)
+		return (DCMD_USAGE);
+
+	/*
+	 * If no client address was specified on the command line, we can
+	 * print out all clients by invoking the walker, using this
+	 * dcmd itself as the callback.
+	 */
+	if (!(flags & DCMD_ADDRSPEC)) {
+		if (mdb_walk_dcmd("client_walk", "client_pids",
+		    argc, argv) == -1) {
+			mdb_warn("failed to walk 'client_walk'");
+			return (DCMD_ERR);
+		}
+		return (DCMD_OK);
+	}
+
+	/*
+	 * If this is the first invocation of the command, print a nice
+	 * header line for the output that will follow.
+	 */
+	if (DCMD_HDRSPEC(flags))
+		mdb_printf("CLIENT SEQUENCE #  FD  PIDS\n");
+
+
+	if (mdb_vread(&clientP, sizeof (clientP), addr) == sizeof (clientP)) {
+
+	    if (mdb_vread(&client_data, sizeof (client_data), clientP) == sizeof (client_data)) {
+		mdb_printf("%5d  %10d", client_data.index, client_data.sequence);
+
+		if (client_data.osPrivate != NULL) {
+		    OsCommRec oscomm;
+
+		    if (mdb_vread(&oscomm, sizeof (oscomm),
+		      (uintptr_t)client_data.osPrivate) == sizeof (oscomm)) {
+			ClientProcessPtr cpp = NULL;
+
+			mdb_printf("%4d ", oscomm.fd);
+
+			/* Xorg 1.6 or later */
+			{
+			    int IAPrivKeyIndex;
+			    GElf_Sym privkey_sym;
+			    if (mdb_lookup_by_obj("libia.so", "IAPrivKeyIndex",
+						   &privkey_sym) == -1) {
+				mdb_warn("failed to lookup 'libia.so`IAPrivKeyIndex'");
+			    } else {
+				if (mdb_vread(&IAPrivKeyIndex, sizeof(int),
+					      privkey_sym.st_value) != sizeof(int)) {
+				    mdb_warn("failed to read 'IAPrivKeyIndex'");
+				} else {
+				    void *dpaddr = &(client_data.devPrivates[IAPrivKeyIndex]);
+				    struct _Private devPriv;
+
+				    if (mdb_vread(&devPriv, sizeof (devPriv),
+						  (uintptr_t) dpaddr) != sizeof (devPriv)) {
+					mdb_warn("failed to read client_data.devPrivates[IAPrivKeyIndex]");
+				    } else {
+
+					void *cppaddr = devPriv.value;
+
+					if (mdb_vread(&cpp, sizeof (cpp), (uintptr_t) cppaddr) != sizeof (cpp)) {
+					    cpp = NULL;
+					    mdb_warn("failed to read client_data.devPrivates[IAPrivKeyIndex].value");
+					}
+				    }
+				}
+			    }
+			}
+
+			if (cpp != NULL) {
+			    ClientProcessRec cpr;
+			    ConnectionPidRec pid;
+
+			    if (mdb_vread(&cpr, sizeof (cpr),
+					  (uintptr_t)cpp) == sizeof (cpr)) {
+				int i;
+				uintptr_t pidP = (uintptr_t) cpr.pids;
+
+				for (i = 0; i < cpr.count; i++, pidP += sizeof(pid)) {
+				    if (mdb_vread(&pid, sizeof (pid), pidP) == sizeof (pid)) {
+					mdb_printf("%d ", pid);
+				    } else {
+					mdb_warn("failed to read pid #%d from %p", i, pidP);
+				    }
+				}
+				mdb_printf("\n");
+
+			    } else {
+				mdb_warn("failed to read struct ClientProcessRec at %p", client_data.osPrivate);
+			    }
+			} else {
+			    mdb_printf(" ??? - NULL ClientProcessPtr\n");
+			}
+		    } else {
+			mdb_warn("failed to read struct OsCommRec at %p", client_data.osPrivate);
+		    }
+		} else {
+		    mdb_printf(" ??? - NULL ClientPtr->osPrivate\n");
+		}
+	    } else {
+		mdb_warn("failed to read ClientRec at %p", clientP);
+	    }
+	} else {
+	    mdb_warn("failed to read ClientPtr at %p", addr);
+	}
+
+	return (DCMD_OK);
+}