Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/back/SDE.c
38765 views
/*1* Copyright (c) 2001, 2013, 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. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <setjmp.h>2627#include "util.h"28#include "SDE.h"2930#ifdef __APPLE__31/* use setjmp/longjmp versions that do not save/restore the signal mask */32#define setjmp _setjmp33#define longjmp _longjmp34#endif3536/**37* This SourceDebugExtension code does not38* allow concurrent translation - due to caching method.39* A separate thread setting the default stratum ID40* is, however, fine.41*/4243#define INIT_SIZE_FILE 1044#define INIT_SIZE_LINE 10045#define INIT_SIZE_STRATUM 34647#define BASE_STRATUM_NAME "Java"4849#define null NULL50#define true JNI_TRUE51#define false JNI_FALSE52#define String char *53#define private static5455typedef struct {56int fileId;57String sourceName;58String sourcePath; // do not read - use accessor59int isConverted;60} FileTableRecord;6162typedef struct {63int jplsStart;64int jplsEnd;65int jplsLineInc;66int njplsStart;67int njplsEnd;68int fileId;69} LineTableRecord;7071typedef struct {72String id;73int fileIndex;74int lineIndex;75} StratumTableRecord;7677/* back-end wide value for default stratum */78private String globalDefaultStratumId = null;7980/* reference type default */81private String defaultStratumId = null;8283private jclass cachedClass = NULL;8485private FileTableRecord* fileTable;86private LineTableRecord* lineTable;87private StratumTableRecord* stratumTable;8889private int fileTableSize;90private int lineTableSize;91private int stratumTableSize;9293private int fileIndex;94private int lineIndex;95private int stratumIndex = 0;96private int currentFileId;9798private int defaultStratumIndex;99private int baseStratumIndex;100private char* sdePos;101102private char* jplsFilename = null;103private char* NullString = null;104105/* mangled in parse, cannot be parsed. Must be kept. */106private String sourceDebugExtension;107108private jboolean sourceMapIsValid;109110private jmp_buf jmp_buf_env;111112private int stratumTableIndex(String stratumId);113private int stiLineTableIndex(int sti, int jplsLine);114private int stiLineNumber(int sti, int lti, int jplsLine);115private void decode(void);116private void ignoreWhite(void);117private jboolean isValid(void);118119private void120loadDebugInfo(JNIEnv *env, jclass clazz) {121122if (!isSameObject(env, clazz, cachedClass)) {123/* Not the same - swap out the info */124125/* Delete existing info */126if ( cachedClass != null ) {127tossGlobalRef(env, &cachedClass);128cachedClass = null;129}130if ( sourceDebugExtension!=null ) {131jvmtiDeallocate(sourceDebugExtension);132}133sourceDebugExtension = null;134135/* Init info */136lineTable = null;137fileTable = null;138stratumTable = null;139lineTableSize = 0;140fileTableSize = 0;141stratumTableSize = 0;142fileIndex = 0;143lineIndex = 0;144stratumIndex = 0;145currentFileId = 0;146defaultStratumId = null;147defaultStratumIndex = -1;148baseStratumIndex = -2; /* so as not to match -1 above */149sourceMapIsValid = false;150151if (getSourceDebugExtension(clazz, &sourceDebugExtension) ==152JVMTI_ERROR_NONE) {153sdePos = sourceDebugExtension;154if (setjmp(jmp_buf_env) == 0) {155/* this is the initial (non-error) case, do parse */156decode();157}158}159160cachedClass = null;161saveGlobalRef(env, clazz, &cachedClass);162}163}164165/* Return 1 if match, 0 if no match */166private int167patternMatch(char *classname, const char *pattern) {168int pattLen;169int compLen;170char *start;171int offset;172173if (pattern == NULL || classname == NULL) {174return 0;175}176pattLen = (int)strlen(pattern);177178if ((pattern[0] != '*') && (pattern[pattLen-1] != '*')) {179return strcmp(pattern, classname) == 0;180}181182compLen = pattLen - 1;183offset = (int)strlen(classname) - compLen;184if (offset < 0) {185return 0;186}187if (pattern[0] == '*') {188pattern++;189start = classname + offset;190} else {191start = classname;192}193return strncmp(pattern, start, compLen) == 0;194}195196/**197* Return 1 if p1 is a SourceName for stratum sti,198* else, return 0.199*/200private int201searchOneSourceName(int sti, char *p1) {202int fileIndexStart = stratumTable[sti].fileIndex;203/* one past end */204int fileIndexEnd = stratumTable[sti+1].fileIndex;205int ii;206for (ii = fileIndexStart; ii < fileIndexEnd; ++ii) {207if (patternMatch(fileTable[ii].sourceName, p1)) {208return 1;209}210}211return 0;212}213214/**215* Return 1 if p1 is a SourceName for any stratum216* else, return 0.217*/218int searchAllSourceNames(JNIEnv *env,219jclass clazz,220char *p1) {221int ii;222loadDebugInfo(env, clazz);223if (!isValid()) {224return 0; /* no SDE or not SourceMap */225}226227for (ii = 0; ii < stratumIndex - 1; ++ii) {228if (searchOneSourceName(ii, p1) == 1) {229return 1;230}231}232return 0;233}234235/**236* Convert a line number table, as returned by the JVMTI237* function GetLineNumberTable, to one for another stratum.238* Conversion is by overwrite.239* Actual line numbers are not returned - just a unique240* number (file ID in top 16 bits, line number in241* bottom 16 bits) - this is all stepping needs.242*/243void244convertLineNumberTable(JNIEnv *env, jclass clazz,245jint *entryCountPtr,246jvmtiLineNumberEntry **tablePtr) {247jvmtiLineNumberEntry *fromEntry = *tablePtr;248jvmtiLineNumberEntry *toEntry = *tablePtr;249int cnt = *entryCountPtr;250int lastLn = 0;251int sti;252253loadDebugInfo(env, clazz);254if (!isValid()) {255return; /* no SDE or not SourceMap - return unchanged */256}257sti = stratumTableIndex(globalDefaultStratumId);258if (sti == baseStratumIndex) {259return; /* Java stratum - return unchanged */260}261LOG_MISC(("SDE is re-ordering the line table"));262for (; cnt-->0; ++fromEntry) {263int jplsLine = fromEntry->line_number;264int lti = stiLineTableIndex(sti, jplsLine);265if (lti >= 0) {266int fileId = lineTable[lti].fileId;267int ln = stiLineNumber(sti, lti, jplsLine);268ln += (fileId << 16); /* create line hash */269if (ln != lastLn) {270lastLn = ln;271toEntry->start_location = fromEntry->start_location;272toEntry->line_number = ln;273++toEntry;274}275}276}277/*LINTED*/278*entryCountPtr = (int)(toEntry - *tablePtr);279}280281/**282* Set back-end wide default stratum ID .283*/284void285setGlobalStratumId(char *id) {286globalDefaultStratumId = id;287}288289290private void syntax(String msg) {291char buf[200];292(void)snprintf(buf, sizeof(buf),293"bad SourceDebugExtension syntax - position %d - %s\n",294/*LINTED*/295(int)(sdePos-sourceDebugExtension),296msg);297JDI_ASSERT_FAILED(buf);298299longjmp(jmp_buf_env, 1); /* abort parse */300}301302private char sdePeek(void) {303if (*sdePos == 0) {304syntax("unexpected EOF");305}306return *sdePos;307}308309private char sdeRead(void) {310if (*sdePos == 0) {311syntax("unexpected EOF");312}313return *sdePos++;314}315316private void sdeAdvance(void) {317sdePos++;318}319320private void assureLineTableSize(void) {321if (lineIndex >= lineTableSize) {322size_t allocSize;323LineTableRecord* new_lineTable;324int new_lineTableSize;325326new_lineTableSize = lineTableSize == 0?327INIT_SIZE_LINE :328lineTableSize * 2;329allocSize = new_lineTableSize * (int)sizeof(LineTableRecord);330new_lineTable = jvmtiAllocate((jint)allocSize);331if ( new_lineTable == NULL ) {332EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY, "SDE line table");333}334if ( lineTable!=NULL ) {335(void)memcpy(new_lineTable, lineTable,336lineTableSize * (int)sizeof(LineTableRecord));337jvmtiDeallocate(lineTable);338}339lineTable = new_lineTable;340lineTableSize = new_lineTableSize;341}342}343344private void assureFileTableSize(void) {345if (fileIndex >= fileTableSize) {346size_t allocSize;347FileTableRecord* new_fileTable;348int new_fileTableSize;349350new_fileTableSize = fileTableSize == 0?351INIT_SIZE_FILE :352fileTableSize * 2;353allocSize = new_fileTableSize * (int)sizeof(FileTableRecord);354new_fileTable = jvmtiAllocate((jint)allocSize);355if ( new_fileTable == NULL ) {356EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY, "SDE file table");357}358if ( fileTable!=NULL ) {359(void)memcpy(new_fileTable, fileTable,360fileTableSize * (int)sizeof(FileTableRecord));361jvmtiDeallocate(fileTable);362}363fileTable = new_fileTable;364fileTableSize = new_fileTableSize;365}366}367368private void assureStratumTableSize(void) {369if (stratumIndex >= stratumTableSize) {370size_t allocSize;371StratumTableRecord* new_stratumTable;372int new_stratumTableSize;373374new_stratumTableSize = stratumTableSize == 0?375INIT_SIZE_STRATUM :376stratumTableSize * 2;377allocSize = new_stratumTableSize * (int)sizeof(StratumTableRecord);378new_stratumTable = jvmtiAllocate((jint)allocSize);379if ( new_stratumTable == NULL ) {380EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY, "SDE stratum table");381}382if ( stratumTable!=NULL ) {383(void)memcpy(new_stratumTable, stratumTable,384stratumTableSize * (int)sizeof(StratumTableRecord));385jvmtiDeallocate(stratumTable);386}387stratumTable = new_stratumTable;388stratumTableSize = new_stratumTableSize;389}390}391392private String readLine(void) {393char *initialPos;394char ch;395396ignoreWhite();397initialPos = sdePos;398while (((ch = *sdePos) != '\n') && (ch != '\r')) {399if (ch == 0) {400syntax("unexpected EOF");401}402++sdePos;403}404*sdePos++ = 0; /* null terminate string - mangles SDE */405406/* check for CR LF */407if ((ch == '\r') && (*sdePos == '\n')) {408++sdePos;409}410ignoreWhite(); /* leading white */411return initialPos;412}413414private int defaultStratumTableIndex(void) {415if ((defaultStratumIndex == -1) && (defaultStratumId != null)) {416defaultStratumIndex =417stratumTableIndex(defaultStratumId);418}419return defaultStratumIndex;420}421422private int stratumTableIndex(String stratumId) {423int i;424425if (stratumId == null) {426return defaultStratumTableIndex();427}428for (i = 0; i < (stratumIndex-1); ++i) {429if (strcmp(stratumTable[i].id, stratumId) == 0) {430return i;431}432}433return defaultStratumTableIndex();434}435436437/*****************************438* below functions/methods are written to compile under either Java or C439*440* Needed support functions:441* sdePeek()442* sdeRead()443* sdeAdvance()444* readLine()445* assureLineTableSize()446* assureFileTableSize()447* assureStratumTableSize()448* syntax(String)449*450* stratumTableIndex(String)451*452* Needed support variables:453* lineTable454* lineIndex455* fileTable456* fileIndex457* currentFileId458*459* Needed types:460* String461*462* Needed constants:463* NullString464*/465466private void ignoreWhite(void) {467char ch;468469while (((ch = sdePeek()) == ' ') || (ch == '\t')) {470sdeAdvance();471}472}473474private void ignoreLine(void) {475char ch;476477do {478ch = sdeRead();479} while ((ch != '\n') && (ch != '\r'));480481/* check for CR LF */482if ((ch == '\r') && (sdePeek() == '\n')) {483sdeAdvance();484}485ignoreWhite(); /* leading white */486}487488private int readNumber(void) {489int value = 0;490char ch;491492ignoreWhite();493while (((ch = sdePeek()) >= '0') && (ch <= '9')) {494sdeAdvance();495value = (value * 10) + ch - '0';496}497ignoreWhite();498return value;499}500501private void storeFile(int fileId, String sourceName, String sourcePath) {502assureFileTableSize();503fileTable[fileIndex].fileId = fileId;504fileTable[fileIndex].sourceName = sourceName;505fileTable[fileIndex].sourcePath = sourcePath;506++fileIndex;507}508509private void fileLine(void) {510int hasAbsolute = 0; /* acts as boolean */511int fileId;512String sourceName;513String sourcePath = null;514515/* is there an absolute filename? */516if (sdePeek() == '+') {517sdeAdvance();518hasAbsolute = 1;519}520fileId = readNumber();521sourceName = readLine();522if (hasAbsolute == 1) {523sourcePath = readLine();524}525storeFile(fileId, sourceName, sourcePath);526}527528private void storeLine(int jplsStart, int jplsEnd, int jplsLineInc,529int njplsStart, int njplsEnd, int fileId) {530assureLineTableSize();531lineTable[lineIndex].jplsStart = jplsStart;532lineTable[lineIndex].jplsEnd = jplsEnd;533lineTable[lineIndex].jplsLineInc = jplsLineInc;534lineTable[lineIndex].njplsStart = njplsStart;535lineTable[lineIndex].njplsEnd = njplsEnd;536lineTable[lineIndex].fileId = fileId;537++lineIndex;538}539540/**541* Parse line translation info. Syntax is542* <NJ-start-line> [ # <file-id> ] [ , <line-count> ] :543* <J-start-line> [ , <line-increment> ] CR544*/545private void lineLine(void) {546int lineCount = 1;547int lineIncrement = 1;548int njplsStart;549int jplsStart;550551njplsStart = readNumber();552553/* is there a fileID? */554if (sdePeek() == '#') {555sdeAdvance();556currentFileId = readNumber();557}558559/* is there a line count? */560if (sdePeek() == ',') {561sdeAdvance();562lineCount = readNumber();563}564565if (sdeRead() != ':') {566syntax("expected ':'");567}568jplsStart = readNumber();569if (sdePeek() == ',') {570sdeAdvance();571lineIncrement = readNumber();572}573ignoreLine(); /* flush the rest */574575storeLine(jplsStart,576jplsStart + (lineCount * lineIncrement) -1,577lineIncrement,578njplsStart,579njplsStart + lineCount -1,580currentFileId);581}582583/**584* Until the next stratum section, everything after this585* is in stratumId - so, store the current indicies.586*/587private void storeStratum(String stratumId) {588/* remove redundant strata */589if (stratumIndex > 0) {590if ((stratumTable[stratumIndex-1].fileIndex591== fileIndex) &&592(stratumTable[stratumIndex-1].lineIndex593== lineIndex)) {594/* nothing changed overwrite it */595--stratumIndex;596}597}598/* store the results */599assureStratumTableSize();600stratumTable[stratumIndex].id = stratumId;601stratumTable[stratumIndex].fileIndex = fileIndex;602stratumTable[stratumIndex].lineIndex = lineIndex;603++stratumIndex;604currentFileId = 0;605}606607/**608* The beginning of a stratum's info609*/610private void stratumSection(void) {611storeStratum(readLine());612}613614private void fileSection(void) {615ignoreLine();616while (sdePeek() != '*') {617fileLine();618}619}620621private void lineSection(void) {622ignoreLine();623while (sdePeek() != '*') {624lineLine();625}626}627628/**629* Ignore a section we don't know about.630*/631private void ignoreSection(void) {632ignoreLine();633while (sdePeek() != '*') {634ignoreLine();635}636}637638/**639* A base "Java" stratum is always available, though640* it is not in the SourceDebugExtension.641* Create the base stratum.642*/643private void createJavaStratum(void) {644baseStratumIndex = stratumIndex;645storeStratum(BASE_STRATUM_NAME);646storeFile(1, jplsFilename, NullString);647/* JPL line numbers cannot exceed 65535 */648storeLine(1, 65536, 1, 1, 65536, 1);649storeStratum("Aux"); /* in case they don't declare */650}651652/**653* Decode a SourceDebugExtension which is in SourceMap format.654* This is the entry point into the recursive descent parser.655*/656private void decode(void) {657/* check for "SMAP" - allow EOF if not ours */658if (strlen(sourceDebugExtension) <= 4 ||659(sdeRead() != 'S') ||660(sdeRead() != 'M') ||661(sdeRead() != 'A') ||662(sdeRead() != 'P')) {663return; /* not our info */664}665ignoreLine(); /* flush the rest */666jplsFilename = readLine();667defaultStratumId = readLine();668createJavaStratum();669while (true) {670if (sdeRead() != '*') {671syntax("expected '*'");672}673switch (sdeRead()) {674case 'S':675stratumSection();676break;677case 'F':678fileSection();679break;680case 'L':681lineSection();682break;683case 'E':684/* set end points */685storeStratum("*terminator*");686sourceMapIsValid = true;687return;688default:689ignoreSection();690}691}692}693694/***************** query functions ***********************/695696private int stiLineTableIndex(int sti, int jplsLine) {697int i;698int lineIndexStart;699int lineIndexEnd;700701lineIndexStart = stratumTable[sti].lineIndex;702/* one past end */703lineIndexEnd = stratumTable[sti+1].lineIndex;704for (i = lineIndexStart; i < lineIndexEnd; ++i) {705if ((jplsLine >= lineTable[i].jplsStart) &&706(jplsLine <= lineTable[i].jplsEnd)) {707return i;708}709}710return -1;711}712713private int stiLineNumber(int sti, int lti, int jplsLine) {714return lineTable[lti].njplsStart +715(((jplsLine - lineTable[lti].jplsStart) /716lineTable[lti].jplsLineInc));717}718719private int fileTableIndex(int sti, int fileId) {720int i;721int fileIndexStart = stratumTable[sti].fileIndex;722/* one past end */723int fileIndexEnd = stratumTable[sti+1].fileIndex;724for (i = fileIndexStart; i < fileIndexEnd; ++i) {725if (fileTable[i].fileId == fileId) {726return i;727}728}729return -1;730}731732private int stiFileTableIndex(int sti, int lti) {733return fileTableIndex(sti, lineTable[lti].fileId);734}735736private jboolean isValid(void) {737return sourceMapIsValid;738}739740741