Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/parser/GcdaRecordsParser.java')
-rw-r--r--gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/parser/GcdaRecordsParser.java272
1 files changed, 272 insertions, 0 deletions
diff --git a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/parser/GcdaRecordsParser.java b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/parser/GcdaRecordsParser.java
new file mode 100644
index 0000000000..5b51b3fffe
--- /dev/null
+++ b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/parser/GcdaRecordsParser.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2009 STMicroelectronics.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Xavier Raynaud <xavier.raynaud@st.com> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.gcov.parser;
+
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.linuxtools.gcov.Activator;
+import org.eclipse.linuxtools.internal.gcov.utils.BEDataInputStream;
+import org.eclipse.linuxtools.internal.gcov.utils.LEDataInputStream;
+import org.eclipse.linuxtools.internal.gcov.utils.MasksGenerator;
+
+
+
+public class GcdaRecordsParser {
+
+
+ private static final int GCOV_DATA_MAGIC = 0x67636461; // en ASCII: 67=g 63=c 64=d 61=a
+ private static final int GCOV_TAG_FUNCTION = 0x01000000;
+ private static final int GCOV_COUNTER_ARCS = 0x01a10000;
+ private static final int GCOV_TAG_OBJECT_SYMMARY = 0xa1000000;
+ private static final int GCOV_TAG_PROGRAM_SUMMARY = 0xa3000000;
+
+ private final ArrayList<GcnoFunction> fnctns;
+ private long objSmryNbrPgmRuns = 0;
+ private long pgmSmryChksm = 0;
+ private long objSmryChksm = 0;
+ private long objSmryArcCnts = 0;
+ private long objSmrytotalCnts = 0;
+ private long objSmryRunMax = 0;
+ private long objSmrySumMax = 0;
+
+
+ public GcdaRecordsParser(ArrayList<GcnoFunction> fnctns) {
+ this.fnctns = fnctns;
+ }
+
+ public void parseGcdaRecord(DataInput stream) throws IOException, CoreException {
+ // header data
+ int magic = 0;
+
+ // data & flags to process tests
+ GcnoFunction currentFnctn = null;
+
+ //read magic
+ magic = stream.readInt();
+ //read version
+ //version = stream.readInt();
+ stream.readInt();
+ //read stamp
+ //stamp = stream.readInt();
+ stream.readInt();
+
+ if (magic == GCOV_DATA_MAGIC){
+ stream = new BEDataInputStream((DataInputStream) stream);
+ }else{
+ magic = (magic >> 16) | (magic << 16);
+ magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff);
+ if (magic == GCOV_DATA_MAGIC){
+ stream = new LEDataInputStream((DataInputStream) stream);
+ }else{
+ String message = magic + " :desn't correspond to a correct data file header\n";
+ Status status = new Status(Status.ERROR, Activator.PLUGIN_ID, message);
+ throw new CoreException(status);
+ }
+ }
+
+ while (true) {
+ try {
+ // parse header
+ int tag = stream.readInt();
+ long length = (stream.readInt() & MasksGenerator.UNSIGNED_INT_MASK);
+ // parse gcda data
+ switch ((int) tag) {
+ case GCOV_TAG_FUNCTION: {
+ long fnctnId = stream.readInt() & MasksGenerator.UNSIGNED_INT_MASK;
+ if (!fnctns.isEmpty()) {
+ boolean fnctnFound = false;
+ for (GcnoFunction f: fnctns) {
+ if (f.getIdent() == fnctnId) {
+ fnctnFound = true;
+ currentFnctn = f;
+ long fnctnChksm = stream.readInt()& MasksGenerator.UNSIGNED_INT_MASK;
+ if (f.getCheksum() != fnctnChksm){
+ String message = "Checksums don't correspond for " +
+ currentFnctn.getName() + " (Id: " + fnctnId + ")\n";
+ Status status = new Status(Status.ERROR, Activator.PLUGIN_ID, message);
+ throw new CoreException(status);
+ }
+ break;
+ }
+ }
+
+ if (fnctnFound == false){
+ currentFnctn = null;
+ String message = "Function with Id: " + fnctnId +
+ " not found in function list\n";
+ Status status = new Status(Status.ERROR, Activator.PLUGIN_ID, message);
+ throw new CoreException(status);
+ }
+
+ }
+ break;
+ }
+
+ case GCOV_COUNTER_ARCS: {
+ if (currentFnctn == null){
+ String message = "Missing function or duplicate counter tag\n";
+ Status status = new Status(Status.ERROR, Activator.PLUGIN_ID, message);
+ throw new CoreException(status);
+ }
+
+ if (length != 2 * (currentFnctn.getNumCounts())){
+ String message = "GCDA content is inconsistent\n";
+ Status status = new Status(Status.ERROR, Activator.PLUGIN_ID, message);
+ throw new CoreException(status);
+ }
+
+ ArrayList<Block> fnctnBlcks = currentFnctn.getFunctionBlocks();
+ if (fnctnBlcks.isEmpty()){
+ String message = "Function block list is empty\n";
+ Status status = new Status(Status.ERROR, Activator.PLUGIN_ID, message);
+ throw new CoreException(status);
+ }
+
+ for (int i = 0; i < fnctnBlcks.size(); i++) {
+ Block b = fnctnBlcks.get(i);
+ int nonFakeExit = 0;
+
+ ArrayList<Arc> arcsExit = b.getExitArcs();
+ for (Arc extArc: arcsExit) {
+ if (extArc.isFake() == false)
+ nonFakeExit++;
+ if (extArc.isOnTree() == false) {
+ long arcsCnts = stream.readLong();
+ extArc.setCount(arcsCnts);
+ extArc.setCountValid(true);
+ b.decNumSuccs();
+ extArc.getDstnatnBlock().decNumPreds();
+ }
+ }
+
+ // If there is only one non-fake exit, it is an
+ // unconditional branch.
+ if (nonFakeExit == 1) {
+ for (Arc extArc: arcsExit) {
+ if (extArc.isFake() == false) {
+ extArc.setUnconditionnal(true);
+
+ // If this block is instrumenting a call, it might be
+ // an artificial block. It is not artificial if it has
+ // a non-fallthrough exit, or the destination of this
+ // arc has more than one entry. Mark the destination
+ // block as a return site, if none of those conditions hold.
+
+ if (b.isCallSite() == true
+ && extArc.isFallthrough() == true
+ && extArc.getDstnatnBlock()
+ .getEntryArcs().get(0)
+ .equals(extArc)
+ && extArc.getDstnatnBlock()
+ .getEntryArcs().size() == 1)
+ extArc.getDstnatnBlock()
+ .setCallReturn(true);
+ }
+ }
+ }
+ }
+
+ // counters arcs process data reset
+ currentFnctn = null;
+ break;
+ }
+
+ case GCOV_TAG_OBJECT_SYMMARY: {
+ objSmryChksm = (stream.readInt() & MasksGenerator.UNSIGNED_INT_MASK);
+ objSmryArcCnts = (stream.readInt() & MasksGenerator.UNSIGNED_INT_MASK);
+ objSmryNbrPgmRuns = (stream.readInt() & MasksGenerator.UNSIGNED_INT_MASK);
+ objSmrytotalCnts = stream.readLong();
+ objSmryRunMax = stream.readLong();
+ objSmrySumMax = stream.readLong();
+ break;
+ }
+
+ // program summary tag
+ case GCOV_TAG_PROGRAM_SUMMARY: {
+ //long[] pgmSmryskips = new long[(int) length];
+ pgmSmryChksm = (stream.readInt() & MasksGenerator.UNSIGNED_INT_MASK);
+ for (int i = 0; i < length - 1; i++) {
+ //pgmSmryskips[i] = (stream.readInt() & MasksGenerator.UNSIGNED_INT_MASK);
+ stream.readInt();
+ }
+ break;
+ }
+
+ default: {
+ //System.out.println("wrong gcda tag");
+ break;
+ }
+ }
+ }
+ catch (EOFException _) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * @return the objSmryNbrPgmRuns
+ */
+ public long getObjSmryNbrPgmRuns() {
+ return objSmryNbrPgmRuns;
+ }
+
+ /**
+ * @return the objSmryChksm
+ */
+ public long getObjSmryChksm() {
+ return objSmryChksm;
+ }
+
+ /**
+ * @return the objSmryArcCnts
+ */
+ public long getObjSmryArcCnts() {
+ return objSmryArcCnts;
+ }
+
+ /**
+ * @return the objSmrytotalCnts
+ */
+ public long getObjSmrytotalCnts() {
+ return objSmrytotalCnts;
+ }
+
+ /**
+ * @return the objSmryRunMax
+ */
+ public long getObjSmryRunMax() {
+ return objSmryRunMax;
+ }
+
+ /**
+ * @return the objSmrySumMax
+ */
+ public long getObjSmrySumMax() {
+ return objSmrySumMax;
+ }
+
+ /**
+ * @return the pgmSmryChksm
+ */
+ public long getPgmSmryChksm() {
+ return pgmSmryChksm;
+ }
+
+
+
+}

Back to the top