about summary refs log tree commit diff
path: root/qemu_mode/libcompcov
diff options
context:
space:
mode:
Diffstat (limited to 'qemu_mode/libcompcov')
-rw-r--r--qemu_mode/libcompcov/Makefile8
-rw-r--r--qemu_mode/libcompcov/README.md (renamed from qemu_mode/libcompcov/README.compcov)16
-rw-r--r--qemu_mode/libcompcov/compcovtest.cc32
-rw-r--r--qemu_mode/libcompcov/libcompcov.so.c213
-rw-r--r--qemu_mode/libcompcov/pmparser.h434
5 files changed, 412 insertions, 291 deletions
diff --git a/qemu_mode/libcompcov/Makefile b/qemu_mode/libcompcov/Makefile
index c984588b..d078ae06 100644
--- a/qemu_mode/libcompcov/Makefile
+++ b/qemu_mode/libcompcov/Makefile
@@ -18,25 +18,25 @@ HELPER_PATH  = $(PREFIX)/lib/afl
 
 VERSION     = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
 
-CFLAGS      ?= -O3 -funroll-loops
+CFLAGS      ?= -O3 -funroll-loops -I ../../include/
 CFLAGS      += -Wall -Wno-unused-result -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
 LDFLAGS     += -ldl
 
 all: libcompcov.so compcovtest
 
 libcompcov.so: libcompcov.so.c ../../config.h
-	$(CC) $(CFLAGS) -shared -fPIC $< -o $@ $(LDFLAGS)
+	$(CC) $(CFLAGS) -shared -fPIC $< -o ../../$@ $(LDFLAGS)
 
 .NOTPARALLEL: clean
 
 clean:
 	rm -f *.o *.so *~ a.out core core.[1-9][0-9]*
-	rm -f libcompcov.so compcovtest
+	rm -f ../../libcompcov.so compcovtest
 
 compcovtest:	compcovtest.cc
 	$(CXX) $< -o $@ 
 
 install: all
-	install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH)
+	install -m 755 ../../libcompcov.so $${DESTDIR}$(HELPER_PATH)
 	install -m 644 README.compcov $${DESTDIR}$(HELPER_PATH)
 
diff --git a/qemu_mode/libcompcov/README.compcov b/qemu_mode/libcompcov/README.md
index 2a4a0ee5..5aaa3dd8 100644
--- a/qemu_mode/libcompcov/README.compcov
+++ b/qemu_mode/libcompcov/README.md
@@ -1,10 +1,8 @@
-================================================================
-strcmp() / memcmp() CompareCoverage library for AFLplusplus-QEMU
-================================================================
+# strcmp() / memcmp() CompareCoverage library for afl++ QEMU
 
   Written by Andrea Fioraldi <andreafioraldi@gmail.com>
 
-This Linux-only companion library allows you to instrument strcmp(), memcmp(),
+This Linux-only companion library allows you to instrument `strcmp()`, `memcmp()`,
 and related functions to log the CompareCoverage of these libcalls.
 
 Use this with caution. While this can speedup a lot the bypass of hard
@@ -18,14 +16,20 @@ For optimized binaries this is an issue, those functions are often inlined
 and this module is not capable to log the coverage in this case.
 
 If you have the source code of the fuzzing target you should nto use this
-library and QEMU but build ot with afl-clang-fast and the laf-intel options.
+library and QEMU but build it with afl-clang-fast and the laf-intel options.
 
 To use this library make sure to preload it with AFL_PRELOAD.
 
+```
   export AFL_PRELOAD=/path/to/libcompcov.so
-  export AFL_QEMU_COMPCOV=1
+  export AFL_COMPCOV_LEVEL=1
   
   afl-fuzz -Q -i input -o output <your options> -- <target args>
+```
+
+The AFL_COMPCOV_LEVEL tells to QEMU and libcompcov how to log comaprisons.
+Level 1 logs just comparison with immediates / read-only memory and level 2
+logs all the comparisons.
 
 The library make use of https://github.com/ouadev/proc_maps_parser and so it is
 Linux specific. However this is not a strict dependency, other UNIX operating
diff --git a/qemu_mode/libcompcov/compcovtest.cc b/qemu_mode/libcompcov/compcovtest.cc
index fd1fda00..171e4526 100644
--- a/qemu_mode/libcompcov/compcovtest.cc
+++ b/qemu_mode/libcompcov/compcovtest.cc
@@ -3,13 +3,13 @@
 // Author: Mateusz Jurczyk (mjurczyk@google.com)

 //

 // Copyright 2019 Google LLC

-// 

+//

 // 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

-// 

+//

 // https://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.

@@ -17,7 +17,8 @@
 // limitations under the License.

 //

 

-// solution: echo -ne 'The quick brown fox jumps over the lazy dog\xbe\xba\xfe\xca\xbe\xba\xfe\xca\xde\xc0\xad\xde\xef\xbe' | ./compcovtest

+// solution: echo -ne 'The quick brown fox jumps over the lazy

+// dog\xbe\xba\xfe\xca\xbe\xba\xfe\xca\xde\xc0\xad\xde\xef\xbe' | ./compcovtest

 

 #include <cstdint>

 #include <cstdio>

@@ -25,39 +26,40 @@
 #include <cstring>

 

 int main() {

-  char buffer[44] = { /* zero padding */ };

+
+  char buffer[44] = {/* zero padding */};

   fread(buffer, 1, sizeof(buffer) - 1, stdin);

 

   if (memcmp(&buffer[0], "The quick brown fox ", 20) != 0 ||

       strncmp(&buffer[20], "jumps over ", 11) != 0 ||

       strcmp(&buffer[31], "the lazy dog") != 0) {

+
     return 1;

+
   }

 

   uint64_t x = 0;

   fread(&x, sizeof(x), 1, stdin);

-  if (x != 0xCAFEBABECAFEBABE) {

-    return 2;

-  }

+  if (x != 0xCAFEBABECAFEBABE) { return 2; }

 

   uint32_t y = 0;

   fread(&y, sizeof(y), 1, stdin);

-  if (y != 0xDEADC0DE) {

-    return 3;

-  }

+  if (y != 0xDEADC0DE) { return 3; }

 

   uint16_t z = 0;

   fread(&z, sizeof(z), 1, stdin);

 

   switch (z) {

-    case 0xBEEF:

-      break;

+
+    case 0xBEEF: break;

 

-    default:

-      return 4;

+    default: return 4;

+
   }

 

   printf("Puzzle solved, congrats!\n");

   abort();

   return 0;

+
 }

+
diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c
index 582230db..dd9e2773 100644
--- a/qemu_mode/libcompcov/libcompcov.so.c
+++ b/qemu_mode/libcompcov/libcompcov.so.c
@@ -5,7 +5,7 @@
 
    Written and maintained by Andrea Fioraldi <andreafioraldi@gmail.com>
 
-   Copyright 2019 Andrea Fioraldi. All rights reserved.
+   Copyright 2019 AFLplusplus Project. All rights reserved.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -27,23 +27,24 @@
 #include <sys/types.h>
 #include <sys/shm.h>
 
-#include "../../types.h"
-#include "../../config.h"
+#include "types.h"
+#include "config.h"
 
 #include "pmparser.h"
 
 #ifndef __linux__
-#  error "Sorry, this library is Linux-specific for now!"
-#endif /* !__linux__ */
+#error "Sorry, this library is Linux-specific for now!"
+#endif                                                        /* !__linux__ */
 
 /* Change this value to tune the compare coverage */
 
 #define MAX_CMP_LENGTH 32
 
-static void *__compcov_code_start,
-            *__compcov_code_end;
+static void *__compcov_code_start, *__compcov_code_end;
 
-static u8 *__compcov_afl_map;
+static u8* __compcov_afl_map;
+
+static u32 __compcov_level;
 
 static int (*__libc_strcmp)(const char*, const char*);
 static int (*__libc_strncmp)(const char*, const char*, size_t);
@@ -53,27 +54,54 @@ static int (*__libc_memcmp)(const void*, const void*, size_t);
 
 static int debug_fd = -1;
 
+#define MAX_MAPPINGS 1024
+
+static struct mapping { void *st, *en; } __compcov_ro[MAX_MAPPINGS];
+
+static u32 __compcov_ro_cnt;
+
+/* Check an address against the list of read-only mappings. */
+
+static u8 __compcov_is_ro(const void* ptr) {
+
+  u32 i;
+
+  for (i = 0; i < __compcov_ro_cnt; i++)
+    if (ptr >= __compcov_ro[i].st && ptr <= __compcov_ro[i].en) return 1;
+
+  return 0;
+
+}
+
+static size_t __strlen2(const char* s1, const char* s2, size_t max_length) {
 
-static size_t __strlen2(const char *s1, const char *s2, size_t max_length) {
   // from https://github.com/googleprojectzero/CompareCoverage
-  
+
   size_t len = 0;
-  for (; len < max_length && s1[len] != '\0' && s2[len] != '\0'; len++) { }
+  for (; len < max_length && s1[len] != '\0' && s2[len] != '\0'; len++) {}
   return len;
+
 }
 
 /* Identify the binary boundaries in the memory mapping */
 
 static void __compcov_load(void) {
-  
+
   __libc_strcmp = dlsym(RTLD_NEXT, "strcmp");
   __libc_strncmp = dlsym(RTLD_NEXT, "strncmp");
   __libc_strcasecmp = dlsym(RTLD_NEXT, "strcasecmp");
   __libc_strncasecmp = dlsym(RTLD_NEXT, "strncasecmp");
   __libc_memcmp = dlsym(RTLD_NEXT, "memcmp");
-  
-  char *id_str = getenv(SHM_ENV_VAR);
-  int shm_id;
+
+  if (getenv("AFL_QEMU_COMPCOV")) { __compcov_level = 1; }
+  if (getenv("AFL_COMPCOV_LEVEL")) {
+
+    __compcov_level = atoi(getenv("AFL_COMPCOV_LEVEL"));
+
+  }
+
+  char* id_str = getenv(SHM_ENV_VAR);
+  int   shm_id;
 
   if (id_str) {
 
@@ -81,55 +109,72 @@ static void __compcov_load(void) {
     __compcov_afl_map = shmat(shm_id, NULL, 0);
 
     if (__compcov_afl_map == (void*)-1) exit(1);
+
   } else {
-  
+
     __compcov_afl_map = calloc(1, MAP_SIZE);
+
   }
 
   if (getenv("AFL_INST_LIBS")) {
-  
+
     __compcov_code_start = (void*)0;
     __compcov_code_end = (void*)-1;
     return;
+
   }
 
   char* bin_name = getenv("AFL_COMPCOV_BINNAME");
 
   procmaps_iterator* maps = pmparser_parse(-1);
-  procmaps_struct* maps_tmp = NULL;
+  procmaps_struct*   maps_tmp = NULL;
 
   while ((maps_tmp = pmparser_next(maps)) != NULL) {
-  
+
     /* If AFL_COMPCOV_BINNAME is not set pick the first executable segment */
     if (!bin_name || strstr(maps_tmp->pathname, bin_name) != NULL) {
-    
+
       if (maps_tmp->is_x) {
-        if (!__compcov_code_start)
-            __compcov_code_start = maps_tmp->addr_start;
-        if (!__compcov_code_end)
-            __compcov_code_end = maps_tmp->addr_end;
+
+        if (!__compcov_code_start) __compcov_code_start = maps_tmp->addr_start;
+        if (!__compcov_code_end) __compcov_code_end = maps_tmp->addr_end;
+
       }
+
     }
+
+    if ((maps_tmp->is_w && !maps_tmp->is_r) || __compcov_ro_cnt == MAX_MAPPINGS)
+      continue;
+
+    __compcov_ro[__compcov_ro_cnt].st = maps_tmp->addr_start;
+    __compcov_ro[__compcov_ro_cnt].en = maps_tmp->addr_end;
+
   }
 
   pmparser_free(maps);
-}
 
+}
 
 static void __compcov_trace(u64 cur_loc, const u8* v0, const u8* v1, size_t n) {
 
   size_t i;
-  
+
   if (debug_fd != 1) {
+
     char debugbuf[4096];
-    snprintf(debugbuf, sizeof(debugbuf), "0x%llx %s %s %lu\n", cur_loc, v0 == NULL ? "(null)" : (char*)v0, v1 == NULL ? "(null)" : (char*)v1, n);
+    snprintf(debugbuf, sizeof(debugbuf), "0x%llx %s %s %lu\n", cur_loc,
+             v0 == NULL ? "(null)" : (char*)v0,
+             v1 == NULL ? "(null)" : (char*)v1, n);
     write(debug_fd, debugbuf, strlen(debugbuf));
+
   }
-  
+
   for (i = 0; i < n && v0[i] == v1[i]; ++i) {
-  
-    __compcov_afl_map[cur_loc +i]++;
+
+    __compcov_afl_map[cur_loc + i]++;
+
   }
+
 }
 
 /* Check an address against the list of read-only mappings. */
@@ -137,8 +182,8 @@ static void __compcov_trace(u64 cur_loc, const u8* v0, const u8* v1, size_t n) {
 static u8 __compcov_is_in_bound(const void* ptr) {
 
   return ptr >= __compcov_code_start && ptr < __compcov_code_end;
-}
 
+}
 
 /* Replacements for strcmp(), memcmp(), and so on. Note that these will be used
    only if the target is compiled with -fno-builtins and linked dynamically. */
@@ -148,122 +193,145 @@ static u8 __compcov_is_in_bound(const void* ptr) {
 int strcmp(const char* str1, const char* str2) {
 
   void* retaddr = __builtin_return_address(0);
-  
-  if (__compcov_is_in_bound(retaddr)) {
 
-    size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH +1);
-    
+  if (__compcov_is_in_bound(retaddr) &&
+      !(__compcov_level < 2 && !__compcov_is_ro(str1) &&
+        !__compcov_is_ro(str2))) {
+
+    size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH + 1);
+
     if (n <= MAX_CMP_LENGTH) {
-    
+
       u64 cur_loc = (u64)retaddr;
-      cur_loc  = (cur_loc >> 4) ^ (cur_loc << 8);
+      cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
       cur_loc &= MAP_SIZE - 1;
-      
+
       __compcov_trace(cur_loc, str1, str2, n);
+
     }
+
   }
 
   return __libc_strcmp(str1, str2);
-}
 
+}
 
 #undef strncmp
 
 int strncmp(const char* str1, const char* str2, size_t len) {
 
   void* retaddr = __builtin_return_address(0);
-  
-  if (__compcov_is_in_bound(retaddr)) {
 
-    size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH +1);
+  if (__compcov_is_in_bound(retaddr) &&
+      !(__compcov_level < 2 && !__compcov_is_ro(str1) &&
+        !__compcov_is_ro(str2))) {
+
+    size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH + 1);
     n = MIN(n, len);
-    
+
     if (n <= MAX_CMP_LENGTH) {
-    
+
       u64 cur_loc = (u64)retaddr;
-      cur_loc  = (cur_loc >> 4) ^ (cur_loc << 8);
+      cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
       cur_loc &= MAP_SIZE - 1;
-      
+
       __compcov_trace(cur_loc, str1, str2, n);
+
     }
+
   }
-  
+
   return __libc_strncmp(str1, str2, len);
-}
 
+}
 
 #undef strcasecmp
 
 int strcasecmp(const char* str1, const char* str2) {
 
   void* retaddr = __builtin_return_address(0);
-  
-  if (__compcov_is_in_bound(retaddr)) {
+
+  if (__compcov_is_in_bound(retaddr) &&
+      !(__compcov_level < 2 && !__compcov_is_ro(str1) &&
+        !__compcov_is_ro(str2))) {
+
     /* Fallback to strcmp, maybe improve in future */
 
-    size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH +1);
-    
+    size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH + 1);
+
     if (n <= MAX_CMP_LENGTH) {
-    
+
       u64 cur_loc = (u64)retaddr;
-      cur_loc  = (cur_loc >> 4) ^ (cur_loc << 8);
+      cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
       cur_loc &= MAP_SIZE - 1;
-      
+
       __compcov_trace(cur_loc, str1, str2, n);
+
     }
+
   }
 
   return __libc_strcasecmp(str1, str2);
-}
 
+}
 
 #undef strncasecmp
 
 int strncasecmp(const char* str1, const char* str2, size_t len) {
 
   void* retaddr = __builtin_return_address(0);
-  
-  if (__compcov_is_in_bound(retaddr)) {
+
+  if (__compcov_is_in_bound(retaddr) &&
+      !(__compcov_level < 2 && !__compcov_is_ro(str1) &&
+        !__compcov_is_ro(str2))) {
+
     /* Fallback to strncmp, maybe improve in future */
 
-    size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH +1);
+    size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH + 1);
     n = MIN(n, len);
-    
+
     if (n <= MAX_CMP_LENGTH) {
-    
+
       u64 cur_loc = (u64)retaddr;
-      cur_loc  = (cur_loc >> 4) ^ (cur_loc << 8);
+      cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
       cur_loc &= MAP_SIZE - 1;
-      
+
       __compcov_trace(cur_loc, str1, str2, n);
+
     }
+
   }
 
   return __libc_strncasecmp(str1, str2, len);
-}
 
+}
 
 #undef memcmp
 
 int memcmp(const void* mem1, const void* mem2, size_t len) {
 
   void* retaddr = __builtin_return_address(0);
-  
-  if (__compcov_is_in_bound(retaddr)) {
+
+  if (__compcov_is_in_bound(retaddr) &&
+      !(__compcov_level < 2 && !__compcov_is_ro(mem1) &&
+        !__compcov_is_ro(mem2))) {
 
     size_t n = len;
-    
+
     if (n <= MAX_CMP_LENGTH) {
-    
+
       u64 cur_loc = (u64)retaddr;
-      cur_loc  = (cur_loc >> 4) ^ (cur_loc << 8);
+      cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
       cur_loc &= MAP_SIZE - 1;
-      
+
       __compcov_trace(cur_loc, mem1, mem2, n);
+
     }
+
   }
 
   return __libc_memcmp(mem1, mem2, len);
+
 }
 
 /* Init code to open init the library. */
@@ -271,9 +339,10 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
 __attribute__((constructor)) void __compcov_init(void) {
 
   if (getenv("AFL_QEMU_COMPCOV_DEBUG") != NULL)
-    debug_fd = open("compcov.debug", O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
+    debug_fd =
+        open("compcov.debug", O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
 
   __compcov_load();
-}
 
+}
 
diff --git a/qemu_mode/libcompcov/pmparser.h b/qemu_mode/libcompcov/pmparser.h
index 34d0cd50..e7fcf187 100644
--- a/qemu_mode/libcompcov/pmparser.h
+++ b/qemu_mode/libcompcov/pmparser.h
@@ -24,43 +24,49 @@ implied warranty.
 #include <errno.h>
 #include <linux/limits.h>
 
-//maximum line length in a procmaps file
-#define PROCMAPS_LINE_MAX_LENGTH  (PATH_MAX + 100) 
+// maximum line length in a procmaps file
+#define PROCMAPS_LINE_MAX_LENGTH (PATH_MAX + 100)
 /**
  * procmaps_struct
  * @desc hold all the information about an area in the process's  VM
  */
-typedef struct procmaps_struct{
-	void* addr_start; 	//< start address of the area
-	void* addr_end; 	//< end address
-	unsigned long length; //< size of the range
-
-	char perm[5];		//< permissions rwxp
-	short is_r;			//< rewrote of perm with short flags
-	short is_w;
-	short is_x;
-	short is_p;
-
-	long offset;	//< offset
-	char dev[12];	//< dev major:minor
-	int inode;		//< inode of the file that backs the area
-
-	char pathname[600];		//< the path of the file that backs the area
-	//chained list
-	struct procmaps_struct* next;		//<handler of the chinaed list
+typedef struct procmaps_struct {
+
+  void*         addr_start;  //< start address of the area
+  void*         addr_end;    //< end address
+  unsigned long length;      //< size of the range
+
+  char  perm[5];  //< permissions rwxp
+  short is_r;     //< rewrote of perm with short flags
+  short is_w;
+  short is_x;
+  short is_p;
+
+  long offset;   //< offset
+  char dev[12];  //< dev major:minor
+  int  inode;    //< inode of the file that backs the area
+
+  char pathname[600];  //< the path of the file that backs the area
+  // chained list
+  struct procmaps_struct* next;  //<handler of the chinaed list
+
 } procmaps_struct;
 
 /**
  * procmaps_iterator
  * @desc holds iterating information
  */
-typedef struct procmaps_iterator{
-	procmaps_struct* head;
-	procmaps_struct* current;
+typedef struct procmaps_iterator {
+
+  procmaps_struct* head;
+  procmaps_struct* current;
+
 } procmaps_iterator;
+
 /**
  * pmparser_parse
- * @param pid the process id whose memory map to be parser. the current process if pid<0
+ * @param pid the process id whose memory map to be parser. the current process
+ * if pid<0
  * @return an iterator over all the nodes
  */
 procmaps_iterator* pmparser_parse(int pid);
@@ -83,198 +89,238 @@ void pmparser_free(procmaps_iterator* p_procmaps_it);
  * _pmparser_split_line
  * @description internal usage
  */
-void _pmparser_split_line(char*buf,char*addr1,char*addr2,char*perm, char* offset, char* device,char*inode,char* pathname);
+void _pmparser_split_line(char* buf, char* addr1, char* addr2, char* perm,
+                          char* offset, char* device, char* inode,
+                          char* pathname);
 
 /**
  * pmparser_print
  * @param map the head of the list
  * @order the order of the area to print, -1 to print everything
  */
-void pmparser_print(procmaps_struct* map,int order);
-
+void pmparser_print(procmaps_struct* map, int order);
 
 /**
  * gobal variables
  */
-//procmaps_struct* g_last_head=NULL;
-//procmaps_struct* g_current=NULL;
-
-
-procmaps_iterator* pmparser_parse(int pid){
-	procmaps_iterator* maps_it = malloc(sizeof(procmaps_iterator));
-	char maps_path[500];
-	if(pid>=0 ){
-		sprintf(maps_path,"/proc/%d/maps",pid);
-	}else{
-		sprintf(maps_path,"/proc/self/maps");
-	}
-	FILE* file=fopen(maps_path,"r");
-	if(!file){
-		fprintf(stderr,"pmparser : cannot open the memory maps, %s\n",strerror(errno));
-		return NULL;
-	}
-	int ind=0;char buf[PROCMAPS_LINE_MAX_LENGTH];
-	//int c;
-	procmaps_struct* list_maps=NULL;
-	procmaps_struct* tmp;
-	procmaps_struct* current_node=list_maps;
-	char addr1[20],addr2[20], perm[8], offset[20], dev[10],inode[30],pathname[PATH_MAX];
-	while( !feof(file) ){
-		fgets(buf,PROCMAPS_LINE_MAX_LENGTH,file);
-		//allocate a node
-		tmp=(procmaps_struct*)malloc(sizeof(procmaps_struct));
-		//fill the node
-		_pmparser_split_line(buf,addr1,addr2,perm,offset, dev,inode,pathname);
-		//printf("#%s",buf);
-		//printf("%s-%s %s %s %s %s\t%s\n",addr1,addr2,perm,offset,dev,inode,pathname);
-		//addr_start & addr_end
-		//unsigned long l_addr_start;
-		sscanf(addr1,"%lx",(long unsigned *)&tmp->addr_start );
-		sscanf(addr2,"%lx",(long unsigned *)&tmp->addr_end );
-		//size
-		tmp->length=(unsigned long)(tmp->addr_end-tmp->addr_start);
-		//perm
-		strcpy(tmp->perm,perm);
-		tmp->is_r=(perm[0]=='r');
-		tmp->is_w=(perm[1]=='w');
-		tmp->is_x=(perm[2]=='x');
-		tmp->is_p=(perm[3]=='p');
-
-		//offset
-		sscanf(offset,"%lx",&tmp->offset );
-		//device
-		strcpy(tmp->dev,dev);
-		//inode
-		tmp->inode=atoi(inode);
-		//pathname
-		strcpy(tmp->pathname,pathname);
-		tmp->next=NULL;
-		//attach the node
-		if(ind==0){
-			list_maps=tmp;
-			list_maps->next=NULL;
-			current_node=list_maps;
-		}
-		current_node->next=tmp;
-		current_node=tmp;
-		ind++;
-		//printf("%s",buf);
-	}
-
-	//close file
-	fclose(file);
-
-
-	//g_last_head=list_maps;
-	maps_it->head = list_maps;
-	maps_it->current =  list_maps;
-	return maps_it;
+// procmaps_struct* g_last_head=NULL;
+// procmaps_struct* g_current=NULL;
+
+procmaps_iterator* pmparser_parse(int pid) {
+
+  procmaps_iterator* maps_it = malloc(sizeof(procmaps_iterator));
+  char               maps_path[500];
+  if (pid >= 0) {
+
+    sprintf(maps_path, "/proc/%d/maps", pid);
+
+  } else {
+
+    sprintf(maps_path, "/proc/self/maps");
+
+  }
+
+  FILE* file = fopen(maps_path, "r");
+  if (!file) {
+
+    fprintf(stderr, "pmparser : cannot open the memory maps, %s\n",
+            strerror(errno));
+    return NULL;
+
+  }
+
+  int  ind = 0;
+  char buf[PROCMAPS_LINE_MAX_LENGTH];
+  // int c;
+  procmaps_struct* list_maps = NULL;
+  procmaps_struct* tmp;
+  procmaps_struct* current_node = list_maps;
+  char addr1[20], addr2[20], perm[8], offset[20], dev[10], inode[30],
+      pathname[PATH_MAX];
+  while (!feof(file)) {
+
+    fgets(buf, PROCMAPS_LINE_MAX_LENGTH, file);
+    // allocate a node
+    tmp = (procmaps_struct*)malloc(sizeof(procmaps_struct));
+    // fill the node
+    _pmparser_split_line(buf, addr1, addr2, perm, offset, dev, inode, pathname);
+    // printf("#%s",buf);
+    // printf("%s-%s %s %s %s
+    // %s\t%s\n",addr1,addr2,perm,offset,dev,inode,pathname); addr_start &
+    // addr_end unsigned long l_addr_start;
+    sscanf(addr1, "%lx", (long unsigned*)&tmp->addr_start);
+    sscanf(addr2, "%lx", (long unsigned*)&tmp->addr_end);
+    // size
+    tmp->length = (unsigned long)(tmp->addr_end - tmp->addr_start);
+    // perm
+    strcpy(tmp->perm, perm);
+    tmp->is_r = (perm[0] == 'r');
+    tmp->is_w = (perm[1] == 'w');
+    tmp->is_x = (perm[2] == 'x');
+    tmp->is_p = (perm[3] == 'p');
+
+    // offset
+    sscanf(offset, "%lx", &tmp->offset);
+    // device
+    strcpy(tmp->dev, dev);
+    // inode
+    tmp->inode = atoi(inode);
+    // pathname
+    strcpy(tmp->pathname, pathname);
+    tmp->next = NULL;
+    // attach the node
+    if (ind == 0) {
+
+      list_maps = tmp;
+      list_maps->next = NULL;
+      current_node = list_maps;
+
+    }
+
+    current_node->next = tmp;
+    current_node = tmp;
+    ind++;
+    // printf("%s",buf);
+
+  }
+
+  // close file
+  fclose(file);
+
+  // g_last_head=list_maps;
+  maps_it->head = list_maps;
+  maps_it->current = list_maps;
+  return maps_it;
+
 }
 
+procmaps_struct* pmparser_next(procmaps_iterator* p_procmaps_it) {
 
-procmaps_struct* pmparser_next(procmaps_iterator* p_procmaps_it){
-	if(p_procmaps_it->current == NULL)
-		return NULL;
-	procmaps_struct* p_current = p_procmaps_it->current;
-	p_procmaps_it->current = p_procmaps_it->current->next;
-	return p_current;
-	/*
-	if(g_current==NULL){
-		g_current=g_last_head;
-	}else
-		g_current=g_current->next;
-
-	return g_current;
-	*/
-}
+  if (p_procmaps_it->current == NULL) return NULL;
+  procmaps_struct* p_current = p_procmaps_it->current;
+  p_procmaps_it->current = p_procmaps_it->current->next;
+  return p_current;
+  /*
+  if(g_current==NULL){
+
+          g_current=g_last_head;
 
+  }else
 
+          g_current=g_current->next;
 
-void pmparser_free(procmaps_iterator* p_procmaps_it){
-	procmaps_struct* maps_list = p_procmaps_it->head;
-	if(maps_list==NULL) return ;
-	procmaps_struct* act=maps_list;
-	procmaps_struct* nxt=act->next;
-	while(act!=NULL){
-		free(act);
-		act=nxt;
-		if(nxt!=NULL)
-			nxt=nxt->next;
-	}
+  return g_current;
+  */
 
 }
 
+void pmparser_free(procmaps_iterator* p_procmaps_it) {
+
+  procmaps_struct* maps_list = p_procmaps_it->head;
+  if (maps_list == NULL) return;
+  procmaps_struct* act = maps_list;
+  procmaps_struct* nxt = act->next;
+  while (act != NULL) {
 
-void _pmparser_split_line(
-		char*buf,char*addr1,char*addr2,
-		char*perm,char* offset,char* device,char*inode,
-		char* pathname){
-	//
-	int orig=0;
-	int i=0;
-	//addr1
-	while(buf[i]!='-'){
-		addr1[i-orig]=buf[i];
-		i++;
-	}
-	addr1[i]='\0';
-	i++;
-	//addr2
-	orig=i;
-	while(buf[i]!='\t' && buf[i]!=' '){
-		addr2[i-orig]=buf[i];
-		i++;
-	}
-	addr2[i-orig]='\0';
-
-	//perm
-	while(buf[i]=='\t' || buf[i]==' ')
-		i++;
-	orig=i;
-	while(buf[i]!='\t' && buf[i]!=' '){
-		perm[i-orig]=buf[i];
-		i++;
-	}
-	perm[i-orig]='\0';
-	//offset
-	while(buf[i]=='\t' || buf[i]==' ')
-		i++;
-	orig=i;
-	while(buf[i]!='\t' && buf[i]!=' '){
-		offset[i-orig]=buf[i];
-		i++;
-	}
-	offset[i-orig]='\0';
-	//dev
-	while(buf[i]=='\t' || buf[i]==' ')
-		i++;
-	orig=i;
-	while(buf[i]!='\t' && buf[i]!=' '){
-		device[i-orig]=buf[i];
-		i++;
-	}
-	device[i-orig]='\0';
-	//inode
-	while(buf[i]=='\t' || buf[i]==' ')
-		i++;
-	orig=i;
-	while(buf[i]!='\t' && buf[i]!=' '){
-		inode[i-orig]=buf[i];
-		i++;
-	}
-	inode[i-orig]='\0';
-	//pathname
-	pathname[0]='\0';
-	while(buf[i]=='\t' || buf[i]==' ')
-		i++;
-	orig=i;
-	while(buf[i]!='\t' && buf[i]!=' ' && buf[i]!='\n'){
-		pathname[i-orig]=buf[i];
-		i++;
-	}
-	pathname[i-orig]='\0';
+    free(act);
+    act = nxt;
+    if (nxt != NULL) nxt = nxt->next;
+
+  }
 
 }
 
+void _pmparser_split_line(char* buf, char* addr1, char* addr2, char* perm,
+                          char* offset, char* device, char* inode,
+                          char* pathname) {
+
+  //
+  int orig = 0;
+  int i = 0;
+  // addr1
+  while (buf[i] != '-') {
+
+    addr1[i - orig] = buf[i];
+    i++;
+
+  }
+
+  addr1[i] = '\0';
+  i++;
+  // addr2
+  orig = i;
+  while (buf[i] != '\t' && buf[i] != ' ') {
+
+    addr2[i - orig] = buf[i];
+    i++;
+
+  }
+
+  addr2[i - orig] = '\0';
+
+  // perm
+  while (buf[i] == '\t' || buf[i] == ' ')
+    i++;
+  orig = i;
+  while (buf[i] != '\t' && buf[i] != ' ') {
+
+    perm[i - orig] = buf[i];
+    i++;
+
+  }
+
+  perm[i - orig] = '\0';
+  // offset
+  while (buf[i] == '\t' || buf[i] == ' ')
+    i++;
+  orig = i;
+  while (buf[i] != '\t' && buf[i] != ' ') {
+
+    offset[i - orig] = buf[i];
+    i++;
+
+  }
+
+  offset[i - orig] = '\0';
+  // dev
+  while (buf[i] == '\t' || buf[i] == ' ')
+    i++;
+  orig = i;
+  while (buf[i] != '\t' && buf[i] != ' ') {
+
+    device[i - orig] = buf[i];
+    i++;
+
+  }
+
+  device[i - orig] = '\0';
+  // inode
+  while (buf[i] == '\t' || buf[i] == ' ')
+    i++;
+  orig = i;
+  while (buf[i] != '\t' && buf[i] != ' ') {
+
+    inode[i - orig] = buf[i];
+    i++;
+
+  }
+
+  inode[i - orig] = '\0';
+  // pathname
+  pathname[0] = '\0';
+  while (buf[i] == '\t' || buf[i] == ' ')
+    i++;
+  orig = i;
+  while (buf[i] != '\t' && buf[i] != ' ' && buf[i] != '\n') {
+
+    pathname[i - orig] = buf[i];
+    i++;
+
+  }
+
+  pathname[i - orig] = '\0';
+
+}
 
 #endif
+