Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/InstallSDE.java
51715 views
/*1* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22package nsk.share.jdi.sde;2324import java.io.File;25import java.io.FileInputStream;26import java.io.FileOutputStream;27import java.io.IOException;28import java.io.InputStream;29import java.io.UnsupportedEncodingException;3031import nsk.share.Consts;3233/*34* Inserts in class file 'SourceDebugExtension' attribute based on input .SMAP file.35*/36public class InstallSDE {37static final String nameSDE = "SourceDebugExtension";3839private byte[] orig;4041private byte[] sdeAttr;4243private byte[] gen;4445private int origPos = 0;4647private int genPos = 0;4849private int sdeIndex;5051public static void install(File inClassFile, File smapFile, File outClassFile, boolean verbose) throws IOException {52new InstallSDE(inClassFile, smapFile, outClassFile, verbose);53}5455public static void install(byte[] aOrig, byte[] aSdeAttr, File outClassFile, boolean verbose) throws IOException {56new InstallSDE(aOrig, aSdeAttr, outClassFile, verbose);57}5859public static void install(File inOutClassFile, File attrFile, boolean verbose) throws IOException {60File tmpFile = new File(inOutClassFile.getPath() + "tmp-out");61File tmpInOutClassFile = new File(inOutClassFile.getPath() + "tmp-in");6263// Workaround delayed file deletes on Windows using a tmp file name64if (!inOutClassFile.renameTo(tmpInOutClassFile)) {65throw new IOException("inOutClassFile.renameTo(tmpInOutClassFile) failed");66}6768new InstallSDE(tmpInOutClassFile, attrFile, tmpFile, verbose);6970if (!tmpInOutClassFile.delete()) {71throw new IOException("tmpInOutClassFile.delete() failed");72}73if (!tmpFile.renameTo(inOutClassFile)) {74throw new IOException("tmpFile.renameTo(inOutClassFile) failed");75}76}7778private static void abort(String msg) {79System.err.println(msg);80System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);81}8283private InstallSDE(File inClassFile, File attrFile, File outClassFile, boolean verbose) throws IOException {84if (!inClassFile.exists()) {85abort("no such file: " + inClassFile);86}87if (!attrFile.exists()) {88abort("no such file: " + attrFile);89}9091// get the bytes92orig = readWhole(inClassFile);93sdeAttr = readWhole(attrFile);94gen = new byte[orig.length + sdeAttr.length + 100];9596// do it97addSDE(verbose);9899// write result100FileOutputStream outStream = new FileOutputStream(outClassFile);101outStream.write(gen, 0, genPos);102outStream.close();103}104105private InstallSDE(byte[] aOrig, byte[] aSdeAttr, File outClassFile, boolean verbose) throws IOException {106orig = aOrig;107sdeAttr = aSdeAttr;108gen = new byte[orig.length + sdeAttr.length + 100];109110// do it111addSDE(verbose);112113// write result114FileOutputStream outStream = new FileOutputStream(outClassFile);115outStream.write(gen, 0, genPos);116outStream.close();117}118119private byte[] readWhole(File input) throws IOException {120FileInputStream inStream = new FileInputStream(input);121try {122return readWhole(inStream, (int) input.length());123} finally {124inStream.close();125}126}127128private byte[] readWhole(InputStream inStream, int len) throws IOException {129byte[] bytes = new byte[len];130131if (inStream.read(bytes, 0, len) != len) {132abort("expected size: " + len);133}134135return bytes;136}137138private void addSDE(boolean verbose) throws UnsupportedEncodingException {139copy(4 + 2 + 2); // magic min/maj version140int constantPoolCountPos = genPos;141int constantPoolCount = readU2();142writeU2(constantPoolCount);143// copy old constant pool return index of SDE symbol, if found144sdeIndex = copyConstantPool(constantPoolCount, verbose);145if (sdeIndex < 0) {146// if "SourceDebugExtension" symbol not there add it147writeUtf8ForSDE();148149// increment the countantPoolCount150sdeIndex = constantPoolCount;151++constantPoolCount;152randomAccessWriteU2(constantPoolCountPos, constantPoolCount);153154if (verbose) {155System.out.println("SourceDebugExtension not found, installed at: " + sdeIndex);156}157} else {158if (verbose) {159System.out.println("SourceDebugExtension found at: " + sdeIndex);160}161}162copy(2 + 2 + 2); // access, this, super163int interfaceCount = readU2();164writeU2(interfaceCount);165if (verbose) {166System.out.println("interfaceCount: " + interfaceCount);167}168copy(interfaceCount * 2);169copyMembers(verbose); // fields170copyMembers(verbose); // methods171int attrCountPos = genPos;172int attrCount = readU2();173writeU2(attrCount);174if (verbose) {175System.out.println("class attrCount: " + attrCount);176}177// copy the class attributes, return true if SDE attr found (not copied)178if (!copyAttrs(attrCount, verbose)) {179// we will be adding SDE and it isn't already counted180++attrCount;181randomAccessWriteU2(attrCountPos, attrCount);182if (verbose) {183System.out.println("class attrCount incremented");184}185}186writeAttrForSDE(sdeIndex);187}188189private void copyMembers(boolean verbose) {190int count = readU2();191writeU2(count);192if (verbose) {193System.out.println("members count: " + count);194}195for (int i = 0; i < count; ++i) {196copy(6); // access, name, descriptor197int attrCount = readU2();198writeU2(attrCount);199if (verbose) {200System.out.println("member attr count: " + attrCount);201}202copyAttrs(attrCount, verbose);203}204}205206private boolean copyAttrs(int attrCount, boolean verbose) {207boolean sdeFound = false;208for (int i = 0; i < attrCount; ++i) {209int nameIndex = readU2();210// don't write old SDE211if (nameIndex == sdeIndex) {212sdeFound = true;213if (verbose) {214System.out.println("SDE attr found");215}216} else {217writeU2(nameIndex); // name218int len = readU4();219writeU4(len);220copy(len);221if (verbose) {222System.out.println("attr len: " + len);223}224}225}226return sdeFound;227}228229private void writeAttrForSDE(int index) {230writeU2(index);231writeU4(sdeAttr.length);232for (int i = 0; i < sdeAttr.length; ++i) {233writeU1(sdeAttr[i]);234}235}236237private void randomAccessWriteU2(int pos, int val) {238int savePos = genPos;239genPos = pos;240writeU2(val);241genPos = savePos;242}243244private int readU1() {245return ((int) orig[origPos++]) & 0xFF;246}247248private int readU2() {249int res = readU1();250return (res << 8) + readU1();251}252253private int readU4() {254int res = readU2();255return (res << 16) + readU2();256}257258private void writeU1(int val) {259gen[genPos++] = (byte) val;260}261262private void writeU2(int val) {263writeU1(val >> 8);264writeU1(val & 0xFF);265}266267private void writeU4(int val) {268writeU2(val >> 16);269writeU2(val & 0xFFFF);270}271272private void copy(int count) {273for (int i = 0; i < count; ++i) {274gen[genPos++] = orig[origPos++];275}276}277278private byte[] readBytes(int count) {279byte[] bytes = new byte[count];280for (int i = 0; i < count; ++i) {281bytes[i] = orig[origPos++];282}283return bytes;284}285286private void writeBytes(byte[] bytes) {287for (int i = 0; i < bytes.length; ++i) {288gen[genPos++] = bytes[i];289}290}291292private int copyConstantPool(int constantPoolCount, boolean verbose) throws UnsupportedEncodingException {293int sdeIndex = -1;294// copy const pool index zero not in class file295if ( verbose )296System.out.println("cp count=" + constantPoolCount);297for (int i = 1; i < constantPoolCount; ++i) {298int tag = readU1();299writeU1(tag);300if ( verbose )301System.out.println(i + ": tag=" + tag);302switch (tag) {303case 7: // Class304case 8: // String305case 16: // MethodType306copy(2);307break;308case 15: // MethodHandle309copy(3);310break;311case 9: // Field312case 10: // Method313case 11: // InterfaceMethod314case 3: // Integer315case 4: // Float316case 12: // NameAndType317case 17: // InvokeDynamic_17 (will go away)318case 18: // InokeDynamic319copy(4);320break;321case 5: // Long322case 6: // Double323copy(8);324++i;325break;326case 1: // Utf8327int len = readU2();328writeU2(len);329byte[] utf8 = readBytes(len);330String str = new String(utf8, "UTF-8");331if (verbose) {332System.out.println(i + " read class attr -- '" + str + "'");333}334if (str.equals(nameSDE)) {335sdeIndex = i;336}337writeBytes(utf8);338break;339default:340abort("unexpected tag: " + tag);341break;342}343}344return sdeIndex;345}346347private void writeUtf8ForSDE() {348int len = nameSDE.length();349writeU1(1); // Utf8 tag350writeU2(len);351for (int i = 0; i < len; ++i) {352writeU1(nameSDE.charAt(i));353}354}355}356357358