citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

commit e345b2c0c83f618033c4821fc853f8269505b056
parent bd4f2ed2015c10f06eac77434383d22273da7b06
Author: kyle <kyle@getaddrinfo.net>
Date:   Wed,  9 Mar 2016 19:38:45 -0700

start using newly minted tu chaining instrumentation

- now we instrument every primary source file with a node for itself that is
  linked to the next primary source file
- sometimes another primary source file comes along and replaces the previous
  definition of its own node with the real deal
- if no next source file is processed then the application happily links because
  theres no unresolved dependencies

Diffstat:
MSCV/Project.pm | 20++++++++++++++------
Ainclude/scv_global.h | 7+++++++
Minstrument/instrumenter.cpp | 31+++++++++----------------------
Mruntime/Makefile | 2+-
Druntime/libruntime.so | 0
Mruntime/runtime.c | 48+++++++++++++++++++++++++++---------------------
At/multiple_sources.t | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 113 insertions(+), 50 deletions(-)

diff --git a/SCV/Project.pm b/SCV/Project.pm @@ -12,25 +12,33 @@ sub new { # Make new temporary directory, clean it up at exit $self->{tmp_dir} = tempdir( CLEANUP => 1 ); + $self->{src_files} = []; return $self; } sub add_src { my ($self, $source) = @_; + my $num_src_files = scalar(@{ $self->{src_files} }); + + # Create temporary file name + my $src_name = "source_$num_src_files.c"; # Write source code to temp directory - open( my $src_fh, ">", "$self->{tmp_dir}/source.c" ); + open( my $src_fh, ">", "$self->{tmp_dir}/$src_name" ); syswrite( $src_fh, $source ); close( $src_fh ); + + push @{ $self->{src_files} }, $src_name; } sub compile { my ($self) = @_; my $tmp_dir = $self->{tmp_dir}; + my $src_files = join(" ", @{ $self->{src_files} }); my $makefile = <<EOF; BIN = program -SRCS = source.c +SRCS = $src_files OBJS = \$(SRCS:c=o) \$(BIN): \$(OBJS) @@ -46,9 +54,9 @@ EOF $ENV{PATH} = "$ENV{SCV_PATH}:$ENV{PATH}"; # Link in the runtime - $ENV{CFLAGS} = "-pthread"; - # $ENV{LDLIBS} = "-Lruntime -lruntime -pthread"; - # $ENV{LD_LIBRARY_PATH} = "runtime"; + $ENV{CFLAGS} = "-pthread -I/home/kyle/src/scv/include"; + $ENV{LDLIBS} = "-L/home/kyle/src/scv/runtime -lruntime -pthread"; + $ENV{LD_LIBRARY_PATH} = "runtime"; my $ret = system( "make -C $tmp_dir" ); die "make failed: $ret\n" if ($ret); @@ -57,7 +65,7 @@ EOF sub instrumented_src { my ($self) = @_; - open( my $inst_fh, "<", "$self->{tmp_dir}/inst/source.c" ); + open( my $inst_fh, "<", "$self->{tmp_dir}/inst/source_0.c" ); my $inst_src; while (my $line = <$inst_fh>) { $inst_src .= $line; diff --git a/include/scv_global.h b/include/scv_global.h @@ -0,0 +1,7 @@ +struct scv_node { + unsigned int *lines_ptr; + unsigned int size; + const char *file_name; + struct scv_node *next; + /* unsigned int not_end; */ +}; diff --git a/instrument/instrumenter.cpp b/instrument/instrumenter.cpp @@ -134,16 +134,9 @@ get_src_number() std::string src_number_filename(cwd); src_number_filename.append("/SRC_NUMBER"); - std::cerr << "src num file is " << src_number_filename << std::endl; - std::fstream src_number_file; - if (access(src_number_filename.c_str(), F_OK) == -1) { - // SRC_NUMBER does not exist - std::cerr << "SRC_NUMBER does not exist" << std::endl; - std::cerr << "creating with contents '0'" << std::endl; - - // Create SRC_NUMBER + // SRC_NUMBER does not exist, create it src_number_file.open(src_number_filename, std::fstream::out); src_number_file << 0; src_number_file.close(); @@ -157,9 +150,7 @@ get_src_number() unsigned int src_num = 0; src_number_file >> src_num; - ++src_num; - std::cerr << "src num is " << src_num << std::endl; // Write the new source number src_number_file.seekg(0); @@ -180,30 +171,26 @@ MyFrontendAction::EndSourceFileAction() SourceLocation start = sm.getLocForStartOfFile(main_fid); std::string file_name = getCurrentFile(); - unsigned int src_number = get_src_number(); + unsigned int tu_number = get_src_number(); std::stringstream ss; // Add declarations for coverage buffers int file_bytes = sm.getFileIDSize(main_fid); ss << "#include <scv_global.h>" << std::endl; + // Define storage for coverage data ss << "static unsigned int lines[" << file_bytes << "];" << std::endl; - if (src_number != 0) { - unsigned int prev_src_number = src_number - 1; - ss << "extern struct scv_node node" << prev_src_number << ";" << std::endl; - } + // Always declare this. The next TU will overwrite this or there won't + // be a next TU. + ss << "struct scv_node node" << tu_number + 1 << ";" << std::endl; - ss << "struct scv_node node" << src_number << " = {" << std::endl + // Define this translation units main book keeping data structure + ss << "struct scv_node node" << tu_number << " = {" << std::endl << " .lines_ptr = lines," << std::endl << " .size = " << file_bytes << "," << std::endl << " .file_name = \"" << file_name << "\"," << std::endl; - if (src_number != 0) { - unsigned int prev_src_number = src_number - 1; - ss << " .next = &node" << prev_src_number << "," << std::endl; - } else { - ss << " .next = 0," << std::endl; - } + ss << " .next = &node" << tu_number + 1 << "," << std::endl; ss << "};" << std::endl; TheRewriter.InsertTextAfter(start, ss.str()); diff --git a/runtime/Makefile b/runtime/Makefile @@ -2,7 +2,7 @@ error_SCV_PATH .endif -CFLAGS += -fPIC -pthread +CFLAGS += -fPIC -pthread -I../include LIB = libruntime.so SRCS = runtime.c OBJS = $(SRCS:c=o) diff --git a/runtime/libruntime.so b/runtime/libruntime.so Binary files differ. diff --git a/runtime/runtime.c b/runtime/runtime.c @@ -5,19 +5,36 @@ #include <sys/socket.h> // AF_UNIX #include <sys/un.h> // sockaddr_un +#include <scv_global.h> -/* guaranteed to exist at link time because of instrumentation */ -extern unsigned int lines[]; -extern int size; -extern const char file_name[]; +/* Entry point into an instrumented application */ +extern struct scv_node node0; + +void * +walk_nodes(void *arg) +{ + int i; + + printf("%s: alive", __func__); + + struct scv_node *temp = &node0; + while (temp) { + printf("filename = %s\n", temp->file_name); + printf("size = %u\n", temp->size); + for (i = 0; i < temp->size; i++) { + printf(" ln %i = %u\n", i, temp->lines_ptr[i]); + } + temp = temp->next; + } + + printf("%s: done", __func__); +} void * control_thread(void *arg) { int fd; - int i, set; - - printf("%s: file '%s' (%i bytes)\n", __func__, file_name, size); + int i; fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) @@ -28,22 +45,12 @@ control_thread(void *arg) addr.sun_family = AF_UNIX; strncpy(addr.sun_path, "socket", sizeof(addr.sun_path) - 1); - printf("%s: initialized\n", __func__); + return; + // fprintf(stderr, "%s: initialized\n", __func__); while (1) { if (connect(fd, (struct sockaddr *)&addr, sizeof(addr))) - warn("connect"); - - set = 0; - for (i = 0; i < size; i++) - if (lines[i] == 1) { - set++; - lines[i] = 0; - } - - printf("%i lines set\n", set); - - sleep(1); + err(1, "connect"); } } @@ -51,6 +58,5 @@ __attribute__((constructor)) static void runtime_init() { pthread_t tid; - pthread_create(&tid, NULL, control_thread, NULL); } diff --git a/t/multiple_sources.t b/t/multiple_sources.t @@ -0,0 +1,55 @@ +use strict; +use SCV::Project; +use Test::More tests => 2; +use Test::Differences; + +my $project = SCV::Project->new(); +unified_diff; + +$project->add_src(<<EOF +void second_func(); + +int +main(void) +{ + second_func(); + return 0; +} +EOF +); + +$project->add_src(<<EOF +void third_func(); + +void +second_func(void) +{ + third_func(); + return; +} +EOF +); + +$project->add_src(<<EOF +void +third_func(void) +{ + return; +} +EOF +); + +$project->compile(); + +my $tmp_dir = $project->get_tmpdir(); + +my $inst_src_good = <<EOF; +EOF + +my $inst_src = $project->instrumented_src(); +ok( $inst_src ); + +#eq_or_diff $inst_src, $inst_src_good, "instrumented source comparison"; + +my ($ret, $err) = $project->run(); +is($ret, 0, "instrumented program check return code");