/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * 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. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" */ package org.opensolaris.os.dtrace; import java.io.*; import java.beans.*; /** * A value generated by the DTrace {@code mod()}, {@code func()}, or * {@code sym()} action used to lookup the symbol associated with a * kernel address. *

* Immutable. Supports persistence using {@link java.beans.XMLEncoder}. * * @author Tom Erickson */ public final class KernelSymbolRecord implements SymbolValueRecord, Serializable, Comparable { static final long serialVersionUID = -7156627773519296848L; static { try { BeanInfo info = Introspector.getBeanInfo(KernelSymbolRecord.class); PersistenceDelegate persistenceDelegate = new DefaultPersistenceDelegate( new String[] {"symbol", "address"}) { /* * Need to prevent DefaultPersistenceDelegate from using * overridden equals() method, resulting in a * StackOverFlowError. Revert to PersistenceDelegate * implementation. See * http://forum.java.sun.com/thread.jspa?threadID= * 477019&tstart=135 */ protected boolean mutatesTo(Object oldInstance, Object newInstance) { return (newInstance != null && oldInstance != null && oldInstance.getClass() == newInstance.getClass()); } }; BeanDescriptor d = info.getBeanDescriptor(); d.setValue("persistenceDelegate", persistenceDelegate); } catch (IntrospectionException e) { e.printStackTrace(); } } /** @serial */ private String symbol; // set natively after creation; treat as final /** @serial */ private final long address; /** * Called by native code. */ private KernelSymbolRecord(long addressValue) { address = addressValue; } /** * Creates a {@code KernelSymbolRecord} with the given symbol lookup * and kernel address converted in probe context as a result of the * DTrace {@code mod()}, {@code func()}, or {@code sym()} action. *

* Supports XML persistence. * * @param addressValue symbol address * @param lookupValue the result in the native DTrace library of * looking up the symbol associated with the given kernel address * @throws NullPointerException if the given lookup value is {@code null} */ public KernelSymbolRecord(String lookupValue, long addressValue) { symbol = lookupValue; address = addressValue; validate(); } private final void validate() { if (symbol == null) { throw new NullPointerException("symbol is null"); } } /** * Gets the result of the address lookup in the same form returned * by {@link Consumer#lookupKernelFunction(long address)}. * * @return non-null address lookup in the format defined by the * native DTrace library */ public String getSymbol() { return symbol; } /** * Called by native code and ProbeData addSymbolRecord() */ void setSymbol(String lookupValue) { symbol = lookupValue; validate(); } /** * Gets the symbol's kernel address. * * @return the symbol's kernel address */ public long getAddress() { return address; } /** * Gets the symbol's kernel address. The value is used in {@link * #equals(Object o) equals()} and {@link * #compareTo(KernelSymbolRecord r) compareTo()} to test equality * and to determine the natural ordering of {@code * KernelSymbolRecord} instances. * * @return non-null value of the symbol's kernel address */ public Long getValue() { return address; } /** * Compares the specified object with this {@code KernelSymbolRecord} * for equality. Returns {@code true} if and only if the specified * object is also a {@code KernelSymbolRecord} and both records have * the same address. * * @return {@code true} if and only if the specified object is also * a {@code KernelSymbolRecord} and both records have the same * address */ @Override public boolean equals(Object o) { if (o instanceof KernelSymbolRecord) { KernelSymbolRecord r = (KernelSymbolRecord)o; return (address == r.address); } return false; } /** * Overridden to ensure that equal instances have equal hash codes. */ @Override public int hashCode() { return (int)(address ^ (address >>> 32)); } /** * Compares this record with the given kernel symbol lookup and * orders by address. The comparison treats addresses as unsigned * values so the ordering is consistent with that defined in the * native DTrace library. The {@code compareTo()} method is * compatible with {@link #equals(Object o) equals()}. * * @return -1, 0, or 1 as this record's address is less than, equal * to, or greater than the given record's address */ public int compareTo(KernelSymbolRecord r) { return ProbeData.compareUnsigned(address, r.address); } private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); // check class invariants try { validate(); } catch (Exception e) { InvalidObjectException x = new InvalidObjectException( e.getMessage()); x.initCause(e); throw x; } } /** * Gets the result of this symbol lookup. The format is defined in * the native DTrace library and is as stable as that library * definition. * * @return {@link #getSymbol()} */ @Override public String toString() { return symbol; } }