citrun

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

commit 20c42c844382d3f5ec2eb5e82a67d119fbc3e84c
parent b646474ac3b1a658a91df3bfcf8f4ee6f5fac747
Author: Kyle Milz <kyle@getaddrinfo.net>
Date:   Tue, 15 Mar 2016 18:34:08 -0600

runtime: add get metadata message type

- add message type for requesting metadata
- we don't really need to send sizes and filenames every time we request the
  execution counters anyways

Diffstat:
MSCV/Viewer.pm | 37+++++++++++++++++++++++++------------
Mlib/runtime.c | 50++++++++++++++++++++++----------------------------
Mt/runtime_counters_increase.t | 16++++++++--------
Mt/runtime_sanity.t | 24+++++++++++++++++-------
4 files changed, 72 insertions(+), 55 deletions(-)

diff --git a/SCV/Viewer.pm b/SCV/Viewer.pm @@ -27,21 +27,17 @@ sub accept { $self->{client_socket} = $socket->accept(); } -sub request_data { +sub get_metadata { my ($self) = @_; my $client = $self->{client_socket}; $client->syswrite("\x00", 1); - # First thing sent back is total message size and then the total number - # of translation units. - my $buf = read_all($client, 8); - my $msg_size = unpack("Q", $buf); - + # First thing sent is total number of translation units my $buf = read_all($client, 8); my $num_tus = unpack("Q", $buf); - my %tu_data; + my @tus; for (1..$num_tus) { my $buf = read_all($client, 8); my $file_name_sz = unpack("Q", $buf); @@ -51,13 +47,30 @@ sub request_data { $buf = read_all($client, 8); my $num_lines = unpack("Q", $buf); - $buf = read_all($client, 8 * $num_lines); - my @data = unpack("Q$num_lines", $buf); - - $tu_data{$file_name} = \@data ; + push @tus, { filename => $file_name, lines => $num_lines }; } - return \%tu_data; + $self->{tus} = \@tus; + return \@tus; +} + +sub get_execution_data { + my ($self) = @_; + my $client = $self->{client_socket}; + my @tus = @{ $self->{tus} }; + + $client->syswrite("\x01", 1); + + my @data; + for (@tus) { + my $num_lines = $_->{lines}; + + my $buf = read_all($client, 8 * $num_lines); + my @data_tmp = unpack("Q$num_lines", $buf); + + push @data, [@data_tmp]; + } + return \@data; } sub read_all { diff --git a/lib/runtime.c b/lib/runtime.c @@ -10,7 +10,8 @@ /* Entry point into instrumented application */ extern struct scv_node node0; -void walk_nodes(int); +void send_metadata(int); +void send_execution_data(int); void * @@ -37,7 +38,9 @@ control_thread(void *arg) xread(fd, &msg_type, 1); if (msg_type == 0) - walk_nodes(fd); + send_metadata(fd); + else if (msg_type == 1) + send_execution_data(fd); else errx(1, "unknown message type %i", msg_type); } @@ -51,50 +54,41 @@ static void runtime_init() } void -walk_nodes(int fd) +send_metadata(int fd) { size_t file_name_sz; uint64_t num_tus = 0; - uint64_t msg_size = 0; - struct scv_node walk = node0; - /* Find out the total size of data we're going to send */ while (walk.size != 0) { - /* Number of tus is 8 bytes */ - msg_size += sizeof(num_tus); - - /* File name size, 8 bytes */ - msg_size += sizeof(file_name_sz); - /* The file name */ - msg_size += strnlen(walk.file_name, PATH_MAX); - - /* Number of coverage lines */ - msg_size += sizeof(uint64_t); - /* Coverage lines, one 8 byte integer each */ - msg_size += walk.size * sizeof(uint64_t); - - num_tus++; + ++num_tus; walk = *walk.next; } - /* Send total size and total number of translation units */ - xwrite(fd, &msg_size, sizeof(msg_size)); xwrite(fd, &num_tus, sizeof(num_tus)); - /* Reset walk back to the start */ walk = node0; while (walk.size != 0) { - file_name_sz = strnlen(walk.file_name, PATH_MAX); - /* Send file name size and then the file name itself. */ + file_name_sz = strnlen(walk.file_name, PATH_MAX); xwrite(fd, &file_name_sz, sizeof(file_name_sz)); xwrite(fd, walk.file_name, file_name_sz); - /* Send the contents of the coverage buffer */ - xwrite(fd, &walk.size, sizeof(uint64_t)); - xwrite(fd, walk.lines_ptr, walk.size * sizeof(uint64_t)); + /* Send the size of the execution buffers */ + xwrite(fd, &walk.size, sizeof(walk.size)); + + walk = *walk.next; + } +} +void +send_execution_data(int fd) +{ + struct scv_node walk = node0; + + while (walk.size != 0) { + /* Write execution buffer, one 8 byte counter per source line */ + xwrite(fd, walk.lines_ptr, walk.size * sizeof(uint64_t)); walk = *walk.next; } } diff --git a/t/runtime_counters_increase.t b/t/runtime_counters_increase.t @@ -53,17 +53,17 @@ $project->run(45); # Accept the runtime's connection $viewer->accept(); +my $metadata = $viewer->get_metadata(); +is( scalar(@{ $metadata }), 1, "runtime check for a single tu" ); -usleep(100 * 1000); -my $data = $viewer->request_data(); - -my ($file_name, @others) = keys %$data; -like ($file_name, qr/tmp\/.*source_0\.c/, "runtime filename check"); -is( @others, 0, "runtime check for a single tu" ); +my $source_0 = $metadata->[0]; +like ($source_0->{filename}, qr/tmp\/.*source_0\.c/, "runtime filename check"); +is( $source_0->{lines}, 33, "runtime lines count" ); -my @lines = @{ $data->{$file_name} }; -is (scalar(@lines), 33, "runtime lines count"); +usleep(100 * 1000); +my $data = $viewer->get_execution_data(); +my @lines = @{ $data->[0] }; # Do a pretty thorough coverage check is ( $lines[$_], 0, "line $_ check" ) for (0..8); cmp_ok ( $lines[$_], ">", 0, "line $_ check" ) for (9..12); diff --git a/t/runtime_sanity.t b/t/runtime_sanity.t @@ -2,7 +2,7 @@ use strict; use Data::Dumper; use SCV::Project; use SCV::Viewer; -use Test::More tests => 47; +use Test::More tests => 50; use Test::Differences; my $viewer = SCV::Viewer->new(); @@ -66,12 +66,22 @@ $project->compile(); $project->run(45); $viewer->accept(); -my $data = $viewer->request_data(); -like ($_, qr/tmp\/.*source_.*\.c/, "runtime filename check") for (keys %$data); -my ($src_filename_0, $src_filename_1, $src_filename_2) = sort keys %$data; +# Request and check metadata first +my $metadata = $viewer->get_metadata(); -my @lines = @{ $data->{$src_filename_0} }; +my ($source_0, $source_1, $source_2) = @{ $metadata }; +like ($source_0->{filename}, qr/tmp\/.*source_0.c/, "runtime filename check 0") ; +is ($source_0->{lines}, 24, "runtime line count check 0"); +like ($source_1->{filename}, qr/tmp\/.*source_1.c/, "runtime filename check 1") ; +is ($source_1->{lines}, 11, "runtime line count check 1"); +like ($source_2->{filename}, qr/tmp\/.*source_2.c/, "runtime filename check 2") ; +is ($source_2->{lines}, 9, "runtime line count check 2"); + +# Request and check execution data +my $data = $viewer->get_execution_data(); + +my @lines = @{ $data->[0] }; is ( $lines[$_], 0, "src 0 line $_ check" ) for (0..13); is ( $lines[14], 1, "src 0 line 14 check" ); is ( $lines[$_], 0, "src 0 line $_ check" ) for (15..16); @@ -80,12 +90,12 @@ is ( $lines[$_], 0, "src 0 line $_ check" ) for (19..20); is ( $lines[21], 2, "src 0 line 21 check" ); is ( $lines[$_], 0, "src 0 line $_ check" ) for (22..23); -my @lines = @{ $data->{$src_filename_1} }; +my @lines = @{ $data->[1] }; is ( $lines[$_], 0, "src 1 line $_ check" ) for (0..3); cmp_ok ( $lines[$_], ">", 100, "src 1 line $_ check" ) for (4..7); is ( $lines[8], 0, "src 1 line 8 check" ); -my @lines = @{ $data->{$src_filename_2} }; +my @lines = @{ $data->[2] }; is ( $lines[$_], 0, "src 2 line $_ check" ) for (0..8); $project->kill();