1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * ident "%Z%%M% %I% %E% SMI" 27 */ 28 package org.opensolaris.os.dtrace; 29 30 import java.io.*; 31 import java.beans.*; 32 33 /** 34 * A value generated by the DTrace {@code mod()}, {@code func()}, or 35 * {@code sym()} action used to lookup the symbol associated with a 36 * kernel address. 37 * <p> 38 * Immutable. Supports persistence using {@link java.beans.XMLEncoder}. 39 * 40 * @author Tom Erickson 41 */ 42 public final class KernelSymbolRecord implements SymbolValueRecord, 43 Serializable, Comparable <KernelSymbolRecord> 44 { 45 static final long serialVersionUID = -7156627773519296848L; 46 47 static { 48 try { 49 BeanInfo info = Introspector.getBeanInfo(KernelSymbolRecord.class); 50 PersistenceDelegate persistenceDelegate = 51 new DefaultPersistenceDelegate( 52 new String[] {"symbol", "address"}) 53 { 54 /* 55 * Need to prevent DefaultPersistenceDelegate from using 56 * overridden equals() method, resulting in a 57 * StackOverFlowError. Revert to PersistenceDelegate 58 * implementation. See 59 * http://forum.java.sun.com/thread.jspa?threadID= 60 * 477019&tstart=135 61 */ 62 protected boolean 63 mutatesTo(Object oldInstance, Object newInstance) 64 { 65 return (newInstance != null && oldInstance != null && 66 oldInstance.getClass() == newInstance.getClass()); 67 } 68 }; 69 BeanDescriptor d = info.getBeanDescriptor(); 70 d.setValue("persistenceDelegate", persistenceDelegate); 71 } catch (IntrospectionException e) { 72 e.printStackTrace(); 73 } 74 } 75 76 /** @serial */ 77 private String symbol; // set natively after creation; treat as final 78 /** @serial */ 79 private final long address; 80 81 /** 82 * Called by native code. 83 */ 84 private 85 KernelSymbolRecord(long addressValue) 86 { 87 address = addressValue; 88 } 89 90 /** 91 * Creates a {@code KernelSymbolRecord} with the given symbol lookup 92 * and kernel address converted in probe context as a result of the 93 * DTrace {@code mod()}, {@code func()}, or {@code sym()} action. 94 * <p> 95 * Supports XML persistence. 96 * 97 * @param addressValue symbol address 98 * @param lookupValue the result in the native DTrace library of 99 * looking up the symbol associated with the given kernel address 100 * @throws NullPointerException if the given lookup value is {@code null} 101 */ 102 public 103 KernelSymbolRecord(String lookupValue, long addressValue) 104 { 105 symbol = lookupValue; 106 address = addressValue; 107 validate(); 108 } 109 110 private final void 111 validate() 112 { 113 if (symbol == null) { 114 throw new NullPointerException("symbol is null"); 115 } 116 } 117 118 /** 119 * Gets the result of the address lookup in the same form returned 120 * by {@link Consumer#lookupKernelFunction(long address)}. 121 * 122 * @return non-null address lookup in the format defined by the 123 * native DTrace library 124 */ 125 public String 126 getSymbol() 127 { 128 return symbol; 129 } 130 131 /** 132 * Called by native code and ProbeData addSymbolRecord() 133 */ 134 void 135 setSymbol(String lookupValue) 136 { 137 symbol = lookupValue; 138 validate(); 139 } 140 141 /** 142 * Gets the symbol's kernel address. 143 * 144 * @return the symbol's kernel address 145 */ 146 public long 147 getAddress() 148 { 149 return address; 150 } 151 152 /** 153 * Gets the symbol's kernel address. The value is used in {@link 154 * #equals(Object o) equals()} and {@link 155 * #compareTo(KernelSymbolRecord r) compareTo()} to test equality 156 * and to determine the natural ordering of {@code 157 * KernelSymbolRecord} instances. 158 * 159 * @return non-null value of the symbol's kernel address 160 */ 161 public Long 162 getValue() 163 { 164 return address; 165 } 166 167 /** 168 * Compares the specified object with this {@code KernelSymbolRecord} 169 * for equality. Returns {@code true} if and only if the specified 170 * object is also a {@code KernelSymbolRecord} and both records have 171 * the same address. 172 * 173 * @return {@code true} if and only if the specified object is also 174 * a {@code KernelSymbolRecord} and both records have the same 175 * address 176 */ 177 @Override 178 public boolean 179 equals(Object o) 180 { 181 if (o instanceof KernelSymbolRecord) { 182 KernelSymbolRecord r = (KernelSymbolRecord)o; 183 return (address == r.address); 184 } 185 return false; 186 } 187 188 /** 189 * Overridden to ensure that equal instances have equal hash codes. 190 */ 191 @Override 192 public int 193 hashCode() 194 { 195 return (int)(address ^ (address >>> 32)); 196 } 197 198 /** 199 * Compares this record with the given kernel symbol lookup and 200 * orders by address. The comparison treats addresses as unsigned 201 * values so the ordering is consistent with that defined in the 202 * native DTrace library. The {@code compareTo()} method is 203 * compatible with {@link #equals(Object o) equals()}. 204 * 205 * @return -1, 0, or 1 as this record's address is less than, equal 206 * to, or greater than the given record's address 207 */ 208 public int 209 compareTo(KernelSymbolRecord r) 210 { 211 return ProbeData.compareUnsigned(address, r.address); 212 } 213 214 private void 215 readObject(ObjectInputStream s) 216 throws IOException, ClassNotFoundException 217 { 218 s.defaultReadObject(); 219 // check class invariants 220 try { 221 validate(); 222 } catch (Exception e) { 223 InvalidObjectException x = new InvalidObjectException( 224 e.getMessage()); 225 x.initCause(e); 226 throw x; 227 } 228 } 229 230 /** 231 * Gets the result of this symbol lookup. The format is defined in 232 * the native DTrace library and is as stable as that library 233 * definition. 234 * 235 * @return {@link #getSymbol()} 236 */ 237 @Override 238 public String 239 toString() 240 { 241 return symbol; 242 } 243 } 244