benchmark: detect libteec offset

Add detection of an offset of load-time relocatable libteec for correct
translation of addresses into file name/line numbers.

Acked-by: Joakim Bech <joakim.bech@linaro.org>
Signed-off-by: Igor Opaniuk <igor.opaniuk@linaro.org>
diff --git a/benchmark_aux.c b/benchmark_aux.c
index 222b179..c997403 100644
--- a/benchmark_aux.c
+++ b/benchmark_aux.c
@@ -149,3 +149,47 @@
 	close(devmem);
 	return (hw_addr + offset);
 }
+
+size_t get_library_load_offset(pid_t pid, const char *libname)
+{
+	char path[256];
+	char buf[256];
+	FILE *file;
+	size_t addr = 0;
+	size_t start, end, offset;
+	char flags[4];
+	int len;
+	int len_libname = strlen(libname);
+
+	snprintf(path, sizeof(path), "/proc/%d/smaps", pid);
+
+	file = fopen(path, "rt");
+	if (file == NULL)
+		return 0;
+
+	while (fgets(buf, sizeof(buf), file) != NULL) {
+		len = strlen(buf);
+		if (len > 0 && buf[len-1] == '\n')
+			buf[--len] = '\0';
+
+		if (len <= len_libname || !strstr(buf, libname))
+			continue;
+
+		printf("%s\n", buf);
+		if (sscanf(buf, "%zx-%zx %c%c%c%c %zx", &start, &end,
+			   &flags[0], &flags[1],
+			   &flags[2], &flags[3], &offset) != 7)
+			continue;
+
+		if (flags[0] != 'r' || flags[2] != 'x')
+			continue;
+
+		addr = start - offset;
+		break;
+	}
+
+	fclose(file);
+
+	return addr;
+}
+
diff --git a/benchmark_aux.h b/benchmark_aux.h
index fc612f4..6419263 100644
--- a/benchmark_aux.h
+++ b/benchmark_aux.h
@@ -44,6 +44,7 @@
 void dealloc_argv(int new_argc, char **new_argv);
 
 void *mmap_paddr(intptr_t paddr, uint64_t size);
+size_t get_library_load_offset(pid_t pid, const char *libname);
 
 /* get amount of cores */
 uint32_t get_cores(void);
diff --git a/common.h b/common.h
index a4f3ee9..54cc36c 100644
--- a/common.h
+++ b/common.h
@@ -74,5 +74,6 @@
 #define RING_BADPARM	-1
 #define RING_NODATA		-2
 
+#define LIBTEEC_NAME	"libteec.so"
 #endif /* COMMON.H */
 
diff --git a/main.c b/main.c
index ffbb4a5..a3b4a02 100644
--- a/main.c
+++ b/main.c
@@ -55,7 +55,10 @@
 static sig_atomic_t is_running;
 static yaml_emitter_t emitter;
 
-
+struct consumer_param {
+	pid_t child_pid;
+	char *ts_filepath;
+};
 void sigint_handler(int data)
 {
 	(void)data;
@@ -321,7 +324,10 @@
 	uint32_t cores;
 	struct tee_time_st ts_data;
 	FILE *ts_file;
-	char *tsfile_path = arg;
+	struct consumer_param *prm = (struct consumer_param *)arg;
+	char *tsfile_path = prm->ts_filepath;
+	pid_t child_pid = prm->child_pid;
+	size_t teec_dyn_addr = 0;
 
 	if (!tsfile_path)
 		ERROR_GOTO(exit, "Wrong timestamp file path");
@@ -349,6 +355,18 @@
 					"pc = 0x%" PRIx64 "; system = %s",
 					i, ts_data.cnt, ts_data.addr,
 					bench_str_src(ts_data.src));
+				if (!teec_dyn_addr) {
+					teec_dyn_addr = get_library_load_offset
+						(child_pid,
+						LIBTEEC_NAME);
+					INFO("Libteec load address = %x",
+						teec_dyn_addr);
+				}
+				if (ts_data.src == TEE_BENCH_CLIENT) {
+					DBG("ts_addr = %llx, teec_addr = %x",
+						ts_data.addr, teec_dyn_addr);
+					ts_data.addr -= teec_dyn_addr;
+				}
 				if (!fill_timestamp(i, ts_data.cnt,
 					ts_data.addr,
 					bench_str_src(ts_data.src)))
@@ -389,6 +407,7 @@
 	char *tsfile_path;
 	uint32_t cores;
 	pthread_t consumer_thread;
+	struct consumer_param prm;
 
 	if (argc == 1) {
 		usage(argv[0]);
@@ -432,7 +451,6 @@
 		ERROR_EXIT("Starting origin host application failed.");
 	} else if (pid > 0) {
 		is_running = 1;
-
 		tsfile_path = malloc(strlen(testapp_path) +
 					strlen(TSFILE_NAME_SUFFIX) + 1);
 		if (!tsfile_path)
@@ -445,8 +463,11 @@
 		INFO("Dumping timestamps to %s ...", tsfile_path);
 		print_line();
 
+		prm.child_pid = pid;
+		prm.ts_filepath = tsfile_path;
+
 		if (pthread_create(&consumer_thread, NULL,
-				ts_consumer, tsfile_path)) {
+				ts_consumer, &prm)) {
 			DBG( "Error creating ts consumer thread");
 			ERROR_EXIT("Can't start process of reading timestamps");
 		}