0N/A/*
1472N/A * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
0N/A *
0N/A */
0N/A
0N/Apackage sun.jvm.hotspot.debugger.cdbg.basic;
0N/A
0N/Aimport java.util.*;
0N/Aimport sun.jvm.hotspot.debugger.*;
0N/Aimport sun.jvm.hotspot.debugger.cdbg.*;
0N/Aimport sun.jvm.hotspot.utilities.AddressOps;
0N/A
0N/Apublic class BasicLineNumberMapping {
0N/A private List infoList;
0N/A
0N/A public BasicLineNumberMapping() {
0N/A }
0N/A
0N/A /** Add line number information for the given PC. The end PC may be
0N/A a very loose approximation (i.e., the end of the given DLL) if
0N/A that information is not available in the debug information.
0N/A recomputeEndPCs() will recompute them if needed. */
0N/A public void addLineNumberInfo(BasicLineNumberInfo info) {
0N/A if (infoList == null) {
0N/A infoList = new ArrayList();
0N/A }
0N/A infoList.add(info);
0N/A }
0N/A
0N/A /** Sort the line number information by increasing starting program
0N/A counter. This must be done before any queries are made. */
0N/A public void sort() {
0N/A if (infoList == null) return;
0N/A Collections.sort(infoList, new Comparator() {
0N/A public int compare(Object o1, Object o2) {
0N/A BasicLineNumberInfo l1 = (BasicLineNumberInfo) o1;
0N/A BasicLineNumberInfo l2 = (BasicLineNumberInfo) o2;
0N/A Address a1 = l1.getStartPC();
0N/A Address a2 = l2.getStartPC();
0N/A if (AddressOps.lt(a1, a2)) { return -1; }
0N/A if (AddressOps.gt(a1, a2)) { return 1; }
0N/A return 0;
0N/A }
0N/A });
0N/A }
0N/A
0N/A /** Recomputes the ending PCs of each interval based on the starting
0N/A PC of the next one. If this needs to be called, must be called
0N/A after sort(). */
0N/A public void recomputeEndPCs() {
0N/A if (infoList == null) return;
0N/A for (int i = 0; i < infoList.size() - 1; i++) {
0N/A BasicLineNumberInfo i1 = get(i);
0N/A BasicLineNumberInfo i2 = get(i + 1);
0N/A i1.setEndPC(i2.getStartPC());
0N/A }
0N/A }
0N/A
0N/A public BasicLineNumberInfo lineNumberForPC(Address pc) throws DebuggerException {
0N/A if (infoList == null) return null;
0N/A return searchLineNumbers(pc, 0, infoList.size() - 1);
0N/A }
0N/A
0N/A public void iterate(LineNumberVisitor v) {
0N/A if (infoList == null) return;
0N/A for (int i = 0; i < infoList.size(); i++) {
0N/A v.doLineNumber(get(i));
0N/A }
0N/A }
0N/A
0N/A //----------------------------------------------------------------------
0N/A // Internals only below this point
0N/A //
0N/A
0N/A private BasicLineNumberInfo get(int i) {
0N/A return (BasicLineNumberInfo) infoList.get(i);
0N/A }
0N/A
0N/A private BasicLineNumberInfo searchLineNumbers(Address addr, int lowIdx, int highIdx) {
0N/A if (highIdx < lowIdx) return null;
0N/A if (lowIdx == highIdx) {
0N/A // Base case: see whether start PC is less than or equal to addr
0N/A if (check(addr, lowIdx)) {
0N/A return get(lowIdx);
0N/A } else {
0N/A return null;
0N/A }
0N/A } else if (lowIdx == highIdx - 1) {
0N/A if (check(addr, lowIdx)) {
0N/A return get(lowIdx);
0N/A } else if (check(addr, highIdx)) {
0N/A return get(highIdx);
0N/A } else {
0N/A return null;
0N/A }
0N/A }
0N/A int midIdx = (lowIdx + highIdx) >> 1;
0N/A BasicLineNumberInfo info = get(midIdx);
0N/A if (AddressOps.lt(addr, info.getStartPC())) {
0N/A // Always move search down
0N/A return searchLineNumbers(addr, lowIdx, midIdx);
0N/A } else if (AddressOps.equal(addr, info.getStartPC())) {
0N/A return info;
0N/A } else {
0N/A // Move search up
0N/A return searchLineNumbers(addr, midIdx, highIdx);
0N/A }
0N/A }
0N/A
0N/A private boolean check(Address addr, int idx) {
0N/A BasicLineNumberInfo info = get(idx);
0N/A if (AddressOps.lte(info.getStartPC(), addr)) {
0N/A return true;
0N/A } else {
0N/A return false;
0N/A }
0N/A }
0N/A}