1 /*
  2  * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2015, Red Hat Inc.
  4  * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved.
  5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  6  *
  7  * This code is free software; you can redistribute it and/or modify it
  8  * under the terms of the GNU General Public License version 2 only, as
  9  * published by the Free Software Foundation.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  *
 25  */
 26 
 27 package sun.jvm.hotspot.runtime.linux_riscv64;
 28 
 29 import java.io.*;
 30 import java.util.*;
 31 import sun.jvm.hotspot.debugger.*;
 32 import sun.jvm.hotspot.debugger.riscv64.*;
 33 import sun.jvm.hotspot.runtime.*;
 34 import sun.jvm.hotspot.runtime.riscv64.*;
 35 import sun.jvm.hotspot.types.*;
 36 import sun.jvm.hotspot.utilities.*;
 37 import sun.jvm.hotspot.utilities.Observable;
 38 import sun.jvm.hotspot.utilities.Observer;
 39 
 40 public class LinuxRISCV64JavaThreadPDAccess implements JavaThreadPDAccess {
 41   private static AddressField  lastJavaFPField;
 42   private static AddressField  osThreadField;
 43 
 44   // Field from OSThread
 45   private static CIntegerField osThreadThreadIDField;
 46 
 47   // This is currently unneeded but is being kept in case we change
 48   // the currentFrameGuess algorithm
 49   private static final long GUESS_SCAN_RANGE = 128 * 1024;
 50 
 51   static {
 52     VM.registerVMInitializedObserver(new Observer() {
 53         public void update(Observable o, Object data) {
 54           initialize(VM.getVM().getTypeDataBase());
 55         }
 56       });
 57   }
 58 
 59   private static synchronized void initialize(TypeDataBase db) {
 60     Type type = db.lookupType("JavaThread");
 61     osThreadField           = type.getAddressField("_osthread");
 62 
 63     Type anchorType = db.lookupType("JavaFrameAnchor");
 64     lastJavaFPField         = anchorType.getAddressField("_last_Java_fp");
 65 
 66     Type osThreadType = db.lookupType("OSThread");
 67     osThreadThreadIDField   = osThreadType.getCIntegerField("_thread_id");
 68   }
 69 
 70   public Address getLastJavaFP(Address addr) {
 71     return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
 72   }
 73 
 74   public Address getLastJavaPC(Address addr) {
 75     return null;
 76   }
 77 
 78   public Address getBaseOfStackPointer(Address addr) {
 79     return null;
 80   }
 81 
 82   public Frame getLastFramePD(JavaThread thread, Address addr) {
 83     Address fp = thread.getLastJavaFP();
 84     if (fp == null) {
 85       return null; // no information
 86     }
 87     return new RISCV64Frame(thread.getLastJavaSP(), fp);
 88   }
 89 
 90   public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
 91     return new RISCV64RegisterMap(thread, updateMap);
 92   }
 93 
 94   public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
 95     ThreadProxy t = getThreadProxy(addr);
 96     RISCV64ThreadContext context = (RISCV64ThreadContext) t.getContext();
 97     RISCV64CurrentFrameGuess guesser = new RISCV64CurrentFrameGuess(context, thread);
 98     if (!guesser.run(GUESS_SCAN_RANGE)) {
 99       return null;
100     }
101     if (guesser.getPC() == null) {
102       return new RISCV64Frame(guesser.getSP(), guesser.getFP());
103     } else {
104       return new RISCV64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
105     }
106   }
107 
108   public void printThreadIDOn(Address addr, PrintStream tty) {
109     tty.print(getThreadProxy(addr));
110   }
111 
112   public void printInfoOn(Address threadAddr, PrintStream tty) {
113     tty.print("Thread id: ");
114     printThreadIDOn(threadAddr, tty);
115   }
116 
117   public Address getLastSP(Address addr) {
118     ThreadProxy t = getThreadProxy(addr);
119     RISCV64ThreadContext context = (RISCV64ThreadContext) t.getContext();
120     return context.getRegisterAsAddress(RISCV64ThreadContext.SP);
121   }
122 
123   public ThreadProxy getThreadProxy(Address addr) {
124     // Addr is the address of the JavaThread.
125     // Fetch the OSThread (for now and for simplicity, not making a
126     // separate "OSThread" class in this package)
127     Address osThreadAddr = osThreadField.getValue(addr);
128     // Get the address of the _thread_id from the OSThread
129     Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
130 
131     JVMDebugger debugger = VM.getVM().getDebugger();
132     return debugger.getThreadForIdentifierAddress(threadIdAddr);
133   }
134 }