diff --git a/kernel/behave.c b/kernel/behave.c
index f90b5a503ffbcccdc34faf8c12db6fc4bda73972..ffd18d9f7ee71efa5657cdc9805e904d89d1fd25 100644
--- a/kernel/behave.c
+++ b/kernel/behave.c
@@ -145,13 +145,27 @@ pbm_NODE* task_alloc(void) {
     return new_task_node;
 }
 
+/*
+* Get the index of a given task (which can then be used as an unambiguous identificator).
+* Returns -1 if given NULL.
+*/
+static int64_t task_2_index(pbm_NODE* task) {
+    int64_t res = ((uint64_t)task - (uint64_t)tasks->task_buffer) / sizeof(pbm_NODE);
+    if (!task || res > PROC_BUF_SIZE) {
+        return -1;
+    } else {
+        return res;
+    }
+}
+
 void debug_print_tasks(void) {
     size_t i;
     pbm_NODE t;
     printk(KERN_WARNING "-----\nTASKS:\n");
     for(i = 0; i <= tasks->curr_task_index; i++) {
         t = tasks->task_buffer[i];
-        printk(KERN_WARNING "type: %u, thread_id: %u, count: %llu,  children: %llx, next_sib: %llx\n", t.type, t.thread_id, t.count, (uint64_t)t.children, (uint64_t)t.next_sib);
+        printk(KERN_WARNING "addr: %lu, type: %u, thread_id: %u, count: %llu,  children: %lli, next_sib: %lli\n",
+                i, t.type, t.thread_id, t.count, task_2_index(t.children), task_2_index(t.next_sib));
     }
     printk(KERN_WARNING "^^^^^\n");
 }
@@ -196,13 +210,28 @@ PBM* proc_alloc(void) {
     return new_pbm;
 }
 
+/*
+* Get the index of a given PBM (which can then be used as an unambiguous identificator)
+* Returns -1 if given NULL.
+*/
+static int64_t pbm_2_index(PBM* pbm) {
+    int64_t res = ((uint64_t)pbm - (uint64_t)procs->process_buffer) / sizeof(PBM);
+    if (!pbm || res > PROC_BUF_SIZE) {
+        return -1;
+    } else {
+        return res;
+    }
+}
+
 void debug_print_procs(void) {
     size_t i;
     PBM p;
     printk(KERN_WARNING "-----\nPROCS:\n");
     for(i = 0; i <= procs->curr_proc_index; i++) {
         p = procs->process_buffer[i];
-        printk(KERN_WARNING "root: %llx, last: %llx, children: %llx, next_sib: %llx\n", (uint64_t)p.root, (uint64_t)p.last, (uint64_t)p.children, (uint64_t)p.next_sib);
+        printk(KERN_WARNING "index: %lu, root: %lli, last: %lli, children: %lli, next_sib: %lli\n",
+                // calculate indices instead of using the pointers for more readability and represent NULL-values with -1
+                i, task_2_index(p.root), task_2_index(p.last), pbm_2_index(p.children), pbm_2_index(p.next_sib));
     }
     printk(KERN_WARNING "^^^^^\n");
 }
@@ -395,7 +424,8 @@ int pbm_task_end(PBM* pbm) {
 
 	/*
     * Before starting the new task, append the fork-node to the task graph to maintain the correct order
-    */ 
+    */
+    printk(KERN_WARNING ">> CREATE NEW FORK NODE! by %u\n", parent_proc->pid);
     fork_node = _pbm_create_node(FORK, parent_proc->pid);
     if(!fork_node) {
         printk(KERN_WARNING "COULD NOT CREATE NEW FORK NODE!\n");
@@ -408,6 +438,10 @@ int pbm_task_end(PBM* pbm) {
     }
     parent_pbm->last = fork_node; // the new node becomes the last inserted one
 
+    // any fork-node has exactly two children because a fork creates only one
+    // copy of an existing process (1 (copy) + 1 (existing) = 2)
+    fork_node->count = 2;
+
     // start the new task
 	pbm_task_start(parent_pbm, COMP, parent_proc);
 
@@ -422,7 +456,7 @@ int pbm_task_end(PBM* pbm) {
  * This function must get called in the _do_fork() routine AFTER (!) the child process starts to
  * run (current == child) otherwise the perf counting will fail!
  */
-int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_date) {
+int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_node) {
 	unsigned long irq_flags;
 
 	PBM* parent_pbm;
@@ -494,11 +528,23 @@ int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_date) {
     // We have to know WHEN the exit happens relative to the parent. So every child remembers the
     // current fork-task-node of the parent on exit (so that the join can happen at the correct
     // position (more or less, may be imperfect due to parallelism))
-    child_pbm->fork_date = fork_date;
+    child_pbm->fork_date = fork_node;
 
     // continue performance counting for child (restarting parent counting has already been started
     pbm_task_start(child_pbm, COMP, proc);
 
+    // insert front of child task graph into parent task graph:
+    // prepend child-task-tree to list of child-nodes in the fork-node
+    // preconditions:
+    //      * child_pbm->root->next_sib == NULL: since any fork-node has at most two children and
+    //        only one before the join-operation)
+    //      * child_pbm->root != NULL: since the previously called pbm_task_start() should have
+    //        written to that
+    if (fork_node) {
+        child_pbm->root->next_sib = fork_node->children;
+        fork_node->children = child_pbm->root;
+    }
+
     return 1;
 }
 
@@ -539,6 +585,7 @@ int pbm_join(PBM* child_pbm) {
     if(!child_pbm)
         return 0;
 
+    printk(KERN_WARNING "Joining thread %u with fork_node: %lli\n", child_pbm->last->thread_id, task_2_index(child_pbm->fork_date));
     fork_node = child_pbm->fork_date;
 
     // the child process is used to label the join operation to know which process the join belongs
@@ -551,31 +598,20 @@ int pbm_join(PBM* child_pbm) {
         return 0;
     }
 
-    // any fork-node has exactly two children because a fork creates only one
-    // copy of an existing process (1 (copy) + 1 (existing) = 2)
-    fork_node->count = 2;
+    // any join-node has exactly two children because it is reversing a fork
+    // which creates only one copy of an existing process (1 (copy) + 1 (existing) = 2)
     join_node->count = 2;
 
-    // insert front of child task graph into parent task graph:
-    // prepend child-task-tree to list of child-nodes in the fork-node
-    {
-        // assumption: child_pbm->root->next_sib == NULL (since any fork-node
-        // has at most two children and only one before the join-operation)
-        child_pbm->root->next_sib = fork_node->children;
-        fork_node->children = child_pbm->root;
-    }
-
-    // insert back of child task graph with appended join-node into parent task
-    // graph
-    {
-        // assumption: child_pbm->last->children == NULL (since it should be
-        // the last task the child did before exit)
-        // append join node to child task-graph
-        child_pbm->last->children = join_node;
-        // insert join node directly after the exit-date-node in the parent pbm
-        join_node->children = child_pbm->exit_date->children;
-        child_pbm->exit_date->children = join_node->children;
-    }
+    // insert back of child task graph with appended join-node into parent task graph
+    // precondition:
+    //      * child_pbm->last->children == NULL: since it should be the last task the child did
+    //        before exit
+    // append join node to child task-graph
+    child_pbm->last->children = join_node;
+    // insert join node directly after the exit-date-node in the parent pbm
+    printk(KERN_WARNING "Exit-date: %lli, child: %lli\n", task_2_index(child_pbm->exit_date), task_2_index(child_pbm->exit_date->children));
+    join_node->children = child_pbm->exit_date->children;
+    child_pbm->exit_date->children = join_node;
 
     return 1;
 }
@@ -585,6 +621,7 @@ void pbm_post_processing(PBM* pbm) {
     PBM* sib_pbm;
     PBM* child_pbm = pbm->children;
     if(child_pbm) {
+        printk(KERN_WARNING "Joining child thread %u\n", child_pbm->last->thread_id);
         pbm_post_processing(child_pbm);
         pbm_join(child_pbm);
         // TODO Remove from list of childs or just mark as visited?
@@ -592,7 +629,9 @@ void pbm_post_processing(PBM* pbm) {
 
     sib_pbm = pbm->next_sib;
     if(sib_pbm) {
+        printk(KERN_WARNING "Joining sib thread %u\n", sib_pbm->last->thread_id);
         pbm_post_processing(sib_pbm);
+        pbm_join(sib_pbm);
         // TODO Remove from list of siblings or just mark as visited?
     }
 }
@@ -611,6 +650,8 @@ void pbm_join_and_print_graph_self(pid_t pid) {
     pbm = get_pbm_by_pid(pid);
     if (pbm) {
         pbm_post_processing(pbm);
+        printk(KERN_WARNING "After post-processing:\n");
+        debug_print_tasks();
         pbm_print_graph(pbm, pbm->root);
     } else {
         printk(KERN_WARNING "JOIN: PBM not found for: %u\n", pid);
@@ -629,17 +670,20 @@ void pbm_print_graph(PBM* pbm, pbm_NODE* node) {
         return;
 
     root = node;
-
-    printk(KERN_WARNING "Node %p: (%s, count = %llu), children:\n", node, types[node->type], node->count);
+    printk(KERN_WARNING "Node %lli: (%s, pid = %u, count = %llu), children:\n",
+            task_2_index(node), types[node->type], node->thread_id, node->count);
 
     if(node->children)
     {
         node = node->children;
         while(node)
         {
-            printk(KERN_WARNING "  -- Node %p: (%s, count = %llu), next sibling: %p\n", node, types[node->type], node->count, node->next_sib);
+            printk(KERN_WARNING "  -- Node %lli: (%s, pid = %u, count = %llu), next sibling: %lli\n",
+                    task_2_index(node), types[node->type], node->thread_id, node->count, task_2_index(node->next_sib));
             node = node->next_sib;
         }
+    } else {
+        printk(KERN_WARNING "  -- Exit (pid = %u)\n", node->thread_id);
     }
 
     if(root->children)
diff --git a/kernel/behave.h b/kernel/behave.h
index 881970f662dedbf241261bb474334ec4deb5c1cd..e55a10a86fe4a35c55072066aec3b541a93ba2db 100644
--- a/kernel/behave.h
+++ b/kernel/behave.h
@@ -128,7 +128,7 @@ int pbm_task_end(PBM* pbm);
 *
 * The process as an explicit argument is needed since the fork is called by the parent.
 */
-int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_date);
+int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_node);
 
 int pbm_exit(pid_t pid, pid_t parent_pid);