1 /*
 2  * Copyright (c) 2003, 2013, 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.debugger.linux.riscv64;
28 
29 import sun.jvm.hotspot.debugger.*;
30 import sun.jvm.hotspot.debugger.riscv64.*;
31 import sun.jvm.hotspot.debugger.linux.*;
32 import sun.jvm.hotspot.debugger.cdbg.*;
33 import sun.jvm.hotspot.debugger.cdbg.basic.*;
34 
35 public final class LinuxRISCV64CFrame extends BasicCFrame {
36    private static final int C_FRAME_LINK_OFFSET        = -2;
37    private static final int C_FRAME_RETURN_ADDR_OFFSET = -1;
38 
39    public LinuxRISCV64CFrame(LinuxDebugger dbg, Address fp, Address pc) {
40       super(dbg.getCDebugger());
41       this.fp = fp;
42       this.pc = pc;
43       this.dbg = dbg;
44    }
45 
46    // override base class impl to avoid ELF parsing
47    public ClosestSymbol closestSymbolToPC() {
48       // try native lookup in debugger.
49       return dbg.lookup(dbg.getAddressValue(pc()));
50    }
51 
52    public Address pc() {
53       return pc;
54    }
55 
56    public Address localVariableBase() {
57       return fp;
58    }
59 
60    public CFrame sender(ThreadProxy thread) {
61       RISCV64ThreadContext context = (RISCV64ThreadContext) thread.getContext();
62       Address rsp = context.getRegisterAsAddress(RISCV64ThreadContext.SP);
63 
64       if ((fp == null) || fp.lessThan(rsp)) {
65         return null;
66       }
67 
68       // Check alignment of fp
69       if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) {
70         return null;
71       }
72 
73       Address nextFP = fp.getAddressAt(C_FRAME_LINK_OFFSET * ADDRESS_SIZE);
74       if (nextFP == null || nextFP.lessThanOrEqual(fp)) {
75         return null;
76       }
77       Address nextPC  = fp.getAddressAt(C_FRAME_RETURN_ADDR_OFFSET * ADDRESS_SIZE);
78       if (nextPC == null) {
79         return null;
80       }
81       return new LinuxRISCV64CFrame(dbg, nextFP, nextPC);
82    }
83 
84    // package/class internals only
85    private static final int ADDRESS_SIZE = 8;
86    private Address pc;
87    private Address sp;
88    private Address fp;
89    private LinuxDebugger dbg;
90 }