Path: blob/master/debugtools/DDR_VM/src/com/ibm/j9ddr/DDRSymbolFinder.java
6004 views
/*******************************************************************************1* Copyright (c) 2012, 2019 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122package com.ibm.j9ddr;2324import static java.util.logging.Level.FINE;25import static java.util.logging.Level.FINER;2627import java.util.Collection;28import java.util.HashSet;29import java.util.LinkedList;30import java.util.List;31import java.util.Set;32import java.util.logging.Logger;3334import com.ibm.j9ddr.StructureReader.FieldDescriptor;35import com.ibm.j9ddr.corereaders.memory.IMemoryRange;36import com.ibm.j9ddr.corereaders.memory.IModule;37import com.ibm.j9ddr.corereaders.memory.IProcess;38import com.ibm.j9ddr.corereaders.memory.ISymbol;39import com.ibm.j9ddr.corereaders.memory.MemoryFault;40import com.ibm.j9ddr.corereaders.memory.SymbolUtil;41import com.ibm.j9ddr.logging.LoggerNames;4243public class DDRSymbolFinder {4445private static boolean addSymbols = true;4647private static List<String[][]> paths = new LinkedList<String[][]>();4849/* Set of known fields to ignore as StructureName.fieldName */50private static Set<String> ignoredSymbols = new HashSet<String>();5152static {53// Each table off function pointers to add has a path of pointers to follow to find it54// below. The path begins at J9JavaVM structure for the process so the first entry in55// the path is always a field within that.56// The path is an array of tuples of type and field names.57// (Except that java hasn't got tuples so it's a 2 element array instead.)58// All paths are from the J9JavaVM given in ctx.vmAddress.59// The types are necessary because a lot of the pointers are void * in their parent60// structure. By default we just add all the pointers from the last structure in the61// path.6263/* Port Library */64paths.add( new String[][] { {"J9PortLibrary","portLibrary"} });6566ignoredSymbols.add("J9PortLibrary.portVersion");67ignoredSymbols.add("J9PortLibrary.portGlobals");6869/* Internal Functions. */70paths.add( new String[][] { {"J9InternalVMFunctions","internalVMFunctions"} });7172ignoredSymbols.add("J9InternalVMFunctions.reserved0");73ignoredSymbols.add("J9InternalVMFunctions.reserved1");74ignoredSymbols.add("J9InternalVMFunctions.reserved2");7576paths.add( new String[][] { {"J9InternalVMLabels","internalVMLabels"} });7778/* GC Functions */79paths.add( new String[][] { {"J9MemoryManagerFunctions","memoryManagerFunctions"} });8081/* Jni functions */82paths.add( new String[][] { {"jniNativeInterface", "jniFunctionTable"} });8384ignoredSymbols.add("jniNativeInterface.reserved0");85ignoredSymbols.add("jniNativeInterface.reserved1");86ignoredSymbols.add("jniNativeInterface.reserved2");87ignoredSymbols.add("jniNativeInterface.reserved3");8889/* Reflection functions */90paths.add( new String[][] { {"J9ReflectFunctionTable", "reflectFunctions"} });9192/* RAS Trace functions */93paths.add( new String[][] { {"RasGlobalStorage","j9rasGlobalStorage"},94{"UtInterface","utIntf"},95{"UtServerInterface","server"}, });9697ignoredSymbols.add("UtServerInterface.header");9899paths.add( new String[][] { {"RasGlobalStorage","j9rasGlobalStorage"},100{"UtInterface","utIntf"},101{"UtClientInterface","client"}, });102103ignoredSymbols.add("UtClientInterface.header");104105paths.add( new String[][] { {"RasGlobalStorage","j9rasGlobalStorage"},106{"UtInterface","utIntf"},107{"UtModuleInterface","module"}, });108109/* RAS Dump Functions */110paths.add( new String[][] { {"J9RASdumpFunctions","j9rasDumpFunctions"} });111112ignoredSymbols.add("J9RASdumpFunctions.reserved");113}114115public static void addSymbols(IProcess process, long j9RasAddress, StructureReader structureReader) {116117long vmAddress = 0;118119try {120121vmAddress = followPointerFromStructure("J9RAS", j9RasAddress, "vm", structureReader, process);122123} catch (MemoryFault e) {124Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);125logger.log(FINE, null, e);126} catch (com.ibm.j9ddr.NoSuchFieldException e){127Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);128logger.log(FINE, null, e);129} catch (Exception e) {130// This is optional information, we don't want to let an exception escape131// and block DDR startup!132Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);133logger.log(FINE, null, e);134}135136if( vmAddress == 0 ) {137return;138}139140for( String[][] path: paths) {141try {142long currentAddress = vmAddress;143String currentType = "J9JavaVM";144for( String[] pathEntry: path ) {145String structType = pathEntry[0];146String fieldName = pathEntry[1];147currentAddress = followPointerFromStructure(currentType, currentAddress, fieldName, structureReader, process);148currentType = structType;149}150addVoidPointersAsSymbols(currentType, currentAddress, structureReader, process );151} catch (MemoryFault e) {152Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);153logger.log(FINE, null, e);154} catch (com.ibm.j9ddr.NoSuchFieldException e){155Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);156logger.log(FINE, null, e);157} catch (CorruptDataException e) {158Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);159logger.log(FINE, null, e);160} catch (DataUnavailableException e) {161Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);162logger.log(FINE, null, e);163} catch (Exception e) {164// This is optional information, we don't want to let an exception escape165// and block DDR startup!166Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);167logger.log(FINE, null, e);168}169}170171172173}174175private static void addVoidPointersAsSymbols(String structureName,176long structureAddress, StructureReader structureReader, IProcess process) throws DataUnavailableException, CorruptDataException {177178if( structureAddress == 0 ) {179return;180}181182List<String> voidFields = getVoidPointerFieldsFromStructure(structureReader, structureName);183184if( voidFields == null ) {185return;186}187188// Format the hex and structure name the same as the rest of DDR.189int paddingSize = process.bytesPerPointer() * 2;190String formatString = "[!%s 0x%0"+ paddingSize + "X->%s]";191192for( String field : voidFields ) {193194if( ignoredSymbols.contains(structureName+"."+field)) {195// Ignore this field, it's not a function.196continue;197}198199long functionAddress = followPointerFromStructure(structureName, structureAddress, field, structureReader, process);200if( functionAddress == 0 ) {201continue; // Skip null pointers.202}203// Lower case the structure name to match the rest of the DDR !<struct> commands.204String symName = String.format(formatString, structureName.toLowerCase(), structureAddress, field);205if( functionAddress == 0 ) {206// Null pointer, possibly unset or no longer used.207continue;208}209if( addSymbols ) {210IModule module = getModuleForInstructionAddress(process, functionAddress);211if( module == null ) {212continue;213}214boolean found = false;215// Don't override/duplicate symbols we've already seen.216for( ISymbol sym : module.getSymbols() ) {217if( sym.getAddress() == functionAddress ) {218Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);219logger.log(FINER, "DDRSymbolFinder: Found exact match with " + sym.toString() + " not adding.");220found = true;221break;222}223}224if( !found ) {225Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);226logger.log(FINER, "DDRSymbolFinder: Adding new DDR symbol " + symName);227SymbolUtil.addDDRSymbolToModule(module, "["+field+"]", symName, functionAddress);228}229}230}231}232233private static long followPointerFromStructure(String structureName, long structureAddress, String fieldName, StructureReader reader, IProcess process) throws MemoryFault, NullPointerException {234235if( structureAddress == 0 ) {236throw new NullPointerException("Null " + structureName + " found.");237}238239for( FieldDescriptor f: reader.getFields(structureName)) {240if( f.getDeclaredName().equals(fieldName)) {241long offset = f.getOffset();242long pointerAddress = structureAddress + offset;243long pointer = process.getPointerAt(pointerAddress);244return pointer;245}246}247return 0;248}249250private static List<String> getVoidPointerFieldsFromStructure(StructureReader reader, String structureName) throws MemoryFault {251252List<String> functionPointers = new LinkedList<String>();253for( FieldDescriptor f: reader.getFields(structureName)) {254String name = f.getDeclaredName();255String type = f.getDeclaredType();256if( "void *".equals(type) ) {257functionPointers.add(name);258}259}260return functionPointers;261}262263/* Logic stolen from SymbolUtil. */264private static IModule getModuleForInstructionAddress(IProcess process, long address) throws CorruptDataException {265Collection<? extends IModule> modules = process.getModules();266267IModule matchingModule = null;268269OUTER_LOOP: for (IModule thisModule : modules) {270for (IMemoryRange thisRange : thisModule.getMemoryRanges()) {271if (thisRange.contains(address)) {272matchingModule = thisModule;273break OUTER_LOOP;274}275}276}277return matchingModule;278}279}280281282