diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2013-05-23 19:36:35 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-07-12 09:48:43 -0500 |
commit | b9c5a79eb89e837981f7743569b715923d8b4c75 (patch) | |
tree | ec7df5130219d926eb3d00ff5de453696a726ba4 | |
parent | 1a0daf283888feaf77a2d7152b851498385b4491 (diff) | |
download | talos-hostboot-b9c5a79eb89e837981f7743569b715923d8b4c75.tar.gz talos-hostboot-b9c5a79eb89e837981f7743569b715923d8b4c75.zip |
Eliminate tracepp!
Change-Id: I67a7d626c81b0b90e25057c486d490e6e2b5aede
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/5132
Tested-by: Jenkins Server
Reviewed-by: Zane Shelley <zshelle@us.ibm.com>
Reviewed-by: Brian H. Horton <brianh@linux.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r-- | img/.gitignore | 2 | ||||
-rw-r--r-- | src/build/linker/linker.C | 54 | ||||
-rw-r--r-- | src/build/makefile | 30 | ||||
-rw-r--r-- | src/build/mkrules/cc.env.mk | 8 | ||||
-rw-r--r-- | src/build/mkrules/cc.rules.mk | 17 | ||||
-rw-r--r-- | src/build/mkrules/cflags.env.mk | 3 | ||||
-rw-r--r-- | src/build/mkrules/images.rules.mk | 3 | ||||
-rw-r--r-- | src/build/trace/.gitignore | 1 | ||||
-rw-r--r-- | src/build/trace/makefile | 31 | ||||
-rwxr-xr-x | src/build/trace/trace_parse | 101 | ||||
-rw-r--r-- | src/build/trace/tracehash.c | 907 | ||||
-rwxr-xr-x | src/build/trace/tracepp | 422 | ||||
-rwxr-xr-x | src/build/trace/trexhash | bin | 11316 -> 0 bytes | |||
-rw-r--r-- | src/include/assert.h | 81 | ||||
-rw-r--r-- | src/include/usr/trace/interface.H | 69 | ||||
-rw-r--r-- | src/include/usr/trace/trace.H | 21 | ||||
-rwxr-xr-x | src/usr/diag/prdf/common/framework/service/prdfTargetServices.C | 4 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/pegasus/prdfPlatCenMembuf.C | 2 | ||||
-rw-r--r-- | src/usr/trace/interface.C | 6 | ||||
-rwxr-xr-x | src/usr/vpd/test/cvpdtest.H | 8 |
20 files changed, 1126 insertions, 644 deletions
diff --git a/img/.gitignore b/img/.gitignore index 4c83d78a0..d44c499bb 100644 --- a/img/.gitignore +++ b/img/.gitignore @@ -8,7 +8,7 @@ *.ruhx *.so *.syms -.*.lnkout +.*.lnkout.bz2 hbotStringFile *.toc errlparser diff --git a/src/build/linker/linker.C b/src/build/linker/linker.C index 1a9a88ba3..cebfb31d5 100644 --- a/src/build/linker/linker.C +++ b/src/build/linker/linker.C @@ -1,25 +1,25 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/build/linker/linker.C $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/build/linker/linker.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ /** * @file linker.C Linker to generate the host boot binary images */ @@ -662,7 +662,10 @@ bool Object::read_relocation() // Check weak symbol list for duplicate weak symbols. if (syms[i]->flags & (BSF_WEAK)) { - if (weak_symbols[syms[i]->name]++) + // Need to ignore special trace symbols. + if ((string::npos == + string(syms[i]->name).find("traceData_codeInfo")) + && (weak_symbols[syms[i]->name]++)) { weak_symbols_to_check.insert(syms[i]->name); } @@ -711,6 +714,11 @@ bool Object::read_relocation() cout << "Relocs: " << std::dec << locs << endl; for (int i = 0; i < locs; i++) { + if (loc[i]->howto->name == string("R_PPC64_NONE")) + { + continue; + } + Symbol s; s.name = loc[i]->sym_ptr_ptr[0]->name; diff --git a/src/build/makefile b/src/build/makefile index b138664ca..003c73e88 100644 --- a/src/build/makefile +++ b/src/build/makefile @@ -1,27 +1,27 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. # -# $Source: src/build/makefile $ +# $Source: src/build/makefile $ # -# IBM CONFIDENTIAL +# IBM CONFIDENTIAL # -# COPYRIGHT International Business Machines Corp. 2010 - 2011 +# COPYRIGHT International Business Machines Corp. 2010,2013 # -# p1 +# p1 # -# Object Code Only (OCO) source materials -# Licensed Internal Code Source Materials -# IBM HostBoot Licensed Internal Code +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code # -# The source code for this program is not published or other- -# wise divested of its trade secrets, irrespective of what has -# been deposited with the U.S. Copyright Office. +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. # -# Origin: 30 +# Origin: 30 # -# IBM_PROLOG_END +# IBM_PROLOG_END_TAG ROOTPATH = ../.. -SUBDIRS = linker.d buildpnor.d +SUBDIRS = linker.d buildpnor.d trace.d include ${ROOTPATH}/config.mk diff --git a/src/build/mkrules/cc.env.mk b/src/build/mkrules/cc.env.mk index 8a8024c43..1b36762ac 100644 --- a/src/build/mkrules/cc.env.mk +++ b/src/build/mkrules/cc.env.mk @@ -30,8 +30,8 @@ HOST_PREFIX ?= x86_64-pc-linux-gnu- CC_RAW = $(CROSS_PREFIX)gcc -std=c99 CXX_RAW = $(CROSS_PREFIX)g++ -CC = $(TRACEPP) $(CC_RAW) -CXX = $(TRACEPP) $(CXX_RAW) +CC = $(CC_RAW) +CXX = $(CXX_RAW) LD = $(CROSS_PREFIX)ld OBJDUMP = $(CROSS_PREFIX)objdump @@ -40,3 +40,7 @@ GCOV = $(CROSS_PREFIX)gcov CUSTOM_LINKER_EXE = $(ROOTPATH)/src/build/linker/linker CUSTOM_LINKER = $(HOST_PREFIX)jail $(CUSTOM_LINKER_EXE) +TRACE_HASHER_EXE = $(ROOTPATH)/src/build/trace/tracehash +#TRACE_HASHER = $(TRACE_HASHER_EXE) +TRACE_HASHER = $(HOST_PREFIX)jail $(TRACE_HASHER_EXE) + diff --git a/src/build/mkrules/cc.rules.mk b/src/build/mkrules/cc.rules.mk index 100575095..b837b56a3 100644 --- a/src/build/mkrules/cc.rules.mk +++ b/src/build/mkrules/cc.rules.mk @@ -33,13 +33,18 @@ $(OBJDIR)/%.o : %.C @mkdir -p $(OBJDIR) $(C2) " CXX $(notdir $<)" $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $< \ - -o $@ $(INCFLAGS) -iquote . + -o $@.trace $(INCFLAGS) -iquote . + $(C1)$(TRACE_HASHER) $@ + @rm $@.trace # Compiling *.cc files $(OBJDIR)/%.o : %.cc @mkdir -p $(OBJDIR) $(C2) " CXX $(notdir $<)" - $(C1)$(CXX) -c $(CXXFLAGS) $< -o $@ $(INCFLAGS) -iquote . + $(C1)$(CXX) -c $(CXXFLAGS) $< -o $@.trace $(INCFLAGS) -iquote . + $(C1)$(TRACE_HASHER) $@ + @rm $@.trace + $(OBJDIR)/%.o : %.c @mkdir -p $(OBJDIR) @@ -48,12 +53,14 @@ $(OBJDIR)/%.o : %.c ifndef CC_OVERRIDE $(C2) " CC $(notdir $<)" $(C1)$(CC) -c $(call FLAGS_FILTER, $(CFLAGS), $<) $< \ - -o $@ $(INCFLAGS) -iquote . + -o $@.trace $(INCFLAGS) -iquote . else $(C2) " CXX $(notdir $<)" $(C1)$(CXX) -c $(call FLAGS_FILTER, $(CXXFLAGS), $<) $< \ - -o $@ $(INCFLAGS) -iquote . + -o $@.trace $(INCFLAGS) -iquote . endif + $(C1)$(TRACE_HASHER) $@ + @rm $@.trace $(OBJDIR)/%.o : %.S @mkdir -p $(OBJDIR) @@ -63,7 +70,7 @@ $(OBJDIR)/%.o : %.S ifdef MODULE $(IMGDIR)/lib$(MODULE).so : $(OBJECTS) $(ROOTPATH)/src/module.ld $(MODULE_INIT) $(C2) " LD $(notdir $@)" - $(C1)$(LD) -shared -z now $(LDFLAGS) \ + $(C1)$(LD) -shared -z now -x $(LDFLAGS) \ $(OBJECTS) $(MODULE_INIT) \ -T $(ROOTPATH)/src/module.ld -o $@ endif diff --git a/src/build/mkrules/cflags.env.mk b/src/build/mkrules/cflags.env.mk index 852464c68..1ab9b9a30 100644 --- a/src/build/mkrules/cflags.env.mk +++ b/src/build/mkrules/cflags.env.mk @@ -34,7 +34,8 @@ endif COMMONFLAGS += $(OPT_LEVEL) -nostdlib CFLAGS += $(COMMONFLAGS) -mcpu=power7 -nostdinc -g -mno-vsx -mno-altivec\ - -Wall -Werror -mtraceback=no -pipe + -Wall -Werror -mtraceback=no -pipe \ + -ffunction-sections -fdata-sections ASMFLAGS += $(COMMONFLAGS) -mcpu=power7 CXXFLAGS += $(CFLAGS) -nostdinc++ -fno-rtti -fno-exceptions -Wall LDFLAGS += --nostdlib --sort-common $(COMMONFLAGS) diff --git a/src/build/mkrules/images.rules.mk b/src/build/mkrules/images.rules.mk index 3b8229314..8c23ec23f 100644 --- a/src/build/mkrules/images.rules.mk +++ b/src/build/mkrules/images.rules.mk @@ -31,6 +31,7 @@ IMAGES += $(addsuffix .bin, $(_IMGS)) $(addsuffix .elf, $(_IMGS)) IMAGE_PASS_POST += $(addsuffix .list.bz2, $(_IMGS)) $(addsuffix .syms, $(_IMGS)) CLEAN_TARGETS += $(addsuffix .list.bz2, $(_IMGS)) $(addsuffix .syms, $(_IMGS)) +CLEAN_TARGETS += $(addsuffix .lnkout.bz2, $(addprefix $(IMGDIR)/., $(IMGS))) define ELF_template $$(IMGDIR)/$(1).elf: $$(addprefix $$(OBJDIR)/, $$($(1)_OBJECTS)) \ @@ -51,7 +52,7 @@ $(IMGDIR)/%.bin: $(IMGDIR)/%.elf \ --extended=0x40000 $(IMGDIR)/$*_extended.bin \ $(addprefix $(IMGDIR)/lib, $(addsuffix .so, $($*_EXTENDED_MODULES))) \ $(addprefix $(IMGDIR)/, $($*_DATA_MODULES)) \ - | bzip2 -zc > $(IMGDIR)/.$*.lnkout + | bzip2 -zc > $(IMGDIR)/.$*.lnkout.bz2 $(C1)$(ROOTPATH)/src/build/tools/addimgid $@ $< $(IMGDIR)/%.list.bz2 $(IMGDIR)/%.syms: $(IMGDIR)/%.bin diff --git a/src/build/trace/.gitignore b/src/build/trace/.gitignore new file mode 100644 index 000000000..9da7e6ddf --- /dev/null +++ b/src/build/trace/.gitignore @@ -0,0 +1 @@ +tracehash diff --git a/src/build/trace/makefile b/src/build/trace/makefile new file mode 100644 index 000000000..06c5e8d16 --- /dev/null +++ b/src/build/trace/makefile @@ -0,0 +1,31 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/trace/makefile $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2013 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG +ROOTPATH = ../../.. + +GEN_PASS_BODY += tracehash +CLEAN_TARGETS += tracehash + +include $(ROOTPATH)/config.mk + +tracehash: tracehash.c + $(HOST_PREFIX)gcc -std=c99 -O3 -g $< -o $@ -lbfd diff --git a/src/build/trace/trace_parse b/src/build/trace/trace_parse deleted file mode 100755 index b36dcb68f..000000000 --- a/src/build/trace/trace_parse +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/perl - -use strict; -my $buf; - -my $memory_file = shift; -my $syms_file = "./img/hbicore.syms"; -my $search_path = "./obj/"; - -# Print header. -printf "-------------------------------------------------------------------------------\n"; -printf "%8s %6s %5s %8s %4s %s\n", - "Sec", "Usec", - "PID", "Comp", "Line", - "Entry Data"; -printf "-------------------------------------------------------------------------------\n"; - - - -open MEMORY, $memory_file || die "Cannot open $memory_file"; -binmode MEMORY; - -# Find pointer for trace buffer instance. -my $first_page = hex ((split ",",`grep ",Singleton<TraceBuffer>::instance()::instance" $syms_file`)[1]); - -seek MEMORY, $first_page, 0; -read MEMORY, $buf, 8; -$first_page = unpack "Q>1", $buf; - -# Iterate over all the trace pages. -while (0 != $first_page) -{ - printf "Buffer Page: 0x%08x - ", $first_page; - - # Read page size (in bytes) - seek MEMORY, $first_page + 8, 0; - read MEMORY, $buf, 8; - my $page_size = unpack "Q>1", $buf; - if ($page_size > 4096) { $page_size = 4096; } - printf "%d bytes\n", $page_size; - - while ($page_size) - { - read MEMORY, $buf, 32; - my ($comp, $tid, $len, $hash, $timestamp, $line, $unused) = - unpack "Q>1 S>1 S>1 L>1 Q>1 L>1 L>1", $buf; - - if (0 == $hash) - { - $page_size = 0; - } - else - { - my $hash_string = - `find $search_path -name "*.hash" | xargs grep $hash`; - chomp $hash_string; - my ($unused, $format, $file) = split /\|\|/, $hash_string; - $page_size -= 32; - - # Read extra words. - my @extra_words = (); - while ($len) - { - read MEMORY, $buf, 8; - my $data = unpack "Q>1", $buf; - $len -= 8; - $page_size -= 8; - - push @extra_words, $data; - } - - # Read component string. - if (0 != $comp) - { - my $loc = tell MEMORY; - seek MEMORY, $comp, 0; - $/ = "\0"; - $comp = <MEMORY>; - seek MEMORY, $loc, 0; - } - - # Calculate time in seconds. - my $timesec = int($timestamp / 512000000); - my $timeusec = int(($timestamp - ($timesec * 512000000)) / 512); - - printf "%08d.%06d|%5d|%8s|%4d|$format\n", - $timesec, $timeusec, - $tid, - $comp, - $line, - @extra_words; - } - } - - # Find pointer to next page. - seek MEMORY, $first_page, 0; - read MEMORY, $buf, 8; - $first_page = unpack "Q>1", $buf; -} - -close MEMORY; diff --git a/src/build/trace/tracehash.c b/src/build/trace/tracehash.c new file mode 100644 index 000000000..27bbc9c40 --- /dev/null +++ b/src/build/trace/tracehash.c @@ -0,0 +1,907 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/build/trace/tracehash.c $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/** @file tracehash.c + * + * Usage: 'tracehash foo.o' + * Generates foo.o and foo.o.hash from foo.o.trace. + * + * The original trace strings are compiled into a foo.o.trace and need + * to be extracted and turned into hash numbers. To accomplish this + * we create static structures at the trace call location and use the GCC + * options '-ffunction-sections' and '-fdata-sections' to force these + * structures into their own ELF sections that we can find / remove / update. + * + * This program uses libbfd, which is not very well documented. Some of + * the sequencing of bfd calls were determined by trial and error. The + * intention is that this program supports [ppc|x86]-[32|64]bit, but + * some aspects of BFD / ELF are 'fragile' and may break between compiler + * versions. I have found this is especially true in the interpretation / + * creation of relocation information. + * + * Hostboot also uses 'libbfd' for the custom linker so it is likely that + * any changes needed here (or there) need to be replicated in both. + */ +#define _POSIX_C_SOURCE 200809L +#define _GNU_SOURCE + +#include <bfd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <stdint.h> +#include <unistd.h> +#include <time.h> + +/** @fn bfd_elf_gnu_hash + * + * Hash function built into the BFD library which has decent non-collision + * properties. The trace tools don't care what hash function is used as + * long as it is used consistently. + * + * Alternatively, using a truncated MD5 or SHA hash would likely work as + * well. + */ +unsigned long bfd_elf_gnu_hash(const char*); + +/** @struct traceCodeInfo + * + * Only used for reference as to the file format of the original files. + * See same named structure in trace interface files. + * + * This is the layout of the CODEINFO_SECTION_NAME sections. + */ +struct traceCodeInfo +{ + const char *formatString; + uint32_t hash; +}; + +/** @struct traceParseInfo + * + * Only used for reference as to the file format of the original files. + * See same named structure in trace interface files. + * + * This is the layout of the PARSEINFO_SECTION_NAME sections. + */ +struct traceParseInfo +{ + uint16_t len_string; + uint16_t len_file; + uint32_t padding; + const char string[512]; + const char file[256]; + struct traceCodeInfo* code; +}; + +/** Suffix name of the sections containing traceCodeInfo structs. */ +const char* CODEINFO_SECTION_NAME = "__traceData_codeInfo"; +/** Suffix name of the sections containing traceParseInfo structs. */ +const char* PARSEINFO_SECTION_NAME = "__traceData_parseInfo"; +/** Destination section name for the resulting format strings. */ +const char* FORMATSTRING_SECTION_NAME = ".rodata.str.fsptrace.format"; +/** String to replace with the basename of the source file. */ +const char* TRACEPP_REPLACE_WITH_FILENAME = "TRACEPP_INSERT_FILENAME"; + +/** Macro to verify errors from BFD library. */ +#define CHECK_ERR(i) \ + { \ + if (!(i)) \ + { \ + printf("Error: %s\n", bfd_errmsg(bfd_get_error())); \ + printf("\tLine %d : %s\n", __LINE__, #i); \ + exit(-1); \ + } \ + } + +/** Macro to verify allocations from BFD library. */ +#define CHECK_NONNULL(i) CHECK_ERR(NULL != (i)); + +/** Global pointer to Original / Source symbol table. */ +static asymbol** origsymtab = NULL; +/** Global pointer to Result symbol table. */ +static asymbol** symtab = NULL; + +/** A linked-list of BFD asymbols */ +typedef struct symbol_list +{ + struct symbol_list* next; + asymbol* sym; +} asymbol_list; + +/** Global list of symbols that should be excluded from the result file. */ +asymbol_list* filtered_syms = NULL; + +/** A linked-list of trace hash-string infos. */ +typedef struct hash_string_list +{ + struct hash_string_list* next; + + char* string; //< Original source string. + char* file; //< Original source file. + uint32_t hash; //< Calculated hash value of string. + + // These three are used to create an ELF relocation for the + // format string pointer. + asymbol* fixup_symbol; //< Symbol of traceCodeInfo object. + bfd_vma fixup_offset; //< Offset of traceCodeInfo object in its section. + bfd_vma fixup_data; //< Data to place at 'format' location for reloc. + +} ahash_string_list; + +/** Global linked list of hash-strings. */ +ahash_string_list* hash_strings = NULL; +/** Global count of hash strings. */ +size_t hash_counts = 0; +/** Global pointer to BFD section for format strings from hashes. */ +asection* hash_section = NULL; + +/** A linked-list of resulting format strings. */ +typedef struct format_list +{ + struct format_list* next; + + char* format; //< Reduced format string. + bfd_vma offset; //< Destination offset in the format string section. + +} aformat_list; + +/** Global linked list of format strings. */ +aformat_list* format_strings = NULL; +/** Current size of the format string section. */ +size_t format_offset = 0; +/** Content to place into the format string section. */ +char* format_content = NULL; + +///--------- Forward Declarations ------------------/// +void create_sections(bfd*, asection*, void*); +void copy_relocs(bfd*, asection*, void*); +void copy_content(bfd*, asection*, void*); +char* create_format_string(const char*); +void create_hashstring_section(bfd*); + +size_t filter_symtab(size_t, size_t); +size_t filter_relocs(arelent***, size_t, size_t, const char*); + +void parse_traceinfo(bfd*, asection*); +void parse_traceinfo_sections(bfd*, asection*, void*); + +int check_hash_collision(ahash_string_list*); +void write_hash_file(const char*); +///--------- End Forward Declarations --------------/// + +/** @fn main + */ +int main(int argc, char** argv) +{ + static const char* inFileSuffix = ".trace"; + + char* outFileName = strdup(argv[1]); + + char* inFileName = (char*) malloc(strlen(outFileName) + + strlen(inFileSuffix) + 1); + strcpy(inFileName, outFileName); + strcat(inFileName, inFileSuffix); + + // Open input .o.trace file. + bfd* inFile = bfd_openr(inFileName, NULL); + CHECK_ERR(bfd_check_format(inFile, bfd_object)); + + // Open output .o file. + bfd* outFile = bfd_openw(outFileName, bfd_get_target(inFile)); + CHECK_NONNULL(outFile); + + // Copy header data from .o.trace file. + CHECK_ERR(bfd_set_arch_mach(outFile, bfd_get_arch(inFile), + bfd_get_mach(inFile))); + CHECK_ERR(bfd_set_format(outFile, bfd_get_format(inFile))); + + // Load symbol table from .o.trace file. + size_t symsize = bfd_get_symtab_upper_bound(inFile); + origsymtab = symtab = (asymbol**) malloc(symsize); + size_t symcount = bfd_canonicalize_symtab(inFile, symtab); + + // Copy over other sections to new file. + bfd_map_over_sections(inFile, create_sections, outFile); + // Create hash-string section. + create_hashstring_section(outFile); + + // Copy ELF private header. + CHECK_ERR(bfd_copy_private_header_data(inFile, outFile)); + + // Filter symbol table and add to destination file. + symcount = filter_symtab(symsize, symcount); + bfd_set_symtab(outFile, symtab, symcount); + + // Parse trace info sections and update format-string section size. + bfd_map_over_sections(inFile, parse_traceinfo_sections, outFile); + bfd_set_section_size(outFile, hash_section, format_offset); + + // Copy relocations and content into destination file. + bfd_map_over_sections(inFile, copy_relocs, outFile); + bfd_map_over_sections(inFile, copy_content, outFile); + bfd_set_section_contents(outFile, hash_section, + format_content, 0, format_offset); + + // Write .o.hash file. + write_hash_file(outFileName); + + // Copy additional private BFD data and close file. + CHECK_ERR(bfd_copy_private_bfd_data(inFile, outFile)); + bfd_close(outFile); + + return 0; +} + +/** @fn create_sections + * + * Creates a section in the result file based from the corresponding + * section in the source file. Sections which should not be created in + * the result are skipped. + * + * @param[in] inFile - Source file. + * @param[in] s - Section to create. + * @param[in] param(outFile) - Destination file. + */ +void create_sections(bfd* inFile, asection* s, void* param) +{ + bfd* outFile = (bfd*)param; + + // Clear output-file section reference in the source section. + s->output_section = NULL; + + // Skip traceParseInfo and ELF-groups sections. + if (NULL != strstr(s->name, PARSEINFO_SECTION_NAME)) { return; } + if (bfd_get_section_flags(inFile, s) & SEC_GROUP) { return; } + + // Create result section. + asection* new_s = + bfd_make_section_anyway_with_flags(outFile, s->name, + bfd_get_section_flags(inFile, s)); + CHECK_NONNULL(new_s); + + // Copy section sizes. + new_s->entsize = s->entsize; + size_t section_size = bfd_get_section_size(s); + CHECK_ERR(bfd_set_section_size(outFile, new_s, section_size)); + CHECK_ERR(bfd_set_section_vma(outFile, new_s, bfd_section_vma(inFile, s))); + new_s->lma = s->lma; + + // Copy alignment and private data. + CHECK_ERR(bfd_set_section_alignment(outFile, new_s, + bfd_section_alignment(inFile, s))); + CHECK_ERR(bfd_copy_private_section_data(inFile, s, outFile, new_s)); + + // Hook up output_section reference to source section. + s->output_section = new_s; +} + +/** @fn copy_relocs + * + * Copy relocation information from source section to result section. + * + * @param[in] inFile - Source file. + * @param[in] s - Source section. + * @param[in] param(outFile) - Destination file. + */ +void copy_relocs(bfd* inFile, asection* s, void* param) +{ + bfd* outFile = (bfd*)param; + + // Get destination section and skip if it doesn't exist. + asection* new_s = s->output_section; + if (NULL == new_s) return; + + // Allocate new relocations based on source relocations. + size_t relocsize = bfd_get_reloc_upper_bound(inFile, s); + arelent** relocs = (arelent**) malloc(relocsize); + size_t reloccount = bfd_canonicalize_reloc(inFile, s, relocs, origsymtab); + + // Filter out relocations corresponding to symbols in filtered sections. + reloccount = filter_relocs(&relocs, relocsize, reloccount, + PARSEINFO_SECTION_NAME); + + // If this is a traceCodeInfo section, create new relocations for the + // format strings. + if (NULL != strstr(s->name, CODEINFO_SECTION_NAME)) + { + // Increase number of relocations by number of format strings. + relocs = (arelent**) + realloc(relocs, sizeof(arelent*)*(reloccount + hash_counts)); + + // Search for relocations in this section. + ahash_string_list* list = hash_strings; + while(list != NULL) + { + // Section mismatch, continue to next symbol. + if (list->fixup_symbol->section != s) + { + list = list->next; + continue; + } + + // Find format string corresponding to this symbol. + char* format = create_format_string(list->string); + aformat_list* format_node = format_strings; + while(format_node != NULL) + { + if (0 == strcmp(format, format_node->format)) + { + break; + } + + format_node = format_node->next; + } + assert(format_node != NULL); + + // Create relocation. + relocs[reloccount] = (arelent*) malloc(sizeof(arelent)); + relocs[reloccount]->sym_ptr_ptr = hash_section->symbol_ptr_ptr; + relocs[reloccount]->address = list->fixup_offset; + // 64 and 32 bit relocations are done differently. + // 64 bit has 0 in the destination area and offset in the + // relocation itself. + // 32 bit has offset in the destination area and 0 in the + // relocation itself. + if (bfd_arch_bits_per_address(inFile) == 64) + { + relocs[reloccount]->addend = format_node->offset; + list->fixup_data = 0; + } + else + { + relocs[reloccount]->addend = 0; + list->fixup_data = format_node->offset; + } + relocs[reloccount]->howto = + bfd_reloc_type_lookup(outFile, + (bfd_arch_bits_per_address(inFile) == 64 ? + BFD_RELOC_64 : BFD_RELOC_32) + ); + reloccount++; + + // Increment to next symbol. + list = list->next; + } + + // Turn on relocation flag (in case it wasn't already on). + new_s->flags |= SEC_RELOC; + } + + // Assign relocations to result section. + bfd_set_reloc(outFile, new_s, relocs, reloccount); +} + +/** @fn copy_content + * + * Copies (and possibly updates) content from source to result sections. + * + * Sections containing traceCodeInfo need to be updated with new hash and + * relocation values. + * + * @param[in] inFile - Source file. + * @param[in] s - Source section. + * @param[in] param(outFile) - Destination file. + */ +void copy_content(bfd* inFile, asection* s, void* param) +{ + bfd* outFile = (bfd*) param; + + // Get destination section and skip if it doesn't exist. + asection* new_s = s->output_section; + if (NULL == new_s) return; + + // Skip if destination section doesn't have any contents. + if (!(new_s->flags & SEC_HAS_CONTENTS)) + { + return; + } + + // Read contents from source section. + bfd_byte* contents = NULL; + CHECK_ERR(bfd_get_full_section_contents(inFile, s, &contents)); + size_t content_size = bfd_get_section_size(new_s); + + // Perform fix-ups if this is a traceCodeInfo section. + if (NULL != strstr(s->name, CODEINFO_SECTION_NAME)) + { + int big_endian = bfd_big_endian(inFile); + int sixtyfour = bfd_arch_bits_per_address(inFile) == 64; + ahash_string_list* list = hash_strings; + + // Search hash list for symbols in this section. + while(list != NULL) + { + // Skip if symbol doesn't match. + if (list->fixup_symbol->section != s) + { + list = list->next; + continue; + } + + // Update hash value. + (big_endian ? bfd_putb32 : bfd_putl32) + (list->hash, + &contents[list->fixup_offset + (sixtyfour ? 8 : 4)]); + + // Update fixup location. + (big_endian ? (sixtyfour ? bfd_putb64 : bfd_putb32) : + (sixtyfour ? bfd_putl64 : bfd_putl32)) + (list->fixup_data, &contents[list->fixup_offset]); + + // Increment to next symbol. + list = list->next; + } + } + + // Write section contents into result section. + CHECK_ERR(bfd_set_section_contents(outFile, new_s, contents, 0, + content_size)); + + // Free temporary content buffer. + free(contents); +} + +/** @fn create_format_string + * + * Creates a stripped down format string based on a source string. + * + * @param[in] string - The source string to strip. + * @return Format string allocated with 'malloc'. + */ +char* create_format_string(const char* string) +{ + size_t length = strlen(string) + 1; + + char* result = malloc(length); + memset(result, '\0', length); + + size_t r_pos = 0; // Current position in result string. + + // Iterate through source string looking for format tags. + for(size_t pos = 0; pos < length; pos++) + { + // Skip if not %. + if (string[pos] != '%') continue; + // Skip over %%. + if (string[pos+1] == '%') { pos++; continue; } + + // Found a valid start of a format tag... start in result. + result[r_pos++] = '%'; + + // Search for remainder of format and copy to result. + int done = 0; + do + { + switch(string[pos]) + { + // Length tags. + case 'h': case 'l': case 'L': case 'q': + case 'j': case 'z': case 't': + result[r_pos++] = string[pos++]; + break; + + // Type tags. + case 'd': case 'i': case 'o': case 'u': + case 'x': case 'X': case 'e': case 'E': + case 'f': case 'F': case 'g': case 'G': + case 'a': case 'A': case 'c': case 'C': + case 's': case 'S': case 'p': case 'n': + result[r_pos++] = string[pos]; + done = 1; + break; + + default: + pos++; + } + } while(!done); + } + + return result; +} + +/** @fn create_hashstring_section + * + * Allocate a section for the format strings and add it to the result file. + * + * @param[in] outFile - Result file. + */ +void create_hashstring_section(bfd* outFile) +{ + hash_section = bfd_make_section(outFile, FORMATSTRING_SECTION_NAME); + CHECK_NONNULL(hash_section); + + // Set section flags: + // SEC_ALLOC - VMA Memory needs to be allocated. + // SEC_LOAD - The contents should be loaded into memory. + // SEC_READONLY - Read-only content. + // SEC_HAS_CONTENTS - The section has contents associated with it. + // SEC_MERGE - Duplicate sections (ex. two .o files) should be + // merged together. + // SEC_STRINGS - The section content type is string. + bfd_set_section_flags(outFile, hash_section, + SEC_ALLOC | SEC_LOAD | SEC_READONLY | + SEC_HAS_CONTENTS | SEC_MERGE | SEC_STRINGS); + + // Each entry is 1 byte (a character). + hash_section->entsize = 1; +} + +/** @fn filter_symtab + * + * Filters symbols from the source symtab that should not be placed into + * the result file. + * + * @param[in] symsize - Size of current symbol table. + * @param[in] symcount - Number of current symbols. + * + * @return Number of symbols in new table. + */ +size_t filter_symtab(size_t symsize, size_t symcount) +{ + asymbol** new_table = malloc(symsize+sizeof(asymbol*)); + size_t newcount = 0; + + for(size_t i = 0; i < symcount; i++) + { + // Filter symbols without an output section. + if (NULL == symtab[i]->section->output_section) + { + // If the symbol isn't a section symbol then it is a + // traceParseInfo struct, so create an entry for it on the + // list of filtered_symbols. + if (!(symtab[i]->flags & BSF_SECTION_SYM)) + { + asymbol_list* node = malloc(sizeof(asymbol_list)); + node->next = filtered_syms; + node->sym = symtab[i]; + filtered_syms = node; + } + continue; + } + + // Symbol was not filtered, so copy it to the new table. + new_table[newcount++] = symtab[i]; + } + + // Insert the symbol for the format string section. + new_table[newcount++] = hash_section->symbol; + + symtab = new_table; + return newcount; +} + +/** @fn filter_relocs + * + * Filters relocations from the source table the at should not be placed + * into the result file. + * + * @param[in,out] relocs - Relocation table. + * @param[in] relocsize - Size (in bytes) of relocation table. + * @param[in] reloccount - Number of relocations. + * @param[in] section - Section name suffix/pattern to filter. + */ +size_t filter_relocs(arelent*** relocs, size_t relocsize, + size_t reloccount, const char* section) +{ + arelent** old_table = *relocs; + arelent** new_table = malloc(relocsize); + + size_t newcount = 0; + for(size_t i = 0; i < reloccount; i++) + { + asymbol** symtable = old_table[i]->sym_ptr_ptr; + + // Skip symbols in sections with pattern match. + if (NULL != strstr((*symtable)->section->name, section)) + { + continue; + } + + // Copy non-skipped symbols into result table. + new_table[newcount++] = old_table[i]; + } + + free(old_table); + (*relocs) = new_table; + + return newcount; +} + +/** @fn parse_traceinfo + * + * Parses traceParseInfo sections and extracts the trace information for + * each symbol / section. + * + * @param[in] inFile - Source file. + * @param[in] s - Source section, should be a traceParseInfo section. + */ +void parse_traceinfo(bfd* inFile, asection* s) +{ + // Get contents of the section. + bfd_byte* contents = NULL; + CHECK_ERR(bfd_get_full_section_contents(inFile, s, &contents)); + + int big_endian = bfd_big_endian(inFile); + size_t size = bfd_get_section_size(s); + + // Save a reference to the current position in the hash_strings list. + ahash_string_list* original_hash_strings = hash_strings; + + // Get relocations for the section. + size_t relocsize = bfd_get_reloc_upper_bound(inFile, s); + arelent** relocs = (arelent**) malloc(relocsize); + size_t reloccount = bfd_canonicalize_reloc(inFile, s, + relocs, origsymtab); + + asymbol_list* list = filtered_syms; + while(list != NULL) + { + // Skip symbols in other sections. + if (list->sym->section != s) + { + list = list->next; continue; + } + + // Find offset of the symbol in the section (contents). + size_t pos = list->sym->value; + + // Read the string length. + size_t length_str = + (big_endian ? bfd_getb16 : bfd_getl16)(&contents[pos]); + pos += 2; + + // Read the filename length. + size_t length_file = + (big_endian ? bfd_getb16 : bfd_getl16)(&contents[pos]); + pos += 2; + + // Padding + pos += 4; + + // Create node for string information. + ahash_string_list* new_node = malloc(sizeof(ahash_string_list)); + new_node->next = hash_strings; + + // Copy original filename from contents. + new_node->file = strdup(&contents[pos+length_str]); + + // Copy original string from contents, calculate hash. + char* replace_pos = strstr(&contents[pos], + TRACEPP_REPLACE_WITH_FILENAME); + if (NULL != replace_pos) + { + char* filename = basename(new_node->file); + static const char filesep[] = ": "; + + size_t len_begin = replace_pos - (char*)&contents[pos]; + size_t len_end = strlen(&contents[pos]) - + strlen(TRACEPP_REPLACE_WITH_FILENAME); + size_t length = len_begin + strlen(filename) + len_end + + strlen(filesep) + 1; + new_node->string = malloc(length); + + memcpy(new_node->string, &contents[pos], len_begin); + new_node->string[len_begin] = '\0'; + + strcat(new_node->string, filename); + strcat(new_node->string, filesep); + strcat(new_node->string, &contents[pos + len_begin + + strlen(TRACEPP_REPLACE_WITH_FILENAME)]); + } + else + { + new_node->string = strdup(&contents[pos]); + } + new_node->hash = bfd_elf_gnu_hash(new_node->string); + + // Advance position to (traceCodeInfo*). + pos += length_str + length_file; + + // Search relocations to find the traceCodeInfo symbol. + for (size_t i = 0; i < reloccount; i++) + { + if (relocs[i]->address == pos) + { + // Get the symbol itself. + new_node->fixup_symbol = *(relocs[i]->sym_ptr_ptr); + + // Find offset into the traceCodeInfo's section. + if (big_endian) + { + new_node->fixup_offset = + (bfd_arch_bits_per_address(inFile) == 64 ? + bfd_getb64 : bfd_getb32) + (&contents[relocs[i]->address]); + } + else + { + new_node->fixup_offset = + (bfd_arch_bits_per_address(inFile) == 64 ? + bfd_getl64 : bfd_getl32) + (&contents[relocs[i]->address]); + + } + new_node->fixup_offset += relocs[i]->addend; + } + } + + // Insert string information onto list. + if (check_hash_collision(new_node)) + { + hash_strings = new_node; + hash_counts++; + } + + // Increment to next symbol. + list = list->next; + } + + // Release memory for contents. + free(contents); + + // Create format strings and content blob for CODEINFO_SECTION_NAME. + ahash_string_list* hash_list = hash_strings; + while(hash_list != original_hash_strings) + { + char* format = create_format_string(hash_list->string); + + // Search for existing format string that matches. + aformat_list* format_node = format_strings; + while(format_node != NULL) + { + if (0 == strcmp(format, format_node->format)) + { + break; + } + + format_node = format_node->next; + } + + // If we found a matching format string, it is already created. + if (format_node != NULL) + { + free(format); + } + else // Create it. + { + // Create format string node. + aformat_list* new_node = malloc(sizeof(aformat_list)); + new_node->next = format_strings; + new_node->format = format; + format_strings = new_node; + + // Update position in the format string section. + new_node->offset = format_offset; + format_offset += strlen(new_node->format) + 1; + + // Copy string into section. + format_content = realloc(format_content, format_offset); + strcpy(&format_content[new_node->offset], new_node->format); + } + + // Increment to next item on the format string list. + hash_list = hash_list->next; + } +} + +/** @fn parse_traceinfo_sections + * + * Calls parse_traceinfo on any sections containing traceParseInfo structs. + * + * @param[in] inFile - Source file. + * @param[in] s - Source section. + * @param[in] param(outFile) - Destination file. + */ +void parse_traceinfo_sections(bfd* inFile, asection* s, void* param) +{ + if (NULL != strstr(s->name, PARSEINFO_SECTION_NAME)) + { + parse_traceinfo(inFile, s); + } +} + +/** @fn check_hash_collision + * + * Searches existing trace strings for any hash collisions. + * + * @return 1 - No collision found, 0 - Collision found. + */ +int check_hash_collision(ahash_string_list* node) +{ + ahash_string_list* list = node->next; + + while(list != NULL) + { + if ((list->hash == node->hash) && + (0 != strcmp(list->string, node->string))) + { + printf("Hash collision detected:\n\t%s\n\t%s\n", + list->string, node->string); + return 0; + } + + list = list->next; + } + + return 1; +} + +/** @fn write_hash_file + * + * Writes the FSP_TRACE format hash file for the result .o. + * + * @param[in] file - Filename of output file. + */ +void write_hash_file(const char* file) +{ + // No hashes, then no file to write. + if (NULL == hash_strings) return; + + // Open hash-result file (foo.o.hash). + char* hash_file_name = malloc(strlen(file) + 6); + strcpy(hash_file_name,file); strcat(hash_file_name, ".hash"); + FILE* hash_file = fopen(hash_file_name, "w"); + + // Output header. + time_t t = time(NULL); + char* t_str = ctime(&t); + (*strchr(t_str, '\n')) = '\0'; + + fprintf(hash_file, "#FSP_TRACE_v2|||%s|||BUILD:%s\n", + t_str, + get_current_dir_name()); + + // Iterate through all the strings. + ahash_string_list* list = hash_strings; + while(NULL != list) + { + // Output hash value. + fprintf(hash_file, "%u||", list->hash); + + // Output original string and fix-up special symbols, such as '\n'. + for (size_t i = 0; list->string[i] != '\0'; i++) + { + if (list->string[i] == '\n') + { + fputs("\\n", hash_file); + } + else if (list->string[i] == '\t') + { + fputs("\\t", hash_file); + } + else + { + fputc(list->string[i], hash_file); + } + } + + // Output source file name (ex foo.C). + fprintf(hash_file, "||%s\n", list->file); + + list = list->next; + } + + fclose(hash_file); +} diff --git a/src/build/trace/tracepp b/src/build/trace/tracepp deleted file mode 100755 index bc570aeb8..000000000 --- a/src/build/trace/tracepp +++ /dev/null @@ -1,422 +0,0 @@ -#!/usr/bin/perl -w -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/build/trace/tracepp $ -# -# IBM CONFIDENTIAL -# -# COPYRIGHT International Business Machines Corp. 2011 - 2012 -# -# p1 -# -# Object Code Only (OCO) source materials -# Licensed Internal Code Source Materials -# IBM HostBoot Licensed Internal Code -# -# The source code for this program is not published or other- -# wise divested of its trade secrets, irrespective of what has -# been deposited with the U.S. Copyright Office. -# -# Origin: 30 -# -# IBM_PROLOG_END -use strict; -use File::Basename; - -# *** tracepp - 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_adal_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: -# tracepp $(CC) $(CFLAGS) -o $@ $< -# tracepp 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 -# -# tracepp creates a file "$target.hash" with the trace strings and the hash values. -# -# to enable debug mode set envvar TRACEPPDEBUG 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_adal_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 - -my $debug = 0; -if (exists $ENV{TRACEPPDEBUG}) { - $debug = $ENV{TRACEPPDEBUG}; -} - -my $version = '$Id: tracepp,v 1.8 2007/06/22 13:37:17 fldbuild Exp $'; -$version =~ s/^.*(\d+(\.\d+)+).*$/$1/; -# api/macro version. to #error if macro and tracepp doesn't fit -my $macro_version = '1'; - -sub parse_line($$); -sub get_has($$); - -if (@ARGV == 0 || (@ARGV == 1 && lc($ARGV[0]) eq '-h') ) { - print STDERR "usage: $0 realcompiler compileroptions -o target source\n"; - exit 127; -} -my $realcc = shift @ARGV; -my $cctype = 'c++'; -my $optx_found = 0; - -if ($realcc eq '-d') { - $debug = 1; - $realcc = shift @ARGV; -} - -# wait until -d options is handled before checking $debug -print STDERR "tracepp version $version - API/macro version $macro_version\n" if $debug; - -my $realcpp = $ENV{REALCPP}; -if (!$realcpp) { - print STDERR "cannot find cpp, using \<realcompiler\> -E'\n" if $debug; - $realcpp = "$realcc -E"; -} -print "realcpp is $realcpp\n" if $debug; - -my $opt; -my ($source, $object, @ccopts, @cppopts); -my $source_basename; -my $dodeps = 0; -my $depfile; -my @origargs = @ARGV; -while(defined($opt = shift @ARGV)) { - if ($opt =~ m/^-o(.*)$/) { - if (defined $object) { - print STDERR "two -o options, aborting\n"; - exit 1; - } - if ($1) { - $object = $1; - } else { - $object = shift @ARGV; - } - print "object is now $object\n" if $debug; - } elsif ($opt eq '-c') { - # don't call cpp with -c, this is for the compiler - #push @cppopts, $opt; - push @ccopts, $opt; - print "found -c option\n" if $debug; - } elsif ($opt =~ m/^-l/) { - # cpp doesn't need library arguments - push @ccopts, $opt; - } elsif ($opt =~ m/^-i./) { - # option takes an argument, handle it too - my$optarg = shift @ARGV; - push @ccopts, $opt, $optarg; - push @cppopts, $opt, $optarg; - print "found option '$opt $optarg'\n" if $debug; - } elsif ($opt =~ m/^-[LIxbBVD]$/ || $opt eq '--param' || $opt =~ m/^-M[QT]$/) { - # option takes an argument, handle it too - my $optarg = shift @ARGV; - push @ccopts, $opt, $optarg; - push @cppopts, $opt, $optarg; - print "found option '$opt $optarg'\n" if $debug; - if ($opt eq '-x') { - # option x sets the language - c or c++ - if ($optarg ne 'c' and $optarg ne 'c++') { - print STDERR "cannot process language '$optarg', aborting\n"; - exit 1; - } - $cctype = $optarg; - $optx_found = 1; - } - } elsif ($opt eq '-MD' or $opt eq '-MG') { - # gen deps - $dodeps = 1; - print "found $opt, creating dependencies\n" if $debug; - } elsif ($opt eq '-MF') { - # set dependencies file - $depfile = shift @ARGV; - print "set dependencies file to '$depfile'\n" if $debug; - } elsif ($opt =~ m/^-/) { - # arg starts with - so it's an option - push @ccopts, $opt; - push @cppopts, $opt; - print "found option '$opt'\n" if $debug; - } elsif ($opt =~ m/\.[ao]$/) { - # an object or archive, ignore this but give it to cc - push @ccopts, $opt; - print "found object/archive '$opt'\n" if $debug; - } elsif ($opt =~ m/\.c[cxp]*$/i) { - # the source file(s). we should only get one - if (defined $source) { - print STDERR "don't know to handle two source files, aborting\n"; - exit 1; - } - $source = $opt; - $source_basename = basename($source).": "; - # put the - (for read-from-stdin) where the source file was - # (order is important!) - push @ccopts, "-"; - print "found source file $source\n" if $debug; - } elsif (!-f $opt) { - # option but not a file, an unknown option? - push @ccopts, $opt; - push @cppopts, $opt; - print "found unknown option '$opt'\n" if $debug; - } -} - -if (!defined $source) { - # this might be a call to link a program instead of compile a source (or asm source) - print "NOTME: starting as cc '$realcc @origargs'\n" if $debug; - exec($realcc, @origargs) || die "cannot exec $realcc\n"; -} -if (!defined $object) { - print STDERR "no object file given, default to source name\n" if $debug; - # 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! - my ($n,$d,$s) = fileparse($source, qr{\.[^.]+}); - if ($n && $s) { - $object = "$n.o"; - print "tracpp: guessing object name $object\n", - " from source name $source\n" if $debug; - } else { - print STDERR "Unable to determine Source File Name\n"; - exit 1; - } -} -my $hashtype; -# set value of trace hash according to language -# check source file extension if no explicit -x option given -if (!$optx_found) { - if ($realcc =~ m/g\+\+/) { - print "compiler language: C++ (from compiler name)\n" if $debug; - $cctype = 'c++'; - } else { - if ($source =~ m/\.c$/) { - print "compiler language: C (from source file extension)\n" - if $debug; - $cctype = 'c'; - } else { - print "compiler language: C++ (default)\n" if $debug; - $cctype = 'c++'; - } - } -} else { - print "compiler language: $cctype (from option '-x')\n" if $debug; -} - -if ($cctype eq 'c') { - $hashtype = 'unsigned long'; -} else { - $hashtype = 'trace_hash_val'; -} -# define TRAC_TRACEPP for macros -push(@cppopts,"-DTRAC_TRACEPP -DTRAC_PPVER=$macro_version"); -if ($dodeps) { - if (!defined $depfile) { - if (exists $ENV{DEPENDENCIES_OUTPUT}) { - $depfile = $ENV{DEPENDENCIES_OUTPUT}; - } elsif (exists $ENV{SUNPRO_DEPENDENCIES}) { - $depfile = $ENV{SUNPRO_DEPENDENCIES}; - } else { - ($depfile = $object) =~ s/.o$/.d/; - } - } - push @cppopts, "-MD -MF $depfile"; -} -# start cpp. -print "starting as cpp '$realcpp @cppopts $source -o-'\n" if $debug; -if (!open(CPP, "$realcpp @cppopts $source -o-|")) { - print STDERR "cannot start cpp '$realcpp'\n"; - perror(""); - exit 1; -} -# start cc. manually set language as source file extension not available to cc -my $type_str = ''; -if ($optx_found == 0) { - # no option -x given by caller, set manually - $type_str = "-x $cctype"; -} -print "starting as cc '$realcc $type_str @ccopts -o $object'\n" if $debug; -if (!open(CC, "| $realcc $type_str @ccopts -o $object")) { - print STDERR "cannot start cc '$realcc'\n"; - perror(""); - exit 1; -} - -my $modifiedfile = 0; -my $unmodifiedfile = 0; -if ($debug) { - $modifiedfile = $object . ".debug"; - if (!open(DEBUG, ">$modifiedfile")) { - perror("cannot open file $modifiedfile"); - $modifiedfile = 0; - } else { - print STDERR "writing preprocessed source to $modifiedfile\n"; - } - $unmodifiedfile = $object . ".debug_in"; - if (!open(DEBUGIN, ">$unmodifiedfile")) { - perror("cannot open file $unmodifiedfile"); - $unmodifiedfile = 0; - } else { - print STDERR "writing unprocessed source to $unmodifiedfile\n"; - } -} - -my %hashtab; -my $oldline; -while(defined($oldline = <CPP>)) { - print DEBUGIN $oldline if $unmodifiedfile; - my $newline = parse_line(\%hashtab, $oldline); - #print "oldline = $oldline"; - #print "newline = $newline"; - if (!defined $newline) { - print STDERR "hash error in/with file $source\n"; - exit 1; - } - #print "newline = $newline\n"; - print CC $newline; - print DEBUG $newline if $modifiedfile; -} -if ($modifiedfile) { - close DEBUG; -} -if ($unmodifiedfile) { - close DEBUGIN; -} -if (!close(CPP) || ($? >> 8 != 0)) { - print STDERR "error from cpp\n"; - if ($? & 127) { - print STDERR "cpp got signal ",$? & 127,"\n"; - exit 1; - } elsif ($? >> 8) { - print STDERR "cpp returned ",$? >> 8,"\n"; - exit $? >> 8; - } -} -if (!close(CC) || ($? >> 8 != 0)) { - print STDERR "error from cc\n"; - if ($? & 127) { - print STDERR "cc got signal ",$? & 127,"\n"; - exit 1; - } elsif ($? >> 8) { - print STDERR "cc returned ",$? >> 8,"\n"; - exit $? >> 8; - } -} -if (%hashtab) { - my $stringfile = "$object.hash"; - # open trace string file - if (!open(TRC, ">$stringfile")) { - print STDERR "cannot write trace string file '$stringfile'\n"; - exit 1; - } - print "Writing to file $stringfile\n" if $debug; - - printf TRC "#FSP_TRACE_v2|||%s|||BUILD:%s",scalar(localtime()),`pwd`; - foreach my $key (keys %hashtab) { - if ($hashtab{$key} =~ m/\|\|$source$/) { - # source file name is already part of the string - print TRC "$key||$hashtab{$key}\n"; - } else { - print TRC "$key||$hashtab{$key}||$source\n"; - } - #print TRC "$key||$source||$hashtab{$key}\n"; - } - close TRC; -} else { - print "No trace calls/strings found, not writing hash file\n" if $debug; -} -exit 0; - -sub parse_line($$) -{ - my ($rhash, $line) = @_; - my $format; - my $tmp_strng; - my @format_param = (); - my $data; - my $hash; - my $newline = ''; - my $write_all_suffix; - my ($prefix, $strings, $salt, $suffix); - # trace_adal_hash ( "..." ".." "..." , 2 ) - # regex: PREFIX 'trace_adal_hash' space '(' space STRINGS space ',' space NUMBER space ')' SUFFIX - # STRINGS: '"' .* '"' space? + - while($line =~ m/^(.*?)trace_adal_hash\s*\(\s*((".*?(?<!\\)"\s*)+),\s*(-?\d+)\s*\)(.*)$/) { - ($prefix, $strings, $salt, $suffix) = ($1, $2, $4, $5); - print "\n\nprefix = $prefix\nstrings = $strings\nsalt = $salt\nsuffix = $suffix\n" if $debug; - $strings =~ s/TRACEPP_INSERT_FILENAME/$source_basename/; - $strings =~ s/^"//; - $strings =~ s/"\s*$//; - $strings =~ s/"\s*"//g; - $strings =~ s/\\"/"/g; # remove \ from \" - # is this a trace_adal_write_all call? - if ($prefix =~ m/trace_adal_write_all\s*\(/) { - # yes. replace trace_adal_hash with hash value and reduced format string - (@format_param) = ($strings =~ /(%[#0\- +'I]*\d*(?:\.\d*)?[hlLqjzt]*[diouxXeEfFgGaAcsCSpn])/g); - $format = join(',', @format_param); - # reduced format string will be added after hash value - $write_all_suffix = '," ' . $format . '"'; - if ($salt == -1) { - $salt = scalar(@format_param); - } elsif ($salt != scalar(@format_param)) { - print STDERR ("printf % mismatch in '$line': TRACE says $salt, format says ", - scalar(@format_param), " args\n"); - } - } else { - $write_all_suffix = ''; - } - $hash = get_hash($strings, $salt); - if (exists $$rhash{$hash} && $$rhash{$hash} ne $strings) { - print STDERR "hash collision: two different strings give the same hash value '$hash'\n", - $strings, "\n", $$rhash{$hash}, "\n"; - return undef; - } - $$rhash{$hash} = $strings; - $newline .= $prefix . "(($hashtype) ${hash}U)$write_all_suffix"; - print "changed call: $prefix(($hashtype) ${hash}U)$write_all_suffix...\n" if $debug; - $line = $suffix; - } - $newline .= $line if $line; - $newline .= "\n" unless $newline =~ m/\n$/; - return $newline; -} - -sub get_hash($$) -{ - my ($string, $salt) = @_; - $string =~ s/([\\"])/\\$1/g; - my $hash = `trexhash "$string" $salt`; - chomp $hash; - if ($hash !~ m/^\d+$/) { - print STDERR "trexhash error: $hash\n"; - print STDERR "for call <<trexhash \"$string\" $salt>>\n"; - die "$!"; - } - if (!$hash) { - for (my $i=0; $i < length($string); $i++) { - $hash += ord(substr($string, $i, 1)); - } - } - return $hash; -} diff --git a/src/build/trace/trexhash b/src/build/trace/trexhash Binary files differdeleted file mode 100755 index 9fd2cae77..000000000 --- a/src/build/trace/trexhash +++ /dev/null diff --git a/src/include/assert.h b/src/include/assert.h index fa912b841..84cf1b7b0 100644 --- a/src/include/assert.h +++ b/src/include/assert.h @@ -1,25 +1,25 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/include/assert.h $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/assert.h $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ /** @file assert.h * @brief Define the interfaces for the standard 'assert' macros. * @@ -62,7 +62,7 @@ extern "C" enum AssertBehavior { /** Standard assert, custom trace already done. */ - ASSERT_TRACE_DONE, + ASSERT_TRACE_DONE, /** Standard assert, no custom trace. */ ASSERT_TRACE_NOTDONE, /** Critical / System library assert. */ @@ -80,8 +80,8 @@ enum AssertBehavior * * Current Behaviors: * User-space application - A trace is created, either a custom one - * provided by the caller or a common one - * determined by the trace callback hook, and + * provided by the caller or a common one + * determined by the trace callback hook, and * the asserting task is ended. * * Critical library - A printk is performed, similar in structure to the @@ -99,24 +99,25 @@ void __assert(AssertBehavior i_assertb, int i_line); #define __ASSERT_HAS_TRACE_(_1, _2, ...) _2 #define __ASSERT_HAS_TRACE(...) __ASSERT_HAS_TRACE_(0, ##__VA_ARGS__, 0) -/** - * @brief Macro to do the custom trace if one is provided. +/** + * @brief Macro to do the custom trace if one is provided. * - * This results in larger code size of the caller to call the trace routines + * This results in larger code size of the caller to call the trace routines * but may provide additional debug information. * * The "code" here will be compiled down to nothing or a single trace call by * the optimizer. Search for "Constant Folding" for compiler background. */ -#define __ASSERT_DO_TRACE(expr, ...) { \ - int __assert_unused_var = 0; \ - __assert_unused_var += (__ASSERT_HAS_TRACE(__VA_ARGS__) ? \ +#define __ASSERT_DO_TRACE(expr, ...) \ + { \ + if (__ASSERT_HAS_TRACE(__VA_ARGS__)) \ + { \ TRACFCOMP(TRACE::g_assertTraceBuffer, \ - "Assertion [ " #expr " ] failed; " __VA_ARGS__),1 \ - : 0); \ - } + "Assertion [ " #expr " ] failed; " __VA_ARGS__); \ + } \ + } -/** +/** * @brief Standard assert macro. * * Verfies condition, calls custom trace if provided, and calls internal @@ -183,18 +184,18 @@ void __assert(AssertBehavior i_assertb, int i_line); /** @brief Make an assertion at compile time. If Boolean expression exp * is false, then the compile will stop with an error. Example usage: * CPPASSERT( 2 == sizeof(compId_t)); - * which would be used in front of errl flattening code that assumes - * compId_t is 2 bytes in size. Also with the use of -f short-enums - * compiler switch, one could assert + * which would be used in front of errl flattening code that assumes + * compId_t is 2 bytes in size. Also with the use of -f short-enums + * compiler switch, one could assert * CPPASSERT( 1 == sizeof(errlEventType_t)); - * If the assertion fails, it will be a wakeup call that the errlEventType_t + * If the assertion fails, it will be a wakeup call that the errlEventType_t * enum has grown larger than a byte in size. The mechanism to abend the * compile when the expression is false is to cause a typedef of a char array * that is -1 bytes in size. * * Similar: #define CHECK_SIZE(DATA, EXPECTED_SIZE)\ * typedef char CHECKSIZEVAR[(EXPECTED_SIZE == sizeof(DATA)) -1] - * + * */ #define CPPASSERT(exp) typedef char compile_time_assert_failed[2*((exp)!=0)-1] diff --git a/src/include/usr/trace/interface.H b/src/include/usr/trace/interface.H index 3fc72646d..6b7dee2f7 100644 --- a/src/include/usr/trace/interface.H +++ b/src/include/usr/trace/interface.H @@ -84,6 +84,17 @@ const uint32_t TRACE_FIELD = 0; //Indicates trace is field #define __ALL_HASH(printf_string,num) trace_adal_hash(printf_string,num),printf_string #endif +#define __TRACE_HASH_STRUCTURES(str) \ + static TRACE::traceCodeInfo __traceData_codeInfo \ + __attribute((used)) = \ + { NULL, 1 }; \ + static TRACE::traceParseInfo __traceData_parseInfo \ + __attribute((used)) = \ + { sizeof(TRACE::traceParseInfo::string), \ + sizeof(TRACE::traceParseInfo::file), 0, \ + str, __FILE__, &__traceData_codeInfo } + + /******************************************************************************/ // Macros /******************************************************************************/ @@ -123,11 +134,14 @@ const uint32_t TRACE_FIELD = 0; //Indicates trace is field /* a macro w/o the param number suffix. number is calculated from printf string */ #define TRACDCOMP(des,printf_string,args...) \ + { \ + __TRACE_HASH_STRUCTURES(printf_string); \ TRACE::trace_adal_write_all((des), \ - __ALL_HASH(printf_string,-1), \ + &__traceData_codeInfo, \ __LINE__, \ TRACE_DEBUG, \ - ##args) + ##args); \ + } /** @@ -145,13 +159,17 @@ const uint32_t TRACE_FIELD = 0; //Indicates trace is field * @return void */ -#define TRACDBIN(des,printf_string,address,len) \ +#define TRACDBIN(des,printf_string,address,len) \ + { \ + __TRACE_HASH_STRUCTURES(printf_string); \ TRACE::trace_adal_write_bin((des), \ - __ALL_HASH(printf_string,0), \ - __LINE__, \ - address, \ - len, \ - TRACE_DEBUG) + __traceData_codeInfo.hash, \ + __LINE__, \ + address, \ + len, \ + TRACE_DEBUG); \ + } + #endif /* HOSTBOOT_DEBUG */ #endif /* TRAC_DEBUG_OUT */ @@ -172,11 +190,14 @@ const uint32_t TRACE_FIELD = 0; //Indicates trace is field /* a macro w/o the param number suffix. number is calculated from printf string */ #define TRACFCOMP(des,printf_string,args...) \ + { \ + __TRACE_HASH_STRUCTURES(printf_string); \ TRACE::trace_adal_write_all((des), \ - __ALL_HASH(printf_string,-1), \ + &__traceData_codeInfo, \ __LINE__, \ TRACE_FIELD, \ - ##args) + ##args); \ + } /** @@ -194,13 +215,15 @@ const uint32_t TRACE_FIELD = 0; //Indicates trace is field * @return void */ #define TRACFBIN(des,printf_string,address,len) \ + { \ + __TRACE_HASH_STRUCTURES(printf_string); \ TRACE::trace_adal_write_bin((des), \ - __ALL_HASH(printf_string,0), \ - __LINE__, \ - address, \ - len, \ - TRACE_FIELD) - + __traceData_codeInfo.hash, \ + __LINE__, \ + address, \ + len, \ + TRACE_FIELD); \ + } /** @fn void TRACSCOMP(des, printf_string, args...) @@ -223,11 +246,14 @@ tracepp replaces trace_adal_hash() with hash value and reduced format string /* a macro w/o the param number suffix. number is calculated from printf string */ #define TRACSCOMP(des,printf_string,args...) \ - TRACE::trace_adal_write_all((des), \ - __ALL_HASH(printf_string,-1), \ - __LINE__, \ - TRACE_DEBUG, \ - ##args) + { \ + __TRACE_HASH_STRUCTURES(printf_string); \ + TRACE::trace_adal_write_all((des), \ + &__traceData_codeInfo, \ + __LINE__, \ + TRACE_DEBUG, \ + ##args); \ + } /** @@ -369,6 +395,7 @@ class TracInit }; + } diff --git a/src/include/usr/trace/trace.H b/src/include/usr/trace/trace.H index 7db581dd3..ffbf3a5cb 100644 --- a/src/include/usr/trace/trace.H +++ b/src/include/usr/trace/trace.H @@ -61,6 +61,21 @@ namespace TRACE { class ComponentDesc; // Forward declaration. + struct traceCodeInfo + { + const char* format; + trace_hash_val hash; + } __attribute__((packed)); + + struct traceParseInfo + { + uint16_t len_string; + uint16_t len_file; + uint32_t __padding; + const char string[512]; + const char file[256]; + traceCodeInfo* code; + }; /** @brief Buffer type that a component is directed to. */ enum BUFFER_TYPES @@ -97,16 +112,14 @@ namespace TRACE * name of this function as is. * * @param [in,out] io_td Trace descriptor of buffer to write to. - * @param [in] i_hash Descriptive string hash value - * @param [in] i_fmt Formatting string + * @param [in] i_info Info struct for the hash and format string. * @param [in] i_line Line number trace was done at * @param [in] i_type Type of trace (TRACE_DEBUG, TRACE_FIELD) * * @return void */ void trace_adal_write_all(ComponentDesc *io_td, - const trace_hash_val i_hash, - const char * i_fmt, + const traceCodeInfo* i_info, const uint32_t i_line, const uint32_t i_type, ...); diff --git a/src/usr/diag/prdf/common/framework/service/prdfTargetServices.C b/src/usr/diag/prdf/common/framework/service/prdfTargetServices.C index 0365d8807..f0341d830 100755 --- a/src/usr/diag/prdf/common/framework/service/prdfTargetServices.C +++ b/src/usr/diag/prdf/common/framework/service/prdfTargetServices.C @@ -832,7 +832,9 @@ uint32_t getTargetPosition( TARGETING::TargetHandle_t i_target ) { uint16_t tmpPos = 0; if ( !i_target->tryGetAttr<ATTR_POSITION>(tmpPos) ) + { PRDF_ERR( PRDF_FUNC"Failed to get ATTR_POSITION" ); + } else o_pos = (uint32_t)tmpPos; break; @@ -852,7 +854,9 @@ uint32_t getTargetPosition( TARGETING::TargetHandle_t i_target ) { uint8_t tmpPos = 0; if ( !i_target->tryGetAttr<ATTR_CHIP_UNIT>(tmpPos) ) + { PRDF_ERR( PRDF_FUNC"Failed to get ATTR_CHIP_UNIT" ); + } else o_pos = (uint32_t)tmpPos; break; diff --git a/src/usr/diag/prdf/plat/pegasus/prdfPlatCenMembuf.C b/src/usr/diag/prdf/plat/pegasus/prdfPlatCenMembuf.C index 108c7f28d..3109c3f10 100644 --- a/src/usr/diag/prdf/plat/pegasus/prdfPlatCenMembuf.C +++ b/src/usr/diag/prdf/plat/pegasus/prdfPlatCenMembuf.C @@ -49,7 +49,7 @@ namespace Membuf #define PLUGIN_UNEXPECTED_ATTN( FUNC ) \ int32_t FUNC( ExtensibleChip * i_membChip, STEP_CODE_DATA_STRUCT & i_sc ) \ { \ - PRDF_ERR( "["FUNC"] Unexpected attention in Hostboot: HUID=0x%08x", \ + PRDF_ERR( "["#FUNC"] Unexpected attention in Hostboot: HUID=0x%08x", \ i_membChip->GetId() ); \ CalloutUtil::defaultError( i_sc ); \ return SUCCESS; \ diff --git a/src/usr/trace/interface.C b/src/usr/trace/interface.C index ba9eb765c..5ca18db37 100644 --- a/src/usr/trace/interface.C +++ b/src/usr/trace/interface.C @@ -69,15 +69,15 @@ namespace TRACE } void trace_adal_write_all(ComponentDesc * io_td, - const trace_hash_val i_hash, - const char * i_fmt, + const traceCodeInfo* i_info, const uint32_t i_line, const uint32_t i_type, ...) { va_list args; va_start(args, i_type); - Singleton<Service>::instance().writeEntry(io_td, i_hash, i_fmt, + Singleton<Service>::instance().writeEntry(io_td, + i_info->hash, i_info->format, i_line, i_type, args); va_end(args); diff --git a/src/usr/vpd/test/cvpdtest.H b/src/usr/vpd/test/cvpdtest.H index 0f8865169..957a328ef 100755 --- a/src/usr/vpd/test/cvpdtest.H +++ b/src/usr/vpd/test/cvpdtest.H @@ -267,7 +267,7 @@ class CVPDTest: public CxxTest::TestSuite // first figure out how big the keyword is cmds++; - size_t theSize = 0; + size_t theSize = 0; err = deviceRead( theTarget, testData, theSize, @@ -328,7 +328,7 @@ class CVPDTest: public CxxTest::TestSuite errlCommit( err, VPD_COMP_ID ); continue; - } + } // verify the data got written cmds++; @@ -379,7 +379,7 @@ class CVPDTest: public CxxTest::TestSuite VPD_COMP_ID ); continue; } - + } while( 0 ); if( NULL != testData ) @@ -402,7 +402,7 @@ class CVPDTest: public CxxTest::TestSuite if( cmds == 0 ) { - TS_FAIL(x"testCvpdWrite - No tests ran, something is wrong..."); + TS_FAIL("testCvpdWrite - No tests ran, something is wrong..."); } TRACFCOMP( g_trac_vpd, |