From 1008ef70a71fcfdec398ff30923d5025991c85f4 Mon Sep 17 00:00:00 2001 From: Shakeeb Date: Wed, 31 Aug 2016 15:15:19 -0500 Subject: SBE code restructure: cleanup Change-Id: I354cc79ba25b843fdb1a7524a19b8d0c41bd9051 RTC:159709 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/29060 Tested-by: Jenkins Server Reviewed-by: Sachin Gupta Reviewed-by: AMIT J. TENDOLKAR --- src/tools/debug/hw-debug-framework.py | 136 ++++ src/tools/debug/sbe-debug.py | 136 ---- src/tools/debug/simics-debug-framework.py | 88 +++ src/tools/debug/simics/sbe_standalone.simics | 2 - src/tools/debug/simics/simics-debug-framework.py | 88 --- src/tools/image/Makefile | 24 +- src/tools/ppetracepp/Makefile | 37 - src/tools/ppetracepp/cmvc/makefile | 28 - src/tools/ppetracepp/jhash.h | 166 ---- src/tools/ppetracepp/ppe2fsp.c | 532 ------------- src/tools/ppetracepp/ppe2fsp.h | 33 - src/tools/ppetracepp/ppe2fsp_cmd.c | 138 ---- src/tools/ppetracepp/ppetracepp.C | 949 ----------------------- src/tools/ppetracepp/trac_interface.h | 369 --------- src/tools/ppetracepp/tracehash.pl | 896 --------------------- src/tools/scripts/ppeSetFixed.pl | 3 +- src/tools/trace/Makefile | 37 + src/tools/trace/cmvc/makefile | 28 + src/tools/trace/jhash.h | 166 ++++ src/tools/trace/ppe2fsp.c | 532 +++++++++++++ src/tools/trace/ppe2fsp.h | 33 + src/tools/trace/ppe2fsp_cmd.c | 138 ++++ src/tools/trace/ppetracepp.C | 949 +++++++++++++++++++++++ src/tools/trace/trac_interface.h | 369 +++++++++ src/tools/trace/tracehash.pl | 896 +++++++++++++++++++++ src/tools/utils/modules/gitUtil.pm | 592 ++++++++++++++ src/tools/utils/perl.modules/gitUtil.pm | 592 -------------- src/tools/utils/sbeGitTool.pl | 3 +- 28 files changed, 3978 insertions(+), 3982 deletions(-) create mode 100755 src/tools/debug/hw-debug-framework.py delete mode 100755 src/tools/debug/sbe-debug.py create mode 100755 src/tools/debug/simics-debug-framework.py delete mode 100755 src/tools/debug/simics/sbe_standalone.simics delete mode 100755 src/tools/debug/simics/simics-debug-framework.py delete mode 100644 src/tools/ppetracepp/Makefile delete mode 100644 src/tools/ppetracepp/cmvc/makefile delete mode 100755 src/tools/ppetracepp/jhash.h delete mode 100755 src/tools/ppetracepp/ppe2fsp.c delete mode 100644 src/tools/ppetracepp/ppe2fsp.h delete mode 100644 src/tools/ppetracepp/ppe2fsp_cmd.c delete mode 100755 src/tools/ppetracepp/ppetracepp.C delete mode 100755 src/tools/ppetracepp/trac_interface.h delete mode 100755 src/tools/ppetracepp/tracehash.pl create mode 100644 src/tools/trace/Makefile create mode 100644 src/tools/trace/cmvc/makefile create mode 100755 src/tools/trace/jhash.h create mode 100755 src/tools/trace/ppe2fsp.c create mode 100644 src/tools/trace/ppe2fsp.h create mode 100644 src/tools/trace/ppe2fsp_cmd.c create mode 100755 src/tools/trace/ppetracepp.C create mode 100755 src/tools/trace/trac_interface.h create mode 100755 src/tools/trace/tracehash.pl create mode 100644 src/tools/utils/modules/gitUtil.pm delete mode 100644 src/tools/utils/perl.modules/gitUtil.pm (limited to 'src/tools') diff --git a/src/tools/debug/hw-debug-framework.py b/src/tools/debug/hw-debug-framework.py new file mode 100755 index 00000000..7d294e15 --- /dev/null +++ b/src/tools/debug/hw-debug-framework.py @@ -0,0 +1,136 @@ +#!/usr/bin/python +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/debug/hw-debug-framework.py $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +import os +import subprocess +import re +import random +import argparse +import sys +err = False + +syms = {}; + +def fillSymTable(sbeObjDir): + symFile = sbeObjDir + "/sbe.syms" + f = open( symFile, 'r' ) + for line in f: + words = line.split() + if( len( words ) == 4 ): + syms[words[3]] = [words[0], words[1]] + +def collectTrace( hwpBinDir, sbeObjDir, target, proc ): + cmd1 = ("."+hwpBinDir+"/p9_sbe_pibMemDump_wrap.exe " + \ + syms['g_pk_trace_buf'][0] +\ + " " + syms['g_pk_trace_buf'][1] + " " + target) + cmd2 = "." + "/ppe2fsp dumpPibMem sbetrace.bin " + cmd3 = ("." + "/fsp-trace -s " + sbeObjDir +\ + "/trexStringFile sbetrace.bin > "+\ + "sbe_"+str(proc)+"_tracMERG") + cmd4 = "mv dumpPibMem dumpPibMem_trace" + print "\ncollecting trace with commands -\n" + print "cmd1:", cmd1 + rc = os.system( cmd1 ) + if ( rc ): + print "ERROR running %s: %d " % ( cmd1, rc ) + return 1 + + print "cmd2:", cmd2 + rc = os.system( cmd2 ) + if ( rc ): + print "ERROR running %s: %d " % ( cmd2, rc ) + return 1 + + print "cmd3:", cmd3 + rc = os.system( cmd3 ) + if ( rc ): + print "ERROR running %s: %d " % ( cmd3, rc ) + return 1 + + print "cmd4:", cmd4 + rc = os.system( cmd4 ) + if ( rc ): + print "ERROR running %s: %d " % ( cmd4, rc ) + return 1 + +def collectAttr( hwpBinDir, sbeObjDir, target, proc ): + cmd1 = ("."+hwpBinDir+"/p9_sbe_pibMemDump_wrap.exe " +\ + syms['G_sbe_attrs'][0] + " " + \ + syms['G_sbe_attrs'][1] + " " + target) + cmd2 = "mv dumpPibMem sbeAttr.bin" + cmd3 = ("."+ sbeObjDir + "/p9_xip_tool " +\ + sbeObjDir + "/sbe_seeprom.bin -ifs attrdump sbeAttr.bin > "+\ + "sbe_"+str(proc)+"_attrs") + print "\ncollecting attributes with commands -\n" + print "cmd1:", cmd1 + rc = os.system( cmd1 ) + if ( rc ): + print "ERROR running %s: %d " % ( cmd1, rc ) + return 1 + + print "cmd2:", cmd2 + rc = os.system( cmd2 ) + if ( rc ): + print "ERROR running %s: %d " % ( cmd2, rc ) + return 1 + + print "cmd3:", cmd3 + rc = os.system( cmd3 ) + if ( rc ): + print "ERROR running %s: %d " % ( cmd3, rc ) + return 1 + +def main( argv ): + parser = argparse.ArgumentParser( description = "SBE Dump Parser" ) + + parser.add_argument( '-hwpBinDir', type=str, default = os.getcwd(), \ + help = 'Path of p9_sbe_pibMemDump_wrap.exe') + parser.add_argument( '-sbeObjDir', type=str, default = os.getcwd(), \ + help = 'Path of sbe.syms file') + parser.add_argument( '-l', '--level', choices = ['all', 'trace', 'attr'],\ + default='all', help = 'Parser level' ) + parser.add_argument( '-t', '--target', choices = ['AWAN', 'HW'], \ + required = 'true', help = 'Target type' ) + parser.add_argument( '-p', '--proc', type=int , default = 0, \ + help = 'Proc Number' ) + + args = parser.parse_args() + + if ( args.target == 'AWAN' ): + target = "1" + elif ( args.target == 'HW' ): + target = "0" + + fillSymTable(args.sbeObjDir) + if ( args.level == 'all' ): + print "Parsing everything" + collectTrace( args.hwpBinDir, args.sbeObjDir, target, args.proc ) + collectAttr( args.hwpBinDir, args.sbeObjDir, target, args.proc ) + elif ( args.level == 'trace' ): + collectTrace( args.hwpBinDir, args.sbeObjDir, target, args.proc ) + elif ( args.level == 'attr' ): + collectAttr( args.hwpBinDir, args.sbeObjDir, target, args.proc ) + +if __name__ == "__main__": + main( sys.argv ) diff --git a/src/tools/debug/sbe-debug.py b/src/tools/debug/sbe-debug.py deleted file mode 100755 index dbea27d8..00000000 --- a/src/tools/debug/sbe-debug.py +++ /dev/null @@ -1,136 +0,0 @@ -#!/usr/bin/python -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/tools/debug/sbe-debug.py $ -# -# OpenPOWER sbe Project -# -# Contributors Listed Below - COPYRIGHT 2016 -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG -import os -import subprocess -import re -import random -import argparse -import sys -err = False - -syms = {}; - -def fillSymTable(sbeObjDir): - symFile = sbeObjDir + "/sbe.syms" - f = open( symFile, 'r' ) - for line in f: - words = line.split() - if( len( words ) == 4 ): - syms[words[3]] = [words[0], words[1]] - -def collectTrace( hwpBinDir, sbeObjDir, target, proc ): - cmd1 = ("."+hwpBinDir+"/p9_sbe_pibMemDump_wrap.exe " + \ - syms['g_pk_trace_buf'][0] +\ - " " + syms['g_pk_trace_buf'][1] + " " + target) - cmd2 = "." + "/ppe2fsp dumpPibMem sbetrace.bin " - cmd3 = ("." + "/fsp-trace -s " + sbeObjDir +\ - "/trexStringFile sbetrace.bin > "+\ - "sbe_"+str(proc)+"_tracMERG") - cmd4 = "mv dumpPibMem dumpPibMem_trace" - print "\ncollecting trace with commands -\n" - print "cmd1:", cmd1 - rc = os.system( cmd1 ) - if ( rc ): - print "ERROR running %s: %d " % ( cmd1, rc ) - return 1 - - print "cmd2:", cmd2 - rc = os.system( cmd2 ) - if ( rc ): - print "ERROR running %s: %d " % ( cmd2, rc ) - return 1 - - print "cmd3:", cmd3 - rc = os.system( cmd3 ) - if ( rc ): - print "ERROR running %s: %d " % ( cmd3, rc ) - return 1 - - print "cmd4:", cmd4 - rc = os.system( cmd4 ) - if ( rc ): - print "ERROR running %s: %d " % ( cmd4, rc ) - return 1 - -def collectAttr( hwpBinDir, sbeObjDir, target, proc ): - cmd1 = ("."+hwpBinDir+"/p9_sbe_pibMemDump_wrap.exe " +\ - syms['G_sbe_attrs'][0] + " " + \ - syms['G_sbe_attrs'][1] + " " + target) - cmd2 = "mv dumpPibMem sbeAttr.bin" - cmd3 = ("."+ sbeObjDir + "/p9_xip_tool " +\ - sbeObjDir + "/sbe_seeprom.bin -ifs attrdump sbeAttr.bin > "+\ - "sbe_"+str(proc)+"_attrs") - print "\ncollecting attributes with commands -\n" - print "cmd1:", cmd1 - rc = os.system( cmd1 ) - if ( rc ): - print "ERROR running %s: %d " % ( cmd1, rc ) - return 1 - - print "cmd2:", cmd2 - rc = os.system( cmd2 ) - if ( rc ): - print "ERROR running %s: %d " % ( cmd2, rc ) - return 1 - - print "cmd3:", cmd3 - rc = os.system( cmd3 ) - if ( rc ): - print "ERROR running %s: %d " % ( cmd3, rc ) - return 1 - -def main( argv ): - parser = argparse.ArgumentParser( description = "SBE Dump Parser" ) - - parser.add_argument( '-hwpBinDir', type=str, default = os.getcwd(), \ - help = 'Path of p9_sbe_pibMemDump_wrap.exe') - parser.add_argument( '-sbeObjDir', type=str, default = os.getcwd(), \ - help = 'Path of sbe.syms file') - parser.add_argument( '-l', '--level', choices = ['all', 'trace', 'attr'],\ - default='all', help = 'Parser level' ) - parser.add_argument( '-t', '--target', choices = ['AWAN', 'HW'], \ - required = 'true', help = 'Target type' ) - parser.add_argument( '-p', '--proc', type=int , default = 0, \ - help = 'Proc Number' ) - - args = parser.parse_args() - - if ( args.target == 'AWAN' ): - target = "1" - elif ( args.target == 'HW' ): - target = "0" - - fillSymTable(args.sbeObjDir) - if ( args.level == 'all' ): - print "Parsing everything" - collectTrace( args.hwpBinDir, args.sbeObjDir, target, args.proc ) - collectAttr( args.hwpBinDir, args.sbeObjDir, target, args.proc ) - elif ( args.level == 'trace' ): - collectTrace( args.hwpBinDir, args.sbeObjDir, target, args.proc ) - elif ( args.level == 'attr' ): - collectAttr( args.hwpBinDir, args.sbeObjDir, target, args.proc ) - -if __name__ == "__main__": - main( sys.argv ) diff --git a/src/tools/debug/simics-debug-framework.py b/src/tools/debug/simics-debug-framework.py new file mode 100755 index 00000000..d15212ea --- /dev/null +++ b/src/tools/debug/simics-debug-framework.py @@ -0,0 +1,88 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/debug/simics-debug-framework.py $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +import os +import os.path +import subprocess +import re +import random +import sys +import imp +testIstepAuto = imp.load_source("testIstepAuto", os.environ['SBE_TOOLS_PATH'] + "/testIstepAuto.py") +err = False + +syms = {}; + +def check_sbe_tools_path (): + global SBE_TOOLS_PATH + SBE_TOOLS_PATH = os.environ['SBE_TOOLS_PATH']; + +def register_sbe_debug_framework_tools(): + check_sbe_tools_path () + fillSymTable() + # Create command hook. + new_command("sbe-istep",testIstepAuto.sbe_istep_func, + args = [arg(int_t, "major"), arg(int_t, "minor")], + alias = "istep", + type = ["sbe-commands"], + short = "Runs the debug framework for istep ", + doc = "") + new_command("sbe-trace", collectTrace, + args = [arg(int_t, "procNr")], + alias = "strace", + type = ["sbe-commands"], + short = "Runs the debug framework for trace ", + doc = "") + print "SBE Debug Framework: Registered tool:", "sbe-istep" + print "SBE Debug Framework: Registered tool:", "sbe-trace" + + +def fillSymTable(): +# symFile = os.environ['SBE_IMG_OUT_LOC'] + "/sbe.syms" + symFile = SBE_TOOLS_PATH + "/sbe.syms" +# symFile = os.environ['sb'] + "/../obj/ppc/sbei/sbfw/simics/sbe.syms" + f = open( symFile, 'r') + for line in f: + words = line.split() + if( len( words ) == 4 ): + syms[words[3]] = [words[0], words[1]] + +def collectTrace ( procNr ): + fileName = "sbe_" + `procNr` + "_tracMERG" + cmd1 = "pipe \"p9Proc" + `procNr` + ".sbe.mibo_space.x 0x" + syms['g_pk_trace_buf'][0] + " 0x2028\" \"sed 's/^p:0x........ //g' | sed 's/ ................$//g' | sed 's/ //g' | xxd -r -p> ppetrace.bin\"" + cmd2 = "shell \"" + SBE_TOOLS_PATH + "/ppe2fsp ppetrace.bin sbetrace.bin \"" + cmd3 = "shell \"" + SBE_TOOLS_PATH + "/fsp-trace -s " + SBE_TOOLS_PATH + "/sbeStringFile sbetrace.bin >" + fileName + "\"" + cmd4 = "shell \"" + "cat " + fileName + "\"" + + ( rc, out ) = quiet_run_command( cmd1, output_modes.regular ) + if ( rc ): + print "simics ERROR running %s: %d "%( cmd1, rc ) + + SIM_run_alone( run_command, cmd2 ) + SIM_run_alone( run_command, cmd3 ) + SIM_run_alone( run_command, cmd4 ) + + +# Run the registration automatically whenever this script is loaded. +register_sbe_debug_framework_tools() + diff --git a/src/tools/debug/simics/sbe_standalone.simics b/src/tools/debug/simics/sbe_standalone.simics deleted file mode 100755 index 8fd3bdb0..00000000 --- a/src/tools/debug/simics/sbe_standalone.simics +++ /dev/null @@ -1,2 +0,0 @@ -echo "SBE standalone Tools" - diff --git a/src/tools/debug/simics/simics-debug-framework.py b/src/tools/debug/simics/simics-debug-framework.py deleted file mode 100755 index 87d3656b..00000000 --- a/src/tools/debug/simics/simics-debug-framework.py +++ /dev/null @@ -1,88 +0,0 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/tools/debug/simics/simics-debug-framework.py $ -# -# OpenPOWER sbe Project -# -# Contributors Listed Below - COPYRIGHT 2016 -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG -import os -import os.path -import subprocess -import re -import random -import sys -import imp -testIstepAuto = imp.load_source("testIstepAuto", os.environ['SBE_TOOLS_PATH'] + "/testIstepAuto.py") -err = False - -syms = {}; - -def check_sbe_tools_path (): - global SBE_TOOLS_PATH - SBE_TOOLS_PATH = os.environ['SBE_TOOLS_PATH']; - -def register_sbe_debug_framework_tools(): - check_sbe_tools_path () - fillSymTable() - # Create command hook. - new_command("sbe-istep",testIstepAuto.sbe_istep_func, - args = [arg(int_t, "major"), arg(int_t, "minor")], - alias = "istep", - type = ["sbe-commands"], - short = "Runs the debug framework for istep ", - doc = "") - new_command("sbe-trace", collectTrace, - args = [arg(int_t, "procNr")], - alias = "strace", - type = ["sbe-commands"], - short = "Runs the debug framework for trace ", - doc = "") - print "SBE Debug Framework: Registered tool:", "sbe-istep" - print "SBE Debug Framework: Registered tool:", "sbe-trace" - - -def fillSymTable(): -# symFile = os.environ['SBE_IMG_OUT_LOC'] + "/sbe.syms" - symFile = SBE_TOOLS_PATH + "/sbe.syms" -# symFile = os.environ['sb'] + "/../obj/ppc/sbei/sbfw/simics/sbe.syms" - f = open( symFile, 'r') - for line in f: - words = line.split() - if( len( words ) == 4 ): - syms[words[3]] = [words[0], words[1]] - -def collectTrace ( procNr ): - fileName = "sbe_" + `procNr` + "_tracMERG" - cmd1 = "pipe \"p9Proc" + `procNr` + ".sbe.mibo_space.x 0x" + syms['g_pk_trace_buf'][0] + " 0x2028\" \"sed 's/^p:0x........ //g' | sed 's/ ................$//g' | sed 's/ //g' | xxd -r -p> ppetrace.bin\"" - cmd2 = "shell \"" + SBE_TOOLS_PATH + "/ppe2fsp ppetrace.bin sbetrace.bin \"" - cmd3 = "shell \"" + SBE_TOOLS_PATH + "/fsp-trace -s " + SBE_TOOLS_PATH + "/sbeStringFile sbetrace.bin >" + fileName + "\"" - cmd4 = "shell \"" + "cat " + fileName + "\"" - - ( rc, out ) = quiet_run_command( cmd1, output_modes.regular ) - if ( rc ): - print "simics ERROR running %s: %d "%( cmd1, rc ) - - SIM_run_alone( run_command, cmd2 ) - SIM_run_alone( run_command, cmd3 ) - SIM_run_alone( run_command, cmd4 ) - - -# Run the registration automatically whenever this script is loaded. -register_sbe_debug_framework_tools() - diff --git a/src/tools/image/Makefile b/src/tools/image/Makefile index fab89e66..58650875 100644 --- a/src/tools/image/Makefile +++ b/src/tools/image/Makefile @@ -6,6 +6,7 @@ # OpenPOWER sbe Project # # Contributors Listed Below - COPYRIGHT 2015,2016 +# [+] International Business Machines Corp. # # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -59,28 +60,23 @@ else CXX = g++ endif -UTILITIES-SOURCES = sbe_default_tool.c -UTILITIES = sbe_default_tool - -# Utility targets -UTILITIES-OBJc = $(patsubst %.c,$(BASE_OBJDIR)/%.o,$(UTILITIES-SOURCES)) -UTILITIES-OBJECTS += $(patsubst %.C,$(BASE_OBJDIR)/%.o,$(UTILITIES-OBJc)) -UTILITIES-DEPENDENCIES = $(patsubst %.o,%.d,$(UTILITIES-OBJECTS)) -UTILITIES-EXECUTABLES = $(patsubst %,$(BASE_OBJDIR)/%,$(UTILITIES)) - .PHONY : all utilities clean -all: utilities +all:objdir utilities + +objdir: + mkdir -p $(BASE_OBJDIR)/tools/image -utilities: $(UTILITIES-EXECUTABLES) +utilities: $(IMG_DIR)/sbe_default_tool CXXFLAGS+=-DFAPI2_NO_FFDC -$(BASE_OBJDIR)/%.o: %.c +$(BASE_OBJDIR)/tools/image/%.o: %.c $(CXX) -std=c++11 $(INCLUDES) $(CXXFLAGS) -c -o $@ $< -$(BASE_OBJDIR)/sbe_default_tool: $(P9_XIP_BINDIR)/p9_xip_image.o $(BASE_OBJDIR)/sbe_default_tool.o +$(IMG_DIR)/sbe_default_tool: $(P9_XIP_BINDIR)/p9_xip_image.o $(BASE_OBJDIR)/tools/image/sbe_default_tool.o $(CXX) $(CXXFLAGS) ${INCLUDES} -o $@ $^ clean: - rm -f $(BASE_OBJDIR)/sbe_default_tool* + rm -f $(BASE_OBJDIR)/tools/image/sbe_default_tool* + rm -f $(IMG_DIR)/sbe_default_tool* diff --git a/src/tools/ppetracepp/Makefile b/src/tools/ppetracepp/Makefile deleted file mode 100644 index eec6da6a..00000000 --- a/src/tools/ppetracepp/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/tools/ppetracepp/Makefile $ -# -# OpenPOWER sbe Project -# -# Contributors Listed Below - COPYRIGHT 2015,2016 -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG -include img_defs.mk - -all: ppetracepp ppe2fsp - -ppetracepp: ppetracepp.C - g++ -m32 -O3 -w -g -I./ ppetracepp.C -o $(PPETRACEPP_BIN_DIR)/ppetracepp -# g++ -O3 -w -x c++ -fPIC -g -I./ ppetracepp.C -o ppetracepp - -ppe2fsp: ppe2fsp.c ppe2fsp_cmd.c - gcc -m32 -w -g -I./ -I$(PK_SRCDIR)/trace ppe2fsp.c ppe2fsp_cmd.c -o $(PPETRACEPP_BIN_DIR)/ppe2fsp - -clean: - rm $(PPETRACEPP_BIN_DIR)/ppetracepp $(PPETRACEPP_BIN_DIR)/ppe2fsp - diff --git a/src/tools/ppetracepp/cmvc/makefile b/src/tools/ppetracepp/cmvc/makefile deleted file mode 100644 index cf2ad437..00000000 --- a/src/tools/ppetracepp/cmvc/makefile +++ /dev/null @@ -1,28 +0,0 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/tools/ppetracepp/cmvc/makefile $ -# -# OpenPOWER sbe Project -# -# Contributors Listed Below - COPYRIGHT 2016 -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG -PROGRAMS += ppe2fsp -ppe2fsp_OFILES = ppe2fsp.o ppe2fsp_cmd.o - -.include <${RULES_MK}> - diff --git a/src/tools/ppetracepp/jhash.h b/src/tools/ppetracepp/jhash.h deleted file mode 100755 index 0dcc3bf3..00000000 --- a/src/tools/ppetracepp/jhash.h +++ /dev/null @@ -1,166 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/tools/ppetracepp/jhash.h $ */ -/* */ -/* OpenPOWER sbe Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -#ifndef _LINUX_JHASH_H -#define _LINUX_JHASH_H - -/* jhash.h: Jenkins hash support. - * - * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) - * - * http://burtleburtle.net/bob/hash/ - * - * These are the credits from Bob's sources: - * - * lookup2.c, by Bob Jenkins, December 1996, Public Domain. - * hash(), hash2(), hash3, and mix() are externally useful functions. - * Routines to test the hash are included if SELF_TEST is defined. - * You can use this free for any purpose. It has no warranty. - * - * Copyright (C) 2003 David S. Miller (davem@redhat.com) - * - * I've modified Bob's hash to be useful in the Linux kernel, and - * any bugs present are surely my fault. -DaveM - */ - -/* NOTE: Arguments are modified. */ -#define __jhash_mix(a, b, c) \ -{ \ - a -= b; a -= c; a ^= (c>>13); \ - b -= c; b -= a; b ^= (a<<8); \ - c -= a; c -= b; c ^= (b>>13); \ - a -= b; a -= c; a ^= (c>>12); \ - b -= c; b -= a; b ^= (a<<16); \ - c -= a; c -= b; c ^= (b>>5); \ - a -= b; a -= c; a ^= (c>>3); \ - b -= c; b -= a; b ^= (a<<10); \ - c -= a; c -= b; c ^= (b>>15); \ -} - -/* The golden ration: an arbitrary value */ -#define JHASH_GOLDEN_RATIO 0x9e3779b9 - -/* The most generic version, hashes an arbitrary sequence - * of bytes. No alignment or length assumptions are made about - * the input key. - */ -static inline u32 jhash(const void *key, u32 length, u32 initval) -{ - u32 a, b, c, len; - const u8 *k = (const u8*)key; - - len = length; - a = b = JHASH_GOLDEN_RATIO; - c = initval; - - while (len >= 12) { - a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); - b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); - c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); - - __jhash_mix(a,b,c); - - k += 12; - len -= 12; - } - - c += length; - switch (len) { - case 11: c += ((u32)k[10]<<24); - case 10: c += ((u32)k[9]<<16); - case 9 : c += ((u32)k[8]<<8); - case 8 : b += ((u32)k[7]<<24); - case 7 : b += ((u32)k[6]<<16); - case 6 : b += ((u32)k[5]<<8); - case 5 : b += k[4]; - case 4 : a += ((u32)k[3]<<24); - case 3 : a += ((u32)k[2]<<16); - case 2 : a += ((u32)k[1]<<8); - case 1 : a += k[0]; - }; - - __jhash_mix(a,b,c); - - return c; -} - -/* A special optimized version that handles 1 or more of u32s. - * The length parameter here is the number of u32s in the key. - */ -static inline u32 jhash2(const u32 *k, u32 length, u32 initval) -{ - u32 a, b, c, len; - - a = b = JHASH_GOLDEN_RATIO; - c = initval; - len = length; - - while (len >= 3) { - a += k[0]; - b += k[1]; - c += k[2]; - __jhash_mix(a, b, c); - k += 3; len -= 3; - } - - c += length * 4; - - switch (len) { - case 2 : b += k[1]; - case 1 : a += k[0]; - }; - - __jhash_mix(a,b,c); - - return c; -} - - -/* A special ultra-optimized versions that knows they are hashing exactly - * 3, 2 or 1 word(s). - * - * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally - * done at the end is not done here. - */ -static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) -{ - a += JHASH_GOLDEN_RATIO; - b += JHASH_GOLDEN_RATIO; - c += initval; - - __jhash_mix(a, b, c); - - return c; -} - -static inline u32 jhash_2words(u32 a, u32 b, u32 initval) -{ - return jhash_3words(a, b, 0, initval); -} - -static inline u32 jhash_1word(u32 a, u32 initval) -{ - return jhash_3words(a, 0, 0, initval); -} - -#endif /* _LINUX_JHASH_H */ diff --git a/src/tools/ppetracepp/ppe2fsp.c b/src/tools/ppetracepp/ppe2fsp.c deleted file mode 100755 index d681b147..00000000 --- a/src/tools/ppetracepp/ppe2fsp.c +++ /dev/null @@ -1,532 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/tools/ppetracepp/ppe2fsp.c $ */ -/* */ -/* OpenPOWER sbe Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -#include "pk_trace.h" -#include "ppe2fsp.h" -#include "trac_interface.h" -#include -#include -#include - -#define TRACE_BUF_VERSION 0x01 /*!< Trace buffer version */ -#define TRACE_FIELDTRACE 0x4654 /*!< Field Trace - "FT" */ -#define TRACE_FIELDBIN 0x4644 /*!< Binary Field Trace - "FD" */ - -#define TRAC_TIME_REAL 0 // upper 32 = seconds, lower 32 = nanoseconds -#define TRAC_TIME_50MHZ 1 -#define TRAC_TIME_200MHZ 2 -#define TRAC_TIME_167MHZ 3 // 166666667Hz - -typedef struct -{ - trace_entry_stamp_t stamp; - trace_entry_head_t head; - union - { - uint8_t data[PK_TRACE_MAX_BINARY + 1]; //add 1 byte for padding - uint32_t parms[PK_TRACE_MAX_PARMS]; - }; - uint32_t size; -}largest_fsp_entry_t; - -typedef struct -{ - union - { - uint8_t binary_data[PK_TRACE_MAX_BINARY + 1]; - struct - { - uint8_t rsvd[(PK_TRACE_MAX_BINARY + 1) - (PK_TRACE_MAX_PARMS * sizeof(uint32_t))]; - uint32_t parms[PK_TRACE_MAX_PARMS]; - }; - }; - PkTraceEntryFooter footer; -}LargestPpeEntry; - -//convert a ppe timestamp to an fsp trace timestamp -uint64_t ppe2fsp_time(uint64_t ppe_time, uint32_t hz) -{ - uint32_t seconds; - uint32_t remainder; - uint32_t nseconds; - - //convert from ppe ticks to seconds and nanoseconds - seconds = ppe_time / hz; - remainder = ppe_time - (((uint64_t)seconds) * hz); - nseconds = (((uint64_t)remainder) * 1000000000) / hz; - return (((uint64_t)seconds) << 32) | nseconds; -} - -//Writes an fsp trace entry to the fsp trace buffer -void fsp_put_entry(trace_buf_head_t* tb, largest_fsp_entry_t* fte, size_t entry_size, uint32_t bytes_left) -{ - char* buffer = ((char*)tb) + sizeof(trace_buf_head_t); - char* tb_start; - char* fte_start; - uint32_t copy_bytes; - - if(entry_size <= bytes_left) - { - tb_start = buffer + bytes_left - entry_size; - fte_start = (char*)fte; - copy_bytes = entry_size; - } - else - { - tb_start = buffer; - fte_start = ((char*)fte) + (entry_size - bytes_left); - copy_bytes = bytes_left; - } - - memcpy(tb_start, fte_start, copy_bytes); -} - - -//convert a ppe trace entry to an fsp trace entry -size_t pte2fte(PkTraceBuffer* ptb, - LargestPpeEntry* pte, - size_t pte_size, - largest_fsp_entry_t* fte, - uint64_t ppe_time64) -{ - size_t entry_size; - PkTraceGeneric* pte_footer = &pte->footer.generic; - uint32_t format; - uint32_t hash32; - uint32_t hash32_partial; - uint32_t* parm_start; - uint32_t parm_bytes; - uint64_t fsp_time64; - - //convert the ppe trace time to an fsp trace time - fsp_time64 = ppe2fsp_time(ppe_time64, ntohl(ptb->hz)); - - //fill in the 64 bit timestamp - fte->stamp.tbh = htonl((uint32_t)(fsp_time64 >> 32)); - fte->stamp.tbl = htonl((uint32_t)(fsp_time64 & 0x00000000ffffffffull)); - - //use the ppe instance id as the thread id. - fte->stamp.tid = htonl((uint32_t)ntohs(ptb->instance_id)); - - //merge the hash prefix and the string_id fields together for a 32 bit hash value - hash32 = ((uint32_t)ntohs(ptb->hash_prefix)) << 16; - hash32 |= pte_footer->string_id; - fte->head.hash = htonl(hash32); - - //generate the 32bit hash value for a partial trace entry in case it's needed - hash32_partial = ((uint32_t)ntohs(ptb->hash_prefix)) << 16; - hash32_partial |= ntohs(ptb->partial_trace_hash); - - //set the line number to 1 - fte->head.line = htonl(1); - - //determine the FSP trace format - format = PK_GET_TRACE_FORMAT(pte_footer->time_format.word32); - if(format == PK_TRACE_FORMAT_BINARY) - { - fte->head.tag = htons(TRACE_FIELDBIN); - } - else - { - fte->head.tag = htons(TRACE_FIELDTRACE); - } - - parm_start = (uint32_t*)(((char*)pte) + (sizeof(LargestPpeEntry) - pte_size)); - - //fill in the parameters/binary data and size at the end - switch(format) - { - - case PK_TRACE_FORMAT_TINY: - //one or 0 parameters - entry_size = sizeof(trace_entry_stamp_t) + - sizeof(trace_entry_head_t) + - sizeof(uint32_t); - fte->parms[0] = htonl((uint32_t)(pte_footer->parm16)); - fte->head.length = htons(sizeof(uint32_t)); - parm_bytes = 0; - break; - - case PK_TRACE_FORMAT_BIG: - //1 - 4 parameters - // - //If the trace entry data is incomplete (not all parm data - //had been written at the time the trace was captured) then - //we will write a trace to the fsp buffer that says - //"PARTIAL TRACE ENTRY. HASH_ID = %d" - if(pte_footer->complete) - { - parm_bytes = pte_footer->bytes_or_parms_count * sizeof(uint32_t); - fte->head.length = htons(parm_bytes + sizeof(uint32_t)); - entry_size = sizeof(trace_entry_stamp_t) + - sizeof(trace_entry_head_t) + - parm_bytes + sizeof(uint32_t); - } - else - { - parm_bytes = 0; - entry_size = sizeof(trace_entry_stamp_t) + - sizeof(trace_entry_head_t) + - sizeof(uint32_t); - fte->parms[0] = fte->head.hash; //already corrected for endianess - fte->head.hash = htonl(hash32_partial); - fte->head.length = htons(sizeof(uint32_t)); - } - break; - - case PK_TRACE_FORMAT_BINARY: - //If the trace entry data is incomplete (not all parm data - //had been written at the time the trace was captured) then - //we will write a trace to the fsp buffer that says - //"PARTIAL TRACE ENTRY. HASH_ID = %d" - if(pte_footer->complete) - { - parm_bytes = pte_footer->bytes_or_parms_count; - fte->head.length = htons((uint16_t)parm_bytes); - entry_size = sizeof(trace_entry_stamp_t) + - sizeof(trace_entry_head_t) + - parm_bytes; - - //pad to 4 byte boundary - entry_size = (entry_size + 3) & ~3; - } - else - { - parm_bytes = 0; - entry_size = sizeof(trace_entry_stamp_t) + - sizeof(trace_entry_head_t) + - sizeof(uint32_t); - fte->parms[0] = fte->head.hash; - fte->head.hash = htonl(hash32_partial); - fte->head.length = htons(sizeof(uint32_t)); - fte->head.tag = htons(TRACE_FIELDTRACE); - } - break; - - - default: - entry_size = 0; - parm_bytes = 0; - break; - } - - //copy parameter bytes to the fsp entry if necessary - if(parm_bytes) - { - memcpy(fte->data, parm_start, parm_bytes); - } - - //add the entry size to the end - if(entry_size) - { - uint32_t new_entry_size = entry_size + sizeof(uint32_t); - *((uint32_t*)(((char*)fte) + entry_size)) = htonl(new_entry_size); - entry_size = new_entry_size; - } - - return entry_size; -} - -//retrieve a ppe trace entry from a ppe trace buffer -size_t ppe_get_entry(PkTraceBuffer* tb, uint32_t offset, LargestPpeEntry* pte) -{ - uint32_t mask = ntohs(tb->size) - 1; - PkTraceEntryFooter* footer; - size_t entry_size; - size_t parm_size; - char* dest = (char*)pte; - uint32_t format; - uint32_t start_index; - uint32_t bytes_left; - uint32_t bytes_to_copy; - - //Find the footer in the circular buffer - footer = (PkTraceEntryFooter*)(&tb->cb[(offset - sizeof(PkTraceEntryFooter)) & mask]); - - //always correct endianess for the time and string id words - pte->footer.generic.time_format.word32 = ntohl(footer->generic.time_format.word32); - pte->footer.generic.string_id = ntohs(footer->generic.string_id); - - //only need to byte swap the parm16 value if this is a tiny format - pte->footer.generic.parm16 = footer->generic.parm16; - - //use footer data to determine the length of the binary data or parameters - format = PK_GET_TRACE_FORMAT(pte->footer.generic.time_format.word32); - switch(format) - { - case PK_TRACE_FORMAT_TINY: - pte->footer.generic.parm16 = ntohs(pte->footer.generic.parm16); - parm_size = 0; - entry_size = sizeof(PkTraceEntryFooter); - break; - - case PK_TRACE_FORMAT_BIG: - parm_size = pte->footer.generic.bytes_or_parms_count * sizeof(uint32_t); - entry_size = sizeof(PkTraceEntryFooter); - break; - - case PK_TRACE_FORMAT_BINARY: - parm_size = pte->footer.generic.bytes_or_parms_count; - entry_size = sizeof(PkTraceEntryFooter); - break; - - default: - entry_size = 0; - parm_size = 0; - break; - } - - //pad to 8 byte boundary - parm_size = (parm_size + 7) & ~0x00000007ul; - - //add the parameter size to the total entry size - entry_size += parm_size; - - //copy the entry from the circular buffer to pte - start_index = (offset - entry_size) & mask; - bytes_left = ntohs(tb->size) - start_index; - - //only copy up to the end of the circular buffer - if(parm_size < bytes_left) - { - bytes_to_copy = parm_size; - } - else - { - bytes_to_copy = bytes_left; - } - - dest += sizeof(LargestPpeEntry) - entry_size; - memcpy(dest, &tb->cb[start_index], bytes_to_copy); - - //now copy the rest of the data starting from the beginning of the - //circular buffer. - if(bytes_to_copy < parm_size) - { - memcpy(dest + bytes_to_copy, tb->cb, parm_size - bytes_to_copy); - } - - //return the size of the entry - return entry_size; -} - -//convert a ppe trace buffer to an fsp trace buffer -int ppe2fsp(void* in, size_t in_size, void* out, size_t* io_size) -{ - PkTraceBuffer* ptb = (PkTraceBuffer*)in; - trace_buf_head_t* ftb = (trace_buf_head_t*)out; - uint32_t ppe_bytes_left; - uint32_t fsp_bytes_left; - int rc = 0; - uint32_t ptb_offset; - uint64_t ppe_time64; - uint32_t fte_size, pte_size; - uint32_t fsp_te_count = 0; - uint32_t time_diff32, prev_time32, new_time32; - PkTraceGeneric* pte_footer; - largest_fsp_entry_t fte; - LargestPpeEntry pte; - uint64_t time_adj64; - - do - { - if(!ptb || !ftb || !io_size) - { - rc = P2F_NULL_POINTER; - break; - } - - if(ntohs(ptb->version) != PK_TRACE_VERSION) - { - rc = P2F_INVALID_VERSION; - break; - } - - //check that the input buffer is large enough to have a ppe trace buffer - if(in_size < (((uintptr_t)(&ptb->cb[0])) - (uintptr_t)(ptb))) - { - rc = P2F_INPUT_BUFFER_TOO_SMALL; - break; - } - - //initialize some locals - fsp_bytes_left = *io_size - sizeof(trace_buf_head_t); - ppe_bytes_left = ntohs(ptb->size); - ptb_offset = ntohl(ptb->state.offset); - if(htonl(1) == 1) - { - time_adj64 = ptb->time_adj64; - } - else - { - time_adj64 = ntohl((uint32_t)(ptb->time_adj64 >> 32)); - time_adj64 |= ((uint64_t)(ntohl((uint32_t)(ptb->time_adj64 & 0x00000000ffffffff)))) << 32; - } - - //make sure the ppe buffer size is a power of two - if((ppe_bytes_left - 1) & ppe_bytes_left) - { - //size is not a power of two - rc = P2F_INVALID_INPUT_SIZE; - break; - } - - //The ppe bytes field should always be a multiple of 8 - if(ptb_offset & 0x7) - { - rc = P2F_INVALID_PPE_OFFSET; - break; - } - - //make sure there is enough room for the fsp header - if(*io_size < sizeof(trace_buf_head_t)) - { - rc = P2F_OUTPUT_BUFFER_TOO_SMALL; - break; - } - - - //initialize the fsp header - ftb->ver = TRACE_BUF_VERSION; - ftb->hdr_len = sizeof(trace_buf_head_t); - ftb->time_flg = TRAC_TIME_REAL; - ftb->endian_flg = 'B'; //big endian - memcpy(ftb->comp, ptb->image_str, sizeof(ftb->comp)); - ftb->times_wrap = htonl(1); - ftb->size = htonl(sizeof(trace_buf_head_t) + sizeof(uint32_t)); - ftb->next_free = htonl(sizeof(trace_buf_head_t)); - ftb->extracted = htonl(0); - ftb->te_count = htonl(0); - - //find the latest timestamp so that we can work back from there - ppe_time64 = ((uint64_t)(ntohl(ptb->state.tbu32) & 0xefffffff)) << 32; - pte_size = ppe_get_entry(ptb, ptb_offset, &pte); - prev_time32 = PK_GET_TRACE_TIME(pte.footer.generic.time_format.word32); - ppe_time64 |= prev_time32; - - //process all of the input bytes one trace entry at a time - //from newest to oldest (backwards) until we run out of input bytes or - //we run out of output space. - while(1) - { - //check if we have enough data for a ppe footer - if(ppe_bytes_left < sizeof(PkTraceEntryFooter)) - { - break; - } - - //get the next ppe entry - pte_size = ppe_get_entry(ptb, ptb_offset, &pte); - - //Stop if there are no more entries to retrieve from the ppe trace buffer - if(!pte_size) - { - break; - } - pte_footer = &pte.footer.generic; - - //mark the entry as incomplete if we didn't have enough data - //for the entire entry - if(pte_size > ppe_bytes_left) - { - pte_footer->complete = 0; - ppe_bytes_left = 0; - } - else - { - ppe_bytes_left -= pte_size; - ptb_offset -= pte_size; - } - - //Calculate the 64 bit timestamp for this entry.... - //On PPE, getting the timestamp is not done atomically with writing - //the entry to the buffer. This means that an entry with an older - //timestamp could possibly be added to the buffer after an entry - //with a newer timestamp. Detect this condition by checking if the - //time difference is bigger than the max difference. The max - //difference is enforced by the PPE having a trace added on a - //shorter time boundary (using a timer). - new_time32 = PK_GET_TRACE_TIME(pte_footer->time_format.word32); - time_diff32 = prev_time32 - new_time32; - - if(time_diff32 > ntohl(ptb->max_time_change)) - { - time_diff32 = new_time32 - prev_time32; - ppe_time64 += time_diff32; - } - else - { - ppe_time64 -= time_diff32; - } - - //save off the lower 32bit timestamp for the next iteration - prev_time32 = new_time32; - - //convert the ppe trace entry to an fsp trace entry - fte_size = pte2fte(ptb, &pte, pte_size, &fte, ppe_time64 + time_adj64); - - //fit as much of the entry into the fsp trace buffer as possible - fsp_put_entry(ftb, &fte, fte_size, fsp_bytes_left); - - //update the fsp trace entry count - fsp_te_count++; - - //stop if there is no more room left in the fsp trace buffer - if(fte_size >= fsp_bytes_left) - { - fsp_bytes_left = 0; - ftb->times_wrap = htonl(1); - break; - } - else - { - fsp_bytes_left -= fte_size; - } - }//while(1) - - - //shift the trace data up if there is space to do so - if(fsp_bytes_left) - { - char* dest = ((char*)ftb) + sizeof(trace_buf_head_t); - char* src = dest + fsp_bytes_left; - size_t data_size = *io_size - sizeof(trace_buf_head_t) - fsp_bytes_left; - memmove(dest, src, data_size); - } - - //update the fsp header to reflect the true size and entry count - ftb->te_count = htonl(fsp_te_count); - - //inform the caller of how many bytes were actually used - *io_size -= fsp_bytes_left; - - //shrink the size field to what we actually ended up using - ftb->size = htonl(*io_size); - - }while(0); - - return rc; -} - - - diff --git a/src/tools/ppetracepp/ppe2fsp.h b/src/tools/ppetracepp/ppe2fsp.h deleted file mode 100644 index 2abb146c..00000000 --- a/src/tools/ppetracepp/ppe2fsp.h +++ /dev/null @@ -1,33 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/tools/ppetracepp/ppe2fsp.h $ */ -/* */ -/* OpenPOWER sbe Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -#include - -#define P2F_NULL_POINTER 1 -#define P2F_INVALID_INPUT_SIZE 2 -#define P2F_INVALID_PPE_OFFSET 3 -#define P2F_OUTPUT_BUFFER_TOO_SMALL 4 -#define P2F_INPUT_BUFFER_TOO_SMALL 5 -#define P2F_INVALID_VERSION 6 - -int ppe2fsp(void* in, size_t in_size, void* out, size_t* io_size); diff --git a/src/tools/ppetracepp/ppe2fsp_cmd.c b/src/tools/ppetracepp/ppe2fsp_cmd.c deleted file mode 100644 index c36d735c..00000000 --- a/src/tools/ppetracepp/ppe2fsp_cmd.c +++ /dev/null @@ -1,138 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/tools/ppetracepp/ppe2fsp_cmd.c $ */ -/* */ -/* OpenPOWER sbe Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -#include -#include "ppe2fsp.h" -#include "pk_trace.h" - -#define MAX_INPUT_SIZE 0x2040 //8k -#define MAX_OUTPUT_SIZE (4 * MAX_INPUT_SIZE) - -char* inbuf[MAX_INPUT_SIZE]; -char* outbuf[MAX_OUTPUT_SIZE]; -; -int main(int argc, char** argv) -{ - FILE* in; - FILE* out; - size_t input_size; - size_t output_size; - size_t bytes_written; - int rc = -1; - - do - { - if(argc > 3) - { - fprintf(stderr, "Usage: %s [input file] [output file]\n", argv[0]); - } - - if(argc < 3) - { - out = stdout; - } - else - { - //open the output file for writing - out = fopen(argv[2], "w"); - if(!out) - { - perror("failed to open file for writing"); - break; - } - } - - if(argc < 2) - { - in = stdin; - } - else - { - //open the input file for reading - in = fopen(argv[1], "r"); - if(!in) - { - perror("failed to open file for reading"); - break; - } - } - - //read the input stream until we reach EOF or the max size - input_size = fread(inbuf, 1, MAX_INPUT_SIZE, in); - if(!feof(in)) - { - if(ferror(in)) - { - perror("failed to read input file"); - break; - } - else - { - fprintf(stderr, "Input stream exceeds max size of %d bytes. Exiting.\n", MAX_INPUT_SIZE); - break; - } - } - - output_size = MAX_OUTPUT_SIZE; - - //Actual size of output buffer will be set upon successful completion - rc = ppe2fsp(inbuf, input_size, outbuf, &output_size); - if(rc) - { - fprintf(stderr, "Failed converting ppe trace to fsp trace. rc = %d\n", rc); - if(rc == P2F_INVALID_VERSION) - { - fprintf(stderr, "PPE trace buffer must be version %d.\n", PK_TRACE_VERSION); - } - break; - } - - rc = -1; - //operation was successful. Write out the fsp trace data - bytes_written = fwrite(outbuf, 1, output_size, out); - if(bytes_written != output_size) - { - if(ferror(out)) - { - perror("Failed to write output stream"); - break; - } - fprintf(stderr, "Failure: Only able to write %d of %d bytes to output stream\n", bytes_written, output_size); - break; - } - - fclose(in); - fclose(out); - fclose(stderr); - - rc = 0; - }while(0); - - return rc; -} - - - - - - diff --git a/src/tools/ppetracepp/ppetracepp.C b/src/tools/ppetracepp/ppetracepp.C deleted file mode 100755 index 2829e4dd..00000000 --- a/src/tools/ppetracepp/ppetracepp.C +++ /dev/null @@ -1,949 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/tools/ppetracepp/ppetracepp.C $ */ -/* */ -/* OpenPOWER sbe Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -/* -# *** ppetracepp - a fsp/common Linux trace pre processor -# this one replaces the trace strings by the corresponding hash value -# (i.e. the complete call to trace_ppe_hash is replaced) - -# *** Usage -# -# prepend compiler call with the call of this pre processor, i.e if you have -# $(CC) $(CFLAGS) -o $@ $< -# in your Makefile change it to this: -# ppetracepp $(CC) $(CFLAGS) -o $@ $< -# ppetracepp will use "$(CC) -E" to call the C pre processor "cpp". -# you can set a env var "REALCPP" to the name of a program to select -# a different programm as cpp -# -# ppetracepp creates a file "$target.ppe.hash" with the trace strings and the hash values. -# -# to enable debug mode set envvar PPETRACEPPDEBUG to 1 or give '-d' as first arg - -# *** Change History -# -# 2003-02-26 RBa created from scratch -# 2003-02-28 RBa add C++ support (C++ interface uses own type for the hash) -# 2003-05-28 RBa if cc should link instead of compile just call compiler -# 2003-07-11 AGe Change search alg. slightly and put just format back -# 2003-07-25 RBa just call gcc if called to link instead to compile -# eat argument for option -x -# 2003-11-26 RBa fix c/c++ algo: compile as c++ if realcc=*g++ -# 2004-02-02 RBa remove explicit test whether source file is readable -# it is obsolete and might lead to an error if afs is used -# 2004-02-13 RBa add support for dependency generation (-MD/-MG, -MF) -# don't prepend './' to object filename -# 2006-04-19 RBa rewrite trace_ppe_write_all support, handle C and C++ the same -# 2006-05-24 RBa fix handling of missing -o ; add TRAC_PPVER for macro/API version -# 2006-09-15 RBa add handling of \" in trace format strings ; reduce non-error output -# put object file in current dir if no -o given -# 2007-03-22 RBa handle more gcc options (-i) ; protect " in call to shell -# store output of cpp as "unmodified" output for debug -# only write string/hash file if strings found -# 2012-09-24 hlava Rewritten as C program for better build performance (was perl) -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -typedef u_int32_t u32 ; -typedef u_int8_t u8 ; -#include - -using namespace std; - -static string version = "2.0"; -static string macro_version = "1"; - -static bool debug = false; -#define dprintf(format, ...) if (debug) { printf(format, ##__VA_ARGS__); fflush(stdout); } -static map hashtab; -static string hashtype; -static string hashtype_suffix; - -static string tmp; -static string cmd; -static FILE* CPP = NULL; // pipe from preprocessor -static FILE* CC = NULL; // pipe to compiler -static FILE* DEBUG = NULL; -static FILE* DEBUGIN = NULL; - -//***************************************************************************** -// replace_substr -//***************************************************************************** -void replace_substr(std::string& str, const std::string& oldStr, const std::string& newStr) -{ - size_t pos = 0; - while((pos = str.find(oldStr, pos)) != std::string::npos) - { - str.replace(pos, oldStr.length(), newStr); - pos += newStr.length(); - } - -} - -//***************************************************************************** -// fileparse -//***************************************************************************** -void fileparse(const string& in_str, string& name, string& dir, string& suff) -{ - string str(in_str); - size_t pos; - name = ""; - dir = ""; - suff = ""; - pos = str.find_last_of('.'); - if (pos != string::npos) - { - suff = str.substr(pos); - str = str.substr(0, pos); - } - pos = str.find_last_of('/'); - if (pos != string::npos) - { - name = str.substr(pos+1); - str = str.substr(0, pos+1); - } - dir = str; -} - -static const size_t TRACE_PPE_HASH_LEN = 13; -//***************************************************************************** -// chop_up_line -//***************************************************************************** -bool chop_up_line(string& in_line, string& prefix, string& strings, string& salt, string& suffix) -{ - // First see if this line matches the pattern we're looking for - // Since this will return false 95%+ of the time this function it called, we do it - // before doing any other init for performance reasons. - size_t pos = in_line.find("trace_ppe_hash"); - if (pos == string::npos) { return(false); } - - // trace_ppe_hash ( "..." ".." "..." , 2 ) - // regex: PREFIX 'trace_ppe_hash' space '(' space STRINGS space ',' space NUMBER space ')' SUFFIX - // STRINGS: '"' .* '"' space? + - - // Original perl magic incantation: - // while($line =~ m/^(.*?)trace_ppe_hash\s*\(\s*((".*?(? $1 = everything up to the word "trace_ppe_hash" - // trace_ppe_hash = delimiter - // \s*\(\s* = delimiter = <0-n whitespace chars>, left paren, <0-n whitespace chars> - // ((".*?(? $2 = double-quote, some chars up to last closing double-quote ($3 used for nested regex) - // ,\s* = delimiter = comma followed by some whitespace - // (-?\d+)\s*\)(.*) => $4 and $5 - // $/) = end of the line input string - string line(in_line); - prefix = ""; - strings = ""; - salt = ""; - suffix = ""; - size_t pos1; - size_t pos2; - size_t pos3; - - pos1 = pos + 14; // pos1 = after "trace_ppe_hash" - pos2 = line.find("(", pos1); - if (pos2 == string::npos) { return(false); } - ++pos2; - pos3 = line.find("\"", pos2); - if (pos3 == string::npos) { return(false); } - dprintf("--------\nchop_up_line: Passed basic checks. line= %s\n", line.c_str()); - dprintf("pos1=%d, pos2=%d, pos3=%d\n", pos1, pos2, pos3); - if ((pos1 != (pos2-1)) && (line.find_first_not_of(" \t", pos1, (pos2-pos1)+1) != string::npos)) { return(false); } //non-whitespace? - if ((pos2 != pos3) && (line.find_first_not_of(" \t", pos2, (pos3-pos2)) != string::npos)) { return(false); } //non-whitespace? - - // Get the prefix data - dprintf(">chop_up_line(\"%s\",...)\n", line.c_str()); - prefix = line.substr(0, pos); - line = line.substr(pos + TRACE_PPE_HASH_LEN); - dprintf(" prefix=\"%s\"\n", prefix.c_str()); - - // Get the strings and join/fix them: Store all strings between paired double-quotes up to the - // first comma not inside a string - pos = line.find_first_of('('); - if (pos == string::npos) { return(false); } - line = line.substr(pos + 1); - strings = ""; - while(!line.empty()) - { - pos = line.find_first_of(','); - pos1 = line.find_first_of('"'); - if ((pos1 == string::npos) || ((pos != string::npos) && (pos < pos1))) { break; } // found comma before next quote - pos2 = line.find_first_of('"', (pos1+1)); - if (pos2 == string::npos) { return(false); } // unbalanced quotes! - while(line[pos2-1] == '\\') // skip escaped quotes in the string (they're not the ending quote) - { - pos2 = line.find_first_of('"', (pos2+1)); - if (pos2 == string::npos) { return(false); } // unbalanced quotes! - } - if (!strings.empty()) { strings += " "; } - strings += line.substr(pos1, (pos2-pos1)+1); - line = line.substr(pos2+1); - } - replace_substr(strings, "\" \"", ""); - replace_substr(strings, "\\\"", "ESCAPEDQUOTE"); - replace_substr(strings, "\"", ""); - replace_substr(strings, "ESCAPEDQUOTE", "\""); - // Remove trailing whitespace ah20130717 - pos = strings.find_last_not_of(" \t\n"); - if ((pos != string::npos) && (pos < (strings.length()-1))) - { - strings = strings.substr(0, pos+1); - } - - dprintf(" strings>%s<\n", strings.c_str()); - - // Get the salt - pos = line.find(","); - if (pos != string::npos) { line = line.substr(pos+1); } - pos = line.find_first_of(')'); - if (pos == string::npos) { return(false); } - salt = line.substr(0, pos); - line = line.substr(pos+1); - //dprintf(" salt=\"%s\"\n", salt.c_str()); - pos = salt.find_first_not_of(" \t\n"); - if (pos == string::npos) { return(false); } - salt = salt.substr(pos); - pos = salt.find_last_not_of(" \t\n"); - if (pos == string::npos) { return(false); } - salt = salt.substr(0, pos+1); - dprintf(" salt=\"%s\"\n", salt.c_str()); - - // Get the suffix (i.e. the rest) - suffix = line; - if (suffix[suffix.length()-1] == '\n') { suffix = suffix.substr(0, suffix.length()-1); } - dprintf(" suffix=\"%s\"\nget_hash(\"%s\",%d)\n", str.c_str(), salt_num); - - // Call jhash function to get the hash value - hash_num = jhash((void*)str.c_str(), str.length(), salt_num); - dprintf("jhash() returned: %u\n", hash_num); - sprintf(buf, "%u", hash_num & 0x0000ffff); - hash16 = buf; - sprintf(buf, "%u", ((salt_num << 16) | (hash_num & 0x0000ffff))); - hash32 = buf; - - // validate the hash value - size_t pos = hash32.find_first_not_of("0123456789"); - if (pos != string::npos) - { - fprintf(stderr, "trexhash error: %s\n", hash32.c_str()); - fprintf(stderr, "for call <<%s>>\n", cmd.c_str()); - exit(1); - } - -//removing this since it doesn't seem to have any affect on the output -#if 0 - // If hash is empty, use the sum of the ord values in the original string - if ((hash == "")||(hash == "0")) - { - unsigned int len = str.length(); - unsigned int hash_num = 0; - //unsigned char conv_buf[2] = { '\0', '\0' }; - u_int8_t conv_num; - for (unsigned int i=0; i < len; ++i) - { - //conv_buf[0] = str[i]; - conv_num = (u_int8_t)str[i]; - hash_num += (unsigned int)conv_num; - } - } -#endif - - dprintf("& rhash, string& line, string& out_line) -{ - // NOTE: "line" arg may get modified by this function! Caller must not assume it's unchanged. - string format; - string prefix; - string strings; - string tmp; - string salt; - string hash16; - string hash32; - int salt_num; - int format_salt; - string suffix; - string write_all_suffix; - size_t pos; - - out_line = ""; - // trace_ppe_hash ( "..." ".." "..." , 2 ) - // regex: PREFIX 'trace_ppe_hash' space '(' space STRINGS space ',' space NUMBER space ')' SUFFIX - // STRINGS: '"' .* '"' space? + - //while($line =~ m/^(.*?)trace_ppe_hash\s*\(\s*((".*?(? 1) arg = argv[1]; - if ((argc < 2) || (arg == "-h")) - { - fprintf(stderr, "usage: %s realcompiler compileroptions -o target source\n", argv[0]); - exit(9); - } - string realcc(argv[argi++]); - string cctype("c++"); - bool optx_found = false; - - if (realcc == "-d") - { - debug = true; - realcc = argv[argi++]; - } - - // wait until -d options is handled before checking $debug - dprintf("ppetracepp version %s - API/macro version %s\n", version.c_str(), macro_version.c_str()); - - p_env = getenv("REALCPP"); - string realcpp; - if (p_env) - realcpp = p_env; - if (realcpp.empty()) - { - dprintf("cannot find cpp, using -E\n"); - realcpp = realcc; - realcpp += " -E"; - } - dprintf("realcpp is %s\n", realcpp.c_str()); - -//------------------------------------------------------------------------------ -// parse all the arguments -//------------------------------------------------------------------------------ -string source; -string object; -vector ccopts; -vector cppopts; -bool dodeps = false; -string depfile; -string pfx; -string sfx; -int origargi = argi; -for( ; argi < argc; ++argi) -{ - arg = argv[argi]; - dprintf("Processing argv[%d]: \"%s\"\n", argi, arg.c_str()); - if (arg.length() > 2) - { - pfx = arg.substr(0,2); - sfx = arg.substr(arg.length()-2); - } - else - { - pfx = arg; - sfx = arg; - } - dprintf(" pfx: \"%s\" sfx: \"%s\"\n", pfx.c_str(), sfx.c_str()); - - if (pfx == "-o") - { - if (! object.empty()) - { - fprintf(stderr, "two -o options, aborting\n"); - exit(1); - } - if (arg.length() > 2) - { - object = sfx; - } - else - { - object = argv[++argi]; - } - dprintf("object is now %s\n", object.c_str()); - } - else if (arg == "-c") - { - // don't call cpp with -c, this is for the compiler - ccopts.push_back(arg); - dprintf("found -c option\n"); - } - else if (pfx == "-l") - { - // cpp doesn't need library arguments - cppopts.push_back(arg); - } - else if (pfx == "-i") - { - // option takes an argument, handle it too - optarg = argv[argi++]; - ccopts.push_back(arg); - ccopts.push_back(optarg); - cppopts.push_back(arg); - cppopts.push_back(optarg); - dprintf("found option '%s %s'\n", arg.c_str(), optarg.c_str()); - } - else if ((arg == "-L") || - (arg == "-I") || - (arg == "-x") || - (arg == "-b") || - (arg == "-B") || - (arg == "-V") || - (arg == "-D") || - (arg == "--param") || - (arg == "-MQ") || - (arg == "-MT")) - { - // option takes an argument, handle it too - optarg = argv[argi++]; - ccopts.push_back(arg); - ccopts.push_back(optarg); - cppopts.push_back(arg); - cppopts.push_back(optarg); - dprintf("found option '%s %s'\n", arg.c_str(), optarg.c_str()); - if (arg == "-x") - { - // option x sets the language - c or c++ - if ((optarg != "c") && (optarg != "c++") && (optarg != "assembler-with-cpp")) - { - fprintf(stderr, "cannot process language '%s', aborting\n", optarg.c_str()); - exit(1); - } - cctype = optarg; - optx_found = true; - } - } - else if ((arg == "-MD")||(arg == "-MG")) - { - // gen deps - dodeps = true; - dprintf("found %s, creating dependencies\n", arg.c_str()); - } - else if (arg == "-MF") - { - // set dependencies file - depfile = argv[argi++]; - dprintf("set dependencies file to '%s'\n", depfile.c_str()); - } - else if (arg[0] == '-') - { - // arg starts with - so it's an option - ccopts.push_back(arg); - cppopts.push_back(arg); - dprintf("found option '%s'\n", arg.c_str()); - } - else if ((sfx == ".a") || - (sfx == ".o")) - { - // an object or archive, ignore this but give it to cc - ccopts.push_back(arg); - dprintf("found object/archive '%s'\n", arg.c_str()); - } - else if ((sfx == ".c") || - (sfx == ".C") || - (sfx == ".S") || - (arg.substr(arg.length()-4) == ".cpp") || - (arg.substr(arg.length()-4) == ".cxx")) - { - // the source file(s). we should only get one - if (!source.empty()) - { - fprintf(stderr, "don't know to handle two source files, aborting\n"); - exit(1); - } - source = arg; - // put the - (for read-from-stdin) where the source file was - // (order is important!) - ccopts.push_back("-"); - dprintf("found source file %s\n", source.c_str()); - } - else if (access(arg.c_str(), F_OK)) - { - // option but not a file, an unknown option? - ccopts.push_back(arg); - cppopts.push_back(arg); - dprintf("found unknown option '%s'\n", arg.c_str()); - } -} - -//------------------------------------------------------------------------------ -// set other parameters based on arguments specified -//------------------------------------------------------------------------------ -if (source.empty()) -{ - // this might be a call to link a program instead of compile a source (or asm source) - dprintf("NOTME: starting as cc '%s ...'\n", realcc.c_str()); - execvp(realcc.c_str(), &(argv[origargi])); - fprintf(stderr, "ERROR: returned from execvp() call to run %s\n", realcc.c_str()); -} -if (object.empty()) -{ - dprintf("no object file given, default to source name\n"); - // gcc builds object name from source name if no -o given, replacing - // suffix with .o. The file is placed in the current directory, - // not in the source directory! - string n; - string d; - string s; - fileparse(source, n, d, s); - if (!n.empty() && !s.empty()) - { - object = n + ".o"; - dprintf("tracpp: guessing object name %s\n", object.c_str()); - dprintf(" from source name %s\n", source.c_str()); - } - else - { - fprintf(stderr, "Unable to determine Source File Name\n"); - exit(1);; - } -} - -// set value of trace hash according to language -// check source file extension if no explicit -x option given -if (!optx_found) -{ - if (realcc.find("g++") != string::npos) - { - dprintf("compiler language: C++ (from compiler name)\n"); - cctype = "c++"; - } - else - { - if (source.substr(source.length()-2) == ".c") - { - dprintf("compiler language: C (from source file extension)\n"); - cctype = "c"; - } - else if (source.substr(source.length()-2) == ".S") - { - dprintf("compiler language: assembly (from source file extension)\n"); - cctype = "assembler-with-cpp"; - } - else - { - dprintf("compiler language: C++ (default)\n"); - cctype = "c++"; - } - } -} -else -{ - dprintf("compiler language: %s (from option '-x')\n", cctype.c_str()); -} - -if (cctype == "c") -{ - hashtype = "(unsigned short)"; - hashtype_suffix = "U"; -} -else if (cctype == "assembler-with-cpp") -{ - hashtype = ""; - hashtype_suffix = ""; -} -else -{ - hashtype = "(trace_hash_val)"; - hashtype_suffix = "U"; -} -// define TRAC_PPETRACEPP for macros -tmp = "-DTRAC_PPETRACEPP -DTRAC_PPVER="; -tmp += macro_version; -cppopts.push_back(tmp); -if (dodeps) -{ - if (depfile.empty()) - { - if ((p_env = getenv("DEPENDENCIES_OUTPUT")) != NULL) - { - depfile = p_env; - } - else if ((p_env = getenv("SUNPRO_DEPENDENCIES")) != NULL) - { - depfile = p_env; - } - else - { - depfile = object; - if (depfile.substr(depfile.length()-2) == ".o") - { - depfile = depfile.substr(0, depfile.length()-2); - depfile += ".d"; - } - } - } - tmp = "-MD -MF "; - tmp += depfile; - cppopts.push_back(tmp); -} - -//------------------------------------------------------------------------------ -// start cpp -//------------------------------------------------------------------------------ -cmd = realcpp; -for(vector::iterator p = cppopts.begin(); p != cppopts.end(); ++p) -{ - cmd += " "; - cmd += *p; -} -cmd += " "; -cmd += source; -cmd += " -o-"; -dprintf("starting as cpp '%s'\n", cmd.c_str()); -CPP = popen(cmd.c_str(), "r"); -if (CPP == NULL) -{ - fprintf(stderr, "cannot start cpp '%s'\n", realcpp.c_str()); - perror(""); - exit(1); -} - -//------------------------------------------------------------------------------ -// start cc. manually set language as source file extension not available to cc -//------------------------------------------------------------------------------ -string type_str = ""; -if (!optx_found) -{ - // no option -x given by caller, set manually - type_str = "-x "; - type_str += cctype; -} -cmd = realcc; -cmd += " "; -cmd += type_str; -for(vector::iterator p = ccopts.begin(); p != ccopts.end(); ++p) -{ - cmd += " "; - cmd += *p; -} -cmd += " -o "; -cmd += object; -dprintf("starting as cc '%s'\n", cmd.c_str()); -CC = popen(cmd.c_str(), "w"); -if (CC == NULL) -{ - fprintf(stderr, "cannot start cc '%s'\n", realcc.c_str()); - perror(""); - exit(1); -} - -string modifiedfile; -string unmodifiedfile; -if (debug) -{ - modifiedfile = object + ".debug"; - DEBUG = fopen(modifiedfile.c_str(), "w"); - if (DEBUG == NULL) - { - string msg = "cannot open file "; - msg += modifiedfile; - perror(msg.c_str()); - modifiedfile = ""; - } - else - { - fprintf(stderr, "writing preprocessed source to %s\n", modifiedfile.c_str()); - } - unmodifiedfile = object + ".debug_in"; - DEBUGIN = fopen(unmodifiedfile.c_str(), "w"); - if (DEBUGIN == NULL) - { - string msg = "cannot open file "; - msg += unmodifiedfile; - perror(msg.c_str()); - unmodifiedfile = ""; - } - else - { - fprintf(stderr, "writing unprocessed source to %s\n", unmodifiedfile.c_str()); - } -} - -string oldline; -string newline; -static const int MAX_BUFFER = 51200; -char buf[MAX_BUFFER]; -while (!feof(CPP)) -{ - if (fgets(buf, MAX_BUFFER, CPP) != NULL) - { - oldline = buf; - if (DEBUGIN) { fprintf(DEBUGIN, "%s", oldline.c_str()); } - parse_line(hashtab, oldline, newline); - //#print "oldline = $oldline"; - //#print "newline = $newline"; - if (newline.empty()) - { - fprintf(stderr, "hash error in/with file %s\n", source.c_str()); - exit(1); - } - //#print "newline = $newline\n"; - fprintf(CC, "%s", newline.c_str()); - if (DEBUG) { fprintf(DEBUG, "%s", newline.c_str()); } - } -} -if (DEBUG) { fclose(DEBUG); } -if (DEBUGIN) { fclose(DEBUGIN); } -int cmd_rc = pclose(CPP); -if (cmd_rc) -{ - fprintf(stderr, "error from cpp\n"); - if (cmd_rc & 127) - { - fprintf(stderr, "cpp got signal %d\n", (cmd_rc & 127)); - exit(1); - } - else if (cmd_rc >> 8) - { - fprintf(stderr, "cpp returned %d\n", (cmd_rc >> 8)); - exit(cmd_rc >> 8); - } -} -cmd_rc = pclose(CC); -if (cmd_rc) -{ - fprintf(stderr, "error from cc\n"); - if (cmd_rc & 127) - { - fprintf(stderr, "cc got signal %d\n", (cmd_rc & 127)); - exit(1); - } - else if (cmd_rc >> 8) - { - fprintf(stderr, "cc returned %d\n", (cmd_rc >> 8)); - exit(cmd_rc >> 8); - } -} - -if (!hashtab.empty()) -{ - string stringfile = object; - stringfile += ".ppe.hash"; - // open trace string file - FILE* TRC = fopen(stringfile.c_str(), "w"); - if (TRC == NULL) - { - fprintf(stderr, "cannot write trace string file '%s'\n", stringfile.c_str()); - exit(1); - } - dprintf("Writing to file %s\n", stringfile.c_str()); - - string pwd; - FILE* PWD = popen("pwd", "r"); - fgets(buf, MAX_BUFFER, PWD); - pwd = buf; - pclose(PWD); - time_t tt = time(NULL); - sprintf(buf, "%s", asctime(localtime(&tt))); - buf[strlen(buf)-1] = '\0'; // chop off extra newline - fprintf(TRC, "#FSP_TRACE_v2|||%s|||BUILD:%s", buf, pwd.c_str()); - - string srch_str = "||"; - srch_str += source; - int srch_str_len = srch_str.length(); - size_t pos; - for(map::iterator p = hashtab.begin(); p != hashtab.end(); ++p) - { - pos = (p->second).find(srch_str); - if ((pos != string::npos) && ((pos + srch_str_len) == (p->second).length())) - { - // source file name is already part of the string - fprintf(TRC, "%s||%s\n", (p->first).c_str(), (p->second).c_str()); - } - else - { - fprintf(TRC, "%s||%s||%s\n", (p->first).c_str(), (p->second).c_str(), source.c_str()); - } - //#print TRC "$key||$source||$hashtab{$key}\n"; - } - fclose(TRC); -} -else -{ - dprintf("No trace calls/strings found, not writing hash file\n"); -} -} // end main diff --git a/src/tools/ppetracepp/trac_interface.h b/src/tools/ppetracepp/trac_interface.h deleted file mode 100755 index 2ff9dff0..00000000 --- a/src/tools/ppetracepp/trac_interface.h +++ /dev/null @@ -1,369 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/tools/ppetracepp/trac_interface.h $ */ -/* */ -/* OpenPOWER sbe Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -/****************************************************************************** -// @file trac_interface.h -// @brief Interface codes for TRAC component. -*/ -/****************************************************************************** - * - * @page ChangeLogs Change Logs - * @section _trac_interface_h trac_interface.h - * @verbatim - * - * Flag Def/Fea Userid Date Description - * ------- ---------- -------- ---------- ---------------------------------- - * TEAM 06/16/2010 Port - * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments - * @pb00E pbavari 03/11/2012 Added correct include file - * @at009 859308 alvinwan 10/15/2012 Added tracepp support - * @ai005 860268 ailutsar 11/20/2012 Create trace test applet - * @rc005 864101 rickylie 12/12/2012 add small circ buffer to handle ISR semaphore conflict - * - * @endverbatim - * - *///*************************************************************************/ - -#ifndef _TRAC_INTERFACE_H -#define _TRAC_INTERFACE_H - -/** \defgroup Trace Trace Component - * Port of the trace code used in the fsp and tpmd. - */ - -//************************************************************************* -// Includes -//************************************************************************* - -//************************************************************************* -// Externs -//************************************************************************* - -//************************************************************************* -// Macros -//************************************************************************* -/** - * \defgroup TracMacros Trace Component Macro Interfaces - * \ingroup Trace - * Used to trace 0 - 5 arguments or a binary buffer when using a hash value. - */ -/*@{*/ - - -// @at009c - start -#define TRACE(i_td,i_string,args...) \ - trace_adal_write_all(i_td,trace_adal_hash(i_string,-1),__LINE__,0,##args) - -#define TRACEBIN(i_td,i_string,i_ptr,i_size) \ - trac_write_bin(i_td,trace_adal_hash(i_string,0),__LINE__,i_ptr,i_size) - -#ifndef NO_TRAC_STRINGS - -#define FIELD(a) \ - printf("%s",a) - -#define FIELD1(a,b) \ - printf("%s%lx",a,(unsigned long)b) - -#else // NO_TRAC_STRINGS - -#define FIELD(a) - -#define FIELD1(a,b) - -#endif // NO_TRAC_STRINGS - -#define SUCCESS 0 -// @at009c - end - - - -/*@}*/ - -//************************************************************************* -// Defines/Enums -//************************************************************************* -#define TRACE_MAX_ARGS 5 /*!< Maximum number of args to trace */ - -typedef uint32_t trace_hash_val; - -// NOTE! Increment this when new components are added! -#define TRAC_NUM_TRACE_COMPONENTS 1 - - -#define TRACE_BUFFER_SIZE 8192 // @ai005a - -#define CIRCULAR_BUFFER_SIZE 4 // @rc005a - -typedef uint32_t UINT32; -typedef int32_t INT32; -typedef uint8_t UCHAR; -typedef uint8_t UINT8; -typedef int8_t INT8; -typedef uint16_t UINT16; -typedef int16_t INT16; -typedef char CHAR; -typedef unsigned int UINT; -typedef unsigned long ULONG; -typedef int INT; -typedef void VOID; - -//************************************************************************* -// Structures -//************************************************************************* -/* - * @brief Structure is put at beginning of all trace buffers - */ -typedef struct trace_buf_head { - UCHAR ver; /*!< version of this struct (1) */ - UCHAR hdr_len; /*!< size of this struct in bytes */ - UCHAR time_flg; /*!< meaning of timestamp entry field */ - UCHAR endian_flg; /*!< flag for big ('B') or little ('L') endian */ - CHAR comp[16]; /*!< the buffer name as specified in init call */ - UINT32 size; /*!< size of buffer, including this struct */ - UINT32 times_wrap; /*!< how often the buffer wrapped */ - UINT32 next_free; /*!< offset of the byte behind the latest entry */ - UINT32 te_count; /*!< Updated each time a trace is done */ - UINT32 extracted; /*!< Not currently used */ -}trace_buf_head_t; - -/*! - * @brief Timestamp and thread id for each trace entry. - */ -typedef struct trace_entry_stamp { - UINT32 tbh; /*!< timestamp upper part */ - UINT32 tbl; /*!< timestamp lower part */ - UINT32 tid; /*!< process/thread id */ -}trace_entry_stamp_t; - -/* - * @brief Structure is used by adal app. layer to fill in trace info. - */ -typedef struct trace_entry_head { - UINT16 length; /*!< size of trace entry */ - UINT16 tag; /*!< type of entry: xTRACE xDUMP, (un)packed */ - UINT32 hash; /*!< a value for the (format) string */ - UINT32 line; /*!< source file line number of trace call */ -}trace_entry_head_t; - -/* - * @brief Parameter traces can be all contained in one write. - */ -typedef struct trace_entire_entry { - trace_entry_stamp_t stamp; - trace_entry_head_t head; - UINT32 args[TRACE_MAX_ARGS + 1]; -} trace_entire_entry_t; - - -/* - * @brief Binary first writes header and time stamp. - */ -typedef struct trace_bin_entry { - trace_entry_stamp_t stamp; - trace_entry_head_t head; -} trace_bin_entry_t; - -/** - * @brief Used as input to traces to get to correct buffer. - */ -typedef trace_buf_head_t * tracDesc_t; - -/* - * @brief Structure is used to hold array of all trace descriptors - */ -typedef struct trace_descriptor_array -{ - tracDesc_t *entry; /*!< Pointer to trace descriptor */ - CHAR *comp; /*!< Pointer to component name */ -}trace_descriptor_array_t; - -// @rc005a - start -typedef struct circular_buf_head -{ - UINT32 head; // pointer to head - UINT32 tail; // pointer to tail - UINT32 entryCount; // nums of entry -} circular_buf_header_t; - - -typedef struct circular_entire_data { - UINT32 len; - CHAR comp[4]; - trace_entire_entry_t entry; -} circular_entire_data_t; - -// @rc005a - end - -//************************************************************************* -// Globals -//************************************************************************* -// All TPMF component trace descriptors. -extern tracDesc_t g_trac_inf; // @at009a -extern tracDesc_t g_trac_err; // @at009a -extern tracDesc_t g_trac_imp; // @at009a - -extern const trace_descriptor_array_t g_des_array[]; - -//************************************************************************* -// Function Prototypes -//************************************************************************* - -/** - * \defgroup TracIntefaces Trace Component Interfaces for External Use - * \ingroup Trace - */ -/*@{*/ - - -/** - * @brief Allocate and initialize all trace buffers in memory. - * - * This function will allocate memory for each of the pre-defined trace - * buffers, initilize the buffers with starting data, and setup the - * trace descriptors which each component will use to trace. - * - * This function must be called first before any components try to trace! - * - * @return Non-zero return code on error. - */ -UINT TRAC_init_buffers(void); - -/** - * @brief Retrieve full trace buffer for component i_comp - * - * This function assumes memory has already been allocated for - * the full trace buffer in o_data. - * - * @param i_td_ptr Trace descriptor of buffer to retrieve. - * @param o_data Pre-allocated pointer to where data will be stored. - * - * @return Non-zero return code on error - */ -UINT TRAC_get_buffer(const tracDesc_t i_td_ptr, - void *o_data); - -/** - * @brief Retrieve partial trace buffer for component i_comp - * - * This function assumes memory has already been allocated for - * the trace buffer (size io_size). This function will copy - * in up to io_size in bytes to the buffer and set io_size - * to the exact size that is copied in. - * - * @param i_td_ptr Trace descriptor of buffer to retrieve. - * @param o_data Pre-allocated pointer to where data will be stored. - * @param io_size Size of trace data to retrieve (input) - * Actual size of trace data stored (output) - * - * @return Non-zero return code on error - */ -UINT TRAC_get_buffer_partial(const tracDesc_t i_td_ptr, - void *o_data, - UINT *io_size); - -/** - * @brief Retrieve trace descriptor for input component name - * - * @param i_comp Component name to retrieve trace descriptor for. - * - * @return Valid trace descriptor on success, NULL on failure. - */ -tracDesc_t TRAC_get_td(const char *i_comp); - -/** - * @brief Reset all trace buffers - * - * @return Non-zero return code on error - */ -UINT TRAC_reset_buf(void); - -/*@}*/ // Ending tag for external interface module in doxygen - - -/** - * @brief Trace input integers to trace buffer. - * - * This function assumes i_td has been initialized. - * - * @param io_td Intialized trace descriptor point to buffer to trace to. - * @param i_hash Hash value to be recorded for this trace. - * @param i_fmt Output format - * @param i_line Line number trace is occurring on. - * @param i_type trace type. filed or debug. - * @param ... parames that are limited to a size of 4 bytes, i.e. int, uint32_t, nnn* - * - * @return Non-zero return code on error. - */ -UINT trace_adal_write_all(tracDesc_t io_td,const trace_hash_val i_hash, - const char *i_fmt,const ULONG i_line, const ULONG i_type,...); - - -/** - * @brief Trace input integers to trace buffer. - * - * This function assumes i_td has been initialized. - * - * @param io_td Intialized trace descriptor point to buffer to trace to. - * @param i_hash Hash value to be recorded for this trace. - * @param i_line Line number trace is occurring on. - * @param i_num_args Number of arguments to trace. - * @param i_1 Input Parameter 1 - * @param i_2 Input Parameter 2 - * @param i_3 Input Parameter 3 - * @param i_4 Input Parameter 4 - * @param i_5 Input Parameter 5 - * - * @return Non-zero return code on error. - */ -UINT trac_write_int(tracDesc_t io_td,const trace_hash_val i_hash, - const ULONG i_line, - const UINT i_num_args, - const ULONG i_1,const ULONG i_2,const ULONG i_3, - const ULONG i_4,const ULONG i_5 - ); - - - /** - * @brief Trace binary data to buffer. - * - * This function assumes i_td has been initialized. - * - * @param io_td Intialized trace descriptor point to buffer to trace to. - * @param i_hash Hash value to be recorded for this trace. - * @param i_line Line number trace is occurring on. - * @param i_ptr Pointer to binary data to trace. - * @param i_size Size of data to copy from i_ptr. - * - * @return Non-zero return code on error. - */ -UINT trac_write_bin(tracDesc_t io_td,const trace_hash_val i_hash, - const ULONG i_line, - const void *i_ptr, - const ULONG i_size); - -//************************************************************************* -// Functions -//************************************************************************* - -#endif //_TRAC_INTERFACE_H diff --git a/src/tools/ppetracepp/tracehash.pl b/src/tools/ppetracepp/tracehash.pl deleted file mode 100755 index 8855adee..00000000 --- a/src/tools/ppetracepp/tracehash.pl +++ /dev/null @@ -1,896 +0,0 @@ -#!/usr/bin/perl -w -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/tools/ppetracepp/tracehash.pl $ -# -# OpenPOWER sbe Project -# -# Contributors Listed Below - COPYRIGHT 2015,2016 -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG -# File tracehash.pl created by B J Zander. - -use strict; - -sub determine_args(); -sub launch_cpp_and_parse($$); -sub cpp_dir($); -sub read_string_file(); -sub collect_files($); -sub assimilate_file($); -sub hash_strings(); -sub write_string_file(); -sub help(); - -select (STDERR); -$| = 1; # Make all prints to STDERR flush the buffer immediately -select (STDOUT); -$| = 1; # Make all prints to STDOUT flush the buffer immediately - -# Constants -my $HEAD_SEP = "|||"; -my $HEAD_EYE_CATCHER = "#FSP_TRACE_v"; -my $HEAD_BUILD_FLAG = "BUILD:"; -my $HEAD_VER_FLAG = 2; -my $BB_STRING_FILE = "/opt/fsp/etc/BB_StringFile"; - -# Global Variables -my $debug = 0; -my $seperator = "&&&&"; -my $file_name = "sbeStringFile"; -my $in_sand; -my ($backing) = $ENV{'bb'}; -my $hash_prog = "trexhash"; #default to in path -my $build = ""; -my ($sandbox) = $ENV{'SANDBOX'} || ""; -my ($context) = $ENV{'CONTEXT'} || ""; -my ($sandboxbase) = $ENV{'SANDBOXBASE'} || ""; -my ($bb); -my ($sourcebase) = "$sandboxbase/src"; -my ($version) = $HEAD_VER_FLAG; # default to oldest version -my ($collect) = 0; -my ($INCLUDE, $Arg, $file, $dir, $string_file); -my $args = ""; - -my $fail_on_collision = 0; # 1 = exit with error if hash collision occurs -my $hash_filename_too = 0; # 1 = hash is calculated over format string + filename - -print "sourcebase = $sourcebase\n" if $debug; -print "sandbox = $sandbox\n" if $debug; -print "backing = $backing\n" if $debug; -print "context = $context\n" if $debug; - -if ($context =~ /x86/) -{ - $bb = "i586-pc-linux-gnu"; -} -else -{ - $bb = "powerpc-linux"; -} - -if(($sourcebase =~ /\w+/) && ($sandbox =~ /\w+/)) -{ - $INCLUDE = "-I $sandboxbase/export/$context/fips/include -I $backing/export/$context/fips/include -I /opt/fsp/$bb/include/fsp -I/opt/fsp/$bb/include/ -include /opt/fsp/$bb/include/fsp/tracinterface.H"; -} -else -{ - print "Not in Sandbox so guessing Include Paths...\n" if $debug; - $INCLUDE = "-I/opt/fsp/i586-pc-linux-gnu/include/fsp -I/opt/fsp/i586-pc-linux-gnu/include/ -include /opt/fsp/i586-pc-linux-gnu/include/fsp/tracinterface.H"; -} - -# I/P Series work in ODE sandbox env. -if ($sandboxbase =~ /\w+/) -{ - $in_sand = 1; - print "backing = $backing\n" if $debug; -} -else -{ - $in_sand = 0; -} - - - -# Parse the input parameters. - -while (@ARGV) { - $Arg = shift; - - if ($Arg eq "-h" || $Arg eq "-H") { - help(); - exit(127); - } - if ($Arg eq "-f") { - $file = shift; - next; - } - if ($Arg eq "-d") { - $dir = shift; - next; - } - if ($Arg eq "-s") { - $string_file = shift; - next; - } - if ($Arg eq "-c") { - $collect = 1; - next; - } - if ($Arg eq "-v") { - $debug = 1; - print "debug on\n" if $debug; - next; - } - if ($Arg eq "-C") { # fail if a hash collision is detected - $fail_on_collision = 1; - next; - } - if ($Arg eq "-F") { # hash is calculated over format string + file name - $hash_filename_too = 1; - next; - } - if ($Arg eq "-S") { - $BB_STRING_FILE = ""; - next; - } - - #just pass it onto compiler - $args = $args . " " . $Arg; -} - -print "args = $args\n" if $debug; - -if (!$file && !$dir && !$in_sand) { - help(); - exit(127); -} - -################################# -# M A I N # -################################# - -my $clock = `date`; - -$build = $HEAD_EYE_CATCHER . "$HEAD_VER_FLAG" . $HEAD_SEP . $clock . $HEAD_SEP . $HEAD_BUILD_FLAG; - -$build =~ s/\n//g; - -# Global array to hold the parsed TRAC macro calls. -my @strings = (); - -# Assoc. arrays to hold hash|string values. -my %string_file_array = (); -my %hash_strings_array = (); - -# Check all provided arguments and look for defaults if not provided by user -determine_args(); - -# Scan the appropriate files or directories for TRAC macro calls. - -if (defined $dir) -{ - - $build = $build . $dir; # default to put at top of string file - if($collect) - { - collect_files($dir); - } - else - { - cpp_dir($dir); - # Hash the string that have been scanned. - %hash_strings_array = hash_strings(); - } -} -else -{ - $build = $build . $file; # default to put at top of string file - - if($collect) - { - assimilate_file($file); - } - else - { - # make sure include path includes directory that file is in - if($file =~ /^(.+)\/[^\/]+\.C$/) - { - - launch_cpp_and_parse($file,$1); - } - else - { - # No path in front of file so it has to be local dir - launch_cpp_and_parse($file,"./"); - } - # Hash the string that have been scanned. - %hash_strings_array = hash_strings(); - } -} - -# Read the existing string file into memory. -%string_file_array = read_string_file(); - -# Write out the new string file. check for collisions of new/old string here -write_string_file(); - -print "Hashing Started at $clock\n"; -$clock = `date`; -print "Hashing Finished at $clock\n"; - -exit 0; - - -################################# -# S U B R O U T I N E S # -################################# - -#============================================================================= -# Enhance usability by figuring out which build env. we are in -#============================================================================= -sub determine_args() { - - - # Find trexhash program - # but only if needed (i.e. not in collect mode) - if (!$collect) { - my $tmp = `which $hash_prog`; - chomp $tmp; - - if ($tmp eq '') { - print STDOUT "\nWarning: Program trexhash does not exist in path.\n" if $debug; - $hash_prog = "./trexhash"; - - $tmp = `which $hash_prog`; - chomp $tmp; - if ($tmp eq '') { - print STDOUT "\nError: Unable to find trexhash \n"; - exit(127); - } - } - } - - # Verify input values. - if ((!defined $file) && (!defined $dir)) { - if(!($in_sand)) - { - print STDOUT "\nError: No input directory or file provided as input to scan\n"; - exit(127); - } - - # Assume they want sandbox scanned - if($collect) - { - # collect all string files generated by tracepp and merge - $dir = "$sandboxbase/obj/"; - } - else - { - # generate our own string file by pre-compiling all source code - $dir = "$sandboxbase/src/"; - } - print STDOUT "\n-f or -d not found...scanning $dir by default\n\n"; - } - - if (!defined $string_file) - { - if ($in_sand) - { - - # Copy the current string file from backing build into our sandbox - system ("cp $backing/obj/$file_name $sandboxbase/obj/$file_name") - if !(-e "$sandboxbase/obj/$file_name"); - - $string_file = "$sandboxbase/obj/$file_name"; - } - else - { - $string_file = "./$file_name"; - } - print STDOUT "-sf not specified, using $string_file instead...\n\n" if $debug; - - } - - # Try Creating the string file - `touch $string_file`; - - if (! -f $string_file) { - print STDOUT "\nError: File $string_file does not exist. Current directory may not be writable.\n\n"; - help(); - exit(127); - } - - # Make sure sbeStringFile is readable/writeable - system("chmod ugo+rw $string_file"); - -} - -#============================================================================= -# Launch cpp script and grab input from it looking for trace calls. -#============================================================================= -sub launch_cpp_and_parse($$) { - - my ($l_loc, $l_dir) = @_; - - print "Processing file $l_loc\n" if $debug; - my $cmd = "/usr/bin/cpp $INCLUDE -I $l_dir $args $l_loc|"; - print "$cmd\n" if $debug; - open(FH,"$cmd") - or die ("Cannot open $_:$!,stopped"); - - # Read through all lines in the file.. - my $line = ; - while (defined $line) - { - chop $line; # remove EOL - $line =~ s/^\s*//; # remove unneccesary beginning white space. - $line =~ s/\s*$//; # remove unneccesary ending white space. - # Look for lines that are trace macro calls. - #if (/(trace_adal_hash)(\()( *)(".+")(,)(\d)/) - #if ($line =~ /(.*?)(trace_adal_hash)(\()( *)(".+")(,)(\d)\)+(.*\d.*)/) - while($line =~ m/^(.*?)trace_adal_hash\s*\(\s*(("[^"]*"\s*)+),\s*(\d+)\s*\)(.*)$/) - { - my ($prefix, $strings, $salt, $suffix) = ($1, $2, $4, $5); - print STDOUT "$strings $salt\n" if $debug; - $strings =~ s/"\s*$//; # remove trailing " and space - $strings =~ s/^"//; # remove leading " - $strings =~ s/"\s*"//g; - # Check to see if it's contained on a single line, or if we - # have to combine lines to get a complete trace call. - - # Save the macro call so it can be hashed later.. - push (@strings, [$l_loc, $strings, $salt]); - $line = $suffix; # check rest of line for a second trace call - } - my $nextline = ; - last if !defined $nextline; - # if a trace call is spread over multiple lines we have to add the next - # line from the source. the only problem is the definition/declaration - # of trace_adal_hash: we have to ignore that. we catch that by requiring - # a " after the function name. hopefully nobody writes a comment with - # a " after the function declaration ... - if ($line =~ /trace_adal_hash.*"/) { - $line .= $nextline; - } else { - $line = $nextline; - } - } - close(FH); -} - -#============================================================================= -# run cpp on all files in this directory and return the output -#============================================================================= -sub cpp_dir($) { - - my ($l_dir) = @_; - my @dir_entry; - my $l_entry; - - # Open the directory and read all entry names. - opendir ( DH , "$l_dir") - or die ("Cannot open $l_dir: $!, stopped"); - - print STDOUT "Processing directory $l_dir\n" if $debug; - @dir_entry = readdir(DH); - closedir(DH); - - while (@dir_entry) { - $l_entry = shift(@dir_entry); - - if ($l_dir =~ m"/$") { - $l_entry = "$l_dir$l_entry"; - } - else { - $l_entry = "$l_dir/$l_entry"; - } - - # Is the entry a directory? - if (-d $l_entry) { - - if($l_entry =~ m"/?([^/]+)$") - { - # check dir we are going into - print "dir = $1\n" if $debug; - # should we recurse into this directory. - if ($1 =~ m/^(\.\.?|sim[ou]|bldv)$/) - { - next; # skip '.', '..' and some fips dirs - } - cpp_dir($l_entry); - } - else - { - # unable to determine name of dir (no / in filename) - # should we recurse into this directory. - if ($l_entry =~ m/^(\.\.?|sim[ou]|bldv)$/) - { - next; # skip '.', '..' and some fips dirs - } - cpp_dir($l_entry); - } - } - # Is the entry a file? - elsif ((-f $l_entry) && ($l_entry =~ m/\.C$/)) { - # it's a file so - launch_cpp_and_parse($l_entry,$l_dir); - } - else { - # Not a file or directory so ignore it... - } - } -} - -#============================================================================= -# Read in strings from the existing trace string file.... -#============================================================================= -sub read_string_file() { - - my %o_strings; - my ($line) = ""; - my ($l_hash) = ""; - my ($l_str) = ""; - my ($cur_build) = ""; - my ($l_file) = ""; - - - # Make sure we can open each file. - open ( FH , "<$string_file") - or die ("Cannot open $_: $!, stopped"); - - $line = ; - - print "first line in sbeStringFile= $line\n" if $debug; - - if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) - { - $version = $1; - - print "version = $version\n" if $debug; - - #Always put latest version in file - $line =~ s/^$HEAD_EYE_CATCHER\d/${HEAD_EYE_CATCHER}${HEAD_VER_FLAG}/; - - # Take previous version in file and use it. - $build = $line; - chomp($build); - $line = ; - - while (defined $line) { - chomp $line; # remove EOL - if($version eq "1") - { - ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); - } - elsif($version eq "2") - { - ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); - } - else - { - print "Unknown version of stringfile $version\n"; - exit(127); - } - $o_strings{$l_hash} = $l_str . "||" . $l_file; - $line = ; - } - - } - else - { # If there is a file then we are dealing with the first - # version of sbeStringFile so don't look for file name. - if ($debug) { - print "version 0 stringfile detected: $string_file\n"; - } - - # there is a file and it doesn't have a header - $version = 0; - - while (defined $line) { - chomp $line; # remove EOL - ($l_hash,$l_str) = split(/\|\|/, $line); - $o_strings{$l_hash} =$l_str . "||" . "NO FILE"; - $line = ; - } - } - - close(FH); - - #Time to look for a building block string file - if($BB_STRING_FILE ne "" and $string_file ne $BB_STRING_FILE and -f $BB_STRING_FILE) - { - - # Make sure we can open the file. - open ( FH , "<$BB_STRING_FILE") - or die ("Cannot open $_: $!, stopped"); - - $line = ; - - print "first line in BB_StringFile = $line\n" if $debug; - if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) - { - $version = $1; - - $line = ; - while (defined $line) - { - chop $line; # remove EOL - if($version eq "1") - { - ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); - } - elsif($version eq "2") - { - ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); - } - #($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); - $o_strings{$l_hash} = $l_str . "||" . $l_file ; - $line = ; - } - } - else - { - print "*** ERROR: BB_StringFile '$BB_STRING_FILE' should always have version!!!\n" - } - - } - else - { - print "$BB_STRING_FILE is not available\n" if $debug; - } - #All files are latest version now. - $version = $HEAD_VER_FLAG; - return %o_strings; -} - -#============================================================================= -# Read in strings from the existing trace string file.... -#============================================================================= -sub collect_files($) { - - my ($l_dir) = @_; - my (@dir_entry); - my ($l_entry) = ""; - - # Open the directory and read all entry names. - opendir ( DH , "$l_dir") - or die ("Cannot open $l_dir: $!, stopped"); - - print STDOUT "Processing directory $l_dir\n" if $debug; - @dir_entry = readdir(DH); - closedir(DH); - - while (@dir_entry) { - $l_entry = shift(@dir_entry); - - if ($l_dir =~ m"/$") { - $l_entry = "$l_dir$l_entry"; - } - else { - $l_entry = "$l_dir/$l_entry"; - } - - # Is the entry a directory? - if (-d $l_entry) { - - # should we recurse into this directory. - if ($l_entry =~ m/\/(\.\.?|sim[ou]|bldv)$/) - { - next; # skip '.', '..' and some fips dirs - } - collect_files($l_entry); - } - # Is the entry a file? - elsif ((-f $l_entry) && ($l_entry =~ m"\.hash$")) { - # it's a file so - assimilate_file($l_entry); - } - else { - # Not a file or directory so ignore it... - } - } - -} - -#============================================================================= -# Read in data from file and add to master one -#============================================================================= -sub assimilate_file($) { - - my ($l_loc) = @_; - - my (%o_strings); - my ($line) = ""; - my ($l_hash) = ""; - my ($l_str) = ""; - my ($l_file) = ""; - - # Make sure we can open each file. - open ( FH , "<$l_loc") - or die ("Cannot open $_: $!, stopped"); - - $line = ; - - print "Assimilate: first line in $l_loc = $line" if $debug; - - if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) - { - $version = $1; - if ($version eq "1") { - if ($hash_filename_too) { - print "*** ERROR: hash_filename_too (-F) isn't possible with trace version 1\n"; - print " please rebuild all .hash files and global sbeStringFile\n"; - print " version 1 file is '$l_loc'\n"; - exit(127); - } - } elsif ($version ne "2") { - print "Unknown version of stringfile $version\n"; - exit(127); - } - - $line = ; - - - while (defined $line) { - chop $line; # remove EOL - if($version eq "1") - { - ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); - } - elsif($version eq "2") - { - ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); - } - my $newstring = $l_str . "||" . $l_file; - if (exists $hash_strings_array{$l_hash}) { - my $hashstr1 = $hash_strings_array{$l_hash}; - my $hashstr2 = $newstring; - if (!$hash_filename_too) { - # hash was made over format string only, remove file name - $hashstr1 =~ s/\|\|.*$//; - $hashstr2 = $l_str; - } - if ($debug) { - print "a_f: compare $hashstr1\n", - " vs. $hashstr2\n"; - } - if ($hashstr1 ne $hashstr2) - { - print "*** ERROR: HASH Collision! (a_f)\n", - " Two different strings have the same hash value ($l_hash)\n", - " String 1: $hash_strings_array{$l_hash}\n", - " String 2: $newstring\n"; - if ($fail_on_collision) { - exit(1); - } - } - } - $hash_strings_array{$l_hash} = $newstring; - $line = ; - } - - } - else - { # If there is a file then we are dealing with the first - # version of sbeStringFile so don't look for file name. - # these files shouldn't be there anymore. we don't check for collisions here - if ($debug) { - print "version 0 stringfile detected: $string_file\n"; - } - - if(defined $line) - { - # there is a file and it doesn't have a header - $version = 0; - } - - while (defined $line) { - chop $line; # remove EOL - ($l_hash,$l_str) = split(/\|\|/, $line); - $hash_strings_array{$l_hash} = $l_str . "||" . "NO FILE"; - $line = ; - } - } - $version = $HEAD_VER_FLAG; - close(FH); -} - -#============================================================================= - -#============================================================================= -sub hash_strings() { - - my ($hash_val, $l_key, $l_hash, %l_hash_strings); - my ($line_feed) = chr(10); - my ($l_file_name) = "NO FILENAME"; - print "\nHashing printf strings.\n\n"; - - foreach my $str (@strings) { - my $printf_string; - $l_file_name = $str->[0]; - $printf_string = $str->[1]; - $l_key = $str->[2]; - print "printf_string = $printf_string\n" if $debug; - $printf_string =~ s/"\s?"//g; #multi line traces will have extra " in them - $printf_string =~ s/`/\\`/g; # excape ' - $printf_string =~ s/\\n/$line_feed/g; # escape \n - if ($hash_filename_too) { - $printf_string .= "||" . $l_file_name; - } - - # call the hasher. - print "$hash_prog \"$printf_string\" $l_key\n" if $debug; - $hash_val = `$hash_prog \"$printf_string\" $l_key`; - if ($?) { - my ($hp_ret, $hp_sig) = ($? >> 8, $? & 127); - if ($hp_sig) { - print "*** ERROR: $hash_prog died with signal $hp_sig\n"; - } elsif ($hp_ret) { - print "*** ERROR: $hash_prog returned the error $hp_ret\n"; - if ($hash_val) { - print " error from $hash_prog:\n$hash_val"; - } - } - exit(1); - } - print "printf_string = $printf_string l_key = $l_key hash val = $hash_val\n" if $debug; - - # undo escaping - $printf_string =~ s/$line_feed/\\n/g; - $printf_string =~ s/\\`/`/g; - - if (exists $l_hash_strings{$hash_val}) - { - # hash val was found before. check if it's the same string - # else we have a hash collision - my $l_tmp = $l_hash_strings{$hash_val}; - if (!$hash_filename_too) { - $l_tmp =~ s/\|\|.*$//; - } - if ($l_tmp ne $printf_string) - { - print "*** ERROR: HASH Collision! (h_s)\n", - " Two different strings have the same hash value ($hash_val)\n", - " String 1: $l_hash_strings{$hash_val}\n", - " String 2: $printf_string (file $l_file_name)\n"; - if ($fail_on_collision) { - exit(1); - } - } - } - # this will overwrite an old string with a new one if a collision occurred - # but we might want to bail out in this case anyway - $printf_string = $printf_string . "||" . $l_file_name; - $l_hash_strings{$hash_val} = $printf_string; - } - return %l_hash_strings; -} -#============================================================================= - -#============================================================================= -sub write_string_file() { - - my (@keys) = (); - my ($l_key) = ""; - - # Combine the contents of the existing string file with the trace calls - # that we have just hashed. - print STDOUT "\nCombining Hash strings...\n\n"; - - @keys = keys(%hash_strings_array); - - foreach $l_key (@keys) { - my $l_tmp = $hash_strings_array{$l_key}; # freshly collected strings - if (exists $string_file_array{$l_key}) - { # hash exists in list from sbeStringFile - my $l_tmp2 = $string_file_array{$l_key}; - if (!$hash_filename_too) { - $l_tmp =~ s/\|\|.*$//; - $l_tmp2 =~ s/\|\|.*$//; - } - - # Check for hash collisions. - if ($l_tmp ne $l_tmp2) - { - print "*** ERROR: HASH Collision! (w_s_f)\n", - " Two different strings have the same hash value ($l_key)\n", - " String 1: $hash_strings_array{$l_key}\n", - " String 2: $string_file_array{$l_key}\n"; - if ($fail_on_collision) { - exit(1); - } - # don't fail, write new one - } - } - if($version > 0) - { - # add/replace the new string to the string_file_array. - $string_file_array{$l_key} = $hash_strings_array{$l_key} - } - else - { - # old version so only write out format string (not file name to) - $string_file_array{$l_key} = $l_tmp; - } - } - - # Write out the updated string file. - print STDOUT "\nWriting updated hash||string file...\n\n"; - - @keys = sort(keys(%string_file_array)); - - open ( FH , ">$string_file") - or die ("Cannot open $_: $!, stopped"); - - if($version > 0) - { - print FH "$build\n"; # only print version if newer then version 0 - } - foreach $l_key (@keys) { - print FH "$l_key||$string_file_array{$l_key}\n"; - } - close FH; -} -#============================================================================= - -#============================================================================= -# Display command invokation help for this program... -#============================================================================= -sub help() { - print << "EOF"; -tracehash.pl - create a trace string file from sources or collect tracepp files -Usage: tracehash.pl [options] - General options: - -h - Print this help text. - -v - Be verbose, tell what's going on (debug output) - Operation modes - -c - Collect StringFiles created by tracepp and merge. - default - Scan source files for trace calls. - -Collect mode: tracehash.pl -c [-vFCS] [-d ] [-s ] - tracehash.pl -c [-vFCS] [-f ] [-s ] - Collect string files created by tracepp (.hash) from directory tree at - or read them from string file and write to file - , adding entries already in this file. - -f - String file to read and write/add to . - -d - Start of directory tree to scan for .hash files. Default = . - -s - File with trace strings (and hashes) to read from and write to - default = ./sbeStringFile - -F - hash is calculated over trace string and source file name, - otherwise without source file name - -C - report an error if a hash collisions occurs - -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) - If tracehash.pl is called in a FipS build sandbox without -d and -f - defaults for the sandbox will be used. - -Scan mode: tracehash.pl [-vFCS] [-d ] [-s ] [ccpopts] - tracehash.pl [-vFCS] [-f ] [-s ] [cppopts] - Scan all files in directory tree or scan file and write - strings to file . Strings already in this file will be merged. - -f - Source file to scan for trace entries. - -d - Source directory to scan for trace entries. - -s - File with trace strings (and hashes) to read from and write to. - default = ./sbeStringFile - -F - hash for string was build from format string + source file name - -C - report an error if hash collisions occur - -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) - All other arguments will be passed verbatim to cpp -EOF -} -#============================================================================= - diff --git a/src/tools/scripts/ppeSetFixed.pl b/src/tools/scripts/ppeSetFixed.pl index ab92ec42..52880258 100755 --- a/src/tools/scripts/ppeSetFixed.pl +++ b/src/tools/scripts/ppeSetFixed.pl @@ -7,6 +7,7 @@ # OpenPOWER sbe Project # # Contributors Listed Below - COPYRIGHT 2015,2016 +# [+] International Business Machines Corp. # # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +29,7 @@ use strict; my $attrpath = "../../importtemp/xml"; -my $sbedefaultpath = "../../script/image"; +my $sbedefaultpath = "../../../images"; #------------------------------------------------------------------------------ # Print Command Line Help diff --git a/src/tools/trace/Makefile b/src/tools/trace/Makefile new file mode 100644 index 00000000..547cff57 --- /dev/null +++ b/src/tools/trace/Makefile @@ -0,0 +1,37 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/trace/Makefile $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +include img_defs.mk + +all: ppetracepp ppe2fsp + +ppetracepp: ppetracepp.C + g++ -m32 -O3 -w -g -I./ ppetracepp.C -o $(PPETRACEPP_BIN_DIR)/ppetracepp +# g++ -O3 -w -x c++ -fPIC -g -I./ ppetracepp.C -o ppetracepp + +ppe2fsp: ppe2fsp.c ppe2fsp_cmd.c + gcc -m32 -w -g -I./ -I$(PK_SRCDIR)/trace ppe2fsp.c ppe2fsp_cmd.c -o $(PPETRACEPP_BIN_DIR)/ppe2fsp + +clean: + rm $(PPETRACEPP_BIN_DIR)/ppetracepp $(PPETRACEPP_BIN_DIR)/ppe2fsp + diff --git a/src/tools/trace/cmvc/makefile b/src/tools/trace/cmvc/makefile new file mode 100644 index 00000000..3c96ca18 --- /dev/null +++ b/src/tools/trace/cmvc/makefile @@ -0,0 +1,28 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/trace/cmvc/makefile $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +PROGRAMS += ppe2fsp +ppe2fsp_OFILES = ppe2fsp.o ppe2fsp_cmd.o + +.include <${RULES_MK}> + diff --git a/src/tools/trace/jhash.h b/src/tools/trace/jhash.h new file mode 100755 index 00000000..5bfe5fb3 --- /dev/null +++ b/src/tools/trace/jhash.h @@ -0,0 +1,166 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/trace/jhash.h $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef _LINUX_JHASH_H +#define _LINUX_JHASH_H + +/* jhash.h: Jenkins hash support. + * + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) + * + * http://burtleburtle.net/bob/hash/ + * + * These are the credits from Bob's sources: + * + * lookup2.c, by Bob Jenkins, December 1996, Public Domain. + * hash(), hash2(), hash3, and mix() are externally useful functions. + * Routines to test the hash are included if SELF_TEST is defined. + * You can use this free for any purpose. It has no warranty. + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * + * I've modified Bob's hash to be useful in the Linux kernel, and + * any bugs present are surely my fault. -DaveM + */ + +/* NOTE: Arguments are modified. */ +#define __jhash_mix(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* The golden ration: an arbitrary value */ +#define JHASH_GOLDEN_RATIO 0x9e3779b9 + +/* The most generic version, hashes an arbitrary sequence + * of bytes. No alignment or length assumptions are made about + * the input key. + */ +static inline u32 jhash(const void *key, u32 length, u32 initval) +{ + u32 a, b, c, len; + const u8 *k = (const u8*)key; + + len = length; + a = b = JHASH_GOLDEN_RATIO; + c = initval; + + while (len >= 12) { + a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); + b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); + c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); + + __jhash_mix(a,b,c); + + k += 12; + len -= 12; + } + + c += length; + switch (len) { + case 11: c += ((u32)k[10]<<24); + case 10: c += ((u32)k[9]<<16); + case 9 : c += ((u32)k[8]<<8); + case 8 : b += ((u32)k[7]<<24); + case 7 : b += ((u32)k[6]<<16); + case 6 : b += ((u32)k[5]<<8); + case 5 : b += k[4]; + case 4 : a += ((u32)k[3]<<24); + case 3 : a += ((u32)k[2]<<16); + case 2 : a += ((u32)k[1]<<8); + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + +/* A special optimized version that handles 1 or more of u32s. + * The length parameter here is the number of u32s in the key. + */ +static inline u32 jhash2(const u32 *k, u32 length, u32 initval) +{ + u32 a, b, c, len; + + a = b = JHASH_GOLDEN_RATIO; + c = initval; + len = length; + + while (len >= 3) { + a += k[0]; + b += k[1]; + c += k[2]; + __jhash_mix(a, b, c); + k += 3; len -= 3; + } + + c += length * 4; + + switch (len) { + case 2 : b += k[1]; + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + + +/* A special ultra-optimized versions that knows they are hashing exactly + * 3, 2 or 1 word(s). + * + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally + * done at the end is not done here. + */ +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) +{ + a += JHASH_GOLDEN_RATIO; + b += JHASH_GOLDEN_RATIO; + c += initval; + + __jhash_mix(a, b, c); + + return c; +} + +static inline u32 jhash_2words(u32 a, u32 b, u32 initval) +{ + return jhash_3words(a, b, 0, initval); +} + +static inline u32 jhash_1word(u32 a, u32 initval) +{ + return jhash_3words(a, 0, 0, initval); +} + +#endif /* _LINUX_JHASH_H */ diff --git a/src/tools/trace/ppe2fsp.c b/src/tools/trace/ppe2fsp.c new file mode 100755 index 00000000..c1ddc610 --- /dev/null +++ b/src/tools/trace/ppe2fsp.c @@ -0,0 +1,532 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/trace/ppe2fsp.c $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include "pk_trace.h" +#include "ppe2fsp.h" +#include "trac_interface.h" +#include +#include +#include + +#define TRACE_BUF_VERSION 0x01 /*!< Trace buffer version */ +#define TRACE_FIELDTRACE 0x4654 /*!< Field Trace - "FT" */ +#define TRACE_FIELDBIN 0x4644 /*!< Binary Field Trace - "FD" */ + +#define TRAC_TIME_REAL 0 // upper 32 = seconds, lower 32 = nanoseconds +#define TRAC_TIME_50MHZ 1 +#define TRAC_TIME_200MHZ 2 +#define TRAC_TIME_167MHZ 3 // 166666667Hz + +typedef struct +{ + trace_entry_stamp_t stamp; + trace_entry_head_t head; + union + { + uint8_t data[PK_TRACE_MAX_BINARY + 1]; //add 1 byte for padding + uint32_t parms[PK_TRACE_MAX_PARMS]; + }; + uint32_t size; +}largest_fsp_entry_t; + +typedef struct +{ + union + { + uint8_t binary_data[PK_TRACE_MAX_BINARY + 1]; + struct + { + uint8_t rsvd[(PK_TRACE_MAX_BINARY + 1) - (PK_TRACE_MAX_PARMS * sizeof(uint32_t))]; + uint32_t parms[PK_TRACE_MAX_PARMS]; + }; + }; + PkTraceEntryFooter footer; +}LargestPpeEntry; + +//convert a ppe timestamp to an fsp trace timestamp +uint64_t ppe2fsp_time(uint64_t ppe_time, uint32_t hz) +{ + uint32_t seconds; + uint32_t remainder; + uint32_t nseconds; + + //convert from ppe ticks to seconds and nanoseconds + seconds = ppe_time / hz; + remainder = ppe_time - (((uint64_t)seconds) * hz); + nseconds = (((uint64_t)remainder) * 1000000000) / hz; + return (((uint64_t)seconds) << 32) | nseconds; +} + +//Writes an fsp trace entry to the fsp trace buffer +void fsp_put_entry(trace_buf_head_t* tb, largest_fsp_entry_t* fte, size_t entry_size, uint32_t bytes_left) +{ + char* buffer = ((char*)tb) + sizeof(trace_buf_head_t); + char* tb_start; + char* fte_start; + uint32_t copy_bytes; + + if(entry_size <= bytes_left) + { + tb_start = buffer + bytes_left - entry_size; + fte_start = (char*)fte; + copy_bytes = entry_size; + } + else + { + tb_start = buffer; + fte_start = ((char*)fte) + (entry_size - bytes_left); + copy_bytes = bytes_left; + } + + memcpy(tb_start, fte_start, copy_bytes); +} + + +//convert a ppe trace entry to an fsp trace entry +size_t pte2fte(PkTraceBuffer* ptb, + LargestPpeEntry* pte, + size_t pte_size, + largest_fsp_entry_t* fte, + uint64_t ppe_time64) +{ + size_t entry_size; + PkTraceGeneric* pte_footer = &pte->footer.generic; + uint32_t format; + uint32_t hash32; + uint32_t hash32_partial; + uint32_t* parm_start; + uint32_t parm_bytes; + uint64_t fsp_time64; + + //convert the ppe trace time to an fsp trace time + fsp_time64 = ppe2fsp_time(ppe_time64, ntohl(ptb->hz)); + + //fill in the 64 bit timestamp + fte->stamp.tbh = htonl((uint32_t)(fsp_time64 >> 32)); + fte->stamp.tbl = htonl((uint32_t)(fsp_time64 & 0x00000000ffffffffull)); + + //use the ppe instance id as the thread id. + fte->stamp.tid = htonl((uint32_t)ntohs(ptb->instance_id)); + + //merge the hash prefix and the string_id fields together for a 32 bit hash value + hash32 = ((uint32_t)ntohs(ptb->hash_prefix)) << 16; + hash32 |= pte_footer->string_id; + fte->head.hash = htonl(hash32); + + //generate the 32bit hash value for a partial trace entry in case it's needed + hash32_partial = ((uint32_t)ntohs(ptb->hash_prefix)) << 16; + hash32_partial |= ntohs(ptb->partial_trace_hash); + + //set the line number to 1 + fte->head.line = htonl(1); + + //determine the FSP trace format + format = PK_GET_TRACE_FORMAT(pte_footer->time_format.word32); + if(format == PK_TRACE_FORMAT_BINARY) + { + fte->head.tag = htons(TRACE_FIELDBIN); + } + else + { + fte->head.tag = htons(TRACE_FIELDTRACE); + } + + parm_start = (uint32_t*)(((char*)pte) + (sizeof(LargestPpeEntry) - pte_size)); + + //fill in the parameters/binary data and size at the end + switch(format) + { + + case PK_TRACE_FORMAT_TINY: + //one or 0 parameters + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + sizeof(uint32_t); + fte->parms[0] = htonl((uint32_t)(pte_footer->parm16)); + fte->head.length = htons(sizeof(uint32_t)); + parm_bytes = 0; + break; + + case PK_TRACE_FORMAT_BIG: + //1 - 4 parameters + // + //If the trace entry data is incomplete (not all parm data + //had been written at the time the trace was captured) then + //we will write a trace to the fsp buffer that says + //"PARTIAL TRACE ENTRY. HASH_ID = %d" + if(pte_footer->complete) + { + parm_bytes = pte_footer->bytes_or_parms_count * sizeof(uint32_t); + fte->head.length = htons(parm_bytes + sizeof(uint32_t)); + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + parm_bytes + sizeof(uint32_t); + } + else + { + parm_bytes = 0; + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + sizeof(uint32_t); + fte->parms[0] = fte->head.hash; //already corrected for endianess + fte->head.hash = htonl(hash32_partial); + fte->head.length = htons(sizeof(uint32_t)); + } + break; + + case PK_TRACE_FORMAT_BINARY: + //If the trace entry data is incomplete (not all parm data + //had been written at the time the trace was captured) then + //we will write a trace to the fsp buffer that says + //"PARTIAL TRACE ENTRY. HASH_ID = %d" + if(pte_footer->complete) + { + parm_bytes = pte_footer->bytes_or_parms_count; + fte->head.length = htons((uint16_t)parm_bytes); + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + parm_bytes; + + //pad to 4 byte boundary + entry_size = (entry_size + 3) & ~3; + } + else + { + parm_bytes = 0; + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + sizeof(uint32_t); + fte->parms[0] = fte->head.hash; + fte->head.hash = htonl(hash32_partial); + fte->head.length = htons(sizeof(uint32_t)); + fte->head.tag = htons(TRACE_FIELDTRACE); + } + break; + + + default: + entry_size = 0; + parm_bytes = 0; + break; + } + + //copy parameter bytes to the fsp entry if necessary + if(parm_bytes) + { + memcpy(fte->data, parm_start, parm_bytes); + } + + //add the entry size to the end + if(entry_size) + { + uint32_t new_entry_size = entry_size + sizeof(uint32_t); + *((uint32_t*)(((char*)fte) + entry_size)) = htonl(new_entry_size); + entry_size = new_entry_size; + } + + return entry_size; +} + +//retrieve a ppe trace entry from a ppe trace buffer +size_t ppe_get_entry(PkTraceBuffer* tb, uint32_t offset, LargestPpeEntry* pte) +{ + uint32_t mask = ntohs(tb->size) - 1; + PkTraceEntryFooter* footer; + size_t entry_size; + size_t parm_size; + char* dest = (char*)pte; + uint32_t format; + uint32_t start_index; + uint32_t bytes_left; + uint32_t bytes_to_copy; + + //Find the footer in the circular buffer + footer = (PkTraceEntryFooter*)(&tb->cb[(offset - sizeof(PkTraceEntryFooter)) & mask]); + + //always correct endianess for the time and string id words + pte->footer.generic.time_format.word32 = ntohl(footer->generic.time_format.word32); + pte->footer.generic.string_id = ntohs(footer->generic.string_id); + + //only need to byte swap the parm16 value if this is a tiny format + pte->footer.generic.parm16 = footer->generic.parm16; + + //use footer data to determine the length of the binary data or parameters + format = PK_GET_TRACE_FORMAT(pte->footer.generic.time_format.word32); + switch(format) + { + case PK_TRACE_FORMAT_TINY: + pte->footer.generic.parm16 = ntohs(pte->footer.generic.parm16); + parm_size = 0; + entry_size = sizeof(PkTraceEntryFooter); + break; + + case PK_TRACE_FORMAT_BIG: + parm_size = pte->footer.generic.bytes_or_parms_count * sizeof(uint32_t); + entry_size = sizeof(PkTraceEntryFooter); + break; + + case PK_TRACE_FORMAT_BINARY: + parm_size = pte->footer.generic.bytes_or_parms_count; + entry_size = sizeof(PkTraceEntryFooter); + break; + + default: + entry_size = 0; + parm_size = 0; + break; + } + + //pad to 8 byte boundary + parm_size = (parm_size + 7) & ~0x00000007ul; + + //add the parameter size to the total entry size + entry_size += parm_size; + + //copy the entry from the circular buffer to pte + start_index = (offset - entry_size) & mask; + bytes_left = ntohs(tb->size) - start_index; + + //only copy up to the end of the circular buffer + if(parm_size < bytes_left) + { + bytes_to_copy = parm_size; + } + else + { + bytes_to_copy = bytes_left; + } + + dest += sizeof(LargestPpeEntry) - entry_size; + memcpy(dest, &tb->cb[start_index], bytes_to_copy); + + //now copy the rest of the data starting from the beginning of the + //circular buffer. + if(bytes_to_copy < parm_size) + { + memcpy(dest + bytes_to_copy, tb->cb, parm_size - bytes_to_copy); + } + + //return the size of the entry + return entry_size; +} + +//convert a ppe trace buffer to an fsp trace buffer +int ppe2fsp(void* in, size_t in_size, void* out, size_t* io_size) +{ + PkTraceBuffer* ptb = (PkTraceBuffer*)in; + trace_buf_head_t* ftb = (trace_buf_head_t*)out; + uint32_t ppe_bytes_left; + uint32_t fsp_bytes_left; + int rc = 0; + uint32_t ptb_offset; + uint64_t ppe_time64; + uint32_t fte_size, pte_size; + uint32_t fsp_te_count = 0; + uint32_t time_diff32, prev_time32, new_time32; + PkTraceGeneric* pte_footer; + largest_fsp_entry_t fte; + LargestPpeEntry pte; + uint64_t time_adj64; + + do + { + if(!ptb || !ftb || !io_size) + { + rc = P2F_NULL_POINTER; + break; + } + + if(ntohs(ptb->version) != PK_TRACE_VERSION) + { + rc = P2F_INVALID_VERSION; + break; + } + + //check that the input buffer is large enough to have a ppe trace buffer + if(in_size < (((uintptr_t)(&ptb->cb[0])) - (uintptr_t)(ptb))) + { + rc = P2F_INPUT_BUFFER_TOO_SMALL; + break; + } + + //initialize some locals + fsp_bytes_left = *io_size - sizeof(trace_buf_head_t); + ppe_bytes_left = ntohs(ptb->size); + ptb_offset = ntohl(ptb->state.offset); + if(htonl(1) == 1) + { + time_adj64 = ptb->time_adj64; + } + else + { + time_adj64 = ntohl((uint32_t)(ptb->time_adj64 >> 32)); + time_adj64 |= ((uint64_t)(ntohl((uint32_t)(ptb->time_adj64 & 0x00000000ffffffff)))) << 32; + } + + //make sure the ppe buffer size is a power of two + if((ppe_bytes_left - 1) & ppe_bytes_left) + { + //size is not a power of two + rc = P2F_INVALID_INPUT_SIZE; + break; + } + + //The ppe bytes field should always be a multiple of 8 + if(ptb_offset & 0x7) + { + rc = P2F_INVALID_PPE_OFFSET; + break; + } + + //make sure there is enough room for the fsp header + if(*io_size < sizeof(trace_buf_head_t)) + { + rc = P2F_OUTPUT_BUFFER_TOO_SMALL; + break; + } + + + //initialize the fsp header + ftb->ver = TRACE_BUF_VERSION; + ftb->hdr_len = sizeof(trace_buf_head_t); + ftb->time_flg = TRAC_TIME_REAL; + ftb->endian_flg = 'B'; //big endian + memcpy(ftb->comp, ptb->image_str, sizeof(ftb->comp)); + ftb->times_wrap = htonl(1); + ftb->size = htonl(sizeof(trace_buf_head_t) + sizeof(uint32_t)); + ftb->next_free = htonl(sizeof(trace_buf_head_t)); + ftb->extracted = htonl(0); + ftb->te_count = htonl(0); + + //find the latest timestamp so that we can work back from there + ppe_time64 = ((uint64_t)(ntohl(ptb->state.tbu32) & 0xefffffff)) << 32; + pte_size = ppe_get_entry(ptb, ptb_offset, &pte); + prev_time32 = PK_GET_TRACE_TIME(pte.footer.generic.time_format.word32); + ppe_time64 |= prev_time32; + + //process all of the input bytes one trace entry at a time + //from newest to oldest (backwards) until we run out of input bytes or + //we run out of output space. + while(1) + { + //check if we have enough data for a ppe footer + if(ppe_bytes_left < sizeof(PkTraceEntryFooter)) + { + break; + } + + //get the next ppe entry + pte_size = ppe_get_entry(ptb, ptb_offset, &pte); + + //Stop if there are no more entries to retrieve from the ppe trace buffer + if(!pte_size) + { + break; + } + pte_footer = &pte.footer.generic; + + //mark the entry as incomplete if we didn't have enough data + //for the entire entry + if(pte_size > ppe_bytes_left) + { + pte_footer->complete = 0; + ppe_bytes_left = 0; + } + else + { + ppe_bytes_left -= pte_size; + ptb_offset -= pte_size; + } + + //Calculate the 64 bit timestamp for this entry.... + //On PPE, getting the timestamp is not done atomically with writing + //the entry to the buffer. This means that an entry with an older + //timestamp could possibly be added to the buffer after an entry + //with a newer timestamp. Detect this condition by checking if the + //time difference is bigger than the max difference. The max + //difference is enforced by the PPE having a trace added on a + //shorter time boundary (using a timer). + new_time32 = PK_GET_TRACE_TIME(pte_footer->time_format.word32); + time_diff32 = prev_time32 - new_time32; + + if(time_diff32 > ntohl(ptb->max_time_change)) + { + time_diff32 = new_time32 - prev_time32; + ppe_time64 += time_diff32; + } + else + { + ppe_time64 -= time_diff32; + } + + //save off the lower 32bit timestamp for the next iteration + prev_time32 = new_time32; + + //convert the ppe trace entry to an fsp trace entry + fte_size = pte2fte(ptb, &pte, pte_size, &fte, ppe_time64 + time_adj64); + + //fit as much of the entry into the fsp trace buffer as possible + fsp_put_entry(ftb, &fte, fte_size, fsp_bytes_left); + + //update the fsp trace entry count + fsp_te_count++; + + //stop if there is no more room left in the fsp trace buffer + if(fte_size >= fsp_bytes_left) + { + fsp_bytes_left = 0; + ftb->times_wrap = htonl(1); + break; + } + else + { + fsp_bytes_left -= fte_size; + } + }//while(1) + + + //shift the trace data up if there is space to do so + if(fsp_bytes_left) + { + char* dest = ((char*)ftb) + sizeof(trace_buf_head_t); + char* src = dest + fsp_bytes_left; + size_t data_size = *io_size - sizeof(trace_buf_head_t) - fsp_bytes_left; + memmove(dest, src, data_size); + } + + //update the fsp header to reflect the true size and entry count + ftb->te_count = htonl(fsp_te_count); + + //inform the caller of how many bytes were actually used + *io_size -= fsp_bytes_left; + + //shrink the size field to what we actually ended up using + ftb->size = htonl(*io_size); + + }while(0); + + return rc; +} + + + diff --git a/src/tools/trace/ppe2fsp.h b/src/tools/trace/ppe2fsp.h new file mode 100644 index 00000000..56f0a0bd --- /dev/null +++ b/src/tools/trace/ppe2fsp.h @@ -0,0 +1,33 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/trace/ppe2fsp.h $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include + +#define P2F_NULL_POINTER 1 +#define P2F_INVALID_INPUT_SIZE 2 +#define P2F_INVALID_PPE_OFFSET 3 +#define P2F_OUTPUT_BUFFER_TOO_SMALL 4 +#define P2F_INPUT_BUFFER_TOO_SMALL 5 +#define P2F_INVALID_VERSION 6 + +int ppe2fsp(void* in, size_t in_size, void* out, size_t* io_size); diff --git a/src/tools/trace/ppe2fsp_cmd.c b/src/tools/trace/ppe2fsp_cmd.c new file mode 100644 index 00000000..bab51ab5 --- /dev/null +++ b/src/tools/trace/ppe2fsp_cmd.c @@ -0,0 +1,138 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/trace/ppe2fsp_cmd.c $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include +#include "ppe2fsp.h" +#include "pk_trace.h" + +#define MAX_INPUT_SIZE 0x2040 //8k +#define MAX_OUTPUT_SIZE (4 * MAX_INPUT_SIZE) + +char* inbuf[MAX_INPUT_SIZE]; +char* outbuf[MAX_OUTPUT_SIZE]; +; +int main(int argc, char** argv) +{ + FILE* in; + FILE* out; + size_t input_size; + size_t output_size; + size_t bytes_written; + int rc = -1; + + do + { + if(argc > 3) + { + fprintf(stderr, "Usage: %s [input file] [output file]\n", argv[0]); + } + + if(argc < 3) + { + out = stdout; + } + else + { + //open the output file for writing + out = fopen(argv[2], "w"); + if(!out) + { + perror("failed to open file for writing"); + break; + } + } + + if(argc < 2) + { + in = stdin; + } + else + { + //open the input file for reading + in = fopen(argv[1], "r"); + if(!in) + { + perror("failed to open file for reading"); + break; + } + } + + //read the input stream until we reach EOF or the max size + input_size = fread(inbuf, 1, MAX_INPUT_SIZE, in); + if(!feof(in)) + { + if(ferror(in)) + { + perror("failed to read input file"); + break; + } + else + { + fprintf(stderr, "Input stream exceeds max size of %d bytes. Exiting.\n", MAX_INPUT_SIZE); + break; + } + } + + output_size = MAX_OUTPUT_SIZE; + + //Actual size of output buffer will be set upon successful completion + rc = ppe2fsp(inbuf, input_size, outbuf, &output_size); + if(rc) + { + fprintf(stderr, "Failed converting ppe trace to fsp trace. rc = %d\n", rc); + if(rc == P2F_INVALID_VERSION) + { + fprintf(stderr, "PPE trace buffer must be version %d.\n", PK_TRACE_VERSION); + } + break; + } + + rc = -1; + //operation was successful. Write out the fsp trace data + bytes_written = fwrite(outbuf, 1, output_size, out); + if(bytes_written != output_size) + { + if(ferror(out)) + { + perror("Failed to write output stream"); + break; + } + fprintf(stderr, "Failure: Only able to write %d of %d bytes to output stream\n", bytes_written, output_size); + break; + } + + fclose(in); + fclose(out); + fclose(stderr); + + rc = 0; + }while(0); + + return rc; +} + + + + + + diff --git a/src/tools/trace/ppetracepp.C b/src/tools/trace/ppetracepp.C new file mode 100755 index 00000000..9d795371 --- /dev/null +++ b/src/tools/trace/ppetracepp.C @@ -0,0 +1,949 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/trace/ppetracepp.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/* +# *** ppetracepp - a fsp/common Linux trace pre processor +# this one replaces the trace strings by the corresponding hash value +# (i.e. the complete call to trace_ppe_hash is replaced) + +# *** Usage +# +# prepend compiler call with the call of this pre processor, i.e if you have +# $(CC) $(CFLAGS) -o $@ $< +# in your Makefile change it to this: +# ppetracepp $(CC) $(CFLAGS) -o $@ $< +# ppetracepp will use "$(CC) -E" to call the C pre processor "cpp". +# you can set a env var "REALCPP" to the name of a program to select +# a different programm as cpp +# +# ppetracepp creates a file "$target.ppe.hash" with the trace strings and the hash values. +# +# to enable debug mode set envvar PPETRACEPPDEBUG to 1 or give '-d' as first arg + +# *** Change History +# +# 2003-02-26 RBa created from scratch +# 2003-02-28 RBa add C++ support (C++ interface uses own type for the hash) +# 2003-05-28 RBa if cc should link instead of compile just call compiler +# 2003-07-11 AGe Change search alg. slightly and put just format back +# 2003-07-25 RBa just call gcc if called to link instead to compile +# eat argument for option -x +# 2003-11-26 RBa fix c/c++ algo: compile as c++ if realcc=*g++ +# 2004-02-02 RBa remove explicit test whether source file is readable +# it is obsolete and might lead to an error if afs is used +# 2004-02-13 RBa add support for dependency generation (-MD/-MG, -MF) +# don't prepend './' to object filename +# 2006-04-19 RBa rewrite trace_ppe_write_all support, handle C and C++ the same +# 2006-05-24 RBa fix handling of missing -o ; add TRAC_PPVER for macro/API version +# 2006-09-15 RBa add handling of \" in trace format strings ; reduce non-error output +# put object file in current dir if no -o given +# 2007-03-22 RBa handle more gcc options (-i) ; protect " in call to shell +# store output of cpp as "unmodified" output for debug +# only write string/hash file if strings found +# 2012-09-24 hlava Rewritten as C program for better build performance (was perl) +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +typedef u_int32_t u32 ; +typedef u_int8_t u8 ; +#include + +using namespace std; + +static string version = "2.0"; +static string macro_version = "1"; + +static bool debug = false; +#define dprintf(format, ...) if (debug) { printf(format, ##__VA_ARGS__); fflush(stdout); } +static map hashtab; +static string hashtype; +static string hashtype_suffix; + +static string tmp; +static string cmd; +static FILE* CPP = NULL; // pipe from preprocessor +static FILE* CC = NULL; // pipe to compiler +static FILE* DEBUG = NULL; +static FILE* DEBUGIN = NULL; + +//***************************************************************************** +// replace_substr +//***************************************************************************** +void replace_substr(std::string& str, const std::string& oldStr, const std::string& newStr) +{ + size_t pos = 0; + while((pos = str.find(oldStr, pos)) != std::string::npos) + { + str.replace(pos, oldStr.length(), newStr); + pos += newStr.length(); + } + +} + +//***************************************************************************** +// fileparse +//***************************************************************************** +void fileparse(const string& in_str, string& name, string& dir, string& suff) +{ + string str(in_str); + size_t pos; + name = ""; + dir = ""; + suff = ""; + pos = str.find_last_of('.'); + if (pos != string::npos) + { + suff = str.substr(pos); + str = str.substr(0, pos); + } + pos = str.find_last_of('/'); + if (pos != string::npos) + { + name = str.substr(pos+1); + str = str.substr(0, pos+1); + } + dir = str; +} + +static const size_t TRACE_PPE_HASH_LEN = 13; +//***************************************************************************** +// chop_up_line +//***************************************************************************** +bool chop_up_line(string& in_line, string& prefix, string& strings, string& salt, string& suffix) +{ + // First see if this line matches the pattern we're looking for + // Since this will return false 95%+ of the time this function it called, we do it + // before doing any other init for performance reasons. + size_t pos = in_line.find("trace_ppe_hash"); + if (pos == string::npos) { return(false); } + + // trace_ppe_hash ( "..." ".." "..." , 2 ) + // regex: PREFIX 'trace_ppe_hash' space '(' space STRINGS space ',' space NUMBER space ')' SUFFIX + // STRINGS: '"' .* '"' space? + + + // Original perl magic incantation: + // while($line =~ m/^(.*?)trace_ppe_hash\s*\(\s*((".*?(? $1 = everything up to the word "trace_ppe_hash" + // trace_ppe_hash = delimiter + // \s*\(\s* = delimiter = <0-n whitespace chars>, left paren, <0-n whitespace chars> + // ((".*?(? $2 = double-quote, some chars up to last closing double-quote ($3 used for nested regex) + // ,\s* = delimiter = comma followed by some whitespace + // (-?\d+)\s*\)(.*) => $4 and $5 + // $/) = end of the line input string + string line(in_line); + prefix = ""; + strings = ""; + salt = ""; + suffix = ""; + size_t pos1; + size_t pos2; + size_t pos3; + + pos1 = pos + 14; // pos1 = after "trace_ppe_hash" + pos2 = line.find("(", pos1); + if (pos2 == string::npos) { return(false); } + ++pos2; + pos3 = line.find("\"", pos2); + if (pos3 == string::npos) { return(false); } + dprintf("--------\nchop_up_line: Passed basic checks. line= %s\n", line.c_str()); + dprintf("pos1=%d, pos2=%d, pos3=%d\n", pos1, pos2, pos3); + if ((pos1 != (pos2-1)) && (line.find_first_not_of(" \t", pos1, (pos2-pos1)+1) != string::npos)) { return(false); } //non-whitespace? + if ((pos2 != pos3) && (line.find_first_not_of(" \t", pos2, (pos3-pos2)) != string::npos)) { return(false); } //non-whitespace? + + // Get the prefix data + dprintf(">chop_up_line(\"%s\",...)\n", line.c_str()); + prefix = line.substr(0, pos); + line = line.substr(pos + TRACE_PPE_HASH_LEN); + dprintf(" prefix=\"%s\"\n", prefix.c_str()); + + // Get the strings and join/fix them: Store all strings between paired double-quotes up to the + // first comma not inside a string + pos = line.find_first_of('('); + if (pos == string::npos) { return(false); } + line = line.substr(pos + 1); + strings = ""; + while(!line.empty()) + { + pos = line.find_first_of(','); + pos1 = line.find_first_of('"'); + if ((pos1 == string::npos) || ((pos != string::npos) && (pos < pos1))) { break; } // found comma before next quote + pos2 = line.find_first_of('"', (pos1+1)); + if (pos2 == string::npos) { return(false); } // unbalanced quotes! + while(line[pos2-1] == '\\') // skip escaped quotes in the string (they're not the ending quote) + { + pos2 = line.find_first_of('"', (pos2+1)); + if (pos2 == string::npos) { return(false); } // unbalanced quotes! + } + if (!strings.empty()) { strings += " "; } + strings += line.substr(pos1, (pos2-pos1)+1); + line = line.substr(pos2+1); + } + replace_substr(strings, "\" \"", ""); + replace_substr(strings, "\\\"", "ESCAPEDQUOTE"); + replace_substr(strings, "\"", ""); + replace_substr(strings, "ESCAPEDQUOTE", "\""); + // Remove trailing whitespace ah20130717 + pos = strings.find_last_not_of(" \t\n"); + if ((pos != string::npos) && (pos < (strings.length()-1))) + { + strings = strings.substr(0, pos+1); + } + + dprintf(" strings>%s<\n", strings.c_str()); + + // Get the salt + pos = line.find(","); + if (pos != string::npos) { line = line.substr(pos+1); } + pos = line.find_first_of(')'); + if (pos == string::npos) { return(false); } + salt = line.substr(0, pos); + line = line.substr(pos+1); + //dprintf(" salt=\"%s\"\n", salt.c_str()); + pos = salt.find_first_not_of(" \t\n"); + if (pos == string::npos) { return(false); } + salt = salt.substr(pos); + pos = salt.find_last_not_of(" \t\n"); + if (pos == string::npos) { return(false); } + salt = salt.substr(0, pos+1); + dprintf(" salt=\"%s\"\n", salt.c_str()); + + // Get the suffix (i.e. the rest) + suffix = line; + if (suffix[suffix.length()-1] == '\n') { suffix = suffix.substr(0, suffix.length()-1); } + dprintf(" suffix=\"%s\"\nget_hash(\"%s\",%d)\n", str.c_str(), salt_num); + + // Call jhash function to get the hash value + hash_num = jhash((void*)str.c_str(), str.length(), salt_num); + dprintf("jhash() returned: %u\n", hash_num); + sprintf(buf, "%u", hash_num & 0x0000ffff); + hash16 = buf; + sprintf(buf, "%u", ((salt_num << 16) | (hash_num & 0x0000ffff))); + hash32 = buf; + + // validate the hash value + size_t pos = hash32.find_first_not_of("0123456789"); + if (pos != string::npos) + { + fprintf(stderr, "trexhash error: %s\n", hash32.c_str()); + fprintf(stderr, "for call <<%s>>\n", cmd.c_str()); + exit(1); + } + +//removing this since it doesn't seem to have any affect on the output +#if 0 + // If hash is empty, use the sum of the ord values in the original string + if ((hash == "")||(hash == "0")) + { + unsigned int len = str.length(); + unsigned int hash_num = 0; + //unsigned char conv_buf[2] = { '\0', '\0' }; + u_int8_t conv_num; + for (unsigned int i=0; i < len; ++i) + { + //conv_buf[0] = str[i]; + conv_num = (u_int8_t)str[i]; + hash_num += (unsigned int)conv_num; + } + } +#endif + + dprintf("& rhash, string& line, string& out_line) +{ + // NOTE: "line" arg may get modified by this function! Caller must not assume it's unchanged. + string format; + string prefix; + string strings; + string tmp; + string salt; + string hash16; + string hash32; + int salt_num; + int format_salt; + string suffix; + string write_all_suffix; + size_t pos; + + out_line = ""; + // trace_ppe_hash ( "..." ".." "..." , 2 ) + // regex: PREFIX 'trace_ppe_hash' space '(' space STRINGS space ',' space NUMBER space ')' SUFFIX + // STRINGS: '"' .* '"' space? + + //while($line =~ m/^(.*?)trace_ppe_hash\s*\(\s*((".*?(? 1) arg = argv[1]; + if ((argc < 2) || (arg == "-h")) + { + fprintf(stderr, "usage: %s realcompiler compileroptions -o target source\n", argv[0]); + exit(9); + } + string realcc(argv[argi++]); + string cctype("c++"); + bool optx_found = false; + + if (realcc == "-d") + { + debug = true; + realcc = argv[argi++]; + } + + // wait until -d options is handled before checking $debug + dprintf("ppetracepp version %s - API/macro version %s\n", version.c_str(), macro_version.c_str()); + + p_env = getenv("REALCPP"); + string realcpp; + if (p_env) + realcpp = p_env; + if (realcpp.empty()) + { + dprintf("cannot find cpp, using -E\n"); + realcpp = realcc; + realcpp += " -E"; + } + dprintf("realcpp is %s\n", realcpp.c_str()); + +//------------------------------------------------------------------------------ +// parse all the arguments +//------------------------------------------------------------------------------ +string source; +string object; +vector ccopts; +vector cppopts; +bool dodeps = false; +string depfile; +string pfx; +string sfx; +int origargi = argi; +for( ; argi < argc; ++argi) +{ + arg = argv[argi]; + dprintf("Processing argv[%d]: \"%s\"\n", argi, arg.c_str()); + if (arg.length() > 2) + { + pfx = arg.substr(0,2); + sfx = arg.substr(arg.length()-2); + } + else + { + pfx = arg; + sfx = arg; + } + dprintf(" pfx: \"%s\" sfx: \"%s\"\n", pfx.c_str(), sfx.c_str()); + + if (pfx == "-o") + { + if (! object.empty()) + { + fprintf(stderr, "two -o options, aborting\n"); + exit(1); + } + if (arg.length() > 2) + { + object = sfx; + } + else + { + object = argv[++argi]; + } + dprintf("object is now %s\n", object.c_str()); + } + else if (arg == "-c") + { + // don't call cpp with -c, this is for the compiler + ccopts.push_back(arg); + dprintf("found -c option\n"); + } + else if (pfx == "-l") + { + // cpp doesn't need library arguments + cppopts.push_back(arg); + } + else if (pfx == "-i") + { + // option takes an argument, handle it too + optarg = argv[argi++]; + ccopts.push_back(arg); + ccopts.push_back(optarg); + cppopts.push_back(arg); + cppopts.push_back(optarg); + dprintf("found option '%s %s'\n", arg.c_str(), optarg.c_str()); + } + else if ((arg == "-L") || + (arg == "-I") || + (arg == "-x") || + (arg == "-b") || + (arg == "-B") || + (arg == "-V") || + (arg == "-D") || + (arg == "--param") || + (arg == "-MQ") || + (arg == "-MT")) + { + // option takes an argument, handle it too + optarg = argv[argi++]; + ccopts.push_back(arg); + ccopts.push_back(optarg); + cppopts.push_back(arg); + cppopts.push_back(optarg); + dprintf("found option '%s %s'\n", arg.c_str(), optarg.c_str()); + if (arg == "-x") + { + // option x sets the language - c or c++ + if ((optarg != "c") && (optarg != "c++") && (optarg != "assembler-with-cpp")) + { + fprintf(stderr, "cannot process language '%s', aborting\n", optarg.c_str()); + exit(1); + } + cctype = optarg; + optx_found = true; + } + } + else if ((arg == "-MD")||(arg == "-MG")) + { + // gen deps + dodeps = true; + dprintf("found %s, creating dependencies\n", arg.c_str()); + } + else if (arg == "-MF") + { + // set dependencies file + depfile = argv[argi++]; + dprintf("set dependencies file to '%s'\n", depfile.c_str()); + } + else if (arg[0] == '-') + { + // arg starts with - so it's an option + ccopts.push_back(arg); + cppopts.push_back(arg); + dprintf("found option '%s'\n", arg.c_str()); + } + else if ((sfx == ".a") || + (sfx == ".o")) + { + // an object or archive, ignore this but give it to cc + ccopts.push_back(arg); + dprintf("found object/archive '%s'\n", arg.c_str()); + } + else if ((sfx == ".c") || + (sfx == ".C") || + (sfx == ".S") || + (arg.substr(arg.length()-4) == ".cpp") || + (arg.substr(arg.length()-4) == ".cxx")) + { + // the source file(s). we should only get one + if (!source.empty()) + { + fprintf(stderr, "don't know to handle two source files, aborting\n"); + exit(1); + } + source = arg; + // put the - (for read-from-stdin) where the source file was + // (order is important!) + ccopts.push_back("-"); + dprintf("found source file %s\n", source.c_str()); + } + else if (access(arg.c_str(), F_OK)) + { + // option but not a file, an unknown option? + ccopts.push_back(arg); + cppopts.push_back(arg); + dprintf("found unknown option '%s'\n", arg.c_str()); + } +} + +//------------------------------------------------------------------------------ +// set other parameters based on arguments specified +//------------------------------------------------------------------------------ +if (source.empty()) +{ + // this might be a call to link a program instead of compile a source (or asm source) + dprintf("NOTME: starting as cc '%s ...'\n", realcc.c_str()); + execvp(realcc.c_str(), &(argv[origargi])); + fprintf(stderr, "ERROR: returned from execvp() call to run %s\n", realcc.c_str()); +} +if (object.empty()) +{ + dprintf("no object file given, default to source name\n"); + // gcc builds object name from source name if no -o given, replacing + // suffix with .o. The file is placed in the current directory, + // not in the source directory! + string n; + string d; + string s; + fileparse(source, n, d, s); + if (!n.empty() && !s.empty()) + { + object = n + ".o"; + dprintf("tracpp: guessing object name %s\n", object.c_str()); + dprintf(" from source name %s\n", source.c_str()); + } + else + { + fprintf(stderr, "Unable to determine Source File Name\n"); + exit(1);; + } +} + +// set value of trace hash according to language +// check source file extension if no explicit -x option given +if (!optx_found) +{ + if (realcc.find("g++") != string::npos) + { + dprintf("compiler language: C++ (from compiler name)\n"); + cctype = "c++"; + } + else + { + if (source.substr(source.length()-2) == ".c") + { + dprintf("compiler language: C (from source file extension)\n"); + cctype = "c"; + } + else if (source.substr(source.length()-2) == ".S") + { + dprintf("compiler language: assembly (from source file extension)\n"); + cctype = "assembler-with-cpp"; + } + else + { + dprintf("compiler language: C++ (default)\n"); + cctype = "c++"; + } + } +} +else +{ + dprintf("compiler language: %s (from option '-x')\n", cctype.c_str()); +} + +if (cctype == "c") +{ + hashtype = "(unsigned short)"; + hashtype_suffix = "U"; +} +else if (cctype == "assembler-with-cpp") +{ + hashtype = ""; + hashtype_suffix = ""; +} +else +{ + hashtype = "(trace_hash_val)"; + hashtype_suffix = "U"; +} +// define TRAC_PPETRACEPP for macros +tmp = "-DTRAC_PPETRACEPP -DTRAC_PPVER="; +tmp += macro_version; +cppopts.push_back(tmp); +if (dodeps) +{ + if (depfile.empty()) + { + if ((p_env = getenv("DEPENDENCIES_OUTPUT")) != NULL) + { + depfile = p_env; + } + else if ((p_env = getenv("SUNPRO_DEPENDENCIES")) != NULL) + { + depfile = p_env; + } + else + { + depfile = object; + if (depfile.substr(depfile.length()-2) == ".o") + { + depfile = depfile.substr(0, depfile.length()-2); + depfile += ".d"; + } + } + } + tmp = "-MD -MF "; + tmp += depfile; + cppopts.push_back(tmp); +} + +//------------------------------------------------------------------------------ +// start cpp +//------------------------------------------------------------------------------ +cmd = realcpp; +for(vector::iterator p = cppopts.begin(); p != cppopts.end(); ++p) +{ + cmd += " "; + cmd += *p; +} +cmd += " "; +cmd += source; +cmd += " -o-"; +dprintf("starting as cpp '%s'\n", cmd.c_str()); +CPP = popen(cmd.c_str(), "r"); +if (CPP == NULL) +{ + fprintf(stderr, "cannot start cpp '%s'\n", realcpp.c_str()); + perror(""); + exit(1); +} + +//------------------------------------------------------------------------------ +// start cc. manually set language as source file extension not available to cc +//------------------------------------------------------------------------------ +string type_str = ""; +if (!optx_found) +{ + // no option -x given by caller, set manually + type_str = "-x "; + type_str += cctype; +} +cmd = realcc; +cmd += " "; +cmd += type_str; +for(vector::iterator p = ccopts.begin(); p != ccopts.end(); ++p) +{ + cmd += " "; + cmd += *p; +} +cmd += " -o "; +cmd += object; +dprintf("starting as cc '%s'\n", cmd.c_str()); +CC = popen(cmd.c_str(), "w"); +if (CC == NULL) +{ + fprintf(stderr, "cannot start cc '%s'\n", realcc.c_str()); + perror(""); + exit(1); +} + +string modifiedfile; +string unmodifiedfile; +if (debug) +{ + modifiedfile = object + ".debug"; + DEBUG = fopen(modifiedfile.c_str(), "w"); + if (DEBUG == NULL) + { + string msg = "cannot open file "; + msg += modifiedfile; + perror(msg.c_str()); + modifiedfile = ""; + } + else + { + fprintf(stderr, "writing preprocessed source to %s\n", modifiedfile.c_str()); + } + unmodifiedfile = object + ".debug_in"; + DEBUGIN = fopen(unmodifiedfile.c_str(), "w"); + if (DEBUGIN == NULL) + { + string msg = "cannot open file "; + msg += unmodifiedfile; + perror(msg.c_str()); + unmodifiedfile = ""; + } + else + { + fprintf(stderr, "writing unprocessed source to %s\n", unmodifiedfile.c_str()); + } +} + +string oldline; +string newline; +static const int MAX_BUFFER = 51200; +char buf[MAX_BUFFER]; +while (!feof(CPP)) +{ + if (fgets(buf, MAX_BUFFER, CPP) != NULL) + { + oldline = buf; + if (DEBUGIN) { fprintf(DEBUGIN, "%s", oldline.c_str()); } + parse_line(hashtab, oldline, newline); + //#print "oldline = $oldline"; + //#print "newline = $newline"; + if (newline.empty()) + { + fprintf(stderr, "hash error in/with file %s\n", source.c_str()); + exit(1); + } + //#print "newline = $newline\n"; + fprintf(CC, "%s", newline.c_str()); + if (DEBUG) { fprintf(DEBUG, "%s", newline.c_str()); } + } +} +if (DEBUG) { fclose(DEBUG); } +if (DEBUGIN) { fclose(DEBUGIN); } +int cmd_rc = pclose(CPP); +if (cmd_rc) +{ + fprintf(stderr, "error from cpp\n"); + if (cmd_rc & 127) + { + fprintf(stderr, "cpp got signal %d\n", (cmd_rc & 127)); + exit(1); + } + else if (cmd_rc >> 8) + { + fprintf(stderr, "cpp returned %d\n", (cmd_rc >> 8)); + exit(cmd_rc >> 8); + } +} +cmd_rc = pclose(CC); +if (cmd_rc) +{ + fprintf(stderr, "error from cc\n"); + if (cmd_rc & 127) + { + fprintf(stderr, "cc got signal %d\n", (cmd_rc & 127)); + exit(1); + } + else if (cmd_rc >> 8) + { + fprintf(stderr, "cc returned %d\n", (cmd_rc >> 8)); + exit(cmd_rc >> 8); + } +} + +if (!hashtab.empty()) +{ + string stringfile = object; + stringfile += ".ppe.hash"; + // open trace string file + FILE* TRC = fopen(stringfile.c_str(), "w"); + if (TRC == NULL) + { + fprintf(stderr, "cannot write trace string file '%s'\n", stringfile.c_str()); + exit(1); + } + dprintf("Writing to file %s\n", stringfile.c_str()); + + string pwd; + FILE* PWD = popen("pwd", "r"); + fgets(buf, MAX_BUFFER, PWD); + pwd = buf; + pclose(PWD); + time_t tt = time(NULL); + sprintf(buf, "%s", asctime(localtime(&tt))); + buf[strlen(buf)-1] = '\0'; // chop off extra newline + fprintf(TRC, "#FSP_TRACE_v2|||%s|||BUILD:%s", buf, pwd.c_str()); + + string srch_str = "||"; + srch_str += source; + int srch_str_len = srch_str.length(); + size_t pos; + for(map::iterator p = hashtab.begin(); p != hashtab.end(); ++p) + { + pos = (p->second).find(srch_str); + if ((pos != string::npos) && ((pos + srch_str_len) == (p->second).length())) + { + // source file name is already part of the string + fprintf(TRC, "%s||%s\n", (p->first).c_str(), (p->second).c_str()); + } + else + { + fprintf(TRC, "%s||%s||%s\n", (p->first).c_str(), (p->second).c_str(), source.c_str()); + } + //#print TRC "$key||$source||$hashtab{$key}\n"; + } + fclose(TRC); +} +else +{ + dprintf("No trace calls/strings found, not writing hash file\n"); +} +} // end main diff --git a/src/tools/trace/trac_interface.h b/src/tools/trace/trac_interface.h new file mode 100755 index 00000000..ce9355ae --- /dev/null +++ b/src/tools/trace/trac_interface.h @@ -0,0 +1,369 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/trace/trac_interface.h $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/****************************************************************************** +// @file trac_interface.h +// @brief Interface codes for TRAC component. +*/ +/****************************************************************************** + * + * @page ChangeLogs Change Logs + * @section _trac_interface_h trac_interface.h + * @verbatim + * + * Flag Def/Fea Userid Date Description + * ------- ---------- -------- ---------- ---------------------------------- + * TEAM 06/16/2010 Port + * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments + * @pb00E pbavari 03/11/2012 Added correct include file + * @at009 859308 alvinwan 10/15/2012 Added tracepp support + * @ai005 860268 ailutsar 11/20/2012 Create trace test applet + * @rc005 864101 rickylie 12/12/2012 add small circ buffer to handle ISR semaphore conflict + * + * @endverbatim + * + *///*************************************************************************/ + +#ifndef _TRAC_INTERFACE_H +#define _TRAC_INTERFACE_H + +/** \defgroup Trace Trace Component + * Port of the trace code used in the fsp and tpmd. + */ + +//************************************************************************* +// Includes +//************************************************************************* + +//************************************************************************* +// Externs +//************************************************************************* + +//************************************************************************* +// Macros +//************************************************************************* +/** + * \defgroup TracMacros Trace Component Macro Interfaces + * \ingroup Trace + * Used to trace 0 - 5 arguments or a binary buffer when using a hash value. + */ +/*@{*/ + + +// @at009c - start +#define TRACE(i_td,i_string,args...) \ + trace_adal_write_all(i_td,trace_adal_hash(i_string,-1),__LINE__,0,##args) + +#define TRACEBIN(i_td,i_string,i_ptr,i_size) \ + trac_write_bin(i_td,trace_adal_hash(i_string,0),__LINE__,i_ptr,i_size) + +#ifndef NO_TRAC_STRINGS + +#define FIELD(a) \ + printf("%s",a) + +#define FIELD1(a,b) \ + printf("%s%lx",a,(unsigned long)b) + +#else // NO_TRAC_STRINGS + +#define FIELD(a) + +#define FIELD1(a,b) + +#endif // NO_TRAC_STRINGS + +#define SUCCESS 0 +// @at009c - end + + + +/*@}*/ + +//************************************************************************* +// Defines/Enums +//************************************************************************* +#define TRACE_MAX_ARGS 5 /*!< Maximum number of args to trace */ + +typedef uint32_t trace_hash_val; + +// NOTE! Increment this when new components are added! +#define TRAC_NUM_TRACE_COMPONENTS 1 + + +#define TRACE_BUFFER_SIZE 8192 // @ai005a + +#define CIRCULAR_BUFFER_SIZE 4 // @rc005a + +typedef uint32_t UINT32; +typedef int32_t INT32; +typedef uint8_t UCHAR; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef char CHAR; +typedef unsigned int UINT; +typedef unsigned long ULONG; +typedef int INT; +typedef void VOID; + +//************************************************************************* +// Structures +//************************************************************************* +/* + * @brief Structure is put at beginning of all trace buffers + */ +typedef struct trace_buf_head { + UCHAR ver; /*!< version of this struct (1) */ + UCHAR hdr_len; /*!< size of this struct in bytes */ + UCHAR time_flg; /*!< meaning of timestamp entry field */ + UCHAR endian_flg; /*!< flag for big ('B') or little ('L') endian */ + CHAR comp[16]; /*!< the buffer name as specified in init call */ + UINT32 size; /*!< size of buffer, including this struct */ + UINT32 times_wrap; /*!< how often the buffer wrapped */ + UINT32 next_free; /*!< offset of the byte behind the latest entry */ + UINT32 te_count; /*!< Updated each time a trace is done */ + UINT32 extracted; /*!< Not currently used */ +}trace_buf_head_t; + +/*! + * @brief Timestamp and thread id for each trace entry. + */ +typedef struct trace_entry_stamp { + UINT32 tbh; /*!< timestamp upper part */ + UINT32 tbl; /*!< timestamp lower part */ + UINT32 tid; /*!< process/thread id */ +}trace_entry_stamp_t; + +/* + * @brief Structure is used by adal app. layer to fill in trace info. + */ +typedef struct trace_entry_head { + UINT16 length; /*!< size of trace entry */ + UINT16 tag; /*!< type of entry: xTRACE xDUMP, (un)packed */ + UINT32 hash; /*!< a value for the (format) string */ + UINT32 line; /*!< source file line number of trace call */ +}trace_entry_head_t; + +/* + * @brief Parameter traces can be all contained in one write. + */ +typedef struct trace_entire_entry { + trace_entry_stamp_t stamp; + trace_entry_head_t head; + UINT32 args[TRACE_MAX_ARGS + 1]; +} trace_entire_entry_t; + + +/* + * @brief Binary first writes header and time stamp. + */ +typedef struct trace_bin_entry { + trace_entry_stamp_t stamp; + trace_entry_head_t head; +} trace_bin_entry_t; + +/** + * @brief Used as input to traces to get to correct buffer. + */ +typedef trace_buf_head_t * tracDesc_t; + +/* + * @brief Structure is used to hold array of all trace descriptors + */ +typedef struct trace_descriptor_array +{ + tracDesc_t *entry; /*!< Pointer to trace descriptor */ + CHAR *comp; /*!< Pointer to component name */ +}trace_descriptor_array_t; + +// @rc005a - start +typedef struct circular_buf_head +{ + UINT32 head; // pointer to head + UINT32 tail; // pointer to tail + UINT32 entryCount; // nums of entry +} circular_buf_header_t; + + +typedef struct circular_entire_data { + UINT32 len; + CHAR comp[4]; + trace_entire_entry_t entry; +} circular_entire_data_t; + +// @rc005a - end + +//************************************************************************* +// Globals +//************************************************************************* +// All TPMF component trace descriptors. +extern tracDesc_t g_trac_inf; // @at009a +extern tracDesc_t g_trac_err; // @at009a +extern tracDesc_t g_trac_imp; // @at009a + +extern const trace_descriptor_array_t g_des_array[]; + +//************************************************************************* +// Function Prototypes +//************************************************************************* + +/** + * \defgroup TracIntefaces Trace Component Interfaces for External Use + * \ingroup Trace + */ +/*@{*/ + + +/** + * @brief Allocate and initialize all trace buffers in memory. + * + * This function will allocate memory for each of the pre-defined trace + * buffers, initilize the buffers with starting data, and setup the + * trace descriptors which each component will use to trace. + * + * This function must be called first before any components try to trace! + * + * @return Non-zero return code on error. + */ +UINT TRAC_init_buffers(void); + +/** + * @brief Retrieve full trace buffer for component i_comp + * + * This function assumes memory has already been allocated for + * the full trace buffer in o_data. + * + * @param i_td_ptr Trace descriptor of buffer to retrieve. + * @param o_data Pre-allocated pointer to where data will be stored. + * + * @return Non-zero return code on error + */ +UINT TRAC_get_buffer(const tracDesc_t i_td_ptr, + void *o_data); + +/** + * @brief Retrieve partial trace buffer for component i_comp + * + * This function assumes memory has already been allocated for + * the trace buffer (size io_size). This function will copy + * in up to io_size in bytes to the buffer and set io_size + * to the exact size that is copied in. + * + * @param i_td_ptr Trace descriptor of buffer to retrieve. + * @param o_data Pre-allocated pointer to where data will be stored. + * @param io_size Size of trace data to retrieve (input) + * Actual size of trace data stored (output) + * + * @return Non-zero return code on error + */ +UINT TRAC_get_buffer_partial(const tracDesc_t i_td_ptr, + void *o_data, + UINT *io_size); + +/** + * @brief Retrieve trace descriptor for input component name + * + * @param i_comp Component name to retrieve trace descriptor for. + * + * @return Valid trace descriptor on success, NULL on failure. + */ +tracDesc_t TRAC_get_td(const char *i_comp); + +/** + * @brief Reset all trace buffers + * + * @return Non-zero return code on error + */ +UINT TRAC_reset_buf(void); + +/*@}*/ // Ending tag for external interface module in doxygen + + +/** + * @brief Trace input integers to trace buffer. + * + * This function assumes i_td has been initialized. + * + * @param io_td Intialized trace descriptor point to buffer to trace to. + * @param i_hash Hash value to be recorded for this trace. + * @param i_fmt Output format + * @param i_line Line number trace is occurring on. + * @param i_type trace type. filed or debug. + * @param ... parames that are limited to a size of 4 bytes, i.e. int, uint32_t, nnn* + * + * @return Non-zero return code on error. + */ +UINT trace_adal_write_all(tracDesc_t io_td,const trace_hash_val i_hash, + const char *i_fmt,const ULONG i_line, const ULONG i_type,...); + + +/** + * @brief Trace input integers to trace buffer. + * + * This function assumes i_td has been initialized. + * + * @param io_td Intialized trace descriptor point to buffer to trace to. + * @param i_hash Hash value to be recorded for this trace. + * @param i_line Line number trace is occurring on. + * @param i_num_args Number of arguments to trace. + * @param i_1 Input Parameter 1 + * @param i_2 Input Parameter 2 + * @param i_3 Input Parameter 3 + * @param i_4 Input Parameter 4 + * @param i_5 Input Parameter 5 + * + * @return Non-zero return code on error. + */ +UINT trac_write_int(tracDesc_t io_td,const trace_hash_val i_hash, + const ULONG i_line, + const UINT i_num_args, + const ULONG i_1,const ULONG i_2,const ULONG i_3, + const ULONG i_4,const ULONG i_5 + ); + + + /** + * @brief Trace binary data to buffer. + * + * This function assumes i_td has been initialized. + * + * @param io_td Intialized trace descriptor point to buffer to trace to. + * @param i_hash Hash value to be recorded for this trace. + * @param i_line Line number trace is occurring on. + * @param i_ptr Pointer to binary data to trace. + * @param i_size Size of data to copy from i_ptr. + * + * @return Non-zero return code on error. + */ +UINT trac_write_bin(tracDesc_t io_td,const trace_hash_val i_hash, + const ULONG i_line, + const void *i_ptr, + const ULONG i_size); + +//************************************************************************* +// Functions +//************************************************************************* + +#endif //_TRAC_INTERFACE_H diff --git a/src/tools/trace/tracehash.pl b/src/tools/trace/tracehash.pl new file mode 100755 index 00000000..a278741a --- /dev/null +++ b/src/tools/trace/tracehash.pl @@ -0,0 +1,896 @@ +#!/usr/bin/perl -w +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/trace/tracehash.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +# File tracehash.pl created by B J Zander. + +use strict; + +sub determine_args(); +sub launch_cpp_and_parse($$); +sub cpp_dir($); +sub read_string_file(); +sub collect_files($); +sub assimilate_file($); +sub hash_strings(); +sub write_string_file(); +sub help(); + +select (STDERR); +$| = 1; # Make all prints to STDERR flush the buffer immediately +select (STDOUT); +$| = 1; # Make all prints to STDOUT flush the buffer immediately + +# Constants +my $HEAD_SEP = "|||"; +my $HEAD_EYE_CATCHER = "#FSP_TRACE_v"; +my $HEAD_BUILD_FLAG = "BUILD:"; +my $HEAD_VER_FLAG = 2; +my $BB_STRING_FILE = "/opt/fsp/etc/BB_StringFile"; + +# Global Variables +my $debug = 0; +my $seperator = "&&&&"; +my $file_name = "sbeStringFile"; +my $in_sand; +my ($backing) = $ENV{'bb'}; +my $hash_prog = "trexhash"; #default to in path +my $build = ""; +my ($sandbox) = $ENV{'SANDBOX'} || ""; +my ($context) = $ENV{'CONTEXT'} || ""; +my ($sandboxbase) = $ENV{'SANDBOXBASE'} || ""; +my ($bb); +my ($sourcebase) = "$sandboxbase/src"; +my ($version) = $HEAD_VER_FLAG; # default to oldest version +my ($collect) = 0; +my ($INCLUDE, $Arg, $file, $dir, $string_file); +my $args = ""; + +my $fail_on_collision = 0; # 1 = exit with error if hash collision occurs +my $hash_filename_too = 0; # 1 = hash is calculated over format string + filename + +print "sourcebase = $sourcebase\n" if $debug; +print "sandbox = $sandbox\n" if $debug; +print "backing = $backing\n" if $debug; +print "context = $context\n" if $debug; + +if ($context =~ /x86/) +{ + $bb = "i586-pc-linux-gnu"; +} +else +{ + $bb = "powerpc-linux"; +} + +if(($sourcebase =~ /\w+/) && ($sandbox =~ /\w+/)) +{ + $INCLUDE = "-I $sandboxbase/export/$context/fips/include -I $backing/export/$context/fips/include -I /opt/fsp/$bb/include/fsp -I/opt/fsp/$bb/include/ -include /opt/fsp/$bb/include/fsp/tracinterface.H"; +} +else +{ + print "Not in Sandbox so guessing Include Paths...\n" if $debug; + $INCLUDE = "-I/opt/fsp/i586-pc-linux-gnu/include/fsp -I/opt/fsp/i586-pc-linux-gnu/include/ -include /opt/fsp/i586-pc-linux-gnu/include/fsp/tracinterface.H"; +} + +# I/P Series work in ODE sandbox env. +if ($sandboxbase =~ /\w+/) +{ + $in_sand = 1; + print "backing = $backing\n" if $debug; +} +else +{ + $in_sand = 0; +} + + + +# Parse the input parameters. + +while (@ARGV) { + $Arg = shift; + + if ($Arg eq "-h" || $Arg eq "-H") { + help(); + exit(127); + } + if ($Arg eq "-f") { + $file = shift; + next; + } + if ($Arg eq "-d") { + $dir = shift; + next; + } + if ($Arg eq "-s") { + $string_file = shift; + next; + } + if ($Arg eq "-c") { + $collect = 1; + next; + } + if ($Arg eq "-v") { + $debug = 1; + print "debug on\n" if $debug; + next; + } + if ($Arg eq "-C") { # fail if a hash collision is detected + $fail_on_collision = 1; + next; + } + if ($Arg eq "-F") { # hash is calculated over format string + file name + $hash_filename_too = 1; + next; + } + if ($Arg eq "-S") { + $BB_STRING_FILE = ""; + next; + } + + #just pass it onto compiler + $args = $args . " " . $Arg; +} + +print "args = $args\n" if $debug; + +if (!$file && !$dir && !$in_sand) { + help(); + exit(127); +} + +################################# +# M A I N # +################################# + +my $clock = `date`; + +$build = $HEAD_EYE_CATCHER . "$HEAD_VER_FLAG" . $HEAD_SEP . $clock . $HEAD_SEP . $HEAD_BUILD_FLAG; + +$build =~ s/\n//g; + +# Global array to hold the parsed TRAC macro calls. +my @strings = (); + +# Assoc. arrays to hold hash|string values. +my %string_file_array = (); +my %hash_strings_array = (); + +# Check all provided arguments and look for defaults if not provided by user +determine_args(); + +# Scan the appropriate files or directories for TRAC macro calls. + +if (defined $dir) +{ + + $build = $build . $dir; # default to put at top of string file + if($collect) + { + collect_files($dir); + } + else + { + cpp_dir($dir); + # Hash the string that have been scanned. + %hash_strings_array = hash_strings(); + } +} +else +{ + $build = $build . $file; # default to put at top of string file + + if($collect) + { + assimilate_file($file); + } + else + { + # make sure include path includes directory that file is in + if($file =~ /^(.+)\/[^\/]+\.C$/) + { + + launch_cpp_and_parse($file,$1); + } + else + { + # No path in front of file so it has to be local dir + launch_cpp_and_parse($file,"./"); + } + # Hash the string that have been scanned. + %hash_strings_array = hash_strings(); + } +} + +# Read the existing string file into memory. +%string_file_array = read_string_file(); + +# Write out the new string file. check for collisions of new/old string here +write_string_file(); + +print "Hashing Started at $clock\n"; +$clock = `date`; +print "Hashing Finished at $clock\n"; + +exit 0; + + +################################# +# S U B R O U T I N E S # +################################# + +#============================================================================= +# Enhance usability by figuring out which build env. we are in +#============================================================================= +sub determine_args() { + + + # Find trexhash program + # but only if needed (i.e. not in collect mode) + if (!$collect) { + my $tmp = `which $hash_prog`; + chomp $tmp; + + if ($tmp eq '') { + print STDOUT "\nWarning: Program trexhash does not exist in path.\n" if $debug; + $hash_prog = "./trexhash"; + + $tmp = `which $hash_prog`; + chomp $tmp; + if ($tmp eq '') { + print STDOUT "\nError: Unable to find trexhash \n"; + exit(127); + } + } + } + + # Verify input values. + if ((!defined $file) && (!defined $dir)) { + if(!($in_sand)) + { + print STDOUT "\nError: No input directory or file provided as input to scan\n"; + exit(127); + } + + # Assume they want sandbox scanned + if($collect) + { + # collect all string files generated by tracepp and merge + $dir = "$sandboxbase/obj/"; + } + else + { + # generate our own string file by pre-compiling all source code + $dir = "$sandboxbase/src/"; + } + print STDOUT "\n-f or -d not found...scanning $dir by default\n\n"; + } + + if (!defined $string_file) + { + if ($in_sand) + { + + # Copy the current string file from backing build into our sandbox + system ("cp $backing/obj/$file_name $sandboxbase/obj/$file_name") + if !(-e "$sandboxbase/obj/$file_name"); + + $string_file = "$sandboxbase/obj/$file_name"; + } + else + { + $string_file = "./$file_name"; + } + print STDOUT "-sf not specified, using $string_file instead...\n\n" if $debug; + + } + + # Try Creating the string file + `touch $string_file`; + + if (! -f $string_file) { + print STDOUT "\nError: File $string_file does not exist. Current directory may not be writable.\n\n"; + help(); + exit(127); + } + + # Make sure sbeStringFile is readable/writeable + system("chmod ugo+rw $string_file"); + +} + +#============================================================================= +# Launch cpp script and grab input from it looking for trace calls. +#============================================================================= +sub launch_cpp_and_parse($$) { + + my ($l_loc, $l_dir) = @_; + + print "Processing file $l_loc\n" if $debug; + my $cmd = "/usr/bin/cpp $INCLUDE -I $l_dir $args $l_loc|"; + print "$cmd\n" if $debug; + open(FH,"$cmd") + or die ("Cannot open $_:$!,stopped"); + + # Read through all lines in the file.. + my $line = ; + while (defined $line) + { + chop $line; # remove EOL + $line =~ s/^\s*//; # remove unneccesary beginning white space. + $line =~ s/\s*$//; # remove unneccesary ending white space. + # Look for lines that are trace macro calls. + #if (/(trace_adal_hash)(\()( *)(".+")(,)(\d)/) + #if ($line =~ /(.*?)(trace_adal_hash)(\()( *)(".+")(,)(\d)\)+(.*\d.*)/) + while($line =~ m/^(.*?)trace_adal_hash\s*\(\s*(("[^"]*"\s*)+),\s*(\d+)\s*\)(.*)$/) + { + my ($prefix, $strings, $salt, $suffix) = ($1, $2, $4, $5); + print STDOUT "$strings $salt\n" if $debug; + $strings =~ s/"\s*$//; # remove trailing " and space + $strings =~ s/^"//; # remove leading " + $strings =~ s/"\s*"//g; + # Check to see if it's contained on a single line, or if we + # have to combine lines to get a complete trace call. + + # Save the macro call so it can be hashed later.. + push (@strings, [$l_loc, $strings, $salt]); + $line = $suffix; # check rest of line for a second trace call + } + my $nextline = ; + last if !defined $nextline; + # if a trace call is spread over multiple lines we have to add the next + # line from the source. the only problem is the definition/declaration + # of trace_adal_hash: we have to ignore that. we catch that by requiring + # a " after the function name. hopefully nobody writes a comment with + # a " after the function declaration ... + if ($line =~ /trace_adal_hash.*"/) { + $line .= $nextline; + } else { + $line = $nextline; + } + } + close(FH); +} + +#============================================================================= +# run cpp on all files in this directory and return the output +#============================================================================= +sub cpp_dir($) { + + my ($l_dir) = @_; + my @dir_entry; + my $l_entry; + + # Open the directory and read all entry names. + opendir ( DH , "$l_dir") + or die ("Cannot open $l_dir: $!, stopped"); + + print STDOUT "Processing directory $l_dir\n" if $debug; + @dir_entry = readdir(DH); + closedir(DH); + + while (@dir_entry) { + $l_entry = shift(@dir_entry); + + if ($l_dir =~ m"/$") { + $l_entry = "$l_dir$l_entry"; + } + else { + $l_entry = "$l_dir/$l_entry"; + } + + # Is the entry a directory? + if (-d $l_entry) { + + if($l_entry =~ m"/?([^/]+)$") + { + # check dir we are going into + print "dir = $1\n" if $debug; + # should we recurse into this directory. + if ($1 =~ m/^(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + cpp_dir($l_entry); + } + else + { + # unable to determine name of dir (no / in filename) + # should we recurse into this directory. + if ($l_entry =~ m/^(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + cpp_dir($l_entry); + } + } + # Is the entry a file? + elsif ((-f $l_entry) && ($l_entry =~ m/\.C$/)) { + # it's a file so + launch_cpp_and_parse($l_entry,$l_dir); + } + else { + # Not a file or directory so ignore it... + } + } +} + +#============================================================================= +# Read in strings from the existing trace string file.... +#============================================================================= +sub read_string_file() { + + my %o_strings; + my ($line) = ""; + my ($l_hash) = ""; + my ($l_str) = ""; + my ($cur_build) = ""; + my ($l_file) = ""; + + + # Make sure we can open each file. + open ( FH , "<$string_file") + or die ("Cannot open $_: $!, stopped"); + + $line = ; + + print "first line in sbeStringFile= $line\n" if $debug; + + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + + print "version = $version\n" if $debug; + + #Always put latest version in file + $line =~ s/^$HEAD_EYE_CATCHER\d/${HEAD_EYE_CATCHER}${HEAD_VER_FLAG}/; + + # Take previous version in file and use it. + $build = $line; + chomp($build); + $line = ; + + while (defined $line) { + chomp $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + else + { + print "Unknown version of stringfile $version\n"; + exit(127); + } + $o_strings{$l_hash} = $l_str . "||" . $l_file; + $line = ; + } + + } + else + { # If there is a file then we are dealing with the first + # version of sbeStringFile so don't look for file name. + if ($debug) { + print "version 0 stringfile detected: $string_file\n"; + } + + # there is a file and it doesn't have a header + $version = 0; + + while (defined $line) { + chomp $line; # remove EOL + ($l_hash,$l_str) = split(/\|\|/, $line); + $o_strings{$l_hash} =$l_str . "||" . "NO FILE"; + $line = ; + } + } + + close(FH); + + #Time to look for a building block string file + if($BB_STRING_FILE ne "" and $string_file ne $BB_STRING_FILE and -f $BB_STRING_FILE) + { + + # Make sure we can open the file. + open ( FH , "<$BB_STRING_FILE") + or die ("Cannot open $_: $!, stopped"); + + $line = ; + + print "first line in BB_StringFile = $line\n" if $debug; + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + + $line = ; + while (defined $line) + { + chop $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + #($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + $o_strings{$l_hash} = $l_str . "||" . $l_file ; + $line = ; + } + } + else + { + print "*** ERROR: BB_StringFile '$BB_STRING_FILE' should always have version!!!\n" + } + + } + else + { + print "$BB_STRING_FILE is not available\n" if $debug; + } + #All files are latest version now. + $version = $HEAD_VER_FLAG; + return %o_strings; +} + +#============================================================================= +# Read in strings from the existing trace string file.... +#============================================================================= +sub collect_files($) { + + my ($l_dir) = @_; + my (@dir_entry); + my ($l_entry) = ""; + + # Open the directory and read all entry names. + opendir ( DH , "$l_dir") + or die ("Cannot open $l_dir: $!, stopped"); + + print STDOUT "Processing directory $l_dir\n" if $debug; + @dir_entry = readdir(DH); + closedir(DH); + + while (@dir_entry) { + $l_entry = shift(@dir_entry); + + if ($l_dir =~ m"/$") { + $l_entry = "$l_dir$l_entry"; + } + else { + $l_entry = "$l_dir/$l_entry"; + } + + # Is the entry a directory? + if (-d $l_entry) { + + # should we recurse into this directory. + if ($l_entry =~ m/\/(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + collect_files($l_entry); + } + # Is the entry a file? + elsif ((-f $l_entry) && ($l_entry =~ m"\.hash$")) { + # it's a file so + assimilate_file($l_entry); + } + else { + # Not a file or directory so ignore it... + } + } + +} + +#============================================================================= +# Read in data from file and add to master one +#============================================================================= +sub assimilate_file($) { + + my ($l_loc) = @_; + + my (%o_strings); + my ($line) = ""; + my ($l_hash) = ""; + my ($l_str) = ""; + my ($l_file) = ""; + + # Make sure we can open each file. + open ( FH , "<$l_loc") + or die ("Cannot open $_: $!, stopped"); + + $line = ; + + print "Assimilate: first line in $l_loc = $line" if $debug; + + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + if ($version eq "1") { + if ($hash_filename_too) { + print "*** ERROR: hash_filename_too (-F) isn't possible with trace version 1\n"; + print " please rebuild all .hash files and global sbeStringFile\n"; + print " version 1 file is '$l_loc'\n"; + exit(127); + } + } elsif ($version ne "2") { + print "Unknown version of stringfile $version\n"; + exit(127); + } + + $line = ; + + + while (defined $line) { + chop $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + my $newstring = $l_str . "||" . $l_file; + if (exists $hash_strings_array{$l_hash}) { + my $hashstr1 = $hash_strings_array{$l_hash}; + my $hashstr2 = $newstring; + if (!$hash_filename_too) { + # hash was made over format string only, remove file name + $hashstr1 =~ s/\|\|.*$//; + $hashstr2 = $l_str; + } + if ($debug) { + print "a_f: compare $hashstr1\n", + " vs. $hashstr2\n"; + } + if ($hashstr1 ne $hashstr2) + { + print "*** ERROR: HASH Collision! (a_f)\n", + " Two different strings have the same hash value ($l_hash)\n", + " String 1: $hash_strings_array{$l_hash}\n", + " String 2: $newstring\n"; + if ($fail_on_collision) { + exit(1); + } + } + } + $hash_strings_array{$l_hash} = $newstring; + $line = ; + } + + } + else + { # If there is a file then we are dealing with the first + # version of sbeStringFile so don't look for file name. + # these files shouldn't be there anymore. we don't check for collisions here + if ($debug) { + print "version 0 stringfile detected: $string_file\n"; + } + + if(defined $line) + { + # there is a file and it doesn't have a header + $version = 0; + } + + while (defined $line) { + chop $line; # remove EOL + ($l_hash,$l_str) = split(/\|\|/, $line); + $hash_strings_array{$l_hash} = $l_str . "||" . "NO FILE"; + $line = ; + } + } + $version = $HEAD_VER_FLAG; + close(FH); +} + +#============================================================================= + +#============================================================================= +sub hash_strings() { + + my ($hash_val, $l_key, $l_hash, %l_hash_strings); + my ($line_feed) = chr(10); + my ($l_file_name) = "NO FILENAME"; + print "\nHashing printf strings.\n\n"; + + foreach my $str (@strings) { + my $printf_string; + $l_file_name = $str->[0]; + $printf_string = $str->[1]; + $l_key = $str->[2]; + print "printf_string = $printf_string\n" if $debug; + $printf_string =~ s/"\s?"//g; #multi line traces will have extra " in them + $printf_string =~ s/`/\\`/g; # excape ' + $printf_string =~ s/\\n/$line_feed/g; # escape \n + if ($hash_filename_too) { + $printf_string .= "||" . $l_file_name; + } + + # call the hasher. + print "$hash_prog \"$printf_string\" $l_key\n" if $debug; + $hash_val = `$hash_prog \"$printf_string\" $l_key`; + if ($?) { + my ($hp_ret, $hp_sig) = ($? >> 8, $? & 127); + if ($hp_sig) { + print "*** ERROR: $hash_prog died with signal $hp_sig\n"; + } elsif ($hp_ret) { + print "*** ERROR: $hash_prog returned the error $hp_ret\n"; + if ($hash_val) { + print " error from $hash_prog:\n$hash_val"; + } + } + exit(1); + } + print "printf_string = $printf_string l_key = $l_key hash val = $hash_val\n" if $debug; + + # undo escaping + $printf_string =~ s/$line_feed/\\n/g; + $printf_string =~ s/\\`/`/g; + + if (exists $l_hash_strings{$hash_val}) + { + # hash val was found before. check if it's the same string + # else we have a hash collision + my $l_tmp = $l_hash_strings{$hash_val}; + if (!$hash_filename_too) { + $l_tmp =~ s/\|\|.*$//; + } + if ($l_tmp ne $printf_string) + { + print "*** ERROR: HASH Collision! (h_s)\n", + " Two different strings have the same hash value ($hash_val)\n", + " String 1: $l_hash_strings{$hash_val}\n", + " String 2: $printf_string (file $l_file_name)\n"; + if ($fail_on_collision) { + exit(1); + } + } + } + # this will overwrite an old string with a new one if a collision occurred + # but we might want to bail out in this case anyway + $printf_string = $printf_string . "||" . $l_file_name; + $l_hash_strings{$hash_val} = $printf_string; + } + return %l_hash_strings; +} +#============================================================================= + +#============================================================================= +sub write_string_file() { + + my (@keys) = (); + my ($l_key) = ""; + + # Combine the contents of the existing string file with the trace calls + # that we have just hashed. + print STDOUT "\nCombining Hash strings...\n\n"; + + @keys = keys(%hash_strings_array); + + foreach $l_key (@keys) { + my $l_tmp = $hash_strings_array{$l_key}; # freshly collected strings + if (exists $string_file_array{$l_key}) + { # hash exists in list from sbeStringFile + my $l_tmp2 = $string_file_array{$l_key}; + if (!$hash_filename_too) { + $l_tmp =~ s/\|\|.*$//; + $l_tmp2 =~ s/\|\|.*$//; + } + + # Check for hash collisions. + if ($l_tmp ne $l_tmp2) + { + print "*** ERROR: HASH Collision! (w_s_f)\n", + " Two different strings have the same hash value ($l_key)\n", + " String 1: $hash_strings_array{$l_key}\n", + " String 2: $string_file_array{$l_key}\n"; + if ($fail_on_collision) { + exit(1); + } + # don't fail, write new one + } + } + if($version > 0) + { + # add/replace the new string to the string_file_array. + $string_file_array{$l_key} = $hash_strings_array{$l_key} + } + else + { + # old version so only write out format string (not file name to) + $string_file_array{$l_key} = $l_tmp; + } + } + + # Write out the updated string file. + print STDOUT "\nWriting updated hash||string file...\n\n"; + + @keys = sort(keys(%string_file_array)); + + open ( FH , ">$string_file") + or die ("Cannot open $_: $!, stopped"); + + if($version > 0) + { + print FH "$build\n"; # only print version if newer then version 0 + } + foreach $l_key (@keys) { + print FH "$l_key||$string_file_array{$l_key}\n"; + } + close FH; +} +#============================================================================= + +#============================================================================= +# Display command invokation help for this program... +#============================================================================= +sub help() { + print << "EOF"; +tracehash.pl - create a trace string file from sources or collect tracepp files +Usage: tracehash.pl [options] + General options: + -h - Print this help text. + -v - Be verbose, tell what's going on (debug output) + Operation modes + -c - Collect StringFiles created by tracepp and merge. + default - Scan source files for trace calls. + +Collect mode: tracehash.pl -c [-vFCS] [-d ] [-s ] + tracehash.pl -c [-vFCS] [-f ] [-s ] + Collect string files created by tracepp (.hash) from directory tree at + or read them from string file and write to file + , adding entries already in this file. + -f - String file to read and write/add to . + -d - Start of directory tree to scan for .hash files. Default = . + -s - File with trace strings (and hashes) to read from and write to + default = ./sbeStringFile + -F - hash is calculated over trace string and source file name, + otherwise without source file name + -C - report an error if a hash collisions occurs + -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) + If tracehash.pl is called in a FipS build sandbox without -d and -f + defaults for the sandbox will be used. + +Scan mode: tracehash.pl [-vFCS] [-d ] [-s ] [ccpopts] + tracehash.pl [-vFCS] [-f ] [-s ] [cppopts] + Scan all files in directory tree or scan file and write + strings to file . Strings already in this file will be merged. + -f - Source file to scan for trace entries. + -d - Source directory to scan for trace entries. + -s - File with trace strings (and hashes) to read from and write to. + default = ./sbeStringFile + -F - hash for string was build from format string + source file name + -C - report an error if hash collisions occur + -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) + All other arguments will be passed verbatim to cpp +EOF +} +#============================================================================= + diff --git a/src/tools/utils/modules/gitUtil.pm b/src/tools/utils/modules/gitUtil.pm new file mode 100644 index 00000000..b94f711c --- /dev/null +++ b/src/tools/utils/modules/gitUtil.pm @@ -0,0 +1,592 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/utils/modules/gitUtil.pm $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +package gitUtil; + +use strict; + +my %globals = {}; + +# Function : gitRoot +# +# @brief : Determine the root of the GIT repository +# +# @return root : Root of GIT repository +# +sub gitRoot +{ + return $globals{git_root} if (defined $globals{git_root}); + + open COMMAND, "git rev-parse --show-toplevel |"; + my $root = ; + close COMMAND; + chomp $root; + + die "Unable to determine git_root" if ($root eq ""); + + $globals{git_root} = $root; + return $root; +} + +#################### Begin Gerrit JSON Utility Subroutines ##################### + +# @note There are perl modules for doing this but they are not installed on +# the pool machines. The parsing for JSON (at least the content from +# the Gerrit server) isn't so bad... + +# Function : jsonParse +# +# @brief : Parse a line of JSON into an hash-object. +# +# @param[in] line : The JSON content. +# +# @return hash : The parsed object. +# +sub jsonParse +{ + my $line = shift; + + die "Invalid JSON format: $line" unless ($line =~ m/^\{.*\}$/); + $line =~ s/^\{(.*)}$/$1/; + + my %object = (); + + while($line ne "") + { + my $key; + my $value; + + ($key, $line) = jsonGetString($line); + $key =~ s/^"(.*)"$/$1/; + + $line =~ s/^://; + if ($line =~ m/^"/) + { + ($value, $line) = jsonGetString($line); + $value =~ s/^"(.*)"$/$1/; + } + elsif ($line =~ m/^{/) + { + ($value, $line) = jsonGetObject($line); + $value = jsonParse($value); + } + elsif ($line =~ m/^\[/) + { + ($value, $line) = jsonGetArray($line); + $value = jsonParseArray($value); + } + else + { + $line =~ s/([^,]*)//; + $value = $1; + } + + $object{$key} = $value; + } + + return \%object; +} + +# Function : jsonGetString +# +# @brief : Utility function for jsonParse that extracts +# the string data in a given object +# +# @param[in] line : The JSON line containing the strings. +# +# @return strings : The parsed strings. +# +sub jsonGetString +{ + my $line = shift; + + $line =~ /("[^"]*")(.*)/; + my $first = $1; + my $second = $2; + + if ($first =~ m/\\"$/) + { + my ($more, $rest) = jsonGetString($second); + return ($first.$more , $rest); + } + else + { + return ($first, $second); + } +} + +# Function : jsonGetObject +# +# @brief : Utility function for jsonParse that extracts +# the nested JSON object data in a given object +# +# @param[in] line : The JSON line containing the object +# +# @return object : The nested object +# +sub jsonGetObject +{ + my $line = shift; + + $line =~ s/^{//; + my $object = "{"; + my $frag = ""; + + my $found_object = 0; + + until ((not $found_object) && ($object =~ m/}$/)) + { + $found_object = 0; + + if ($line =~ m/^\{/) + { + ($frag, $line) = jsonGetObject($line); + $object = $object.$frag; + $found_object = 1; + } + elsif ($line =~ m/^"/) + { + ($frag, $line) = jsonGetString($line); + $object = $object.$frag; + } + elsif ($line =~ m/^\[/) + { + ($frag, $line) = jsonGetArray($line); + $object = $object.$frag; + } + elsif ($line =~ m/^[:,}]/) + { + $line =~ s/^([:,}])//; + $frag = $1; + $object = $object.$frag; + } + else + { + $line =~ s/([^,}]*)//; + $frag = $1; + $object = $object.$frag; + } + } + + return ($object, $line); +} + +# Function : jsonGetArray +# +# @brief : Utility function for jsonParse that extracts +# the array in a given object +# +# @param[in] line : The JSON line containing the array +# +# @return array : The array object +# +sub jsonGetArray +{ + my $line = shift; + + $line =~ s/^\[//; + my $array = "["; + my $frag = ""; + + my $found_array = 0; + + until ((not $found_array) && ($array =~ m/]$/)) + { + $found_array = 0; + + if ($line =~ m/^\[/) + { + ($frag, $line) = jsonGetArray($line); + $array = $array.$frag; + $found_array; + } + elsif ($line =~ m/^\{/) + { + ($frag, $line) = jsonGetObject($line); + $array = $array.$frag; + } + elsif ($line =~ m/^"/) + { + ($frag, $line) = jsonGetString($line); + $array = $array.$frag; + } + elsif ($line =~ m/^[:,\]]/) + { + $line =~ s/^([:,\]])//; + $frag = $1; + $array = $array.$frag; + } + else + { + $line =~ s/([^,]*)//; + $frag = $1; + $array = $array.$frag; + } + } + + return ($array, $line); +} + +# Function : jsonParseArray +# +# @brief : Utility function for jsonParse that parses +# the array object +# +# @param[in] line : The array +# +# @return array : The parsed array object +# +# +sub jsonParseArray +{ + my $line = shift; + + $line =~ s/^\[(.*)\]$/$1/; + + my @array = (); + + while ($line ne "") + { + my $value; + + if ($line =~ m/^"/) + { + ($value, $line) = jsonGetString($line); + $value =~ s/^"(.*)"$/$1/; + } + elsif ($line =~ m/^\{/) + { + ($value, $line) = jsonGetObject($line); + $value = jsonParse($value); + } + elsif ($line =~ m/^\[/) + { + ($value, $line) = jsonGetArray($line); + $value = jsonParseArray($value); + } + else + { + $line =~ s/([^,]*)//; + $value = $1; + } + + push @array, $value; + $line =~ s/^,//; + } + + return \@array; +} + +#################### End Gerrit JSON Utility Subroutines ####################### + +# Function : gerritIsPatch +# +# @brief : Determine if patch identifier is a Gerrit patch or not. +# +# @param[in] i_patch : The patch to make determination about. +# +# @retval flag : true/false (patch is/not a valid ID) +# +sub gerritIsPatch +{ + my $patch = shift; + return 1 if ($patch =~ m/I[0-9a-f]+/); + return 0; +} + +# Function : configFilename +# +# @brief : Create the file that stroes the GIT server details +# +# @return : Location of the config file +# +sub configFilename +{ + return gitRoot()."/.git/gitRelease.config"; +} + +# Function : configInit +# +# @brief : Fetch & write server details to the config file +# +sub configInit +{ + return if (defined $globals{configInit}); + + unless (-e configFilename()) + { + open COMMAND, "git config --list | grep remote.*ssh |"; + my $url = ; + close COMMAND; + chomp $url; + + die "Undefined git-remote 'gerrit'" if ($url eq ""); + + die "Unexpected url found: $url" if (not ($url =~ m/ssh:\/\/.*\/.*/)); + + my $server = $url; + my $project = $url; + + # match first occurance of '/' after ssh:// + # eg: remote.gerrit.url=ssh://hw.gerrit/hw/ppe + # $2 is 'hw.gerrit' + # $3 is 'hw/ppe' + $server =~ s/(.*)ssh:\/\/(.*?)\/(.*)/$2/; + $project =~ s/(.*)ssh:\/\/(.*?)\/(.*)/$3/; + + open(UNUSED, ">".configFilename()) || die; + close UNUSED; + + system("git config --file ".configFilename(). + " --add releaseLevels.server $server"); + system("git config --file ".configFilename(). + " --add releaseLevels.project $project"); + } + $globals{configInit} = 1; +} + +# Function : configProject +# +# @brief : Fetch the project name of the current configured repository +# +# @return : GIT project name +# +sub configProject +{ + return $globals{config_project} if (defined $globals{config_project}); + + configInit(); + + open COMMAND, "git config --file ".configFilename(). + " --get releaseLevels.project |"; + my $project = ; chomp($project); + close COMMAND; + + die "Project config does not exist" if ($project eq ""); + + $globals{config_project} = $project; + + return $project; +} + +# Function : configServer +# +# @brief : Fetch the server name of the current configured repository +# +# @return : GIT server location +# +sub configServer +{ + return $globals{config_server} if (defined $globals{config_server}); + + configInit(); + + + open COMMAND, "git config --file ".configFilename(). + " --get releaseLevels.server |"; + my $server = ; chomp($server); + close COMMAND; + + die "Server config does not exist" if ($server eq ""); + + $globals{config_server} = $server; + return $server; + +} + +# Function : gerritSSHCommand +# +# @brief : Creates a properly formed ssh command based on the server address +# +# @return : The basic ssh command to connect to the server. +# +sub gerritSSHCommand +{ + return $globals{gerrit_ssh_command} + if (defined $globals{gerrit_ssh_command}); + + my $server = configServer(); + my $port = ""; + + if ($server =~ m/.*:.*/) + { + $port = $server; + $server =~ s/(.*):.*/$1/; + $port =~ s/.*:(.*)/$1/; + + $port = "-p $port"; + } + + my $command = "ssh -qx $port $server gerrit"; + + $globals{gerrit_ssh_command} = $command; + return $command; +} + +# Function : gerritQuery +# +# @brief : Performs a gerrit query and parses the resulting JSON. +# +# @param[in] query : The query to perform. +# +# @return item : A list of items from the JSON query. Each item is a +# hash (key-value pair) for the item attributes. +# +sub gerritQuery +{ + my $query = shift; + my @items = (); + + $query = gerritSSHCommand()." query $query --current-patch-set --patch-sets --format=JSON |"; + + open COMMAND, $query; + while (my $line = ) + { + chomp $line; + push @items, jsonParse($line); + } + + return \@items; +} + +# Function : gerritQueryReference +# +# @brief : Retrieves reference for a patch id, patchset number +# +# @param[in] changeId : Change id of the patch +# @param[in] patchNumber : Patch set number +# +# @return reference : The reference string +# +sub gerritQueryReference +{ + my $changeId = shift; + my $patchNumber = shift; + + my $project = configProject(); + + my $query_result = gerritQuery("$changeId project:$project"); + + foreach my $result (@{$query_result}) + { + if ($result->{id} eq $changeId) + { + # If all patchsets queried, search all of them for the commit + foreach my $patchset (@{$result->{patchSets}}) + { + if ($patchNumber eq " ") + { + return $patchset->{currentPatchSet}->{ref}; + } + else + { + if ($patchset->{number} =~ m/$patchNumber/) + { + return $patchset->{ref}; + } + } + } + } + } + die "Cannot find $changeId in $project"; +} + +# Function : gerritQueryCommit +# +# @brief : Retrieves commit for a patch id, patchset number +# +# @param[in] changeId : Change id of the patch +# @param[in] patchNumber : Patch set number +# +# @return commit : The commit string +# +sub gerritQueryCommit +{ + my $changeId = shift; + my $patchNumber = shift; + + my $project = configProject(); + + my $query_result = gerritQuery("$changeId project:$project"); + + foreach my $result (@{$query_result}) + { + if ($result->{id} eq $changeId) + { + # If all patchsets queried, search all of them for the commit + foreach my $patchset (@{$result->{patchSets}}) + { + if ($patchNumber eq "") + { + return $patchset->{currentPatchSet}->{revision}; + } + else + { + if ($patchset->{number} =~ m/$patchNumber/) + { + return $patchset->{revision}; + } + } + } + } + } + die "Cannot find $changeId in $project"; +} + +# Function : patchMergeStatus +# +# @brief : Check if given patch is merged into repository +# +# @param[in] changeId : Change id of the patch +# +# @return mergeStatus : 1 if merged; else 0 +# +sub patchMergeStatus +{ + my $mergeStatus = 1; + + my $changeId = shift; + + my $project = configProject(); + + my $query_result = gerritQuery("$changeId project:$project"); + + foreach my $result (@{$query_result}) + { + if ($result->{id} eq $changeId) + { + if ($result->{status} eq "MERGED" || $result->{status} eq "merged") + { + $mergeStatus = 1; + } + else + { + $mergeStatus = 0; + } + return $mergeStatus; + } + } + die "Cannot find $changeId in $project"; +} diff --git a/src/tools/utils/perl.modules/gitUtil.pm b/src/tools/utils/perl.modules/gitUtil.pm deleted file mode 100644 index bbfd7092..00000000 --- a/src/tools/utils/perl.modules/gitUtil.pm +++ /dev/null @@ -1,592 +0,0 @@ -#!/usr/bin/perl -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/tools/utils/perl.modules/gitUtil.pm $ -# -# OpenPOWER sbe Project -# -# Contributors Listed Below - COPYRIGHT 2016 -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG - -package gitUtil; - -use strict; - -my %globals = {}; - -# Function : gitRoot -# -# @brief : Determine the root of the GIT repository -# -# @return root : Root of GIT repository -# -sub gitRoot -{ - return $globals{git_root} if (defined $globals{git_root}); - - open COMMAND, "git rev-parse --show-toplevel |"; - my $root = ; - close COMMAND; - chomp $root; - - die "Unable to determine git_root" if ($root eq ""); - - $globals{git_root} = $root; - return $root; -} - -#################### Begin Gerrit JSON Utility Subroutines ##################### - -# @note There are perl modules for doing this but they are not installed on -# the pool machines. The parsing for JSON (at least the content from -# the Gerrit server) isn't so bad... - -# Function : jsonParse -# -# @brief : Parse a line of JSON into an hash-object. -# -# @param[in] line : The JSON content. -# -# @return hash : The parsed object. -# -sub jsonParse -{ - my $line = shift; - - die "Invalid JSON format: $line" unless ($line =~ m/^\{.*\}$/); - $line =~ s/^\{(.*)}$/$1/; - - my %object = (); - - while($line ne "") - { - my $key; - my $value; - - ($key, $line) = jsonGetString($line); - $key =~ s/^"(.*)"$/$1/; - - $line =~ s/^://; - if ($line =~ m/^"/) - { - ($value, $line) = jsonGetString($line); - $value =~ s/^"(.*)"$/$1/; - } - elsif ($line =~ m/^{/) - { - ($value, $line) = jsonGetObject($line); - $value = jsonParse($value); - } - elsif ($line =~ m/^\[/) - { - ($value, $line) = jsonGetArray($line); - $value = jsonParseArray($value); - } - else - { - $line =~ s/([^,]*)//; - $value = $1; - } - - $object{$key} = $value; - } - - return \%object; -} - -# Function : jsonGetString -# -# @brief : Utility function for jsonParse that extracts -# the string data in a given object -# -# @param[in] line : The JSON line containing the strings. -# -# @return strings : The parsed strings. -# -sub jsonGetString -{ - my $line = shift; - - $line =~ /("[^"]*")(.*)/; - my $first = $1; - my $second = $2; - - if ($first =~ m/\\"$/) - { - my ($more, $rest) = jsonGetString($second); - return ($first.$more , $rest); - } - else - { - return ($first, $second); - } -} - -# Function : jsonGetObject -# -# @brief : Utility function for jsonParse that extracts -# the nested JSON object data in a given object -# -# @param[in] line : The JSON line containing the object -# -# @return object : The nested object -# -sub jsonGetObject -{ - my $line = shift; - - $line =~ s/^{//; - my $object = "{"; - my $frag = ""; - - my $found_object = 0; - - until ((not $found_object) && ($object =~ m/}$/)) - { - $found_object = 0; - - if ($line =~ m/^\{/) - { - ($frag, $line) = jsonGetObject($line); - $object = $object.$frag; - $found_object = 1; - } - elsif ($line =~ m/^"/) - { - ($frag, $line) = jsonGetString($line); - $object = $object.$frag; - } - elsif ($line =~ m/^\[/) - { - ($frag, $line) = jsonGetArray($line); - $object = $object.$frag; - } - elsif ($line =~ m/^[:,}]/) - { - $line =~ s/^([:,}])//; - $frag = $1; - $object = $object.$frag; - } - else - { - $line =~ s/([^,}]*)//; - $frag = $1; - $object = $object.$frag; - } - } - - return ($object, $line); -} - -# Function : jsonGetArray -# -# @brief : Utility function for jsonParse that extracts -# the array in a given object -# -# @param[in] line : The JSON line containing the array -# -# @return array : The array object -# -sub jsonGetArray -{ - my $line = shift; - - $line =~ s/^\[//; - my $array = "["; - my $frag = ""; - - my $found_array = 0; - - until ((not $found_array) && ($array =~ m/]$/)) - { - $found_array = 0; - - if ($line =~ m/^\[/) - { - ($frag, $line) = jsonGetArray($line); - $array = $array.$frag; - $found_array; - } - elsif ($line =~ m/^\{/) - { - ($frag, $line) = jsonGetObject($line); - $array = $array.$frag; - } - elsif ($line =~ m/^"/) - { - ($frag, $line) = jsonGetString($line); - $array = $array.$frag; - } - elsif ($line =~ m/^[:,\]]/) - { - $line =~ s/^([:,\]])//; - $frag = $1; - $array = $array.$frag; - } - else - { - $line =~ s/([^,]*)//; - $frag = $1; - $array = $array.$frag; - } - } - - return ($array, $line); -} - -# Function : jsonParseArray -# -# @brief : Utility function for jsonParse that parses -# the array object -# -# @param[in] line : The array -# -# @return array : The parsed array object -# -# -sub jsonParseArray -{ - my $line = shift; - - $line =~ s/^\[(.*)\]$/$1/; - - my @array = (); - - while ($line ne "") - { - my $value; - - if ($line =~ m/^"/) - { - ($value, $line) = jsonGetString($line); - $value =~ s/^"(.*)"$/$1/; - } - elsif ($line =~ m/^\{/) - { - ($value, $line) = jsonGetObject($line); - $value = jsonParse($value); - } - elsif ($line =~ m/^\[/) - { - ($value, $line) = jsonGetArray($line); - $value = jsonParseArray($value); - } - else - { - $line =~ s/([^,]*)//; - $value = $1; - } - - push @array, $value; - $line =~ s/^,//; - } - - return \@array; -} - -#################### End Gerrit JSON Utility Subroutines ####################### - -# Function : gerritIsPatch -# -# @brief : Determine if patch identifier is a Gerrit patch or not. -# -# @param[in] i_patch : The patch to make determination about. -# -# @retval flag : true/false (patch is/not a valid ID) -# -sub gerritIsPatch -{ - my $patch = shift; - return 1 if ($patch =~ m/I[0-9a-f]+/); - return 0; -} - -# Function : configFilename -# -# @brief : Create the file that stroes the GIT server details -# -# @return : Location of the config file -# -sub configFilename -{ - return gitRoot()."/.git/gitRelease.config"; -} - -# Function : configInit -# -# @brief : Fetch & write server details to the config file -# -sub configInit -{ - return if (defined $globals{configInit}); - - unless (-e configFilename()) - { - open COMMAND, "git config --list | grep remote.*ssh |"; - my $url = ; - close COMMAND; - chomp $url; - - die "Undefined git-remote 'gerrit'" if ($url eq ""); - - die "Unexpected url found: $url" if (not ($url =~ m/ssh:\/\/.*\/.*/)); - - my $server = $url; - my $project = $url; - - # match first occurance of '/' after ssh:// - # eg: remote.gerrit.url=ssh://hw.gerrit/hw/ppe - # $2 is 'hw.gerrit' - # $3 is 'hw/ppe' - $server =~ s/(.*)ssh:\/\/(.*?)\/(.*)/$2/; - $project =~ s/(.*)ssh:\/\/(.*?)\/(.*)/$3/; - - open(UNUSED, ">".configFilename()) || die; - close UNUSED; - - system("git config --file ".configFilename(). - " --add releaseLevels.server $server"); - system("git config --file ".configFilename(). - " --add releaseLevels.project $project"); - } - $globals{configInit} = 1; -} - -# Function : configProject -# -# @brief : Fetch the project name of the current configured repository -# -# @return : GIT project name -# -sub configProject -{ - return $globals{config_project} if (defined $globals{config_project}); - - configInit(); - - open COMMAND, "git config --file ".configFilename(). - " --get releaseLevels.project |"; - my $project = ; chomp($project); - close COMMAND; - - die "Project config does not exist" if ($project eq ""); - - $globals{config_project} = $project; - - return $project; -} - -# Function : configServer -# -# @brief : Fetch the server name of the current configured repository -# -# @return : GIT server location -# -sub configServer -{ - return $globals{config_server} if (defined $globals{config_server}); - - configInit(); - - - open COMMAND, "git config --file ".configFilename(). - " --get releaseLevels.server |"; - my $server = ; chomp($server); - close COMMAND; - - die "Server config does not exist" if ($server eq ""); - - $globals{config_server} = $server; - return $server; - -} - -# Function : gerritSSHCommand -# -# @brief : Creates a properly formed ssh command based on the server address -# -# @return : The basic ssh command to connect to the server. -# -sub gerritSSHCommand -{ - return $globals{gerrit_ssh_command} - if (defined $globals{gerrit_ssh_command}); - - my $server = configServer(); - my $port = ""; - - if ($server =~ m/.*:.*/) - { - $port = $server; - $server =~ s/(.*):.*/$1/; - $port =~ s/.*:(.*)/$1/; - - $port = "-p $port"; - } - - my $command = "ssh -qx $port $server gerrit"; - - $globals{gerrit_ssh_command} = $command; - return $command; -} - -# Function : gerritQuery -# -# @brief : Performs a gerrit query and parses the resulting JSON. -# -# @param[in] query : The query to perform. -# -# @return item : A list of items from the JSON query. Each item is a -# hash (key-value pair) for the item attributes. -# -sub gerritQuery -{ - my $query = shift; - my @items = (); - - $query = gerritSSHCommand()." query $query --current-patch-set --patch-sets --format=JSON |"; - - open COMMAND, $query; - while (my $line = ) - { - chomp $line; - push @items, jsonParse($line); - } - - return \@items; -} - -# Function : gerritQueryReference -# -# @brief : Retrieves reference for a patch id, patchset number -# -# @param[in] changeId : Change id of the patch -# @param[in] patchNumber : Patch set number -# -# @return reference : The reference string -# -sub gerritQueryReference -{ - my $changeId = shift; - my $patchNumber = shift; - - my $project = configProject(); - - my $query_result = gerritQuery("$changeId project:$project"); - - foreach my $result (@{$query_result}) - { - if ($result->{id} eq $changeId) - { - # If all patchsets queried, search all of them for the commit - foreach my $patchset (@{$result->{patchSets}}) - { - if ($patchNumber eq " ") - { - return $patchset->{currentPatchSet}->{ref}; - } - else - { - if ($patchset->{number} =~ m/$patchNumber/) - { - return $patchset->{ref}; - } - } - } - } - } - die "Cannot find $changeId in $project"; -} - -# Function : gerritQueryCommit -# -# @brief : Retrieves commit for a patch id, patchset number -# -# @param[in] changeId : Change id of the patch -# @param[in] patchNumber : Patch set number -# -# @return commit : The commit string -# -sub gerritQueryCommit -{ - my $changeId = shift; - my $patchNumber = shift; - - my $project = configProject(); - - my $query_result = gerritQuery("$changeId project:$project"); - - foreach my $result (@{$query_result}) - { - if ($result->{id} eq $changeId) - { - # If all patchsets queried, search all of them for the commit - foreach my $patchset (@{$result->{patchSets}}) - { - if ($patchNumber eq "") - { - return $patchset->{currentPatchSet}->{revision}; - } - else - { - if ($patchset->{number} =~ m/$patchNumber/) - { - return $patchset->{revision}; - } - } - } - } - } - die "Cannot find $changeId in $project"; -} - -# Function : patchMergeStatus -# -# @brief : Check if given patch is merged into repository -# -# @param[in] changeId : Change id of the patch -# -# @return mergeStatus : 1 if merged; else 0 -# -sub patchMergeStatus -{ - my $mergeStatus = 1; - - my $changeId = shift; - - my $project = configProject(); - - my $query_result = gerritQuery("$changeId project:$project"); - - foreach my $result (@{$query_result}) - { - if ($result->{id} eq $changeId) - { - if ($result->{status} eq "MERGED" || $result->{status} eq "merged") - { - $mergeStatus = 1; - } - else - { - $mergeStatus = 0; - } - return $mergeStatus; - } - } - die "Cannot find $changeId in $project"; -} diff --git a/src/tools/utils/sbeGitTool.pl b/src/tools/utils/sbeGitTool.pl index 9ffd4b2b..120a906e 100755 --- a/src/tools/utils/sbeGitTool.pl +++ b/src/tools/utils/sbeGitTool.pl @@ -7,6 +7,7 @@ # OpenPOWER sbe Project # # Contributors Listed Below - COPYRIGHT 2016 +# [+] International Business Machines Corp. # # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,7 +26,7 @@ use strict; #use lib "$ENV{'PERLMODULES'}"; -use lib "src/tools/utils/perl.modules"; +use lib "src/tools/utils/modules"; use Getopt::Long qw(:config pass_through); use Data::Dumper; use Cwd; -- cgit v1.2.1