diff --git a/src/lib/prof-lean/binarytree.c b/src/lib/prof-lean/binarytree.c index 6bb93077df..826be28310 100644 --- a/src/lib/prof-lean/binarytree.c +++ b/src/lib/prof-lean/binarytree.c @@ -103,25 +103,6 @@ typedef struct binarytree_s { // private operations //****************************************************************************** -// perform an in order traversal and collect nodes into a vector -static void -tree_to_vector_helper -(binarytree_t *nvec[], - binarytree_t *node, - int *count) -{ - if (node) { - // add nodes in left subtree to vector - tree_to_vector_helper(nvec, node->left, count); - - // add subtree root to vector - nvec[(*count)++] = node; - - // add nodes in right subtree to vector - tree_to_vector_helper(nvec, node->right, count); - } -} - static void subtree_tostr2(binarytree_t *subtree, val_tostr tostr, char valstr[], char* left_lead, char result[]) @@ -157,13 +138,11 @@ subtree_tostr2(binarytree_t *subtree, val_tostr tostr, char valstr[], binarytree_t * -binarytree_new(void *value, binarytree_t *left, binarytree_t *right, - mem_alloc m_alloc) +binarytree_new(size_t size, mem_alloc m_alloc) { - binarytree_t *node = (binarytree_t *)m_alloc(sizeof(binarytree_t)); - node->right = right; - node->left = left; - node->val = value; + binarytree_t *node = (binarytree_t *)m_alloc(sizeof(binarytree_t) + size); + node->right = NULL; + node->left = NULL; return node; } @@ -173,9 +152,6 @@ void binarytree_del(binarytree_t **root, mem_free m_free) if (*root) { binarytree_del(&((*root)->left), m_free); binarytree_del(&((*root)->right), m_free); - if ((*root)->val) { - m_free((*root)->val); - } m_free(*root); *root = NULL; } @@ -206,15 +182,6 @@ binarytree_rightsubtree(binarytree_t *tree) return tree->right; } -void -binarytree_set_rootval( - binarytree_t *tree, - void* rootval) -{ - assert(tree != NULL); - tree->val = rootval; -} - void binarytree_set_leftsubtree( binarytree_t *tree, @@ -240,46 +207,52 @@ binarytree_count(binarytree_t *tree) binarytree_count(tree->left) + binarytree_count(tree->right) + 1: 0; } +binarytree_t * +binarytree_list_to_tree(binarytree_t ** head, int count) +{ + if (count == 0) + return NULL; + int mid = count >> 1; + binarytree_t *left = binarytree_list_to_tree(head, mid); + binarytree_t *root = *head; + root->left = left; + *head = (*head)->right; + root->right = binarytree_list_to_tree(head, count - mid - 1); + return root; +} + void -binarytree_to_vector(binarytree_t *nvec[], binarytree_t *tree) +binarytree_listify_helper(binarytree_t *root, binarytree_t **tail) { - int count = 0; - tree_to_vector_helper(nvec, tree, &count); + if (root != NULL) { + binarytree_listify_helper(root->left, tail); + root->left = NULL; + *tail = root; + tail = &root->right; + binarytree_listify_helper(root->right, tail); + } } -// post-condition: 0 <= |depth(left subtree) - depth(right subtree)| <= 1 binarytree_t * -vector_to_binarytree(binarytree_t *nvec[], int lo, int hi) +binarytree_listify(binarytree_t *root) { - // the midpoint of the subvector is the root of the subtree - int mid = ((hi - lo) >> 1) + lo; - binarytree_t *root = nvec[mid]; - - // build left subtree, if any, from nodes to the left of the midpoint - root->left = (mid != lo) ? vector_to_binarytree(nvec, lo, mid - 1) : NULL; - - // build right subtree, if any, from nodes to the right of the midpoint - root->right = (mid != hi) ? vector_to_binarytree(nvec, mid + 1, hi) : NULL; - - return root; + binarytree_t *head; + binarytree_listify_helper(root, &head); + return head; } binarytree_t * -binarytree_rebalance(binarytree_t * root) +binarytree_listalloc(size_t elt_size, int num_elts, mem_alloc m_alloc) { - if (!root) return root; - - int n = binarytree_count(root); - - // collect tree nodes in order into a vector - binarytree_t *vec[n]; - binarytree_to_vector(vec, root); - - // construct a balanced binary tree from an ordered vector of nodes - return vector_to_binarytree(vec, 0, n - 1); + binarytree_t *head; + binarytree_t **tail = &head; + while (num_elts--) { + *tail = binarytree_new(elt_size, m_alloc); + tail = &(*tail)->right; + } + return head; } - binarytree_t * binarytree_find(binarytree_t * root, val_cmp matches, void *val) { @@ -339,78 +312,17 @@ binarytree_height(binarytree_t *root) return 0; } -bool -binarytree_is_balanced(binarytree_t *root) -{ - if (root) { - int ldepth = binarytree_height(root->left); - int rdepth = binarytree_height(root->right); - if (rdepth - ldepth > 1) return 0; - if (!binarytree_is_balanced(root->left)) return 0; - if (!binarytree_is_balanced(root->right)) return 0; - } - return 1; -} - -bool -binarytree_is_inorder(binarytree_t *root, val_cmp compare) -{ - if (!root) return true; // empty tree is trivially in order - if (root->left) { - // value at node is smaller than left child's - if (compare(root->left->val, root->val) >= 0) return false; - // left subtree is not in order - if (!binarytree_is_inorder(root->left, compare)) return false; - } - if (root->right) { - // value at node is larger than right child's - if (compare(root->right->val, root->val) <= 0) return false; - // right subtree is not in order - if (!binarytree_is_inorder(root->right, compare)) return false; - } - return true; // tree is in order -} - binarytree_t * -binarytree_insert(binarytree_t *root, val_cmp compare, void *val, mem_alloc m_alloc) +binarytree_insert(binarytree_t *root, val_cmp compare, binarytree_t *key) { if(!root) { - return binarytree_new(val, NULL, NULL, m_alloc); // empty tree case + return key; // empty tree case } - else if (compare(root->val, val) > 0) { - root->left = binarytree_insert(root->left, compare, val, m_alloc); + else if (compare(root->val, key->val) > 0) { + root->left = binarytree_insert(root->left, compare, key); } - else if (compare(root->val, val) < 0) { - root->right = binarytree_insert(root->right, compare, val, m_alloc); + else if (compare(root->val, key->val) < 0) { + root->right = binarytree_insert(root->right, compare, key); } return root; } - -binarytree_t* -binarytree_remove_leftmostleaf(binarytree_t **tree) -{ - if (*tree == NULL) { - return NULL; - } - if ((*tree)->left){ - return binarytree_remove_leftmostleaf(&((*tree)->left)); - } - else if ((*tree)->right) { - return binarytree_remove_leftmostleaf(&((*tree)->right)); - } - else { - binarytree_t *rml = *tree; - *tree = NULL; - return rml; - } -} - -void -binarytree_leftmostleaf_to_root(binarytree_t **tree) -{ - if (*tree) { - binarytree_t *lml = binarytree_remove_leftmostleaf(tree); - lml->left = *tree; - *tree = lml; - } -} diff --git a/src/lib/prof-lean/binarytree.h b/src/lib/prof-lean/binarytree.h index 1aaba837dd..7dff7f723f 100644 --- a/src/lib/prof-lean/binarytree.h +++ b/src/lib/prof-lean/binarytree.h @@ -98,15 +98,14 @@ typedef struct binarytree_s binarytree_t; typedef struct binarytree_s { struct binarytree_s *left; struct binarytree_s *right; - void* val; + char val[]; } binarytree_t; #endif // constructors binarytree_t * -binarytree_new(void* value, binarytree_t *left, binarytree_t *right, - mem_alloc m_alloc); +binarytree_new(size_t size, mem_alloc m_alloc); // destructor void binarytree_del(binarytree_t **root, mem_free m_free); @@ -131,11 +130,6 @@ binarytree_rightsubtree(binarytree_t *tree); * Settors */ void -binarytree_set_rootval( - binarytree_t *tree, - void* rootval); - -void binarytree_set_leftsubtree( binarytree_t *tree, binarytree_t* subtree); @@ -149,19 +143,18 @@ binarytree_set_rightsubtree( int binarytree_count(binarytree_t *node); -// linearize a binary tree in order traversal into a vector -void -binarytree_to_vector(binarytree_t *nvec[], binarytree_t *tree); +// given a tree that is a list, with all left children empty, +// restructure to make a balanced tree +binarytree_t * +binarytree_list_to_tree(binarytree_t ** head, int count); -// construct a balanced binary tree from a vector of nodes. -// post-condition: 0 <= |height(left subtree) - height(right subtree)| <= 1 +// restructure a binary tree so that all its left children are null binarytree_t * -vector_to_binarytree(binarytree_t *nvec[], int l, int u); +binarytree_listify(binarytree_t *root); -// perform bulk rebalancing by gathering nodes into a vector and -// rebuilding the tree from scratch using the same nodes. +// allocate a binary tree so that all its left children are null binarytree_t * -binarytree_rebalance(binarytree_t *tree); +binarytree_listalloc(size_t elt_size, int num_elts, mem_alloc m_alloc); // use binarytree_node_cmp to find a matching node in a binary search tree. // NULL is returned @@ -187,36 +180,7 @@ binarytree_tostring_indent(binarytree_t *tree, val_tostr tostr, int binarytree_height(binarytree_t *tree); -// an empty binary tree is balanced. -// a non-empty binary tree is balanced iff the difference in height between -// the left and right subtrees is less or equal to 1. -bool -binarytree_is_balanced(binarytree_t *tree); - -// an empty binary tree is in order -// an non-empty binary tree is in order iff -// its left subtree is in order and all of its elements are < the root element -// its right subtree is in order and all of its elements are > the root element -bool -binarytree_is_inorder(binarytree_t *tree, val_cmp compare); - - binarytree_t * -binarytree_insert(binarytree_t *tree, val_cmp compare, void *val, mem_alloc m_alloc); - -/* - * if the tree is not NULL, remove the leftmost left node from the tree, make it - * the new root of the tree, and set its left subtree to the old tree. - * if the tree is NULL, do nothing. - */ -void -binarytree_leftmostleaf_to_root(binarytree_t **tree); - -/* - * if the tree != NULL, remove and return the leftmost leaf node from the tree, - * otherwise return NULL. - */ -binarytree_t* -binarytree_remove_leftmostleaf(binarytree_t **tree); +binarytree_insert(binarytree_t *tree, val_cmp compare, binarytree_t *key); #endif diff --git a/src/tool/hpcrun/Makefile.am b/src/tool/hpcrun/Makefile.am index 1ecc0d1a39..a484fb00ab 100644 --- a/src/tool/hpcrun/Makefile.am +++ b/src/tool/hpcrun/Makefile.am @@ -186,7 +186,6 @@ UNW_UNIV_FILES = \ UNW_COMMON_FILES = \ $(UNW_UNIV_FILES) \ unwind/common/binarytree_uwi.c \ - unwind/common/ildmod_stat.c \ unwind/common/interval_t.c \ unwind/common/stack_troll.c \ unwind/common/uw_recipe_map.c @@ -234,7 +233,7 @@ UNW_PPC64_LD_FLAGS = # configuration UNW_LIBUNW_FILES = \ - $(UNW_UNIV_FILES) \ + $(UNW_COMMON_FILES) \ unwind/generic-libunwind/libunw-unwind.c \ unwind/common/default_validation_summary.c diff --git a/src/tool/hpcrun/Makefile.in b/src/tool/hpcrun/Makefile.in index 6c108f91b1..65e8137de3 100644 --- a/src/tool/hpcrun/Makefile.in +++ b/src/tool/hpcrun/Makefile.in @@ -464,10 +464,10 @@ am__libhpcrun_la_SOURCES_DIST = utilities/first_func.c main.h main.c \ sample-sources/gpu_ctxt_actions.c \ gpu_blame-cuda-driver-table.c gpu_blame-cuda-runtime-table.c \ unwind/common/backtrace.c unwind/common/unw-throw.c \ + unwind/common/binarytree_uwi.c unwind/common/interval_t.c \ + unwind/common/stack_troll.c unwind/common/uw_recipe_map.c \ unwind/generic-libunwind/libunw-unwind.c \ - unwind/common/binarytree_uwi.c unwind/common/ildmod_stat.c \ - unwind/common/interval_t.c unwind/common/stack_troll.c \ - unwind/common/uw_recipe_map.c unwind/ppc64/ppc64-unwind.c \ + unwind/ppc64/ppc64-unwind.c \ unwind/ppc64/ppc64-unwind-interval.c \ unwind/x86-family/x86-all.c unwind/x86-family/amd-xop.c \ unwind/x86-family/x86-cold-path.c \ @@ -572,18 +572,17 @@ am__objects_27 = sample-sources/libhpcrun_la-gpu_blame.lo \ am__objects_29 = unwind/common/libhpcrun_la-backtrace.lo \ unwind/common/libhpcrun_la-unw-throw.lo am__objects_30 = $(am__objects_29) \ - unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo \ - unwind/common/libhpcrun_la-default_validation_summary.lo -am__objects_31 = $(am__objects_29) \ unwind/common/libhpcrun_la-binarytree_uwi.lo \ - unwind/common/libhpcrun_la-ildmod_stat.lo \ unwind/common/libhpcrun_la-interval_t.lo \ unwind/common/libhpcrun_la-stack_troll.lo \ unwind/common/libhpcrun_la-uw_recipe_map.lo -am__objects_32 = $(am__objects_31) \ +am__objects_31 = $(am__objects_30) \ + unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo \ + unwind/common/libhpcrun_la-default_validation_summary.lo +am__objects_32 = $(am__objects_30) \ unwind/ppc64/libhpcrun_la-ppc64-unwind.lo \ unwind/ppc64/libhpcrun_la-ppc64-unwind-interval.lo -am__objects_33 = $(am__objects_31) \ +am__objects_33 = $(am__objects_30) \ unwind/x86-family/libhpcrun_la-x86-all.lo \ unwind/x86-family/libhpcrun_la-amd-xop.lo \ unwind/x86-family/libhpcrun_la-x86-cold-path.lo \ @@ -603,7 +602,7 @@ am__objects_33 = $(am__objects_31) \ unwind/x86-family/manual-intervals/libhpcrun_la-x86-pgi-mp_pexit.lo @UNW_LIBUNW_FALSE@@UNW_PPC64_FALSE@@UNW_X86_TRUE@am__objects_34 = $(am__objects_33) @UNW_LIBUNW_FALSE@@UNW_PPC64_TRUE@am__objects_34 = $(am__objects_32) -@UNW_LIBUNW_TRUE@am__objects_34 = $(am__objects_30) +@UNW_LIBUNW_TRUE@am__objects_34 = $(am__objects_31) am_libhpcrun_la_OBJECTS = $(am__objects_7) $(am__objects_8) \ $(am__objects_10) $(am__objects_12) $(am__objects_14) \ $(am__objects_16) $(am__objects_18) $(am__objects_20) \ @@ -721,11 +720,11 @@ am__libhpcrun_o_SOURCES_DIST = utilities/first_func.c main.h main.c \ sample-sources/papi.c sample-sources/papi-c-cupti.c \ sample-sources/papi-c.c sample-sources/papi-c-extended-info.c \ sample-sources/upc.c unwind/common/backtrace.c \ - unwind/common/unw-throw.c \ - unwind/generic-libunwind/libunw-unwind.c \ - unwind/common/binarytree_uwi.c unwind/common/ildmod_stat.c \ + unwind/common/unw-throw.c unwind/common/binarytree_uwi.c \ unwind/common/interval_t.c unwind/common/stack_troll.c \ - unwind/common/uw_recipe_map.c unwind/ppc64/ppc64-unwind.c \ + unwind/common/uw_recipe_map.c \ + unwind/generic-libunwind/libunw-unwind.c \ + unwind/ppc64/ppc64-unwind.c \ unwind/ppc64/ppc64-unwind-interval.c \ unwind/x86-family/x86-all.c unwind/x86-family/amd-xop.c \ unwind/x86-family/x86-cold-path.c \ @@ -829,18 +828,17 @@ am__objects_50 = sample-sources/libhpcrun_o-upc.$(OBJEXT) am__objects_52 = unwind/common/libhpcrun_o-backtrace.$(OBJEXT) \ unwind/common/libhpcrun_o-unw-throw.$(OBJEXT) am__objects_53 = $(am__objects_52) \ - unwind/generic-libunwind/libhpcrun_o-libunw-unwind.$(OBJEXT) \ - unwind/common/libhpcrun_o-default_validation_summary.$(OBJEXT) -am__objects_54 = $(am__objects_52) \ unwind/common/libhpcrun_o-binarytree_uwi.$(OBJEXT) \ - unwind/common/libhpcrun_o-ildmod_stat.$(OBJEXT) \ unwind/common/libhpcrun_o-interval_t.$(OBJEXT) \ unwind/common/libhpcrun_o-stack_troll.$(OBJEXT) \ unwind/common/libhpcrun_o-uw_recipe_map.$(OBJEXT) -am__objects_55 = $(am__objects_54) \ +am__objects_54 = $(am__objects_53) \ + unwind/generic-libunwind/libhpcrun_o-libunw-unwind.$(OBJEXT) \ + unwind/common/libhpcrun_o-default_validation_summary.$(OBJEXT) +am__objects_55 = $(am__objects_53) \ unwind/ppc64/libhpcrun_o-ppc64-unwind.$(OBJEXT) \ unwind/ppc64/libhpcrun_o-ppc64-unwind-interval.$(OBJEXT) -am__objects_56 = $(am__objects_54) \ +am__objects_56 = $(am__objects_53) \ unwind/x86-family/libhpcrun_o-x86-all.$(OBJEXT) \ unwind/x86-family/libhpcrun_o-amd-xop.$(OBJEXT) \ unwind/x86-family/libhpcrun_o-x86-cold-path.$(OBJEXT) \ @@ -860,7 +858,7 @@ am__objects_56 = $(am__objects_54) \ unwind/x86-family/manual-intervals/libhpcrun_o-x86-pgi-mp_pexit.$(OBJEXT) @UNW_LIBUNW_FALSE@@UNW_PPC64_FALSE@@UNW_X86_TRUE@am__objects_57 = $(am__objects_56) @UNW_LIBUNW_FALSE@@UNW_PPC64_TRUE@am__objects_57 = $(am__objects_55) -@UNW_LIBUNW_TRUE@am__objects_57 = $(am__objects_53) +@UNW_LIBUNW_TRUE@am__objects_57 = $(am__objects_54) am_libhpcrun_o_OBJECTS = $(am__objects_35) $(am__objects_36) \ $(am__objects_38) $(am__objects_40) $(am__objects_42) \ $(am__objects_44) $(am__objects_46) $(am__objects_49) \ @@ -1344,7 +1342,6 @@ UNW_UNIV_FILES = \ UNW_COMMON_FILES = \ $(UNW_UNIV_FILES) \ unwind/common/binarytree_uwi.c \ - unwind/common/ildmod_stat.c \ unwind/common/interval_t.c \ unwind/common/stack_troll.c \ unwind/common/uw_recipe_map.c @@ -1390,7 +1387,7 @@ UNW_PPC64_LD_FLAGS = # library component are handled via the LIBUNWIND # configuration UNW_LIBUNW_FILES = \ - $(UNW_UNIV_FILES) \ + $(UNW_COMMON_FILES) \ unwind/generic-libunwind/libunw-unwind.c \ unwind/common/default_validation_summary.c @@ -2241,21 +2238,9 @@ unwind/common/libhpcrun_la-backtrace.lo: \ unwind/common/libhpcrun_la-unw-throw.lo: \ unwind/common/$(am__dirstamp) \ unwind/common/$(DEPDIR)/$(am__dirstamp) -unwind/generic-libunwind/$(am__dirstamp): - @$(MKDIR_P) unwind/generic-libunwind - @: > unwind/generic-libunwind/$(am__dirstamp) -unwind/generic-libunwind/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) unwind/generic-libunwind/$(DEPDIR) - @: > unwind/generic-libunwind/$(DEPDIR)/$(am__dirstamp) -unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo: \ - unwind/generic-libunwind/$(am__dirstamp) \ - unwind/generic-libunwind/$(DEPDIR)/$(am__dirstamp) unwind/common/libhpcrun_la-binarytree_uwi.lo: \ unwind/common/$(am__dirstamp) \ unwind/common/$(DEPDIR)/$(am__dirstamp) -unwind/common/libhpcrun_la-ildmod_stat.lo: \ - unwind/common/$(am__dirstamp) \ - unwind/common/$(DEPDIR)/$(am__dirstamp) unwind/common/libhpcrun_la-interval_t.lo: \ unwind/common/$(am__dirstamp) \ unwind/common/$(DEPDIR)/$(am__dirstamp) @@ -2265,6 +2250,15 @@ unwind/common/libhpcrun_la-stack_troll.lo: \ unwind/common/libhpcrun_la-uw_recipe_map.lo: \ unwind/common/$(am__dirstamp) \ unwind/common/$(DEPDIR)/$(am__dirstamp) +unwind/generic-libunwind/$(am__dirstamp): + @$(MKDIR_P) unwind/generic-libunwind + @: > unwind/generic-libunwind/$(am__dirstamp) +unwind/generic-libunwind/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) unwind/generic-libunwind/$(DEPDIR) + @: > unwind/generic-libunwind/$(DEPDIR)/$(am__dirstamp) +unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo: \ + unwind/generic-libunwind/$(am__dirstamp) \ + unwind/generic-libunwind/$(DEPDIR)/$(am__dirstamp) unwind/ppc64/$(am__dirstamp): @$(MKDIR_P) unwind/ppc64 @: > unwind/ppc64/$(am__dirstamp) @@ -2576,15 +2570,9 @@ unwind/common/libhpcrun_o-backtrace.$(OBJEXT): \ unwind/common/libhpcrun_o-unw-throw.$(OBJEXT): \ unwind/common/$(am__dirstamp) \ unwind/common/$(DEPDIR)/$(am__dirstamp) -unwind/generic-libunwind/libhpcrun_o-libunw-unwind.$(OBJEXT): \ - unwind/generic-libunwind/$(am__dirstamp) \ - unwind/generic-libunwind/$(DEPDIR)/$(am__dirstamp) unwind/common/libhpcrun_o-binarytree_uwi.$(OBJEXT): \ unwind/common/$(am__dirstamp) \ unwind/common/$(DEPDIR)/$(am__dirstamp) -unwind/common/libhpcrun_o-ildmod_stat.$(OBJEXT): \ - unwind/common/$(am__dirstamp) \ - unwind/common/$(DEPDIR)/$(am__dirstamp) unwind/common/libhpcrun_o-interval_t.$(OBJEXT): \ unwind/common/$(am__dirstamp) \ unwind/common/$(DEPDIR)/$(am__dirstamp) @@ -2594,6 +2582,9 @@ unwind/common/libhpcrun_o-stack_troll.$(OBJEXT): \ unwind/common/libhpcrun_o-uw_recipe_map.$(OBJEXT): \ unwind/common/$(am__dirstamp) \ unwind/common/$(DEPDIR)/$(am__dirstamp) +unwind/generic-libunwind/libhpcrun_o-libunw-unwind.$(OBJEXT): \ + unwind/generic-libunwind/$(am__dirstamp) \ + unwind/generic-libunwind/$(DEPDIR)/$(am__dirstamp) unwind/ppc64/libhpcrun_o-ppc64-unwind.$(OBJEXT): \ unwind/ppc64/$(am__dirstamp) \ unwind/ppc64/$(DEPDIR)/$(am__dirstamp) @@ -2953,7 +2944,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_la-backtrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_la-binarytree_uwi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_la-default_validation_summary.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_la-ildmod_stat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_la-interval_t.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_la-stack_troll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_la-unw-throw.Plo@am__quote@ @@ -2961,7 +2951,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_o-backtrace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_o-binarytree_uwi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_o-default_validation_summary.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_o-ildmod_stat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_o-interval_t.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_o-stack_troll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unwind/common/$(DEPDIR)/libhpcrun_o-unw-throw.Po@am__quote@ @@ -3852,13 +3841,6 @@ unwind/common/libhpcrun_la-unw-throw.lo: unwind/common/unw-throw.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -c -o unwind/common/libhpcrun_la-unw-throw.lo `test -f 'unwind/common/unw-throw.c' || echo '$(srcdir)/'`unwind/common/unw-throw.c -unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo: unwind/generic-libunwind/libunw-unwind.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -MT unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo -MD -MP -MF unwind/generic-libunwind/$(DEPDIR)/libhpcrun_la-libunw-unwind.Tpo -c -o unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo `test -f 'unwind/generic-libunwind/libunw-unwind.c' || echo '$(srcdir)/'`unwind/generic-libunwind/libunw-unwind.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/generic-libunwind/$(DEPDIR)/libhpcrun_la-libunw-unwind.Tpo unwind/generic-libunwind/$(DEPDIR)/libhpcrun_la-libunw-unwind.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind/generic-libunwind/libunw-unwind.c' object='unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -c -o unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo `test -f 'unwind/generic-libunwind/libunw-unwind.c' || echo '$(srcdir)/'`unwind/generic-libunwind/libunw-unwind.c - unwind/common/libhpcrun_la-binarytree_uwi.lo: unwind/common/binarytree_uwi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -MT unwind/common/libhpcrun_la-binarytree_uwi.lo -MD -MP -MF unwind/common/$(DEPDIR)/libhpcrun_la-binarytree_uwi.Tpo -c -o unwind/common/libhpcrun_la-binarytree_uwi.lo `test -f 'unwind/common/binarytree_uwi.c' || echo '$(srcdir)/'`unwind/common/binarytree_uwi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/common/$(DEPDIR)/libhpcrun_la-binarytree_uwi.Tpo unwind/common/$(DEPDIR)/libhpcrun_la-binarytree_uwi.Plo @@ -3866,13 +3848,6 @@ unwind/common/libhpcrun_la-binarytree_uwi.lo: unwind/common/binarytree_uwi.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -c -o unwind/common/libhpcrun_la-binarytree_uwi.lo `test -f 'unwind/common/binarytree_uwi.c' || echo '$(srcdir)/'`unwind/common/binarytree_uwi.c -unwind/common/libhpcrun_la-ildmod_stat.lo: unwind/common/ildmod_stat.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -MT unwind/common/libhpcrun_la-ildmod_stat.lo -MD -MP -MF unwind/common/$(DEPDIR)/libhpcrun_la-ildmod_stat.Tpo -c -o unwind/common/libhpcrun_la-ildmod_stat.lo `test -f 'unwind/common/ildmod_stat.c' || echo '$(srcdir)/'`unwind/common/ildmod_stat.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/common/$(DEPDIR)/libhpcrun_la-ildmod_stat.Tpo unwind/common/$(DEPDIR)/libhpcrun_la-ildmod_stat.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind/common/ildmod_stat.c' object='unwind/common/libhpcrun_la-ildmod_stat.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -c -o unwind/common/libhpcrun_la-ildmod_stat.lo `test -f 'unwind/common/ildmod_stat.c' || echo '$(srcdir)/'`unwind/common/ildmod_stat.c - unwind/common/libhpcrun_la-interval_t.lo: unwind/common/interval_t.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -MT unwind/common/libhpcrun_la-interval_t.lo -MD -MP -MF unwind/common/$(DEPDIR)/libhpcrun_la-interval_t.Tpo -c -o unwind/common/libhpcrun_la-interval_t.lo `test -f 'unwind/common/interval_t.c' || echo '$(srcdir)/'`unwind/common/interval_t.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/common/$(DEPDIR)/libhpcrun_la-interval_t.Tpo unwind/common/$(DEPDIR)/libhpcrun_la-interval_t.Plo @@ -3894,6 +3869,13 @@ unwind/common/libhpcrun_la-uw_recipe_map.lo: unwind/common/uw_recipe_map.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -c -o unwind/common/libhpcrun_la-uw_recipe_map.lo `test -f 'unwind/common/uw_recipe_map.c' || echo '$(srcdir)/'`unwind/common/uw_recipe_map.c +unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo: unwind/generic-libunwind/libunw-unwind.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -MT unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo -MD -MP -MF unwind/generic-libunwind/$(DEPDIR)/libhpcrun_la-libunw-unwind.Tpo -c -o unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo `test -f 'unwind/generic-libunwind/libunw-unwind.c' || echo '$(srcdir)/'`unwind/generic-libunwind/libunw-unwind.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/generic-libunwind/$(DEPDIR)/libhpcrun_la-libunw-unwind.Tpo unwind/generic-libunwind/$(DEPDIR)/libhpcrun_la-libunw-unwind.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind/generic-libunwind/libunw-unwind.c' object='unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -c -o unwind/generic-libunwind/libhpcrun_la-libunw-unwind.lo `test -f 'unwind/generic-libunwind/libunw-unwind.c' || echo '$(srcdir)/'`unwind/generic-libunwind/libunw-unwind.c + unwind/ppc64/libhpcrun_la-ppc64-unwind.lo: unwind/ppc64/ppc64-unwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_la_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_la_CFLAGS) $(CFLAGS) -MT unwind/ppc64/libhpcrun_la-ppc64-unwind.lo -MD -MP -MF unwind/ppc64/$(DEPDIR)/libhpcrun_la-ppc64-unwind.Tpo -c -o unwind/ppc64/libhpcrun_la-ppc64-unwind.lo `test -f 'unwind/ppc64/ppc64-unwind.c' || echo '$(srcdir)/'`unwind/ppc64/ppc64-unwind.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/ppc64/$(DEPDIR)/libhpcrun_la-ppc64-unwind.Tpo unwind/ppc64/$(DEPDIR)/libhpcrun_la-ppc64-unwind.Plo @@ -5161,20 +5143,6 @@ unwind/common/libhpcrun_o-unw-throw.obj: unwind/common/unw-throw.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -c -o unwind/common/libhpcrun_o-unw-throw.obj `if test -f 'unwind/common/unw-throw.c'; then $(CYGPATH_W) 'unwind/common/unw-throw.c'; else $(CYGPATH_W) '$(srcdir)/unwind/common/unw-throw.c'; fi` -unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o: unwind/generic-libunwind/libunw-unwind.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -MT unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o -MD -MP -MF unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Tpo -c -o unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o `test -f 'unwind/generic-libunwind/libunw-unwind.c' || echo '$(srcdir)/'`unwind/generic-libunwind/libunw-unwind.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Tpo unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind/generic-libunwind/libunw-unwind.c' object='unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -c -o unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o `test -f 'unwind/generic-libunwind/libunw-unwind.c' || echo '$(srcdir)/'`unwind/generic-libunwind/libunw-unwind.c - -unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj: unwind/generic-libunwind/libunw-unwind.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -MT unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj -MD -MP -MF unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Tpo -c -o unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj `if test -f 'unwind/generic-libunwind/libunw-unwind.c'; then $(CYGPATH_W) 'unwind/generic-libunwind/libunw-unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind/generic-libunwind/libunw-unwind.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Tpo unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind/generic-libunwind/libunw-unwind.c' object='unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -c -o unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj `if test -f 'unwind/generic-libunwind/libunw-unwind.c'; then $(CYGPATH_W) 'unwind/generic-libunwind/libunw-unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind/generic-libunwind/libunw-unwind.c'; fi` - unwind/common/libhpcrun_o-binarytree_uwi.o: unwind/common/binarytree_uwi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -MT unwind/common/libhpcrun_o-binarytree_uwi.o -MD -MP -MF unwind/common/$(DEPDIR)/libhpcrun_o-binarytree_uwi.Tpo -c -o unwind/common/libhpcrun_o-binarytree_uwi.o `test -f 'unwind/common/binarytree_uwi.c' || echo '$(srcdir)/'`unwind/common/binarytree_uwi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/common/$(DEPDIR)/libhpcrun_o-binarytree_uwi.Tpo unwind/common/$(DEPDIR)/libhpcrun_o-binarytree_uwi.Po @@ -5189,20 +5157,6 @@ unwind/common/libhpcrun_o-binarytree_uwi.obj: unwind/common/binarytree_uwi.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -c -o unwind/common/libhpcrun_o-binarytree_uwi.obj `if test -f 'unwind/common/binarytree_uwi.c'; then $(CYGPATH_W) 'unwind/common/binarytree_uwi.c'; else $(CYGPATH_W) '$(srcdir)/unwind/common/binarytree_uwi.c'; fi` -unwind/common/libhpcrun_o-ildmod_stat.o: unwind/common/ildmod_stat.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -MT unwind/common/libhpcrun_o-ildmod_stat.o -MD -MP -MF unwind/common/$(DEPDIR)/libhpcrun_o-ildmod_stat.Tpo -c -o unwind/common/libhpcrun_o-ildmod_stat.o `test -f 'unwind/common/ildmod_stat.c' || echo '$(srcdir)/'`unwind/common/ildmod_stat.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/common/$(DEPDIR)/libhpcrun_o-ildmod_stat.Tpo unwind/common/$(DEPDIR)/libhpcrun_o-ildmod_stat.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind/common/ildmod_stat.c' object='unwind/common/libhpcrun_o-ildmod_stat.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -c -o unwind/common/libhpcrun_o-ildmod_stat.o `test -f 'unwind/common/ildmod_stat.c' || echo '$(srcdir)/'`unwind/common/ildmod_stat.c - -unwind/common/libhpcrun_o-ildmod_stat.obj: unwind/common/ildmod_stat.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -MT unwind/common/libhpcrun_o-ildmod_stat.obj -MD -MP -MF unwind/common/$(DEPDIR)/libhpcrun_o-ildmod_stat.Tpo -c -o unwind/common/libhpcrun_o-ildmod_stat.obj `if test -f 'unwind/common/ildmod_stat.c'; then $(CYGPATH_W) 'unwind/common/ildmod_stat.c'; else $(CYGPATH_W) '$(srcdir)/unwind/common/ildmod_stat.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/common/$(DEPDIR)/libhpcrun_o-ildmod_stat.Tpo unwind/common/$(DEPDIR)/libhpcrun_o-ildmod_stat.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind/common/ildmod_stat.c' object='unwind/common/libhpcrun_o-ildmod_stat.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -c -o unwind/common/libhpcrun_o-ildmod_stat.obj `if test -f 'unwind/common/ildmod_stat.c'; then $(CYGPATH_W) 'unwind/common/ildmod_stat.c'; else $(CYGPATH_W) '$(srcdir)/unwind/common/ildmod_stat.c'; fi` - unwind/common/libhpcrun_o-interval_t.o: unwind/common/interval_t.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -MT unwind/common/libhpcrun_o-interval_t.o -MD -MP -MF unwind/common/$(DEPDIR)/libhpcrun_o-interval_t.Tpo -c -o unwind/common/libhpcrun_o-interval_t.o `test -f 'unwind/common/interval_t.c' || echo '$(srcdir)/'`unwind/common/interval_t.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/common/$(DEPDIR)/libhpcrun_o-interval_t.Tpo unwind/common/$(DEPDIR)/libhpcrun_o-interval_t.Po @@ -5245,6 +5199,20 @@ unwind/common/libhpcrun_o-uw_recipe_map.obj: unwind/common/uw_recipe_map.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -c -o unwind/common/libhpcrun_o-uw_recipe_map.obj `if test -f 'unwind/common/uw_recipe_map.c'; then $(CYGPATH_W) 'unwind/common/uw_recipe_map.c'; else $(CYGPATH_W) '$(srcdir)/unwind/common/uw_recipe_map.c'; fi` +unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o: unwind/generic-libunwind/libunw-unwind.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -MT unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o -MD -MP -MF unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Tpo -c -o unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o `test -f 'unwind/generic-libunwind/libunw-unwind.c' || echo '$(srcdir)/'`unwind/generic-libunwind/libunw-unwind.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Tpo unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind/generic-libunwind/libunw-unwind.c' object='unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -c -o unwind/generic-libunwind/libhpcrun_o-libunw-unwind.o `test -f 'unwind/generic-libunwind/libunw-unwind.c' || echo '$(srcdir)/'`unwind/generic-libunwind/libunw-unwind.c + +unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj: unwind/generic-libunwind/libunw-unwind.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -MT unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj -MD -MP -MF unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Tpo -c -o unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj `if test -f 'unwind/generic-libunwind/libunw-unwind.c'; then $(CYGPATH_W) 'unwind/generic-libunwind/libunw-unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind/generic-libunwind/libunw-unwind.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Tpo unwind/generic-libunwind/$(DEPDIR)/libhpcrun_o-libunw-unwind.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unwind/generic-libunwind/libunw-unwind.c' object='unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -c -o unwind/generic-libunwind/libhpcrun_o-libunw-unwind.obj `if test -f 'unwind/generic-libunwind/libunw-unwind.c'; then $(CYGPATH_W) 'unwind/generic-libunwind/libunw-unwind.c'; else $(CYGPATH_W) '$(srcdir)/unwind/generic-libunwind/libunw-unwind.c'; fi` + unwind/ppc64/libhpcrun_o-ppc64-unwind.o: unwind/ppc64/ppc64-unwind.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpcrun_o_CPPFLAGS) $(CPPFLAGS) $(libhpcrun_o_CFLAGS) $(CFLAGS) -MT unwind/ppc64/libhpcrun_o-ppc64-unwind.o -MD -MP -MF unwind/ppc64/$(DEPDIR)/libhpcrun_o-ppc64-unwind.Tpo -c -o unwind/ppc64/libhpcrun_o-ppc64-unwind.o `test -f 'unwind/ppc64/ppc64-unwind.c' || echo '$(srcdir)/'`unwind/ppc64/ppc64-unwind.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unwind/ppc64/$(DEPDIR)/libhpcrun_o-ppc64-unwind.Tpo unwind/ppc64/$(DEPDIR)/libhpcrun_o-ppc64-unwind.Po diff --git a/src/tool/hpcrun/cct_insert_backtrace.c b/src/tool/hpcrun/cct_insert_backtrace.c index ecde549e4d..2f026f3bc3 100644 --- a/src/tool/hpcrun/cct_insert_backtrace.c +++ b/src/tool/hpcrun/cct_insert_backtrace.c @@ -196,8 +196,9 @@ hpcrun_cct_insert_bt(cct_node_t* node, backtrace_t* bt, cct_metric_data_t datum, void **trace_pc) { - return hpcrun_cct_insert_backtrace_w_metric(node, metricId, hpcrun_bt_last(bt), - hpcrun_bt_beg(bt), datum); + return hpcrun_cct_insert_backtrace_w_metric(node, metricId, + bt->beg + bt->len - 1, + bt->beg, datum); } @@ -408,7 +409,7 @@ help_hpcrun_backtrace2cct(cct_bundle_t* bundle, ucontext_t* context, // *trace_pc = bt.trace_pc; // JMC - if (bt.trolled) hpcrun_stats_trolled_inc(); + if (bt.n_trolls != 0) hpcrun_stats_trolled_inc(); hpcrun_stats_frames_total_inc((long)(bt.last - bt.begin + 1)); hpcrun_stats_trolled_frames_inc((long) bt.n_trolls); diff --git a/src/tool/hpcrun/main.h b/src/tool/hpcrun/main.h index d8782d6a7e..7aab30fb22 100644 --- a/src/tool/hpcrun/main.h +++ b/src/tool/hpcrun/main.h @@ -54,7 +54,7 @@ extern bool hpcrun_is_initialized(); extern bool hpcrun_is_safe_to_sync(const char* fn); extern void hpcrun_set_safe_to_sync(void); - +extern void hpcrun_set_real_siglongjmp(void); // // fetch the full path of the execname // diff --git a/src/tool/hpcrun/sample_event.c b/src/tool/hpcrun/sample_event.c index 3c688f705a..eb72040813 100644 --- a/src/tool/hpcrun/sample_event.c +++ b/src/tool/hpcrun/sample_event.c @@ -150,7 +150,6 @@ record_partial_unwind( bt.last = bt_last; bt.fence = FENCE_BAD; bt.has_tramp = false; - bt.trolled = false; bt.n_trolls = 0; bt.bottom_frame_elided = false; diff --git a/src/tool/hpcrun/unwind/common/backtrace-lite.c b/src/tool/hpcrun/unwind/common/backtrace-lite.c index 6a2d8f973f..9165e47731 100644 --- a/src/tool/hpcrun/unwind/common/backtrace-lite.c +++ b/src/tool/hpcrun/unwind/common/backtrace-lite.c @@ -97,7 +97,7 @@ hpcrun_backtrace_lite(void** buffer, int size, ucontext_t* context) while (my_size < size) { int ret; - unw_word_t ip = 0; + void *ip = 0; ret = hpcrun_unw_get_ip_reg(&cursor, &ip); if (ret < 0) { /* ignore error */ } diff --git a/src/tool/hpcrun/unwind/common/backtrace.c b/src/tool/hpcrun/unwind/common/backtrace.c index f7b8ac63cb..fb3439e238 100644 --- a/src/tool/hpcrun/unwind/common/backtrace.c +++ b/src/tool/hpcrun/unwind/common/backtrace.c @@ -86,12 +86,6 @@ static void lush_lip2str(char* buf, size_t len, lush_lip_t* lip); // interface functions //*************************************************************************** -void -hpcrun_show_backtrace(char* label, frame_t* beg, frame_t* end) -{ - ; -} - void hpcrun_bt_dump(frame_t* unwind, const char* tag) { @@ -144,157 +138,14 @@ hpcrun_bt_dump(frame_t* unwind, const char* tag) EMSG("-- end backtrace ------------------------------------\n"); } -frame_t* -hpcrun_bt_reset(backtrace_t* bt) -{ - bt->cur = bt->beg; - bt->len = 0; - return bt->cur; -} - void hpcrun_bt_init(backtrace_t* bt, size_t size) { bt->beg = (frame_t*) hpcrun_malloc(sizeof(frame_t) * size); bt->end = bt->beg + (size - 1); bt->size = size; - hpcrun_bt_reset(bt); -} - -frame_t* -hpcrun_bt_push(backtrace_t* bt, frame_t* frame) -{ - TMSG(BT, "pushing frame onto bt"); - if (bt->cur > bt->end) { - - TMSG(BT, "-- push requires allocate new block and copy"); - size_t size = 2 * bt->size; - // reallocate & copy - frame_t* new = hpcrun_malloc(sizeof(frame_t) * size); - memcpy(new, (void*) bt->beg, bt->len * sizeof(frame_t)); - - bt->beg = new; - bt->size = size; - bt->cur = new + bt->len; - bt->end = new + (size - 1); - } - *(bt->cur) = *frame; - frame_t* rv = bt->cur; - bt->cur++; - bt->len++; - TMSG(BT, "after push, len(bt) = %d", bt->len); - return rv; -} - -frame_t* -hpcrun_bt_beg(backtrace_t* bt) -{ - return bt->beg; -} - -frame_t* -hpcrun_bt_last(backtrace_t* bt) -{ - return (bt->beg + bt->len -1); -} - -size_t -hpcrun_bt_len(backtrace_t* bt) -{ - return bt->len; -} - -bool -hpcrun_bt_empty(backtrace_t* bt) -{ - return (bt->len == 0); -} - -frame_t* -hpcrun_bt_cur(backtrace_t* bt) -{ - return bt->cur; -} - -// -// Some sample backtrace mutator functions -// - -void -hpcrun_bt_modify_leaf_addr(backtrace_t* bt, ip_normalized_t ip_norm) -{ - bt->beg->ip_norm = ip_norm; -} - -void -hpcrun_bt_add_leaf_child(backtrace_t* bt, ip_normalized_t ip_norm) -{ - if (bt->cur > bt->end) { - TMSG(BT, "adding a leaf child of ip ==> lm_id = %d and lm_ip = %p", - ip_norm.lm_id, ip_norm.lm_ip); - } - if (bt->cur > bt->end) { - - TMSG(BT, "-- bt is full, reallocate and copy current data"); - size_t size = 2 * bt->size; - // reallocate & copy - frame_t* new = hpcrun_malloc(sizeof(frame_t) * size); - memmove(new, (void*) bt->beg, bt->len * sizeof(frame_t)); - - bt->beg = new; - bt->size = size; - bt->cur = new + bt->len; - bt->end = new + (size - 1); - } - TMSG(BT, "BEFORE copy, innermost ip ==> lm_id = %d and lm_ip = %p", - bt->beg->ip_norm.lm_id, bt->beg->ip_norm.lm_ip); - memcpy((void*)(bt->beg + 1), (void*) bt->beg, bt->len * sizeof(frame_t)); - TMSG(BT, "AFTER copy, innermost ip ==> lm_id = %d and lm_ip = %p", - (bt->beg + 1)->ip_norm.lm_id, (bt->beg + 1)->ip_norm.lm_ip); - bt->cur++; - bt->len++; - bt->beg->ip_norm = ip_norm; - TMSG(BT, "Leaf child added, new ip ==> lm_id = %d and lm_ip = %p", - bt->beg->ip_norm.lm_id, bt->beg->ip_norm.lm_ip); -} - -void -hpcrun_bt_skip_inner(backtrace_t* bt, void* skip) -{ - size_t realskip = (size_t) skip; - bt->beg += realskip; -} - -void -hpcrun_dump_bt(backtrace_t* bt) -{ - for(frame_t* _f = bt->beg; _f < bt->beg + bt->len; _f++) { - TMSG(BT, "ip_norm.lm_id = %d, and ip_norm.lm_ip = %p ", _f->ip_norm.lm_id, - _f->ip_norm.lm_ip); - } -} - -//--------------------------------------------------------------------------- -// function: hpcrun_filter_sample -// -// purpose: -// ignore any samples that aren't rooted at designated call sites in -// monitor that should be at the base of all process and thread call -// stacks. -// -// implementation notes: -// to support this, in monitor we define a pair of labels surrounding the -// call site of interest. it is possible to get a sample between the pair -// of labels that is outside the call. in that case, the length of the -// sample's callstack would be 1, and we ignore it. -//----------------------------------------------------------------------------- -bool -hpcrun_filter_sample(int len, frame_t* start, frame_t* last) -{ - void* ip_unnorm; - hpcrun_unw_get_ip_unnorm_reg(&last->cursor, &ip_unnorm); - return ( !(monitor_in_start_func_narrow(ip_unnorm) - && (len > 1)) ); + bt->cur = bt->beg; + bt->len = 0; } frame_t* @@ -302,17 +153,17 @@ hpcrun_skip_chords(frame_t* bt_outer, frame_t* bt_inner, int skip) { // N.B.: INVARIANT: bt_inner < bt_outer - frame_t* x_inner = bt_inner; - for (int i = 0; (x_inner < bt_outer && i < skip); ++i) { + int nFrames = bt_outer - bt_inner; + if (skip > nFrames) + skip = nFrames; + for (int i = 0; i < skip; ++i) { // for now, do not support M chords - lush_assoc_t as = lush_assoc_info__get_assoc(x_inner->as_info); + lush_assoc_t as = lush_assoc_info__get_assoc(bt_inner[i].as_info); assert(as == LUSH_ASSOC_NULL || as == LUSH_ASSOC_1_to_1 || as == LUSH_ASSOC_1_to_0); - - x_inner++; + } - - return x_inner; + return &bt_inner[skip]; } // @@ -331,14 +182,11 @@ hpcrun_generate_backtrace_no_trampoline(backtrace_info_t* bt, { TMSG(BT, "Generate backtrace (no tramp), skip inner = %d", skipInner); bt->has_tramp = false; - bt->trolled = false; bt->n_trolls = 0; bt->fence = FENCE_BAD; bt->bottom_frame_elided = false; bt->partial_unwind = true; - bool tramp_found = false; - step_state ret = STEP_ERROR; // default return value from stepper //-------------------------------------------------------------------- @@ -355,12 +203,11 @@ hpcrun_generate_backtrace_no_trampoline(backtrace_info_t* bt, hpcrun_unw_cursor_t cursor; hpcrun_unw_init_cursor(&cursor, context); - int unw_len = 0; - while (true) { + do { void* ip; hpcrun_unw_get_ip_unnorm_reg(&cursor, &ip); - if (hpcrun_trampoline_interior((void*) ip)) { + if (hpcrun_trampoline_interior(ip)) { // bail; we shouldn't be unwinding here. hpcrun is in the midst of // counting a return from a sampled frame using a trampoline. // drop the sample. @@ -369,8 +216,8 @@ hpcrun_generate_backtrace_no_trampoline(backtrace_info_t* bt, hpcrun_unw_drop(); } - if (hpcrun_trampoline_at_entry((void*) ip)) { - if (unw_len == 0){ + else if (hpcrun_trampoline_at_entry(ip)) { + if (ret == STEP_ERROR){ // we are about to enter the trampoline code to synchronously // record a return. for now, simply do nothing ... // FIXME: with a bit more effort, we could charge @@ -379,8 +226,7 @@ hpcrun_generate_backtrace_no_trampoline(backtrace_info_t* bt, } else { // we have encountered a trampoline in the middle of an unwind. - bt->has_tramp = (tramp_found = true); - TMSG(TRAMP, "--CURRENT UNWIND FINDS TRAMPOLINE @ (sp:%p, bp:%p", cursor.sp, cursor.bp); + bt->has_tramp = true; // no need to unwind further. the outer frames are already known. bt->fence = FENCE_TRAMP; @@ -399,26 +245,25 @@ hpcrun_generate_backtrace_no_trampoline(backtrace_info_t* bt, td->btbuf_cur->the_function = cursor.the_function; - frame_t* prev = td->btbuf_cur; - td->btbuf_cur++; - unw_len++; + frame_t* prev = td->btbuf_cur++; ret = hpcrun_unw_step(&cursor); - if (ret == STEP_TROLL) { - bt->trolled = true; + switch (ret) { + case STEP_TROLL: bt->n_trolls++; - } - if (ret <= 0) { - if (ret == STEP_ERROR) { - hpcrun_stats_num_samples_dropped_inc(); - } - else { // STEP_STOP - bt->fence = cursor.fence; - } + /* fallthrough */ + default: + prev->ra_loc = hpcrun_unw_get_ra_loc(&cursor); + break; + + case STEP_ERROR: + hpcrun_stats_num_samples_dropped_inc(); + break; + case STEP_STOP: + bt->fence = cursor.fence; break; } - prev->ra_loc = hpcrun_unw_get_ra_loc(&cursor); - } + } while (ret != STEP_ERROR && ret != STEP_STOP); TMSG(FENCE, "backtrace generation detects fence = %s", fence_enum_name(bt->fence)); @@ -530,157 +375,6 @@ hpcrun_generate_backtrace(backtrace_info_t* bt, return true; } -// debug variant of above routine -// -// -// Generate a backtrace, store it in the thread local data -// Return true/false success code -// Also, return (via reference params) backtrace beginning, backtrace end, -// and whether or not a trampoline was found. -// - -bool -hpcrun_dbg_generate_backtrace(backtrace_info_t* bt, - ucontext_t* context, int skipInner) -{ - bt->has_tramp = false; - bt->trolled = false; - bt->n_trolls = 0; - bt->bottom_frame_elided = false; - bt->partial_unwind = true; - - bool tramp_found = false; - - step_state ret = STEP_ERROR; // default return value from stepper - - hpcrun_unw_cursor_t cursor; - hpcrun_dbg_unw_init_cursor(&cursor, context); - - //-------------------------------------------------------------------- - // note: these variables are not local variables so that if a SIGSEGV - // occurs and control returns up several procedure frames, the values - // are accessible to a dumping routine that will tell us where we ran - // into a problem. - //-------------------------------------------------------------------- - - thread_data_t* td = hpcrun_get_thread_data(); - td->btbuf_cur = td->btbuf_beg; // innermost - td->btbuf_sav = td->btbuf_end; - - int unw_len = 0; - while (true) { - void* ip; - hpcrun_unw_get_ip_unnorm_reg(&cursor, &ip); - - if (hpcrun_dbg_trampoline_interior((void*) ip)) { - // bail; we shouldn't be unwinding here. hpcrun is in the midst of - // counting a return from a sampled frame using a trampoline. - // drop the sample. - // FIXME: sharpen the information to indicate why the sample is - // being dropped. - hpcrun_unw_throw(); - } - - if (hpcrun_dbg_trampoline_at_entry((void*) ip)) { - if (unw_len == 0){ - // we are about to enter the trampoline code to synchronously - // record a return. for now, simply do nothing ... - // FIXME: with a bit more effort, we could charge - // the sample to the return address in the caller. - hpcrun_unw_throw(); - } - else { - // we have encountered a trampoline in the middle of an unwind. - bt->has_tramp = (tramp_found = true); - - // no need to unwind further. the outer frames are already known. - break; - } - } - - hpcrun_ensure_btbuf_avail(); - - td->btbuf_cur->cursor = cursor; - //Broken if HPC_UNW_LITE defined - hpcrun_unw_get_ip_norm_reg(&td->btbuf_cur->cursor, - &td->btbuf_cur->ip_norm); - td->btbuf_cur->ra_loc = NULL; - frame_t* prev = td->btbuf_cur; - td->btbuf_cur++; - unw_len++; - - ret = hpcrun_dbg_unw_step(&cursor); - if (ret == STEP_TROLL) { - bt->trolled = true; - bt->n_trolls++; - } - if (ret <= 0) { - break; - } - prev->ra_loc = hpcrun_unw_get_ra_loc(&cursor); - } - - frame_t* bt_beg = td->btbuf_beg; // innermost, inclusive - frame_t* bt_last = td->btbuf_cur - 1; // outermost, inclusive - - bt->begin = bt_beg; // returned backtrace begin - // is buffer beginning - bt->last = bt_last; // returned backtrace end is - // last recorded element - - frame_t* bt_end = bt_last + 1; // outermost, exclusive - size_t new_frame_count = bt_end - bt_beg; - - // soft error mandates returning false - if (! (ret == STEP_STOP)) { - return false; - } - - if (tramp_found) { - TMSG(BACKTRACE, "tramp stop: conjoining backtraces"); - // - // join current backtrace fragment to previous trampoline-marked prefix - // and make this new conjoined backtrace the cached-backtrace - // - frame_t* prefix = td->tramp_frame + 1; // skip top frame - size_t old_frame_count = td->cached_bt_end - prefix; - - hpcrun_cached_bt_adjust_size(new_frame_count + old_frame_count); - - // put the old prefix in place - memmove(td->cached_bt + new_frame_count, prefix, - sizeof(frame_t) * old_frame_count); - - // put the new suffix in place - memcpy(td->cached_bt, bt_beg, sizeof(frame_t) * new_frame_count); - - // update the length of the conjoined backtrace - td->cached_bt_end = td->cached_bt + new_frame_count + old_frame_count; - } - else { - hpcrun_cached_bt_adjust_size(new_frame_count); - memmove(td->cached_bt, bt_beg, sizeof(frame_t) * new_frame_count); - - td->cached_bt_end = td->cached_bt + new_frame_count; - } - - if (skipInner) { - if (ENABLED(USE_TRAMP)){ - // - // FIXME: For the moment, ignore skipInner issues with trampolines. - // Eventually, this will need to be addressed - // - EMSG("WARNING: backtrace detects skipInner != 0 (skipInner = %d)", - skipInner); - } - // adjust the returned backtrace according to the skipInner - bt->begin = hpcrun_skip_chords(bt_last, bt_beg, skipInner); - } - - bt->partial_unwind = false; - return true; -} - //*************************************************************************** // private operations diff --git a/src/tool/hpcrun/unwind/common/backtrace.h b/src/tool/hpcrun/unwind/common/backtrace.h index 37098f273e..c1db951d86 100644 --- a/src/tool/hpcrun/unwind/common/backtrace.h +++ b/src/tool/hpcrun/unwind/common/backtrace.h @@ -102,37 +102,15 @@ typedef void (*bt_mut_fn)(backtrace_t* bt, bt_fn_arg arg); bool hpcrun_backtrace_std(backtrace_t* bt, ucontext_t* context); -bool hpcrun_filter_sample(int len, frame_t* start, frame_t* last); - frame_t* hpcrun_skip_chords(frame_t* bt_outer, frame_t* bt_inner, int skip); void hpcrun_bt_dump(frame_t* unwind, const char* tag); -frame_t* hpcrun_bt_reset(backtrace_t* bt); - void hpcrun_bt_init(backtrace_t* bt, size_t size); -frame_t* hpcrun_bt_push(backtrace_t* bt, frame_t* frame); - -frame_t* hpcrun_bt_beg(backtrace_t* bt); - -frame_t* hpcrun_bt_last(backtrace_t* bt); - -frame_t* hpcrun_bt_cur(backtrace_t* bt); - -size_t hpcrun_bt_len(backtrace_t* bt); - -bool hpcrun_bt_empty(backtrace_t* bt); - bool hpcrun_backtrace_std(backtrace_t* bt, ucontext_t* context); -void hpcrun_bt_modify_leaf_addr(backtrace_t* bt, ip_normalized_t ip_norm); - -void hpcrun_bt_add_leaf_child(backtrace_t* bt, ip_normalized_t ip_norm); - -void hpcrun_dump_bt(backtrace_t* bt); - bool hpcrun_generate_backtrace(backtrace_info_t* bt, ucontext_t* context, int skipInner); diff --git a/src/tool/hpcrun/unwind/common/backtrace_info.h b/src/tool/hpcrun/unwind/common/backtrace_info.h index 1b5bac8d8a..9caaa5e47c 100644 --- a/src/tool/hpcrun/unwind/common/backtrace_info.h +++ b/src/tool/hpcrun/unwind/common/backtrace_info.h @@ -18,12 +18,11 @@ typedef struct { frame_t* begin; // beginning frame of backtrace frame_t* last; // ending frame of backtrace (inclusive) - fence_enum_t fence; // Type of stop -- thread or main *only meaninful when good unwind - bool has_tramp; // true when a trampoline short-circuited the unwind - bool trolled; // true when ANY frame in the backtrace came from a troll size_t n_trolls; // # of frames that resulted from trolling - bool bottom_frame_elided; // true if bottom frame has been elided - bool partial_unwind; // true if not a full unwind + fence_enum_t fence:3; // Type of stop -- thread or main *only meaninful when good unwind + bool has_tramp:1; // true when a trampoline short-circuited the unwind + bool bottom_frame_elided:1; // true if bottom frame has been elided + bool partial_unwind:1; // true if not a full unwind void *trace_pc; // in/out value: modified to adjust trace when modifying backtrace } backtrace_info_t; diff --git a/src/tool/hpcrun/unwind/common/binarytree_uwi.c b/src/tool/hpcrun/unwind/common/binarytree_uwi.c index 6d3ff75211..43d094d712 100644 --- a/src/tool/hpcrun/unwind/common/binarytree_uwi.c +++ b/src/tool/hpcrun/unwind/common/binarytree_uwi.c @@ -1,9 +1,3 @@ -/* - * binarytree_uwi.c - * - * Author: dxnguyen - */ - //****************************************************************************** // global include files //****************************************************************************** @@ -23,10 +17,12 @@ #include "binarytree_uwi.h" #define NUM_NODES 10 -#define BTUWI_DEBUG 0 -static bitree_uwi_t *GF_uwi_tree = NULL; // global free unwind interval tree -static mcs_lock_t GFT_lock; // lock for GF_uwi_tree +static struct { + bitree_uwi_t *tree; // global free unwind interval tree + mcs_lock_t lock; // lock for tree +} GF; + static __thread bitree_uwi_t *_lf_uwi_tree = NULL; // thread local free unwind interval tree /* @@ -35,124 +31,53 @@ static __thread bitree_uwi_t *_lf_uwi_tree = NULL; // thread local free unwind void bitree_uwi_init() { -#if BTUWI_DEBUG - printf("DXN_DBG: bitree_uwi_init mcs_init(&GFT_lock) \n"); -#endif - mcs_init(&GFT_lock); + mcs_init(&GF.lock); } // constructors -static uwi_t* -uwi_t_new(interval_t* interval, uw_recipe_t* recipe, mem_alloc m_alloc) -{ - uwi_t *uwi = m_alloc(sizeof(*uwi)); - uwi->interval = interval; - uwi->recipe = recipe; - return uwi; -} - -bitree_uwi_t* -bitree_uwi_new(uwi_t *val, - bitree_uwi_t *left, bitree_uwi_t *right, mem_alloc m_alloc) -{ - binarytree_t *bt = - binarytree_new(val, (binarytree_t*)left, (binarytree_t*)right, m_alloc); - return (bitree_uwi_t*)bt; -} - -static bitree_uwi_t* -bitree_uwi_new_node(mem_alloc m_alloc, size_t recipe_size) -{ - interval_t *interval = interval_t_new(0, 0, m_alloc); - uw_recipe_t * recipe = uw_recipe_t_new(m_alloc, recipe_size); - binarytree_t *btuwi = binarytree_new(uwi_t_new(interval, recipe, m_alloc), NULL, NULL, m_alloc); - return (bitree_uwi_t*) btuwi; -} - -static void -bitree_uwi_add_nodes_to_lft( - mem_alloc m_alloc, - size_t recipe_size) -{ - bitree_uwi_t *btuwi = bitree_uwi_new_node(m_alloc, recipe_size); - bitree_uwi_t * current = btuwi; - for (int i = 1; i < NUM_NODES; i++) { - bitree_uwi_t *new_node = bitree_uwi_new_node(m_alloc, recipe_size); - bitree_uwi_set_leftsubtree(current, new_node); - current = new_node; - } - bitree_uwi_set_rightsubtree(btuwi, _lf_uwi_tree); - _lf_uwi_tree = btuwi; -} - -static bitree_uwi_t * -bitree_uwi_alloc_from_lft() -{ - return bitree_uwi_remove_leftmostleaf(&_lf_uwi_tree); -} - -static void -bitree_uwi_populate_lft( - mem_alloc m_alloc, - size_t recipe_size) -{ - mcs_node_t me; - bool acquired = mcs_trylock(&GFT_lock, &me); - if (acquired) { - // the global free list is locked, so use it - if (GF_uwi_tree) { - bitree_uwi_t *btuwi = GF_uwi_tree; - GF_uwi_tree = bitree_uwi_rightsubtree(GF_uwi_tree); - mcs_unlock(&GFT_lock, &me); - bitree_uwi_set_rightsubtree(btuwi, _lf_uwi_tree); - _lf_uwi_tree = btuwi; - } - else { - mcs_unlock(&GFT_lock, &me); - } - } - if (!_lf_uwi_tree) { - bitree_uwi_add_nodes_to_lft(m_alloc, recipe_size); - } -} - bitree_uwi_t* bitree_uwi_malloc( mem_alloc m_alloc, size_t recipe_size) { if (!_lf_uwi_tree) { - bitree_uwi_populate_lft(m_alloc, recipe_size); + mcs_node_t me; + if (mcs_trylock(&GF.lock, &me)) { + // the global free list is locked, so use it + _lf_uwi_tree = GF.tree; + if (_lf_uwi_tree) + GF.tree = bitree_uwi_leftsubtree(_lf_uwi_tree); + mcs_unlock(&GF.lock, &me); + if (_lf_uwi_tree) + bitree_uwi_set_leftsubtree(_lf_uwi_tree, NULL); + } + if (!_lf_uwi_tree) + _lf_uwi_tree = + (bitree_uwi_t *)binarytree_listalloc(sizeof(uwi_t) + recipe_size, + NUM_NODES, m_alloc); } -#if BTUWI_DEBUG - assert(_lf_uwi_tree != NULL); -#endif - - return bitree_uwi_alloc_from_lft(); -} - -// destructor -void -bitree_uwi_del(bitree_uwi_t **tree, mem_free m_free) -{ - binarytree_del((binarytree_t**) tree, m_free); + bitree_uwi_t *top = _lf_uwi_tree; + if (top) { + _lf_uwi_tree = bitree_uwi_rightsubtree(top); + bitree_uwi_set_rightsubtree(top, NULL); + } + return top; } /* - * link only non null tree to GF_uwi_tree + * link only non null tree to GF.tree */ void bitree_uwi_free(bitree_uwi_t *tree) { if(!tree) return; - bitree_uwi_leftmostleaf_to_root(&tree); + tree = bitree_uwi_flatten(tree); // link to the global free unwind interval tree: mcs_node_t me; - mcs_lock(&GFT_lock, &me); - bitree_uwi_set_rightsubtree(tree, GF_uwi_tree); - GF_uwi_tree = tree; - bitree_uwi_set_rightsubtree(tree, NULL); - mcs_unlock(&GFT_lock, &me); + mcs_lock(&GF.lock, &me); + bitree_uwi_set_leftsubtree(tree, GF.tree); + GF.tree = tree; + mcs_unlock(&GF.lock, &me); } // return the value at the root @@ -177,14 +102,6 @@ bitree_uwi_rightsubtree(bitree_uwi_t *tree) return (bitree_uwi_t*) binarytree_rightsubtree((binarytree_t*) tree); } -void -bitree_uwi_set_rootval( - bitree_uwi_t *tree, - uwi_t* rootval) -{ - binarytree_set_rootval((binarytree_t*) tree, rootval); -} - void bitree_uwi_set_leftsubtree( bitree_uwi_t *tree, @@ -209,7 +126,7 @@ bitree_uwi_interval(bitree_uwi_t *tree) assert(tree != NULL); uwi_t* uwi = bitree_uwi_rootval(tree); assert(uwi != NULL); - return uwi->interval; + return &uwi->interval; } // return the recipe_t value of the tree root @@ -220,23 +137,22 @@ bitree_uwi_recipe(bitree_uwi_t *tree) assert(tree != NULL); uwi_t* uwi = bitree_uwi_rootval(tree); assert(uwi != NULL); - return uwi->recipe; + return (uw_recipe_t *)uwi->recipe; } -// count the number of nodes in the binary tree. -int -bitree_uwi_count(bitree_uwi_t *tree) +// change a tree of all right children into a balanced tree +bitree_uwi_t* +bitree_uwi_rebalance(bitree_uwi_t * tree, int count) { - return binarytree_count((binarytree_t *)tree); + binarytree_t *balanced = binarytree_list_to_tree((binarytree_t**)&tree, count); + return (bitree_uwi_t*)balanced; } -// perform bulk rebalancing by gathering nodes into a vector and -// rebuilding the tree from scratch using the same nodes. bitree_uwi_t* -bitree_uwi_rebalance(bitree_uwi_t * tree) +bitree_uwi_flatten(bitree_uwi_t * tree) { - binarytree_t *balanced = binarytree_rebalance((binarytree_t*)tree); - return (bitree_uwi_t*)balanced; + binarytree_t *flattened = binarytree_listify((binarytree_t*)tree); + return (bitree_uwi_t*)flattened; } static int @@ -244,7 +160,7 @@ uwi_t_cmp(void* lhs, void* rhs) { uwi_t* uwi1 = (uwi_t*)lhs; uwi_t* uwi2 = (uwi_t*)rhs; - return interval_t_cmp(uwi1->interval, uwi2->interval); + return interval_t_cmp(&uwi1->interval, &uwi2->interval); } // use uwi_t_cmp to find a matching node in a binary search tree of uwi_t @@ -264,7 +180,7 @@ static int uwi_t_inrange(void* lhs, void* address) { uwi_t* uwi = (uwi_t*)lhs; - return interval_t_inrange(uwi->interval, address); + return interval_t_inrange(&uwi->interval, address); } bitree_uwi_t* @@ -286,7 +202,7 @@ uwi_t_tostr(void* uwip, char str[]) { uwi_t *uwi = uwip; char intervalstr[MAX_INTERVAL_STR]; - interval_t_tostr(uwi->interval, intervalstr); + interval_t_tostr(&uwi->interval, intervalstr); char recipestr[MAX_RECIPE_STR]; uw_recipe_tostr(uwi->recipe, recipestr); sprintf(str, "(%s %s)", intervalstr, recipestr); @@ -318,63 +234,3 @@ bitree_uwi_tostring_indent(bitree_uwi_t *tree, char *indents, binarytree_tostring_indent((binarytree_t*)tree, uwi_t_tostr, uwibuff, indents, treestr); } - -// compute the height of the binary tree. -// the height of an empty tree is 0. -// the height of an non-empty tree is 1+ the larger of the height of the left subtree -// and the right subtree. -int -bitree_uwi_height(bitree_uwi_t *tree) -{ - return binarytree_height((binarytree_t*)tree); -} - -// an empty binary tree is balanced. -// a non-empty binary tree is balanced iff the difference in height between -// the left and right subtrees is less or equal to 1. -bool -bitree_uwi_is_balanced(bitree_uwi_t *tree) -{ - return binarytree_is_balanced((binarytree_t*)tree); -} - -// an empty binary tree is in order -// an non-empty binary tree is in order iff -// its left subtree is in order and all of its elements are < the root element -// its right subtree is in order and all of its elements are > the root element -bool -bitree_uwi_is_inorder(bitree_uwi_t *tree) -{ - return binarytree_is_inorder((binarytree_t*)tree, uwi_t_cmp); -} - - -bitree_uwi_t* -bitree_uwi_insert(bitree_uwi_t *tree, uwi_t *val, mem_alloc m_alloc) -{ - return (bitree_uwi_t*)binarytree_insert((binarytree_t*)tree, - uwi_t_cmp, val, m_alloc); -} - - -bitree_uwi_t* -bitree_uwi_finalize(bitree_uwi_t *tree) -{ - if (tree == NULL) return tree; - bitree_uwi_set_leftsubtree(tree, NULL); - bitree_uwi_finalize(bitree_uwi_rightsubtree(tree)); - return tree; -} - - -void -bitree_uwi_leftmostleaf_to_root(bitree_uwi_t **tree) -{ - binarytree_leftmostleaf_to_root((binarytree_t**)tree); -} - -bitree_uwi_t* -bitree_uwi_remove_leftmostleaf(bitree_uwi_t **tree) -{ - return (bitree_uwi_t*) binarytree_remove_leftmostleaf((binarytree_t**)tree); -} diff --git a/src/tool/hpcrun/unwind/common/binarytree_uwi.h b/src/tool/hpcrun/unwind/common/binarytree_uwi.h index 998d957a43..490cd37620 100644 --- a/src/tool/hpcrun/unwind/common/binarytree_uwi.h +++ b/src/tool/hpcrun/unwind/common/binarytree_uwi.h @@ -1,11 +1,3 @@ -/* - * binarytree_uwi.h - * - * binary search tree of unwind intervals uwi_t as specified in uwi.h. - * - * Author: dxnguyen - */ - #ifndef __BINARYTREE_UWI_H__ #define __BINARYTREE_UWI_H__ @@ -23,7 +15,6 @@ #include #include "interval_t.h" -#include "uw_recipe.h" /****************************************************************************** @@ -49,18 +40,19 @@ typedef struct unwind_interval_t unwind_interval; ******************************************************************************/ #define UWI_NEXT(btuwi) (bitree_uwi_rightsubtree(btuwi)) -#define UWI_PREV(btuwi) (bitree_uwi_leftsubtree(btuwi)) #define UWI_START_ADDR(btuwi) (bitree_uwi_interval(btuwi))->start #define UWI_END_ADDR(btuwi) (bitree_uwi_interval(btuwi))->end - +#define MAX_RECIPE_STR 256 //****************************************************************************** // abstract data type //****************************************************************************** +typedef struct recipe_s uw_recipe_t; + typedef struct uwi_s { - interval_t *interval; - uw_recipe_t *recipe; + interval_t interval; + char recipe[]; } uwi_t; typedef struct bitree_uwi_s bitree_uwi_t; @@ -69,6 +61,7 @@ typedef struct bitree_uwi_s bitree_uwi_t; typedef struct btuwi_status_s { char *first_undecoded_ins; bitree_uwi_t *first; + int count; int errcode; } btuwi_status_t; @@ -78,11 +71,6 @@ typedef struct btuwi_status_s { void bitree_uwi_init(); -// constructors -bitree_uwi_t* -bitree_uwi_new(uwi_t *val, bitree_uwi_t *left, bitree_uwi_t *right, - mem_alloc m_alloc); - /* * Returns a bitree_uwi_t node whose left and right subtree nodes are NULL. * The root value of the returned node is a non-null uwi_t*, which is a pair @@ -93,9 +81,6 @@ bitree_uwi_new(uwi_t *val, bitree_uwi_t *left, bitree_uwi_t *right, bitree_uwi_t* bitree_uwi_malloc(mem_alloc m_alloc, size_t recipe_size); -// destructor -void bitree_uwi_del(bitree_uwi_t **tree, mem_free m_free); - /* * If tree != NULL return tree to global free tree, * otherwise do nothing. @@ -116,11 +101,6 @@ bitree_uwi_leftsubtree(bitree_uwi_t *tree); bitree_uwi_t* bitree_uwi_rightsubtree(bitree_uwi_t *tree); -void -bitree_uwi_set_rootval( - bitree_uwi_t *tree, - uwi_t* rootval); - void bitree_uwi_set_leftsubtree( bitree_uwi_t *tree, @@ -141,14 +121,14 @@ bitree_uwi_interval(bitree_uwi_t *tree); uw_recipe_t* bitree_uwi_recipe(bitree_uwi_t *tree); -// count the number of nodes in the binary tree. -int -bitree_uwi_count(bitree_uwi_t * tree); - -// perform bulk rebalancing by gathering nodes into a vector and -// rebuilding the tree from scratch using the same nodes. +// given a tree that is a list, with all left children empty, +// restructure to make a balanced tree bitree_uwi_t * -bitree_uwi_rebalance(bitree_uwi_t * tree); +bitree_uwi_rebalance(bitree_uwi_t * tree, int count); + +// restructure a binary tree so that all its left children are null +bitree_uwi_t* +bitree_uwi_flatten(bitree_uwi_t * tree); // use uwi_t_cmp to find a matching node in a binary search tree of uwi_t // empty tree is returned if no match is found. @@ -161,6 +141,17 @@ bitree_uwi_find(bitree_uwi_t *tree, uwi_t *val); bitree_uwi_t* bitree_uwi_inrange(bitree_uwi_t *tree, uintptr_t address); +/* + * Concrete implementation of the abstract val_tostr function of the + * generic_val class. + * pre-condition: uwr is of type uw_recipe_t* + */ +void +uw_recipe_tostr(void* uwr, char str[]); + +void +uw_recipe_print(void* uwr); + // compute a string representing the binary tree printed vertically and // return result in the treestr parameter. // caller should provide the appropriate length for treestr. @@ -173,37 +164,4 @@ bitree_uwi_tostring_indent(bitree_uwi_t *tree, char *indents, char treestr[]); void bitree_uwi_print(bitree_uwi_t *tree); -// compute the height of the binary tree. -// the height of an empty tree is 0. -// the height of an non-empty tree is 1+ the larger of the height of the left subtree -// and the right subtree. -int -bitree_uwi_height(bitree_uwi_t *tree); - -// an empty binary tree is balanced. -// a non-empty binary tree is balanced iff the difference in height between -// the left and right subtrees is less or equal to 1. -bool -bitree_uwi_is_balanced(bitree_uwi_t *tree); - -// an empty binary tree is in order -// an non-empty binary tree is in order iff -// its left subtree is in order and all of its elements are < the root element -// its right subtree is in order and all of its elements are > the root element -bool -bitree_uwi_is_inorder(bitree_uwi_t *tree); - - -bitree_uwi_t * -bitree_uwi_insert(bitree_uwi_t *tree, uwi_t *val, mem_alloc m_alloc); - -bitree_uwi_t* -bitree_uwi_finalize(bitree_uwi_t *tree); - -void -bitree_uwi_leftmostleaf_to_root(bitree_uwi_t **tree); - -bitree_uwi_t* -bitree_uwi_remove_leftmostleaf(bitree_uwi_t **tree); - #endif /* __BINARYTREE_UWI_H__ */ diff --git a/src/tool/hpcrun/unwind/common/ildmod_stat.c b/src/tool/hpcrun/unwind/common/ildmod_stat.c deleted file mode 100644 index dd0c3ebc3a..0000000000 --- a/src/tool/hpcrun/unwind/common/ildmod_stat.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * ildmod_stat.c - * - * Author: dxnguyen - */ - -//****************************************************************************** -// global include files -//****************************************************************************** - -#include -#include -#include - -//****************************************************************************** -// local include files -//****************************************************************************** - -#include "ildmod_stat.h" - - - -//****************************************************************************** -// Constructors -//****************************************************************************** - -ildmod_stat_t * -ildmod_stat_build(uintptr_t start, uintptr_t end, load_module_t *ldmod, - tree_stat_t treestat, mem_alloc m_alloc) -{ - ildmod_stat_t *ilmstat = m_alloc(sizeof(*ilmstat)); - ilmstat->interval = interval_t_new(start, end, m_alloc); - ilmstat->loadmod = ldmod; - atomic_store_explicit(&ilmstat->stat, treestat, memory_order_relaxed); - return ilmstat; -} - -//****************************************************************************** -// String output -//****************************************************************************** - -void -load_module_tostr(void* lm, char str[]) -{ - load_module_t* ldmod = (load_module_t*)lm; - if (ldmod) { - snprintf(str, LDMOD_NAME_LEN, "%s%s%d", ldmod->name, " ", ldmod->id); - } - else { - snprintf(str, LDMOD_NAME_LEN, "%s", "nil"); - } -} - -void -load_module_print(void* lm) -{ - char str[LDMOD_NAME_LEN]; - load_module_tostr(lm, str); - printf("%s", str); -} - -static char -ILdMod_Stat_MaxSpaces[] = " "; - -void -ildmod_stat_tostr(void* ilms, char str[]) -{ - ildmod_stat_t* ildmod_stat = (ildmod_stat_t*)ilms; - char intervalstr[MAX_INTERVAL_STR]; - interval_t_tostr(ildmod_stat->interval, intervalstr); - char ldmodstr[LDMOD_NAME_LEN]; - load_module_tostr(ildmod_stat->loadmod, ldmodstr); - char statstr[MAX_STAT_STR]; - treestat_tostr(atomic_load_explicit(&ildmod_stat->stat, memory_order_relaxed), statstr); - sprintf(str, "(%s %s %s)", intervalstr, ldmodstr, statstr); -} - -void -ildmod_stat_print(void* ilms) -{ - char str[MAX_ILDMODSTAT_STR]; - ildmod_stat_tostr(ilms, str); - printf("%s", str); -} - -void -treestat_tostr(tree_stat_t stat, char str[]) -{ - switch (stat) { - case NEVER: strcpy(str, " NEVER"); break; - case DEFERRED: strcpy(str, " DEFERRED"); break; - case FORTHCOMING: strcpy(str, "FORTHCOMING"); break; - case READY: strcpy(str, " READY"); break; - default: strcpy(str, "STAT_ERROR"); - } -} - -void -treestat_print(tree_stat_t ts) -{ - char statstr[MAX_STAT_STR]; - treestat_tostr(ts, statstr); - printf("%s", statstr); -} - -/* - * the max spaces occupied by "([start_address ... end_address), load module xx, status) - */ -char* -ildmod_stat_maxspaces() -{ - return ILdMod_Stat_MaxSpaces; -} diff --git a/src/tool/hpcrun/unwind/common/ildmod_stat.h b/src/tool/hpcrun/unwind/common/ildmod_stat.h deleted file mode 100644 index fac3608edd..0000000000 --- a/src/tool/hpcrun/unwind/common/ildmod_stat.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * ildmod_stat.h - * - * Pair of interval_ldmod_pair_t and tree_stat_t. - * (([s, e), lm), stat) - * - * Author: dxnguyen - */ - -#ifndef __ILDMOD_STAT_H__ -#define __ILDMOD_STAT_H__ - -//****************************************************************************** -// local include files -//****************************************************************************** - -#include -#include -#include -#include "interval_t.h" - - -//****************************************************************************** -// macro -//****************************************************************************** - -#define MAX_STAT_STR 14 -#define LDMOD_NAME_LEN 128 -#define MAX_ILDMODSTAT_STR MAX_INTERVAL_STR+LDMOD_NAME_LEN+MAX_STAT_STR - -//****************************************************************************** -// type -//****************************************************************************** - -// Tree status -typedef enum { - NEVER, DEFERRED, FORTHCOMING, READY -} tree_stat_t; - -// {interval, load_module, tree status} -typedef struct ildmod_stat_s { - interval_t *interval; - load_module_t *loadmod; - _Atomic(tree_stat_t) stat; -} ildmod_stat_t; - -//****************************************************************************** -// Constructors -//****************************************************************************** - -ildmod_stat_t * -ildmod_stat_build(uintptr_t start, uintptr_t end, load_module_t *ldmod, - tree_stat_t treestat, mem_alloc m_alloc); - -//****************************************************************************** -// String output -//****************************************************************************** - -/* - * Concrete implementation of the abstract function val_tostr - * of the generic_val class. - * pre-condition: ilmp is of type interval_ldmod_pair_t* - */ - -void -load_module_tostr(void* lm, char str[]); - -void -load_module_print(void* lm); - -/* - * the max spaces occupied by "([start_address ... end_address), load module xx) - */ -char* -interval_ldmod_maxspaces(); - - -/* - * Concrete implementation of the abstract function val_tostr - * of the ildmod_stat class. - * pre-condition: ilms is of type ildmod_stat_t* - */ -void -ildmod_stat_tostr(void* ilms, char str[]); - -void -ildmod_stat_print(void* ilms); - -void -treestat_tostr(tree_stat_t stat, char str[]); - -void -treestat_print(tree_stat_t ts); - -/* - * the max spaces occupied by "([start_address ... end_address), load module xx, status) - */ -char* -ildmod_stat_maxspaces(); - -#endif /* __ILDMOD_STAT_H__ */ diff --git a/src/tool/hpcrun/unwind/common/interval_t.c b/src/tool/hpcrun/unwind/common/interval_t.c index 2a67d01900..62840c866d 100644 --- a/src/tool/hpcrun/unwind/common/interval_t.c +++ b/src/tool/hpcrun/unwind/common/interval_t.c @@ -1,9 +1,3 @@ -/* - * interval_t.c - * - * Author: dxnguyen - */ - //****************************************************************************** // global include files //****************************************************************************** @@ -23,16 +17,6 @@ static char Interval_MaxSpaces[] = " "; -// pre-condition: start <= end -interval_t* -interval_t_new(uintptr_t start, uintptr_t end, mem_alloc m_alloc) -{ - interval_t* ptr_interval = (interval_t*)m_alloc(sizeof(interval_t)); - ptr_interval->start = start; - ptr_interval->end = end; - return ptr_interval; -} - int interval_t_cmp(void* lhs, void* rhs) { diff --git a/src/tool/hpcrun/unwind/common/interval_t.h b/src/tool/hpcrun/unwind/common/interval_t.h index a26e134406..67b35bc796 100644 --- a/src/tool/hpcrun/unwind/common/interval_t.h +++ b/src/tool/hpcrun/unwind/common/interval_t.h @@ -1,15 +1,3 @@ -/* - * interval_t.h - * - * Structure representing a right-opened interval of the form [a, b), where - * a and b are pointers. - * - * Viewed as a concrete "subclass" of the generic_val class defined in - * generic_val.h. - * - * Author: dxnguyen - */ - #ifndef __PTRINTERVAL_T_H__ #define __PTRINTERVAL_T_H__ @@ -41,15 +29,6 @@ typedef struct interval_s { } interval_t; -//****************************************************************************** -// Constructor -//****************************************************************************** - -// pre-condition: start <= end -interval_t* -interval_t_new(uintptr_t start, uintptr_t end, mem_alloc m_alloc); - - //****************************************************************************** // Comparison //****************************************************************************** @@ -70,12 +49,12 @@ interval_t_cmp(void* p1, void* p2); * check if address is inside of interval, i.e. start <= address < end * * // special boundary case: - * if (address == UINTPTR_MAX && interval->start == UINTPTR_MAX) + * if (address == UINTPTR_MAX && interval.start == UINTPTR_MAX) * return 0; * - * if address < interval->start , i.e. interval is "greater than" address + * if address < interval.start , i.e. interval is "greater than" address * return 1 - * if interval->start <= address < interval.end, i.e. address is inside interval + * if interval.start <= address < interval.end, i.e. address is inside interval * return 0 * else , i.e. interval is "less than" address * returns -1 @@ -92,7 +71,7 @@ interval_t_inrange(void* interval, void* address); * concrete implementation of the abstract val_tostr function of the generic_val class. * pre-condition: ptr_interval is of type ptrinterval_t* * pre-condition: result[] is an array of length >= MAX_INTERVAL_STR - * post-condition: result[] is a string of the form [interval->start, interval->end) + * post-condition: result[] is a string of the form [interval.start, interval.end) */ void interval_t_tostr(void* interval, char result[]); diff --git a/src/tool/hpcrun/unwind/common/unwindr_info.h b/src/tool/hpcrun/unwind/common/unwindr_info.h index 49ce198468..aaada5c74e 100644 --- a/src/tool/hpcrun/unwind/common/unwindr_info.h +++ b/src/tool/hpcrun/unwind/common/unwindr_info.h @@ -53,14 +53,21 @@ //*************************** User Include Files **************************** -#include "ildmod_stat.h" #include "binarytree_uwi.h" +#include +#include "interval_t.h" -//******************************* Types ************************************* +//****************************************************************************** +// type +//****************************************************************************** + +// Tree status +typedef enum { + NEVER, DEFERRED, FORTHCOMING, READY +} tree_stat_t; typedef struct unwindr_info_s { - uintptr_t start; - uintptr_t end; + interval_t interval; load_module_t *lm; tree_stat_t treestat; bitree_uwi_t *btuwi; diff --git a/src/tool/hpcrun/unwind/common/uw_recipe.h b/src/tool/hpcrun/unwind/common/uw_recipe.h deleted file mode 100644 index 676988a363..0000000000 --- a/src/tool/hpcrun/unwind/common/uw_recipe.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * uw_recipe.h - * - * Specification of uw_recipe_t, an abstract unwind recipe. - * Known concrete implementations: - * x86recipe_t defined in x86-unwind-interval.h - * ppc64recipe_t defined in ppc64-unwind-interval.h - * - * Author: dxnguyen - */ - -#ifndef __UW_RECIPE_H__ -#define __UW_RECIPE_H__ - -#include - -//****************************************************************************** -// macro -//****************************************************************************** - -#define MAX_RECIPE_STR 256 - - -//****************************************************************************** -// Abstract data type -//****************************************************************************** - -typedef struct recipe_s uw_recipe_t; - -static inline uw_recipe_t* -uw_recipe_t_new(mem_alloc m_alloc, size_t recipe_size) -{ - return (uw_recipe_t*)m_alloc(recipe_size); -} - -/* - * Concrete implementation of the abstract val_tostr function of the - * generic_val class. - * pre-condition: uwr is of type uw_recipe_t* - */ -void -uw_recipe_tostr(void* uwr, char str[]); - -void -uw_recipe_print(void* uwr); - - -#endif /* __UW_RECIPE_H__ */ diff --git a/src/tool/hpcrun/unwind/common/uw_recipe_map.c b/src/tool/hpcrun/unwind/common/uw_recipe_map.c index 17efd9fa28..1f449d6147 100644 --- a/src/tool/hpcrun/unwind/common/uw_recipe_map.c +++ b/src/tool/hpcrun/unwind/common/uw_recipe_map.c @@ -79,13 +79,13 @@ // local include files //--------------------------------------------------------------------- #include +#include #include "uw_recipe_map.h" #include "unwind-interval.h" #include #include #include #include -#include "ildmod_stat.h" #include "binarytree_uwi.h" #include "segv_handler.h" #include @@ -93,12 +93,6 @@ // libmonitor functions #include -/* - * ilmstat_btuwi_pair.c - * - * Author: dxnguyen - */ - //****************************************************************************** // global include files //****************************************************************************** @@ -115,25 +109,14 @@ #define NUM_NODES 10 -/* - * A pair, whose key is a ildmod_stat_t* and whose value is a bitree_uwi_t. - * ildmod_stat_t (interval-load_module/stat) is a struct whose first component is - * an interval_ldmod_pair_t* and whose second component is a tree_stat_t (tree status) - * bitree_uwi_t (binary tree of unwind intervals) is binary search tree of unwind - * intervals uwi_t*. - * uwi_t is a pair whose key is an interval interval_t, and whose - * value is an unwind recipe, recipe_t, as specified in uw_recipe.h. - * - * Author: dxnguyen - */ - //****************************************************************************** // type //****************************************************************************** typedef struct ilmstat_btuwi_pair_s { - struct ilmstat_btuwi_pair_s *next; - ildmod_stat_t *ilmstat; + interval_t interval; + load_module_t *lm; + _Atomic(tree_stat_t) stat; bitree_uwi_t *btuwi; } ilmstat_btuwi_pair_t; @@ -144,25 +127,25 @@ typedef struct ilmstat_btuwi_pair_s { /* * pre-condition: lhs, rhs are ilmstat_btuwi_pair_t* */ -int +static int ilmstat_btuwi_pair_cmp(void *lhs, void *rhs) { ilmstat_btuwi_pair_t *l = (ilmstat_btuwi_pair_t*)lhs; ilmstat_btuwi_pair_t *r = (ilmstat_btuwi_pair_t*)rhs; return interval_t_cmp( - l->ilmstat->interval, - r->ilmstat->interval); + &l->interval, + &r->interval); } /* * pre-condition: itp is a ilmstat_btuwi_pair_t*, address is a uintptr_t * return interval_ldmod_pair_inrange(itp->first, address) */ -extern int +static int ilmstat_btuwi_pair_inrange(void *itp, void *address) { ilmstat_btuwi_pair_t *p = (ilmstat_btuwi_pair_t*)itp; - return interval_t_inrange(p->ilmstat->interval, address); + return interval_t_inrange(&p->interval, address); } static ilmstat_btuwi_pair_t *GF_ilmstat_btuwi = NULL; // global free list of ilmstat_btuwi_pair_t* @@ -175,22 +158,50 @@ static __thread ilmstat_btuwi_pair_t *current_btuwi = NULL; // Constructors //****************************************************************************** +static inline ilmstat_btuwi_pair_t * +ilmstat__btuwi_pair_init(ilmstat_btuwi_pair_t *node, + tree_stat_t treestat, + load_module_t *lm, + uintptr_t start, + uintptr_t end, + bitree_uwi_t *tree) +{ + atomic_store_explicit(&node->stat, treestat, memory_order_relaxed); + node->lm = lm; + node->interval.start = start; + node->interval.end = end; + node->btuwi = tree; + return node; +} + static inline ilmstat_btuwi_pair_t* -ilmstat_btuwi_pair_build(uintptr_t start, uintptr_t end, load_module_t *ldmod, +ilmstat_btuwi_pair_build(uintptr_t start, uintptr_t end, load_module_t *lm, tree_stat_t treestat, bitree_uwi_t *tree, mem_alloc m_alloc) { ilmstat_btuwi_pair_t* node = m_alloc(sizeof(*node)); - node->next = NULL; - node->ilmstat = ildmod_stat_build(start, end, ldmod, treestat, m_alloc); - node->btuwi = tree; - return node; + return ilmstat__btuwi_pair_init(node, treestat, lm, start, end, tree); +} + +static inline void +push_free_pair(ilmstat_btuwi_pair_t **list, ilmstat_btuwi_pair_t *pair) +{ + pair->btuwi = (bitree_uwi_t *)*list; + *list = pair; +} + +static inline ilmstat_btuwi_pair_t * +pop_free_pair(ilmstat_btuwi_pair_t **list) +{ + ilmstat_btuwi_pair_t *head = *list; + *list = (ilmstat_btuwi_pair_t *)head->btuwi; + return head; } static ilmstat_btuwi_pair_t* ilmstat_btuwi_pair_malloc( uintptr_t start, uintptr_t end, - load_module_t *ldmod, + load_module_t *lm, tree_stat_t treestat, bitree_uwi_t *tree, mem_alloc m_alloc) @@ -209,10 +220,8 @@ ilmstat_btuwi_pair_malloc( // transfer a bunch of nodes the global free list to the local free list int n = 0; while (GF_ilmstat_btuwi && n < NUM_NODES) { - ilmstat_btuwi_pair_t *head = GF_ilmstat_btuwi; - GF_ilmstat_btuwi = GF_ilmstat_btuwi->next; - head->next = _lf_ilmstat_btuwi; - _lf_ilmstat_btuwi = head; + ilmstat_btuwi_pair_t *head = pop_free_pair(&GF_ilmstat_btuwi); + push_free_pair(&_lf_ilmstat_btuwi, head); n++; } } @@ -221,10 +230,8 @@ ilmstat_btuwi_pair_malloc( if (!_lf_ilmstat_btuwi) { /* add a bunch of nodes to _lf_ilmstat_btuwi */ for (int i = 0; i < NUM_NODES; i++) { - ilmstat_btuwi_pair_t *node = - ilmstat_btuwi_pair_build(0, 0, NULL, DEFERRED, NULL, m_alloc); - node->next = _lf_ilmstat_btuwi; - _lf_ilmstat_btuwi = node; + ilmstat_btuwi_pair_t *node = m_alloc(sizeof(*node)); + push_free_pair(&_lf_ilmstat_btuwi, node); } } } @@ -238,17 +245,8 @@ ilmstat_btuwi_pair_malloc( * set its fields using the appropriate parameters * return the head node. */ - ilmstat_btuwi_pair_t *ans = _lf_ilmstat_btuwi; - _lf_ilmstat_btuwi = _lf_ilmstat_btuwi->next; - ans->next = NULL; - ans->btuwi = tree; - ildmod_stat_t *ilmstat = ans->ilmstat; - atomic_store_explicit(&ilmstat->stat, treestat, memory_order_relaxed); - ilmstat->loadmod = ldmod; - interval_t *interval = ilmstat->interval; - interval->start = start; - interval->end = end; - return ans; + ilmstat_btuwi_pair_t *ans = pop_free_pair(&_lf_ilmstat_btuwi); + return ilmstat__btuwi_pair_init(ans, treestat, lm, start, end, tree); } //****************************************************************************** @@ -259,23 +257,72 @@ static void ilmstat_btuwi_pair_free(ilmstat_btuwi_pair_t* pair) { if (!pair) return; - - bitree_uwi_t *btuwi = pair->btuwi; - pair->btuwi = NULL; - bitree_uwi_free(btuwi); + bitree_uwi_free(pair->btuwi); // add pair to the front of the global free list of ilmstat_btuwi_pair_t*: mcs_node_t me; mcs_lock(&GFL_lock, &me); - pair->next = GF_ilmstat_btuwi; - GF_ilmstat_btuwi = pair; + push_free_pair(&GF_ilmstat_btuwi, pair); mcs_unlock(&GFL_lock, &me); } +//--------------------------------------------------------------------- +// local data +//--------------------------------------------------------------------- + +// The concrete representation of the abstract data type unwind recipe map. +static cskiplist_t *addr2recipe_map = NULL; + +// memory allocator for creating addr2recipe_map +// and inserting entries into addr2recipe_map: +static mem_alloc my_alloc = hpcrun_malloc; + //****************************************************************************** // String output //****************************************************************************** + +#define MAX_STAT_STR 14 +#define LDMOD_NAME_LEN 128 +#define MAX_ILDMODSTAT_STR MAX_INTERVAL_STR+LDMOD_NAME_LEN+MAX_STAT_STR + +static void +load_module_tostr(void* lm, char str[]) +{ + load_module_t* ldmod = (load_module_t*)lm; + if (ldmod) { + snprintf(str, LDMOD_NAME_LEN, "%s%s%d", ldmod->name, " ", ldmod->id); + } + else { + snprintf(str, LDMOD_NAME_LEN, "%s", "nil"); + } +} + +static void +treestat_tostr(tree_stat_t stat, char str[]) +{ + switch (stat) { + case NEVER: strcpy(str, " NEVER"); break; + case DEFERRED: strcpy(str, " DEFERRED"); break; + case FORTHCOMING: strcpy(str, "FORTHCOMING"); break; + case READY: strcpy(str, " READY"); break; + default: strcpy(str, "STAT_ERROR"); + } +} + +static void +ildmod_stat_tostr(void* ilms, char str[]) +{ + ilmstat_btuwi_pair_t *pair = ilms; + char intervalstr[MAX_INTERVAL_STR]; + interval_t_tostr(&pair->interval, intervalstr); + char ldmodstr[LDMOD_NAME_LEN]; + load_module_tostr(pair->lm, ldmodstr); + char statstr[MAX_STAT_STR]; + treestat_tostr(atomic_load_explicit(&pair->stat, memory_order_relaxed), statstr); + sprintf(str, "(%s %s %s)", intervalstr, ldmodstr, statstr); +} + /* * Compute the string representation of ilmstat_btuwi_pair_t with appropriate * indentation of the second component which is a binary tree. @@ -285,11 +332,10 @@ static void ilmstat_btuwi_pair_tostr_indent(void* itp, char* indents, char str[]) { ilmstat_btuwi_pair_t* it_pair = (ilmstat_btuwi_pair_t*)itp; - ildmod_stat_t *ilms = it_pair->ilmstat; bitree_uwi_t *tree = it_pair->btuwi; char firststr[MAX_ILDMODSTAT_STR]; char secondstr[MAX_TREE_STR]; - ildmod_stat_tostr(ilms, firststr); + ildmod_stat_tostr(it_pair, firststr); bitree_uwi_tostring_indent(tree, indents, secondstr); snprintf(str, strlen(firststr) + strlen(secondstr) + 6, "%s%s%s%s%s", "(", firststr, ", ", secondstr, ")"); @@ -302,16 +348,17 @@ max_ilmstat_btuwi_pair_len() } -//--------------------------------------------------------------------- -// local data -//--------------------------------------------------------------------- - -// The concrete representation of the abstract data type unwind recipe map. -static cskiplist_t *addr2recipe_map = NULL; +static char +ILdMod_Stat_MaxSpaces[] = " "; -// memory allocator for creating addr2recipe_map -// and inserting entries into addr2recipe_map: -static mem_alloc my_alloc = hpcrun_malloc; +/* + * the max spaces occupied by "([start_address ... end_address), load module xx, status) + */ +static char* +ildmod_stat_maxspaces() +{ + return ILdMod_Stat_MaxSpaces; +} //--------------------------------------------------------------------- // private operations @@ -381,15 +428,11 @@ uw_recipe_map_unpoison(uintptr_t start, uintptr_t end) #if UW_RECIPE_MAP_DEBUG assert(ilmstat_btuwi != NULL); // start should be in range of some poisoned interval - - ildmod_stat_t* ilmstat = ilmstat_btuwi->ilmstat; - assert(ilmstat != NULL); - assert(atomic_load_explicit(&ilmstat->stat, memory_order_relaxed) == NEVER); // should be a poisoned node + assert(atomic_load_explicit(&ilmstat_btuwi->stat, memory_order_relaxed) == NEVER); // should be a poisoned node #endif - interval_t* interval = ilmstat_btuwi->ilmstat->interval; - uintptr_t s0 = interval->start; - uintptr_t e0 = interval->end; + uintptr_t s0 = ilmstat_btuwi->interval.start; + uintptr_t e0 = ilmstat_btuwi->interval.end; uw_recipe_map_cmp_del_bulk_unsynch(ilmstat_btuwi, ilmstat_btuwi); uw_recipe_map_poison(s0, start); uw_recipe_map_poison(end, e0); @@ -402,11 +445,10 @@ uw_recipe_map_repoison(uintptr_t start, uintptr_t end) if (start > 0) { ilmstat_btuwi_pair_t* ileft = uw_recipe_map_inrange_find(start - 1); if (ileft) { - ildmod_stat_t* ilmstat = ileft->ilmstat; - if ((ilmstat->interval->end == start) && - (NEVER == atomic_load_explicit(&ilmstat->stat, memory_order_acquire))) { + if ((ileft->interval.end == start) && + (NEVER == atomic_load_explicit(&ileft->stat, memory_order_acquire))) { // poisoned interval adjacent on the left - start = ilmstat->interval->start; + start = ileft->interval.start; uw_recipe_map_cmp_del_bulk_unsynch(ileft, ileft); } } @@ -414,11 +456,10 @@ uw_recipe_map_repoison(uintptr_t start, uintptr_t end) if (end < UINTPTR_MAX) { ilmstat_btuwi_pair_t* iright = uw_recipe_map_inrange_find(end+1); if (iright) { - ildmod_stat_t* ilmstat = iright->ilmstat; - if ((ilmstat->interval->start == end) && - (NEVER == atomic_load_explicit(&ilmstat->stat, memory_order_acquire))) { + if ((iright->interval.start == end) && + (NEVER == atomic_load_explicit(&iright->stat, memory_order_acquire))) { // poisoned interval adjacent on the right - end = ilmstat->interval->end; + end = iright->interval.end; uw_recipe_map_cmp_del_bulk_unsynch(iright, iright); } } @@ -439,6 +480,18 @@ uw_recipe_map_report_and_dump(const char *op, void *start, void *end) #endif +#if UW_RECIPE_MAP_DEBUG_VERBOSE +static void +uw_recipe_map_report_and_dump(const char *op, void *start, void *end) +{ + uw_recipe_map_report(op, start, end); + uw_recipe_map_print(); +} +#else +#define uw_recipe_map_report_and_dump(op, start, end) +#endif + + static void uw_recipe_map_notify_map(void *start, void *end) { @@ -482,10 +535,8 @@ uw_recipe_map_notify_init() static void uw_cleanup(void) { - if (current_btuwi) { - ildmod_stat_t *ilmstat = current_btuwi->ilmstat; - atomic_store_explicit(&ilmstat->stat, NEVER, memory_order_release); - } + if (current_btuwi) + atomic_store_explicit(¤t_btuwi->stat, NEVER, memory_order_release); } //--------------------------------------------------------------------- @@ -495,7 +546,7 @@ uw_cleanup(void) void uw_recipe_map_init(void) { - + hpcrun_set_real_siglongjmp(); #if UW_RECIPE_MAP_DEBUG fprintf(stderr, "uw_recipe_map_init: call a2r_map_init(my_alloc) ... \n"); #endif @@ -544,8 +595,8 @@ uw_recipe_map_lookup(void *addr, unwindr_info_t *unwr_info) unwr_info->btuwi = NULL; unwr_info->treestat = NEVER; unwr_info->lm = NULL; - unwr_info->start = 0; - unwr_info->end = 0; + unwr_info->interval.start = 0; + unwr_info->interval.end = 0; // check if addr is already in the range of an interval key in the map ilmstat_btuwi_pair_t* ilm_btui = @@ -584,38 +635,34 @@ uw_recipe_map_lookup(void *addr, unwindr_info_t *unwr_info) assert(ilm_btui != NULL); #endif - ildmod_stat_t *ilmstat = ilm_btui->ilmstat; tree_stat_t oldstat = DEFERRED; - if (atomic_compare_exchange_strong_explicit(&ilmstat->stat, &oldstat, FORTHCOMING, + if (atomic_compare_exchange_strong_explicit(&ilm_btui->stat, &oldstat, FORTHCOMING, memory_order_release, memory_order_relaxed)) { // it is my responsibility to build the tree of intervals for the function - interval_t *interval = ilmstat->interval; - void *fcn_start = (void*)interval->start; - void *fcn_end = (void*)interval->end; + void *fcn_start = (void*)ilm_btui->interval.start; + void *fcn_end = (void*)ilm_btui->interval.end; // potentially crash in this statement. need to save the state current_btuwi = ilm_btui; btuwi_status_t btuwi_stat = build_intervals(fcn_start, fcn_end - fcn_start, my_alloc); if (btuwi_stat.first == NULL) { + atomic_store_explicit(&ilm_btui->stat, NEVER, memory_order_release); TMSG(UW_RECIPE_MAP, "BAD build_intervals failed: fcn range %p to %p", fcn_start, fcn_end); return false; } - ilm_btui->btuwi = bitree_uwi_rebalance(btuwi_stat.first); + ilm_btui->btuwi = bitree_uwi_rebalance(btuwi_stat.first, btuwi_stat.count); current_btuwi = NULL; - atomic_store_explicit(&ilmstat->stat, READY, memory_order_release); + atomic_store_explicit(&ilm_btui->stat, READY, memory_order_release); } - else switch (oldstat) { - case NEVER: + else { + while (FORTHCOMING == oldstat) + oldstat = atomic_load_explicit(&ilm_btui->stat, memory_order_acquire); + if (oldstat == NEVER) { // addr is in the range of some poisoned load module return false; - case FORTHCOMING: - // invariant: ilm_btui is non-null - while (READY != atomic_load_explicit(&ilmstat->stat, memory_order_acquire)); - break; - default: - break; + } } TMSG(UW_RECIPE_MAP_LOOKUP, "found in unwind tree: addr %p", addr); @@ -623,10 +670,8 @@ uw_recipe_map_lookup(void *addr, unwindr_info_t *unwr_info) bitree_uwi_t *btuwi = ilm_btui->btuwi; unwr_info->btuwi = bitree_uwi_inrange(btuwi, (uintptr_t)addr); unwr_info->treestat = READY; - unwr_info->lm = ilmstat->loadmod; - interval_t *interval = ilmstat->interval; - unwr_info->start = interval->start; - unwr_info->end = interval->end; + unwr_info->lm = ilm_btui->lm; + unwr_info->interval = ilm_btui->interval; return true; } diff --git a/src/tool/hpcrun/unwind/generic-libunwind/libunw-unwind.c b/src/tool/hpcrun/unwind/generic-libunwind/libunw-unwind.c index 0913296537..3e7fe81c0a 100644 --- a/src/tool/hpcrun/unwind/generic-libunwind/libunw-unwind.c +++ b/src/tool/hpcrun/unwind/generic-libunwind/libunw-unwind.c @@ -96,8 +96,11 @@ #include #include +#include #include #include +#include +#include #include //************************************************ @@ -125,12 +128,10 @@ compute_normalized_ips(hpcrun_unw_cursor_t* cursor) // hpcrun_unw_init // ---------------------------------------------------------- -extern void hpcrun_set_real_siglongjmp(void); - void hpcrun_unw_init(void) { - hpcrun_set_real_siglongjmp(); + uw_recipe_map_init(); } @@ -180,27 +181,23 @@ hpcrun_unw_get_ra_loc(hpcrun_unw_cursor_t* c) // except for pc_norm and pc_unnorm. // void -hpcrun_unw_init_cursor(hpcrun_unw_cursor_t* h_cursor, void* context) +hpcrun_unw_init_cursor(hpcrun_unw_cursor_t* cursor, void* context) { - unw_cursor_t *cursor = &(h_cursor->uc); + unw_cursor_t *unw_cursor = &(cursor->uc); unw_context_t *ctx = (unw_context_t *) context; unw_word_t pc; - if (ctx != NULL && unw_init_local_signal(cursor, ctx) == 0) { - unw_get_reg(cursor, UNW_REG_IP, &pc); + if (ctx != NULL && unw_init_local_signal(unw_cursor, ctx) == 0) { + unw_get_reg(unw_cursor, UNW_REG_IP, &pc); } else { pc = 0; } - h_cursor->sp = NULL; - h_cursor->bp = NULL; - h_cursor->pc_unnorm = (void *) pc; - h_cursor->intvl = &(h_cursor->real_intvl); - h_cursor->real_intvl.lm = NULL; + cursor->pc_unnorm = (void *) pc; - compute_normalized_ips(h_cursor); + compute_normalized_ips(cursor); - TMSG(UNW, "init cursor pc = %p\n", h_cursor->pc_unnorm); + TMSG(UNW, "init cursor pc = %p\n", cursor->pc_unnorm); } @@ -215,57 +212,121 @@ hpcrun_unw_init_cursor(hpcrun_unw_cursor_t* h_cursor, void* context) // --------------------------------------------------------- step_state -hpcrun_unw_step(hpcrun_unw_cursor_t* h_cursor) +hpcrun_unw_step(hpcrun_unw_cursor_t* cursor) { // this should never be NULL - if (h_cursor == NULL) { + if (cursor == NULL) { TMSG(UNW, "unw_step: internal error: cursor ptr is NULL\n"); return STEP_ERROR; } // starting pc - unw_cursor_t *cursor = &(h_cursor->uc); + unw_cursor_t *unw_cursor = &(cursor->uc); unw_word_t tmp; void *pc; - unw_get_reg(cursor, UNW_REG_IP, &tmp); + unw_get_reg(unw_cursor, UNW_REG_IP, &tmp); pc = (void *) tmp; // full unwind: stop at libmonitor fence. this is where we hope the // unwind stops. - if (monitor_unwind_process_bottom_frame(pc) - || monitor_unwind_thread_bottom_frame(pc)) - { - TMSG(UNW, "unw_step: stop at monitor fence: %p\n", pc); - return STEP_STOP; - } - - int ret = unw_step(cursor); - - // step error, almost never happens with libunwind. - if (ret < 0) { - TMSG(UNW, "unw_step: error: unw_step failed at: %p\n", pc); - return STEP_ERROR; - } - - // we prefer to stop at monitor fence, but must also stop here. - if (ret == 0) { - TMSG(UNW, "unw_step: stop at unw_step: %p\n", pc); - return STEP_STOP; - } + cursor->fence = (monitor_unwind_process_bottom_frame(pc) ? FENCE_MAIN : + monitor_unwind_thread_bottom_frame(pc)? FENCE_THREAD : FENCE_NONE); + if (cursor->fence != FENCE_NONE) + { + TMSG(UNW, "unw_step: stop at monitor fence: %p\n", pc); + return STEP_STOP; + } + + //----------------------------------------------------------- + // compute unwind information for the caller's pc + //----------------------------------------------------------- + unwindr_info_t unwr_info; + bool found = uw_recipe_map_lookup(pc, &unwr_info); + if (!found) + { + TMSG(UNW, "unw_step: error: unw_step failed at: %p\n", pc); + return STEP_ERROR; + } + + bitree_uwi_t* uw = unwr_info.btuwi; + uwi_t *uwi = bitree_uwi_rootval(uw); + unw_apply_reg_state(unw_cursor, uwi->recipe); // update for new pc - unw_get_reg(cursor, UNW_REG_IP, &tmp); + unw_get_reg(unw_cursor, UNW_REG_IP, &tmp); pc = (void *) tmp; - h_cursor->sp = NULL; - h_cursor->bp = NULL; - h_cursor->pc_unnorm = pc; - h_cursor->intvl = &(h_cursor->real_intvl); - h_cursor->real_intvl.lm = NULL; + cursor->pc_unnorm = pc; - compute_normalized_ips(h_cursor); + compute_normalized_ips(cursor); TMSG(UNW, "unw_step: advance pc: %p\n", pc); return STEP_OK; } + +//*************************************************************************** +// unwind_interval interface +//*************************************************************************** + +struct builder +{ + mem_alloc m_alloc; + bitree_uwi_t *latest; + int count; +}; + +static int +dwarf_reg_states_callback(void *token, + void *rs, + size_t size, + unw_word_t start_ip, unw_word_t end_ip) +{ + struct builder *b = token; + bitree_uwi_t *u = bitree_uwi_malloc(b->m_alloc, size); + bitree_uwi_set_rightsubtree(b->latest, u); + uwi_t *uwi = bitree_uwi_rootval(u); + uwi->interval.start = (uintptr_t)start_ip; + uwi->interval.end = (uintptr_t)end_ip; + memcpy(uwi->recipe, rs, size); + b->latest = u; + b->count++; + hpcrun_stats_num_unwind_intervals_total_inc(); + return 0; +} + + +static btuwi_status_t +libunw_build_intervals(char *beg_insn, unsigned int len, mem_alloc m_alloc) +{ + unw_context_t uc; + unw_getcontext(&uc); + unw_cursor_t c; + unw_init_local_signal(&c, &uc); + unw_set_reg(&c, UNW_REG_IP, (intptr_t)beg_insn); + void *space[2]; // enough space for any binarytree + bitree_uwi_t *dummy = (bitree_uwi_t*)space; + struct builder b = {m_alloc, dummy, 0}; + int status = unw_reg_states_iterate(&c, dwarf_reg_states_callback, &b); + /* whatever libutils says about the last address range, + * we insist that it extend to the last address of this + * function range. */ + bitree_uwi_rootval(b.latest)->interval.end = (uintptr_t)(beg_insn + len); + bitree_uwi_set_rightsubtree(b.latest, NULL); + + btuwi_status_t stat; + stat.first_undecoded_ins = NULL; + stat.count = b.count; + stat.errcode = status; + stat.first = bitree_uwi_rightsubtree(dummy); + + return stat; +} + +btuwi_status_t +build_intervals(char *ins, unsigned int len, mem_alloc m_alloc) +{ + btuwi_status_t stat = libunw_build_intervals(ins, len, m_alloc); + return stat; +} + diff --git a/src/tool/hpcrun/unwind/generic-libunwind/unw-datatypes-specific.h b/src/tool/hpcrun/unwind/generic-libunwind/unw-datatypes-specific.h index de85d97a7f..fa36daa9d1 100644 --- a/src/tool/hpcrun/unwind/generic-libunwind/unw-datatypes-specific.h +++ b/src/tool/hpcrun/unwind/generic-libunwind/unw-datatypes-specific.h @@ -20,21 +20,14 @@ typedef struct { typedef struct hpcrun_unw_cursor_t { - unw_cursor_t uc; - void* sp; - void* bp; void* pc_unnorm; - ip_normalized_t pc_norm; + unw_cursor_t uc; // normalized ip for first instruction in enclosing function ip_normalized_t the_function; + ip_normalized_t pc_norm; + fence_enum_t fence; - fence_enum_t fence; // Details on which fence stopped an unwind - intvl_t* intvl; - load_module_t *lm; // should correspond to intvl at initialization - intvl_t real_intvl; // other unwinders get intervals from elsewhere, - // libunwind does not use intervals, so space for pointer - // allocated internally in cursor } hpcrun_unw_cursor_t; #endif // UNW_DATATYPES_SPECIFIC_H diff --git a/src/tool/hpcrun/unwind/ppc64/ppc64-unwind-interval.c b/src/tool/hpcrun/unwind/ppc64/ppc64-unwind-interval.c index a9be57c278..4d61aa9df4 100644 --- a/src/tool/hpcrun/unwind/ppc64/ppc64-unwind-interval.c +++ b/src/tool/hpcrun/unwind/ppc64/ppc64-unwind-interval.c @@ -132,9 +132,8 @@ new_ui(char *startaddr, // filled in when a successor recipe is linked behind this one or // when the end of the enclosing routine is reached // ---------------------------------------------------------------- - interval_t *interval = uwi->interval; - interval->start = (uintptr_t)startaddr; - interval->end = 0; + uwi->interval.start = (uintptr_t)startaddr; + uwi->interval.end = 0; // ---------------------------------------------------------------- // initialize the unwind recipe for the given interval as specified @@ -514,6 +513,7 @@ ppc64_build_intervals(char *beg_insn, unsigned int len, mem_alloc m_alloc) new_ui(beg_insn, SPTy_Reg, RATy_Reg, PPC_REG_SP, PPC_REG_LR, m_alloc); unwind_interval* ui = beg_ui; unwind_interval* canon_ui = beg_ui; + int count = 1; uint32_t* cur_insn = (uint32_t*) beg_insn; uint32_t* end_insn = (uint32_t*) (beg_insn + len); @@ -685,6 +685,7 @@ ppc64_build_intervals(char *beg_insn, unsigned int len, mem_alloc m_alloc) if (prev_ui != ui) { link_ui(prev_ui, ui); + count++; } cur_insn++; @@ -694,6 +695,7 @@ ppc64_build_intervals(char *beg_insn, unsigned int len, mem_alloc m_alloc) btuwi_status_t stat; stat.first_undecoded_ins = NULL; + stat.count = count; stat.errcode = 0; stat.first = beg_ui; diff --git a/src/tool/hpcrun/unwind/ppc64/ppc64-unwind.c b/src/tool/hpcrun/unwind/ppc64/ppc64-unwind.c index 981d692728..93a3280e35 100644 --- a/src/tool/hpcrun/unwind/ppc64/ppc64-unwind.c +++ b/src/tool/hpcrun/unwind/ppc64/ppc64-unwind.c @@ -84,14 +84,6 @@ #include -//*************************************************************************** -// external declarations -//*************************************************************************** - -extern void -hpcrun_set_real_siglongjmp(void); - - //*************************************************************************** // macros @@ -136,7 +128,7 @@ hpcrun_check_fence(void* ip); static void compute_normalized_ips(hpcrun_unw_cursor_t* cursor) { - void *func_start_pc = (void*) cursor->unwr_info.start; + void *func_start_pc = (void*) cursor->unwr_info.interval.start; load_module_t* lm = cursor->unwr_info.lm; cursor->pc_norm = hpcrun_normalize_ip(cursor->pc_unnorm, lm); @@ -197,7 +189,6 @@ void hpcrun_unw_init(void) { uw_recipe_map_init(); - hpcrun_set_real_siglongjmp(); } int @@ -208,7 +199,7 @@ hpcrun_unw_get_ip_norm_reg(hpcrun_unw_cursor_t* c, ip_normalized_t* reg_value) int -hpcrun_unw_get_ip_unnorm_reg(hpcrun_unw_cursor_t* c, unw_word_t* reg_value) +hpcrun_unw_get_ip_unnorm_reg(hpcrun_unw_cursor_t* c, void** reg_value) { return hpcrun_unw_get_unnorm_reg(c, UNW_REG_IP, reg_value); } diff --git a/src/tool/hpcrun/unwind/ppc64/unw-datatypes-specific.h b/src/tool/hpcrun/unwind/ppc64/unw-datatypes-specific.h index 6ab08e13df..b5de87c177 100644 --- a/src/tool/hpcrun/unwind/ppc64/unw-datatypes-specific.h +++ b/src/tool/hpcrun/unwind/ppc64/unw-datatypes-specific.h @@ -48,6 +48,5 @@ #define UNW_DATATYPES_SPECIFIC_H #include -typedef void* unw_word_t; #endif // UNW_DATATYPES_SPECIFIC_H diff --git a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-32bit-icc-variant.c b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-32bit-icc-variant.c index fe105b1e30..8a7d0d7df6 100644 --- a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-32bit-icc-variant.c +++ b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-32bit-icc-variant.c @@ -82,14 +82,16 @@ adjust_icc_variant_intervals(char *ins, int len, btuwi_status_t* stat) for(; UWI_RECIPE(ui)->ra_status != RA_STD_FRAME; ui = UWI_NEXT(ui)); - int ra_correction = UWI_RECIPE(ui)->sp_ra_pos - 4; // N.B. The '4' is only correct for 32 bit - int bp_correction = UWI_RECIPE(ui)->sp_bp_pos; + x86recipe_t *xr = UWI_RECIPE(ui); + int ra_correction = xr->reg.sp_ra_pos - 4; // N.B. The '4' is only correct for 32 bit + int bp_correction = xr->reg.sp_bp_pos; for(; ui; ui = UWI_NEXT(ui)) { - UWI_RECIPE(ui)->bp_ra_pos -= ra_correction; - UWI_RECIPE(ui)->bp_bp_pos -= bp_correction; - UWI_RECIPE(ui)->sp_ra_pos -= ra_correction; - UWI_RECIPE(ui)->sp_bp_pos -= bp_correction; + xr = UWI_RECIPE(ui); + xr->reg.bp_ra_pos -= ra_correction; + xr->reg.bp_bp_pos -= bp_correction; + xr->reg.sp_ra_pos -= ra_correction; + xr->reg.sp_bp_pos -= bp_correction; } return 1; } diff --git a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-32bit-main.c b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-32bit-main.c index 1c74810e1c..51963c4365 100644 --- a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-32bit-main.c +++ b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-32bit-main.c @@ -69,11 +69,12 @@ adjust_32bit_main_intervals(char *ins, int len, btuwi_status_t *stat) // this won't fix all of the intervals, but it will fix the ones // that we care about. while(ui) { - if (UWI_RECIPE(ui)->ra_status == RA_STD_FRAME){ - UWI_RECIPE(ui)->bp_ra_pos = 4; - UWI_RECIPE(ui)->bp_bp_pos = 0; - UWI_RECIPE(ui)->sp_ra_pos = 4; - UWI_RECIPE(ui)->sp_bp_pos = 0; + x86recipe_t *xr = UWI_RECIPE(ui); + if (xr->ra_status == RA_STD_FRAME){ + xr->reg.bp_ra_pos = 4; + xr->reg.bp_bp_pos = 0; + xr->reg.sp_ra_pos = 4; + xr->reg.sp_bp_pos = 0; } ui = UWI_NEXT(ui); } diff --git a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-gcc-main64.c b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-gcc-main64.c index 7ce2c82d10..aba4ae7497 100644 --- a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-gcc-main64.c +++ b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-gcc-main64.c @@ -78,12 +78,13 @@ adjust_gcc_main64_intervals(char *ins, int len, btuwi_status_t *stat) // this is only correct for 64-bit code for(; ui; ui = UWI_NEXT(ui)) { - if (UWI_RECIPE(ui)->ra_status == RA_SP_RELATIVE) continue; - if ((UWI_RECIPE(ui)->ra_status == RA_STD_FRAME) || - (UWI_RECIPE(ui)->ra_status == RA_BP_FRAME)) { - UWI_RECIPE(ui)->ra_status = RA_BP_FRAME; - UWI_RECIPE(ui)->bp_ra_pos = 8; - UWI_RECIPE(ui)->bp_bp_pos = 0; + x86recipe_t *xr = UWI_RECIPE(ui); + if (xr->ra_status == RA_SP_RELATIVE) continue; + if ((xr->ra_status == RA_STD_FRAME) || + (xr->ra_status == RA_BP_FRAME)) { + xr->ra_status = RA_BP_FRAME; + xr->reg.bp_ra_pos = 8; + xr->reg.bp_bp_pos = 0; } } diff --git a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-align32.c b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-align32.c index 1e810eb109..06c42f89bf 100644 --- a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-align32.c +++ b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-align32.c @@ -79,13 +79,14 @@ adjust_intel_align32_intervals(char *ins, int len, btuwi_status_t *stat) // this is only correct for 64-bit code for(; ui; ui = UWI_NEXT(ui)) { - if (UWI_RECIPE(ui)->ra_status == RA_SP_RELATIVE) continue; - if (((UWI_RECIPE(ui)->ra_status == RA_STD_FRAME) || - (UWI_RECIPE(ui)->ra_status == RA_BP_FRAME)) && - (UWI_RECIPE(ui)->bp_status == BP_SAVED)) { - UWI_RECIPE(ui)->ra_status = RA_BP_FRAME; - UWI_RECIPE(ui)->bp_ra_pos = 8; - UWI_RECIPE(ui)->bp_bp_pos = 0; + x86recipe_t *xr = UWI_RECIPE(ui); + if (xr->ra_status == RA_SP_RELATIVE) continue; + if (((xr->ra_status == RA_STD_FRAME) || + (xr->ra_status == RA_BP_FRAME)) && + (xr->reg.bp_status == BP_SAVED)) { + xr->ra_status = RA_BP_FRAME; + xr->reg.bp_ra_pos = 8; + xr->reg.bp_bp_pos = 0; } } diff --git a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-align64.c b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-align64.c index ba8db5b769..2183e29255 100644 --- a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-align64.c +++ b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-align64.c @@ -78,11 +78,12 @@ adjust_intel_align64_intervals(char *ins, int len, btuwi_status_t *stat) // this is only correct for 64-bit code for(; ui; ui = UWI_NEXT(ui)) { - if (UWI_RECIPE(ui)->ra_status == RA_SP_RELATIVE) continue; - if ((UWI_RECIPE(ui)->ra_status == RA_STD_FRAME) || (UWI_RECIPE(ui)->ra_status == RA_BP_FRAME)) { - UWI_RECIPE(ui)->ra_status = RA_BP_FRAME; - UWI_RECIPE(ui)->bp_ra_pos = 8; - UWI_RECIPE(ui)->bp_bp_pos = 0; + x86recipe_t *xr = UWI_RECIPE(ui); + if (xr->ra_status == RA_SP_RELATIVE) continue; + if ((xr->ra_status == RA_STD_FRAME) || (xr->ra_status == RA_BP_FRAME)) { + xr->ra_status = RA_BP_FRAME; + xr->reg.bp_ra_pos = 8; + xr->reg.bp_bp_pos = 0; } } diff --git a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-composer2013-mic.c b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-composer2013-mic.c index 496ce6329d..883e88a571 100644 --- a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-composer2013-mic.c +++ b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel-composer2013-mic.c @@ -84,9 +84,10 @@ adjust_intelmic_intervals(char *ins, int len, btuwi_status_t *stat) // this won't fix all of the intervals, but it will fix the one we care about. while(ui) { - if (UWI_RECIPE(ui)->ra_status == RA_STD_FRAME){ - UWI_RECIPE(ui)->bp_ra_pos = 8; - UWI_RECIPE(ui)->bp_bp_pos = 0; + x86recipe_t *xr = UWI_RECIPE(ui); + if (xr->ra_status == RA_STD_FRAME){ + xr->reg.bp_ra_pos = 8; + xr->reg.bp_bp_pos = 0; } ui = UWI_NEXT(ui); } diff --git a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel11-f90main.c b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel11-f90main.c index 338702791b..5f8499cac9 100644 --- a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel11-f90main.c +++ b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-intel11-f90main.c @@ -70,9 +70,10 @@ adjust_intel11_f90main_intervals(char *ins, int len, btuwi_status_t *stat) // this won't fix all of the intervals, but it will fix the one we care about. while(ui) { - if (UWI_RECIPE(ui)->ra_status == RA_STD_FRAME){ - UWI_RECIPE(ui)->bp_ra_pos = 8; - UWI_RECIPE(ui)->bp_bp_pos = 0; + x86recipe_t *xr = UWI_RECIPE(ui); + if (xr->ra_status == RA_STD_FRAME){ + xr->reg.bp_ra_pos = 8; + xr->reg.bp_bp_pos = 0; } ui = UWI_NEXT(ui); } diff --git a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-linux-dlresolver.c b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-linux-dlresolver.c index 15e25798d3..00cf197fc0 100644 --- a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-linux-dlresolver.c +++ b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-linux-dlresolver.c @@ -96,7 +96,7 @@ adjust_dl_runtime_resolve_unwind_intervals(char *ins, int len, btuwi_status_t *s // one of the signatures matched unwind_interval *ui = stat->first; while(ui) { - UWI_RECIPE(ui)->sp_ra_pos += 16; + UWI_RECIPE(ui)->reg.sp_ra_pos += 16; ui = UWI_NEXT(ui); } return 1; diff --git a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-pgi-mp_pexit.c b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-pgi-mp_pexit.c index ea1d69250a..f3d56c64f6 100644 --- a/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-pgi-mp_pexit.c +++ b/src/tool/hpcrun/unwind/x86-family/manual-intervals/x86-pgi-mp_pexit.c @@ -66,9 +66,10 @@ adjust_pgi_mp_pexit_intervals(char *ins, int len, btuwi_status_t *stat) // this won't fix all of the intervals, but it will fix the one we care about. while(ui) { - if (UWI_RECIPE(ui)->ra_status == RA_SP_RELATIVE){ - UWI_RECIPE(ui)->sp_ra_pos = 0xb0; - UWI_RECIPE(ui)->sp_bp_pos = 0; + x86recipe_t *xr = UWI_RECIPE(ui); + if (xr->ra_status == RA_SP_RELATIVE){ + xr->reg.sp_ra_pos = 0xb0; + xr->reg.sp_bp_pos = 0; } ui = UWI_NEXT(ui); } diff --git a/src/tool/hpcrun/unwind/x86-family/unw-datatypes-specific.h b/src/tool/hpcrun/unwind/x86-family/unw-datatypes-specific.h index 228b28ad7f..8100b18681 100644 --- a/src/tool/hpcrun/unwind/x86-family/unw-datatypes-specific.h +++ b/src/tool/hpcrun/unwind/x86-family/unw-datatypes-specific.h @@ -48,6 +48,5 @@ #define UNW_DATATYPES_SPECIFIC_H #include -typedef void* unw_word_t; #endif // UNW_DATATYPES_SPECIFIC_H diff --git a/src/tool/hpcrun/unwind/x86-family/x86-addsub.c b/src/tool/hpcrun/unwind/x86-family/x86-addsub.c index 9b387496e3..0866b1d92a 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-addsub.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-addsub.c @@ -66,6 +66,9 @@ process_addsub(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *i const xed_operand_t* op0 = xed_inst_operand(xi,0); const xed_operand_t* op1 = xed_inst_operand(xi,1); xed_operand_enum_t op0_name = xed_operand_name(op0); + x86recipe_t *xr = UWI_RECIPE(iarg->current); + x86registers_t reg = xr->reg; + ra_loc istatus = xr->ra_status; if (op0_name == XED_OPERAND_REG0) { xed_reg_enum_t reg0 = xed_decoded_inst_get_reg(xptr, op0_name); @@ -77,7 +80,6 @@ process_addsub(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *i if (xed_operand_name(op1) == XED_OPERAND_IMM0) { int sign = (iclass_eq(xptr, XED_ICLASS_ADD)) ? -1 : 1; long immedv = sign * xed_decoded_inst_get_signed_immediate(xptr); - ra_loc istatus = UWI_RECIPE(iarg->current)->ra_status; if ((istatus == RA_STD_FRAME) && (immedv > 0) && (hw_tmp->state & HW_SP_DECREMENTED)) { //------------------------------------------------------------------- @@ -92,10 +94,9 @@ process_addsub(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *i // 9 December 2007 -- John Mellor-Crummey //------------------------------------------------------------------- } - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - istatus, UWI_RECIPE(iarg->current)->sp_ra_pos + immedv, UWI_RECIPE(iarg->current)->bp_ra_pos, - UWI_RECIPE(iarg->current)->bp_status, UWI_RECIPE(iarg->current)->sp_bp_pos + immedv, - UWI_RECIPE(iarg->current)->bp_bp_pos, m_alloc); + reg.sp_ra_pos += immedv; + reg.sp_bp_pos += immedv; + next = new_ui(nextInsn(iarg, xptr), istatus, ®, m_alloc); if (immedv > 0) { if (HW_TEST_STATE(hw_tmp->state, 0, HW_SP_DECREMENTED)) { @@ -113,25 +114,20 @@ process_addsub(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *i // 9 December 2007 -- John Mellor-Crummey //----------------------------------------------------------------- hw_tmp->uwi = next; - hw_tmp->succ_inst_ptr = - iarg->ins + xed_decoded_inst_get_length(xptr); - hw_tmp->state = - HW_NEW_STATE(hw_tmp->state, HW_SP_DECREMENTED); + hw_tmp->succ_inst_ptr = nextInsn(iarg, xptr); + hw_tmp->state = HW_NEW_STATE(hw_tmp->state, HW_SP_DECREMENTED); iarg->canonical_interval = next; } } } else { - if (UWI_RECIPE(iarg->current)->ra_status != RA_BP_FRAME){ + if (istatus != RA_BP_FRAME){ //------------------------------------------------------------------- // no immediate in add/subtract from stack pointer; switch to // BP_FRAME // // 9 December 2007 -- John Mellor-Crummey //------------------------------------------------------------------- - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), RA_BP_FRAME, - UWI_RECIPE(iarg->current)->sp_ra_pos, UWI_RECIPE(iarg->current)->bp_ra_pos, - UWI_RECIPE(iarg->current)->bp_status, UWI_RECIPE(iarg->current)->sp_bp_pos, - UWI_RECIPE(iarg->current)->bp_bp_pos, m_alloc); + next = new_ui(nextInsn(iarg, xptr), RA_BP_FRAME, ®, m_alloc); iarg->bp_frames_found = true; } } diff --git a/src/tool/hpcrun/unwind/x86-family/x86-and.c b/src/tool/hpcrun/unwind/x86-family/x86-and.c index 0c0b66f98e..170db57bc8 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-and.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-and.c @@ -66,16 +66,12 @@ process_and(xed_decoded_inst_t *xptr, const xed_inst_t *xi, if (op0_name == XED_OPERAND_REG0) { xed_reg_enum_t reg0 = xed_decoded_inst_get_reg(xptr, op0_name); if (x86_isReg_SP(reg0)) { - if (UWI_RECIPE(iarg->current)->bp_status != BP_UNCHANGED) { + x86recipe_t *xr = UWI_RECIPE(iarg->current); + if (xr->reg.bp_status != BP_UNCHANGED) { //---------------------------------------------------------------------- // we are adjusting the stack pointer via 'and' instruction //---------------------------------------------------------------------- - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - RA_BP_FRAME, UWI_RECIPE(iarg->current)->sp_ra_pos, - UWI_RECIPE(iarg->current)->bp_ra_pos, - UWI_RECIPE(iarg->current)->bp_status, - UWI_RECIPE(iarg->current)->sp_bp_pos, - UWI_RECIPE(iarg->current)->bp_bp_pos, m_alloc); + next = new_ui(nextInsn(iarg, xptr), RA_BP_FRAME, &xr->reg, m_alloc); } else { // remember that SP was adjusted by masking bits iarg->sp_realigned = true; diff --git a/src/tool/hpcrun/unwind/x86-family/x86-build-intervals.c b/src/tool/hpcrun/unwind/x86-family/x86-build-intervals.c index fe800edd61..a0ccf4e1d9 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-build-intervals.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-build-intervals.c @@ -82,7 +82,7 @@ static void set_status(btuwi_status_t *status, char *fui, int errcode, btuwi_status_t x86_build_intervals(void *ins, unsigned int len, int noisy, mem_alloc m_alloc); -static void x86_coalesce_unwind_intervals(unwind_interval *ui); +static int x86_coalesce_unwind_intervals(unwind_interval *ui); /****************************************************************************** * interface operations @@ -92,7 +92,6 @@ btuwi_status_t build_intervals(char *ins, unsigned int len, mem_alloc m_alloc) { btuwi_status_t status = x86_build_intervals(ins, len, 0, m_alloc); - bitree_uwi_finalize(status.first); return status; } @@ -123,13 +122,16 @@ x86_build_intervals(void *ins, unsigned int len, int noisy, mem_alloc m_alloc) void *first_ins = ins; void *end = ins + len; + int count = 1; iarg.beg = first_ins; iarg.end = end; iarg.highwatermark = _h; iarg.ins = ins; - iarg.current = new_ui(ins, RA_SP_RELATIVE, 0, 0, BP_UNCHANGED, 0, 0, m_alloc); + x86registers_t reg = {0, 0, BP_UNCHANGED, 0, 0}; + iarg.current = new_ui(ins, RA_SP_RELATIVE, ®, m_alloc); iarg.first = iarg.current; + iarg.restored_canonical = iarg.current; // handle return is different if there are any bp frames @@ -169,7 +171,7 @@ x86_build_intervals(void *ins, unsigned int len, int noisy, mem_alloc m_alloc) } // ensure that we don't move past the end of the interval because of a misaligned instruction - void *nextins = iarg.ins + xed_decoded_inst_get_length(xptr); + void *nextins = nextInsn(&iarg, xptr); if (nextins > end) break; next = process_inst(xptr, &iarg, m_alloc); @@ -177,6 +179,7 @@ x86_build_intervals(void *ins, unsigned int len, int noisy, mem_alloc m_alloc) if (next != iarg.current) { link_ui(iarg.current, next); iarg.current = next; + count++; if (noisy) dump_ui(iarg.current, true); } @@ -186,10 +189,12 @@ x86_build_intervals(void *ins, unsigned int len, int noisy, mem_alloc m_alloc) UWI_END_ADDR(iarg.current) = (uintptr_t)end; - set_status(&status, iarg.ins, error_count, iarg.first); + status.first_undecoded_ins = iarg.ins; + status.errcode = error_count; + status.first = iarg.first; x86_fix_unwind_intervals(iarg.beg, len, &status); - x86_coalesce_unwind_intervals(status.first); + status.count = count - x86_coalesce_unwind_intervals(status.first); return status; } @@ -203,21 +208,11 @@ static bool x86_ui_same_data(x86recipe_t *proto, x86recipe_t *cand) { return ( (proto->ra_status == cand->ra_status) && - (proto->sp_ra_pos == cand->sp_ra_pos) && - (proto->sp_bp_pos == cand->sp_bp_pos) && - (proto->bp_status == cand->bp_status) && - (proto->bp_ra_pos == cand->bp_ra_pos) && - (proto->bp_bp_pos == cand->bp_bp_pos) ); -} - - -static void -set_status(btuwi_status_t *status, char *fui, int errcode, - unwind_interval *first) -{ - status->first_undecoded_ins = fui; - status->errcode = errcode; - status->first = first; + (proto->reg.sp_ra_pos == cand->reg.sp_ra_pos) && + (proto->reg.sp_bp_pos == cand->reg.sp_bp_pos) && + (proto->reg.bp_status == cand->reg.bp_status) && + (proto->reg.bp_ra_pos == cand->reg.bp_ra_pos) && + (proto->reg.bp_bp_pos == cand->reg.bp_bp_pos) ); } // NOTE: following routine has an additional side effect! @@ -234,13 +229,14 @@ set_status(btuwi_status_t *status, char *fui, int errcode, // building time. If more routine-level information items come up, the reduction side // effect of the coalesce routine can be expanded to accomodate. -static void +static int x86_coalesce_unwind_intervals(unwind_interval *ui) { + int num_freed = 0; TMSG(COALESCE,"coalescing interval list starting @ %p",ui); if (! ui) { TMSG(COALESCE," --interval list empty, so no work"); - return; + return num_freed; } unwind_interval *first = ui; @@ -271,6 +267,7 @@ x86_coalesce_unwind_intervals(unwind_interval *ui) bitree_uwi_set_rightsubtree(ui, NULL); bitree_uwi_set_leftsubtree(ui, NULL); bitree_uwi_free(ui); + ++num_freed; ui = current; TMSG(COALESCE,"Intervals match! Extended interval:"); @@ -287,5 +284,5 @@ x86_coalesce_unwind_intervals(unwind_interval *ui) // update first interval with collected info UWI_RECIPE(first)->has_tail_calls = routine_has_tail_calls; - return; + return num_freed; } diff --git a/src/tool/hpcrun/unwind/x86-family/x86-call.c b/src/tool/hpcrun/unwind/x86-family/x86-call.c index 2b9230753e..ffbac5bb03 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-call.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-call.c @@ -68,7 +68,7 @@ call_is_push_next_addr_idiom(xed_decoded_inst_t* xptr, interval_arg_t* iarg) { void* ins = iarg->ins; void* call_addr = x86_get_branch_target(ins, xptr); - void* next_addr = ((char *) ins) + xed_decoded_inst_get_length(xptr); + void* next_addr = nextInsn(iarg, xptr); return (call_addr == next_addr); } @@ -97,10 +97,11 @@ process_call(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar // As if it were a push // if (call_is_push_next_addr_idiom(xptr, iarg)) { - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), UWI_RECIPE(iarg->current)->ra_status, - UWI_RECIPE(iarg->current)->sp_ra_pos + sizeof(void*), UWI_RECIPE(iarg->current)->bp_ra_pos, - UWI_RECIPE(iarg->current)->bp_status, UWI_RECIPE(iarg->current)->sp_bp_pos + sizeof(void*), - UWI_RECIPE(iarg->current)->bp_bp_pos, m_alloc); + x86recipe_t *xr = UWI_RECIPE(iarg->current); + x86registers_t reg = xr->reg; + reg.sp_ra_pos += sizeof(void*); + reg.sp_bp_pos += sizeof(void*); + next = new_ui(nextInsn(iarg, xptr), xr->ra_status, ®, m_alloc); } #ifdef USE_CALL_LOOKAHEAD next = call_lookahead(xptr, iarg->current, iarg->ins); diff --git a/src/tool/hpcrun/unwind/x86-family/x86-canonical.c b/src/tool/hpcrun/unwind/x86-family/x86-canonical.c index 3e6c26eedb..b9a1ca971f 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-canonical.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-canonical.c @@ -82,19 +82,22 @@ reset_to_canonical_interval(xed_decoded_inst_t *xptr, unwind_interval **next, // if the return is not the last instruction in the interval, // set up an interval for code after the return - if (iarg->ins + xed_decoded_inst_get_length(xptr) < iarg->end){ + if ((void*)nextInsn(iarg, xptr) < iarg->end) { if (iarg->bp_frames_found) { // look for first bp frame first = find_first_bp_frame(first); set_ui_canonical(first, iarg->canonical_interval); iarg->canonical_interval = first; } else if (iarg->canonical_interval) { - if (hw_uwi && UWI_RECIPE(hw_uwi)->bp_status != BP_UNCHANGED) - if ((UWI_RECIPE(iarg->canonical_interval)->bp_status == BP_UNCHANGED) || - ((UWI_RECIPE(iarg->canonical_interval)->bp_status == BP_SAVED) && - (UWI_RECIPE(hw_uwi)->bp_status == BP_HOSED))) { + x86recipe_t *xr = hw_uwi ? UWI_RECIPE(hw_uwi) : NULL; + if (xr && xr->reg.bp_status != BP_UNCHANGED) { + bp_loc bp_status = UWI_RECIPE(iarg->canonical_interval)->reg.bp_status; + if ((bp_status == BP_UNCHANGED) || + ((bp_status == BP_SAVED) && + (xr->reg.bp_status == BP_HOSED))) { set_ui_canonical(hw_uwi, iarg->canonical_interval); iarg->canonical_interval = hw_uwi; + } } first = iarg->canonical_interval; } else { @@ -104,24 +107,26 @@ reset_to_canonical_interval(xed_decoded_inst_t *xptr, unwind_interval **next, iarg->canonical_interval = first; } { - ra_loc ra_status = UWI_RECIPE(first)->ra_status; + x86recipe_t *xr = UWI_RECIPE(current); + x86recipe_t *r1 = UWI_RECIPE(first); + x86registers_t reg = r1->reg; + ra_loc ra_status = r1->ra_status; bp_loc bp_status = - (UWI_RECIPE(current)->bp_status == BP_HOSED) ? BP_HOSED : UWI_RECIPE(first)->bp_status; + (xr->reg.bp_status == BP_HOSED) ? BP_HOSED : reg.bp_status; #ifndef FIX_INTERVALS_AT_RETURN - if ((UWI_RECIPE(current)->ra_status != ra_status) || - (UWI_RECIPE(current)->bp_status != bp_status) || - (UWI_RECIPE(current)->sp_ra_pos != UWI_RECIPE(first)->sp_ra_pos) || - (UWI_RECIPE(current)->bp_ra_pos != UWI_RECIPE(first)->bp_ra_pos) || - (UWI_RECIPE(current)->bp_bp_pos != UWI_RECIPE(first)->bp_bp_pos) || - (UWI_RECIPE(current)->sp_bp_pos != UWI_RECIPE(first)->sp_bp_pos)) + if (xr->ra_status != ra_status) || + xr->reg.bp_status != bp_status) || + xr->reg.sp_ra_pos != reg.sp_ra_pos) || + xr->reg.bp_ra_pos != reg.bp_ra_pos) || + xr->reg.bp_bp_pos != reg.bp_bp_pos) || + xr->reg.sp_bp_pos != reg.sp_bp_pos)) #endif { - *next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - ra_status, UWI_RECIPE(first)->sp_ra_pos, UWI_RECIPE(first)->bp_ra_pos, - bp_status, UWI_RECIPE(first)->sp_bp_pos, UWI_RECIPE(first)->bp_bp_pos, - m_alloc); - set_ui_restored_canonical(*next, UWI_RECIPE(iarg->canonical_interval)->prev_canonical); - if (UWI_RECIPE(first)->bp_status != BP_HOSED && bp_status == BP_HOSED) { + reg.bp_status = bp_status; + *next = new_ui(nextInsn(iarg, xptr), ra_status, ®, m_alloc); + iarg->restored_canonical = *next; + set_ui_canonical(*next, UWI_RECIPE(iarg->canonical_interval)->prev_canonical); + if (r1->reg.bp_status != BP_HOSED && bp_status == BP_HOSED) { set_ui_canonical(*next, iarg->canonical_interval); iarg->canonical_interval = *next; } @@ -150,10 +155,16 @@ find_first_bp_frame(unwind_interval *first) unwind_interval * find_first_non_decr(unwind_interval *first, unwind_interval *highwatermark) { - while (first && UWI_NEXT(first) && - (UWI_RECIPE(first)->sp_ra_pos <= UWI_RECIPE(UWI_NEXT(first))->sp_ra_pos) && + if (first == NULL) + return NULL; + int sp_ra_pos = UWI_RECIPE(first)->reg.sp_ra_pos; + int next_ra_pos; + unwind_interval *next; + while ((next = UWI_NEXT(first)) && + (sp_ra_pos <= (next_ra_pos = UWI_RECIPE(next)->reg.sp_ra_pos)) && (first != highwatermark)) { - first = UWI_NEXT(first); + first = next; + sp_ra_pos = next_ra_pos; } return first; } diff --git a/src/tool/hpcrun/unwind/x86-family/x86-cold-path.c b/src/tool/hpcrun/unwind/x86-family/x86-cold-path.c index 89ac2d72ad..504d54c53f 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-cold-path.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-cold-path.c @@ -97,21 +97,24 @@ static bool confirm_cold_path_call(void *loc, interval_arg_t *iarg); //************************************************************************** void -hpcrun_cold_code_fixup(unwind_interval *current, unwind_interval *warm) +hpcrun_cold_code_fixup(unwind_interval *first, unwind_interval *current, unwind_interval *warm) { TMSG(COLD_CODE," --fixing up current intervals with the warm interval"); - int ra_offset = UWI_RECIPE(warm)->sp_ra_pos; - int bp_offset = UWI_RECIPE(warm)->sp_bp_pos; + x86recipe_t *xr = UWI_RECIPE(warm); + int ra_offset = xr->reg.sp_ra_pos; + int bp_offset = xr->reg.sp_bp_pos; if (ra_offset == 0) { TMSG(COLD_CODE," --warm code calling routine has offset 0," " so no action taken"); return; } TMSG(COLD_CODE," --updating sp_ra_pos with offset %d",ra_offset); - for(unwind_interval *intv = current; intv; intv = UWI_PREV(intv)) { - UWI_RECIPE(intv)->sp_ra_pos += ra_offset; - UWI_RECIPE(intv)->sp_bp_pos += bp_offset; - } + unwind_interval *intv = first; + do { + xr = UWI_RECIPE(intv); + xr->reg.sp_ra_pos += ra_offset; + xr->reg.sp_bp_pos += bp_offset; + } while (intv != current && (intv = UWI_NEXT(intv))); } // The cold code detector is called when unconditional jump is encountered @@ -119,7 +122,7 @@ bool hpcrun_is_cold_code(xed_decoded_inst_t *xptr, interval_arg_t *iarg) { void *ins = iarg->ins; - char *ins_end = ins + xed_decoded_inst_get_length(xptr); + char *ins_end = nextInsn(iarg, xptr); if (ins_end == iarg->end) { void *branch_target = x86_get_branch_target(ins,xptr); @@ -139,7 +142,7 @@ hpcrun_is_cold_code(xed_decoded_inst_t *xptr, interval_arg_t *iarg) return false; } - void *beg = (void*)unwr_info.start; + void *beg = (void*)unwr_info.interval.start; if (branch_target == beg) { TMSG(COLD_CODE," --jump is a regular tail call," " NOT a cold code return"); diff --git a/src/tool/hpcrun/unwind/x86-family/x86-cold-path.h b/src/tool/hpcrun/unwind/x86-family/x86-cold-path.h index 0cc9eb16d6..298f91002f 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-cold-path.h +++ b/src/tool/hpcrun/unwind/x86-family/x86-cold-path.h @@ -52,6 +52,6 @@ #include "x86-interval-arg.h" extern bool hpcrun_is_cold_code(xed_decoded_inst_t *xptr, interval_arg_t *iarg); -extern void hpcrun_cold_code_fixup(unwind_interval *current, unwind_interval *warm); +extern void hpcrun_cold_code_fixup(unwind_interval *first, unwind_interval *current, unwind_interval *warm); #endif // X86_COLD_PATH_H diff --git a/src/tool/hpcrun/unwind/x86-family/x86-debug.c b/src/tool/hpcrun/unwind/x86-family/x86-debug.c index 68a84ee06d..07c3054b81 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-debug.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-debug.c @@ -60,26 +60,7 @@ #include "x86-decoder.h" #include "fnbounds_interface.h" -typedef struct { - void* begin; - void* end; -} fnbounds_t; - -static fnbounds_t local; - -fnbounds_t* -x86_fnbounds(void* addr) -{ - unwindr_info_t unwr_info; - if( !uw_recipe_map_lookup(addr, &unwr_info) ) - EMSG("x86_fnbounds: bounds of addr %p taken, but no bounds known", addr); - local.begin = (void*)unwr_info.start; - local.end = (void*)unwr_info.end; - return &local; -} - - -void +static void x86_print_intervals(btuwi_status_t intervals) { unwind_interval *u; @@ -88,24 +69,30 @@ x86_print_intervals(btuwi_status_t intervals) } } -void -x86_dump_intervals(void* addr) +static void +x86_dump_intervals(void *addr, int noisy) { unwindr_info_t unwr_info; - if( !uw_recipe_map_lookup(addr, &unwr_info) ) - EMSG("x86_fnbounds: bounds of addr %p taken, but no bounds known", addr); - void * s = (void*)unwr_info.start; - void * e = (void*)unwr_info.end; + if (!uw_recipe_map_lookup(addr, &unwr_info)) + EMSG("x86_dump_intervals: bounds of addr %p taken, but no bounds known", addr); + void * s = (void*)unwr_info.interval.start; + void * e = (void*)unwr_info.interval.end; btuwi_status_t intervals; - intervals = x86_build_intervals(s, e - s, 0, hpcrun_malloc); + intervals = x86_build_intervals(s, e - s, noisy, hpcrun_malloc); x86_print_intervals(intervals); } void hpcrun_dump_intervals(void* addr) { - x86_dump_intervals(addr); + x86_dump_intervals(addr, 0); +} + +void +hpcrun_dump_intervals_noisy(void* addr) +{ + x86_dump_intervals(addr, 1); } void @@ -145,20 +132,3 @@ x86_dump_ins(void *ins) fprintf(stderr, errbuf); fflush(stderr); } - -void -hpcrun_dump_intervals_noisy(void* addr) -{ - unwindr_info_t unwr_info; - if (!uw_recipe_map_lookup(addr, &unwr_info)) - EMSG("hpcrun_dump_intervals_noisy: bounds of addr %p taken, but no bounds known", addr); - void * s = (void*)unwr_info.start; - void * e = (void*)unwr_info.end; - - btuwi_status_t intervals = x86_build_intervals(s, e - s, 1, hpcrun_malloc); - - unwind_interval * u; - for(u = intervals.first; u; u = UWI_NEXT(u)) { - dump_ui_dbg(u); - } -} diff --git a/src/tool/hpcrun/unwind/x86-family/x86-enter.c b/src/tool/hpcrun/unwind/x86-family/x86-enter.c index 0f81e64955..285b18ae67 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-enter.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-enter.c @@ -79,11 +79,14 @@ process_enter(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *ia } } TMSG(INTV,"new interval from ENTER"); - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - RA_STD_FRAME, - UWI_RECIPE(iarg->current)->sp_ra_pos + offset, 8, BP_SAVED, - UWI_RECIPE(iarg->current)->sp_bp_pos + offset - 8, 0, - m_alloc); + x86registers_t reg = UWI_RECIPE(iarg->current)->reg; + reg.sp_ra_pos += offset; + reg.sp_bp_pos = 8; + reg.bp_status = BP_SAVED; + reg.sp_bp_pos += offset - 8; + reg.bp_bp_pos = 0; + + next = new_ui(nextInsn(iarg, xptr), RA_STD_FRAME, ®, m_alloc); hw_tmp->uwi = next; hw_tmp->state = HW_NEW_STATE(hw_tmp->state, HW_BP_SAVED | diff --git a/src/tool/hpcrun/unwind/x86-family/x86-interval-arg.h b/src/tool/hpcrun/unwind/x86-family/x86-interval-arg.h index 8008c6797e..4c52694129 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-interval-arg.h +++ b/src/tool/hpcrun/unwind/x86-family/x86-interval-arg.h @@ -68,10 +68,15 @@ typedef struct interval_arg_t { bool bp_just_pushed; highwatermark_t highwatermark; bitree_uwi_t *canonical_interval; + unwind_interval *restored_canonical; bool bp_frames_found; void *rax_rbp_equivalent_at; void *return_addr; // A place to store void * return values. bool sp_realigned; // stack pointer was realigned by masking lower bits } interval_arg_t; +static inline char *nextInsn(interval_arg_t *iarg, xed_decoded_inst_t *xptr) { + return iarg->ins + xed_decoded_inst_get_length(xptr); +} + #endif // X86_INTERVAL_ARG_H diff --git a/src/tool/hpcrun/unwind/x86-family/x86-lea.c b/src/tool/hpcrun/unwind/x86-family/x86-lea.c index 738395cb64..57a93b3b6c 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-lea.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-lea.c @@ -62,23 +62,18 @@ process_lea(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg if ((op0_name == XED_OPERAND_REG0)) { x86recipe_t *xr = UWI_RECIPE(next); + x86registers_t reg = xr->reg; xed_reg_enum_t regname = xed_decoded_inst_get_reg(xptr, op0_name); - char *next_ins = iarg->ins + xed_decoded_inst_get_length(xptr); + char *next_ins = nextInsn(iarg, xptr); if (x86_isReg_BP(regname)) { //======================================================================= // action: clobbering the base pointer; begin a new SP_RELATIVE interval // note: we don't check that BP is BP_SAVED; we might have to //======================================================================= - next = new_ui(next_ins, - RA_SP_RELATIVE, - xr->sp_ra_pos, - xr->bp_ra_pos, - BP_HOSED, - xr->sp_bp_pos, - xr->bp_bp_pos, - m_alloc); + reg.bp_status = BP_HOSED; + next = new_ui(next_ins, RA_SP_RELATIVE, ®, m_alloc); if (HW_TEST_STATE(hw_tmp->state, HW_BP_SAVED, HW_BP_OVERWRITTEN) && - (UWI_RECIPE(hw_tmp->uwi)->sp_ra_pos == xr->sp_ra_pos)) { + (UWI_RECIPE(hw_tmp->uwi)->reg.sp_ra_pos == xr->reg.sp_ra_pos)) { hw_tmp->uwi = next; hw_tmp->state = HW_NEW_STATE(hw_tmp->state, HW_BP_OVERWRITTEN); } @@ -99,15 +94,9 @@ process_lea(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg //================================================================== xed_int64_t disp = xed_decoded_inst_get_memory_displacement(xptr, mem_op_index); - - next = new_ui(next_ins, - xr->ra_status, - xr->sp_ra_pos - disp, - xr->bp_ra_pos, - xr->bp_status, - xr->sp_bp_pos - disp, - xr->bp_bp_pos, - m_alloc); + reg.sp_ra_pos -= disp; + reg.sp_bp_pos -= disp; + next = new_ui(next_ins, xr->ra_status, ®, m_alloc); if (disp < 0) { if (HW_TEST_STATE(hw_tmp->state, 0, HW_SP_DECREMENTED)) { diff --git a/src/tool/hpcrun/unwind/x86-family/x86-leave.c b/src/tool/hpcrun/unwind/x86-family/x86-leave.c index f72aaf4c75..660b9b3d8c 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-leave.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-leave.c @@ -55,9 +55,9 @@ unwind_interval * process_leave(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg, mem_alloc m_alloc) { + x86registers_t reg = { 0, 0, BP_UNCHANGED, 0, 0}; unwind_interval *next; - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - RA_SP_RELATIVE, 0, 0, BP_UNCHANGED, 0, 0, m_alloc); + next = new_ui(nextInsn(iarg, xptr), RA_SP_RELATIVE, ®, m_alloc); return next; } diff --git a/src/tool/hpcrun/unwind/x86-family/x86-move.c b/src/tool/hpcrun/unwind/x86-family/x86-move.c index d90add6747..2eb30b1a1b 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-move.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-move.c @@ -76,6 +76,8 @@ process_move(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar xed_operand_enum_t op0_name = xed_operand_name(op0); xed_operand_enum_t op1_name = xed_operand_name(op1); + x86recipe_t *xr = UWI_RECIPE(iarg->current); + x86registers_t reg = xr->reg; if ((op0_name == XED_OPERAND_MEM0) && (op1_name == XED_OPERAND_REG0)) { //------------------------------------------------------------------------ @@ -92,7 +94,7 @@ process_move(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar //-------------------------------------------------------------------- // register being stored is BP (or a copy in RAX) //-------------------------------------------------------------------- - if (UWI_RECIPE(iarg->current)->bp_status == BP_UNCHANGED) { + if (reg.bp_status == BP_UNCHANGED) { //================================================================== // instruction: save caller's BP into the stack // action: create a new interval with @@ -100,13 +102,9 @@ process_move(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar // (2) BP position relative to the stack pointer set // to the offset from SP //================================================================== - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - UWI_RECIPE(iarg->current)->ra_status, UWI_RECIPE(iarg->current)->sp_ra_pos, - UWI_RECIPE(iarg->current)->bp_ra_pos, - BP_SAVED, - xed_decoded_inst_get_memory_displacement(xptr, 0), - UWI_RECIPE(iarg->current)->bp_bp_pos, - m_alloc); + reg.bp_status = BP_SAVED; + reg.bp_ra_pos = xed_decoded_inst_get_memory_displacement(xptr, 0); + next = new_ui(nextInsn(iarg, xptr), xr->ra_status, ®, m_alloc); hw_tmp->uwi = next; hw_tmp->state = HW_NEW_STATE(hw_tmp->state, HW_BP_SAVED); @@ -122,19 +120,17 @@ process_move(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar //-------------------------------------------------------------------- // register being loaded is BP //-------------------------------------------------------------------- - if (UWI_RECIPE(iarg->current)->bp_status != BP_UNCHANGED) { + if (reg.bp_status != BP_UNCHANGED) { int64_t offset = xed_decoded_inst_get_memory_displacement(xptr, 0); xed_reg_enum_t basereg = xed_decoded_inst_get_base_reg(xptr, 0); - if (x86_isReg_SP(basereg) && (offset == UWI_RECIPE(iarg->current)->sp_bp_pos)) { + if (x86_isReg_SP(basereg) && (offset == reg.sp_bp_pos)) { //================================================================ // instruction: restore BP from its saved location in the stack // action: create a new interval with BP status reset to // BP_UNCHANGED //================================================================ - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - RA_SP_RELATIVE, UWI_RECIPE(iarg->current)->sp_ra_pos, - UWI_RECIPE(iarg->current)->bp_ra_pos, BP_UNCHANGED, UWI_RECIPE(iarg->current)->sp_bp_pos, - UWI_RECIPE(iarg->current)->bp_bp_pos, m_alloc); + reg.bp_status = BP_UNCHANGED; + next = new_ui(nextInsn(iarg, xptr), RA_SP_RELATIVE, ®, m_alloc); } else { //================================================================ // instruction: BP is loaded from a memory address DIFFERENT from @@ -142,14 +138,12 @@ process_move(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar // action: create a new interval with BP status reset to // BP_HOSED //================================================================ - if (UWI_RECIPE(iarg->current)->bp_status != BP_HOSED) { - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - RA_SP_RELATIVE, UWI_RECIPE(iarg->current)->sp_ra_pos, - UWI_RECIPE(iarg->current)->bp_ra_pos, BP_HOSED, UWI_RECIPE(iarg->current)->sp_bp_pos, - UWI_RECIPE(iarg->current)->bp_bp_pos, m_alloc); + if (reg.bp_status != BP_HOSED) { + reg.bp_status = BP_HOSED; + next = new_ui(nextInsn(iarg, xptr), RA_SP_RELATIVE, ®, m_alloc); if (HW_TEST_STATE(hw_tmp->state, HW_BP_SAVED, HW_BP_OVERWRITTEN) && - (UWI_RECIPE(hw_tmp->uwi)->sp_ra_pos == UWI_RECIPE(next)->sp_ra_pos)) { + (UWI_RECIPE(hw_tmp->uwi)->reg.sp_ra_pos == reg.sp_ra_pos)) { hw_tmp->uwi = next; hw_tmp->state = HW_NEW_STATE(hw_tmp->state, HW_BP_OVERWRITTEN); @@ -168,10 +162,9 @@ process_move(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar // action: create a new interval with SP status reset to // BP_UNCHANGED //================================================================ - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - RA_SP_RELATIVE, 0, 0, - UWI_RECIPE(iarg->current)->bp_status, UWI_RECIPE(iarg->current)->sp_bp_pos, - UWI_RECIPE(iarg->current)->bp_bp_pos, m_alloc); + reg.sp_ra_pos = 0; + reg.sp_bp_pos = 0; + next = new_ui(nextInsn(iarg, xptr), RA_SP_RELATIVE, ®, m_alloc); } } } else if ((op0_name == XED_OPERAND_REG0) && (op1_name == XED_OPERAND_REG1)){ @@ -185,30 +178,24 @@ process_move(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar // instruction: restore SP from BP // action: begin a new SP_RELATIVE interval //==================================================================== - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - RA_SP_RELATIVE, UWI_RECIPE(iarg->current)->bp_ra_pos, UWI_RECIPE(iarg->current)->bp_ra_pos, - UWI_RECIPE(iarg->current)->bp_status, UWI_RECIPE(iarg->current)->bp_bp_pos, UWI_RECIPE(iarg->current)->bp_bp_pos, - m_alloc); + next = new_ui(nextInsn(iarg, xptr), RA_SP_RELATIVE, ®, m_alloc); } else if (x86_isReg_BP(reg0) && x86_isReg_SP(reg1)) { //==================================================================== // instruction: initialize BP with value of SP to set up a frame ptr // action: begin a new interval //==================================================================== - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - RA_STD_FRAME, - UWI_RECIPE(iarg->current)->sp_ra_pos, UWI_RECIPE(iarg->current)->sp_ra_pos, BP_SAVED, - UWI_RECIPE(iarg->current)->sp_bp_pos, UWI_RECIPE(iarg->current)->sp_bp_pos, - m_alloc); + reg.bp_status = BP_SAVED; + next = new_ui(nextInsn(iarg, xptr), RA_STD_FRAME, ®, m_alloc); if (iarg->sp_realigned) { // SP was previously realigned. correct RA offsets based on typical // frame layout in these circumstances. // assume RA is in word below BP - UWI_RECIPE(next)->bp_ra_pos = - (UWI_RECIPE(next)->bp_bp_pos + x86_bp_size(reg0)); + UWI_RECIPE(next)->reg.bp_ra_pos = + (UWI_RECIPE(next)->reg.bp_bp_pos + x86_bp_size(reg0)); // RA offset wrt SP is the same, since SP == BP - UWI_RECIPE(next)->sp_ra_pos = UWI_RECIPE(next)->bp_ra_pos; + UWI_RECIPE(next)->reg.sp_ra_pos = UWI_RECIPE(next)->reg.bp_ra_pos; // once we've handled SP realignment in the routine prologue, we can // ignore it for the rest of the routine. @@ -224,21 +211,19 @@ process_move(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar //==================================================================== // instruction: copy BP to RAX //==================================================================== - iarg->rax_rbp_equivalent_at = iarg->ins + xed_decoded_inst_get_length(xptr); + iarg->rax_rbp_equivalent_at = nextInsn(iarg, xptr); } else if (x86_isReg_BP(reg0)) { - if (UWI_RECIPE(iarg->current)->bp_status != BP_HOSED){ + if (reg.bp_status != BP_HOSED){ //================================================================== // instruction: move some NON-special register to BP // state: bp_status is NOT BP_HOSED // action: begin a new RA_SP_RELATIVE,BP_HOSED interval //================================================================== - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), - RA_SP_RELATIVE, - UWI_RECIPE(iarg->current)->sp_ra_pos, UWI_RECIPE(iarg->current)->sp_ra_pos, BP_HOSED, - UWI_RECIPE(iarg->current)->sp_bp_pos, UWI_RECIPE(iarg->current)->sp_bp_pos, m_alloc); + reg.bp_status = BP_HOSED; + next = new_ui(nextInsn(iarg, xptr), RA_SP_RELATIVE, ®, m_alloc); if (HW_TEST_STATE(hw_tmp->state, HW_BP_SAVED, HW_BP_OVERWRITTEN) && - (UWI_RECIPE(hw_tmp->uwi)->sp_ra_pos == UWI_RECIPE(next)->sp_ra_pos)) { + (UWI_RECIPE(hw_tmp->uwi)->reg.sp_ra_pos == reg.sp_ra_pos)) { hw_tmp->uwi = next; hw_tmp->state = HW_NEW_STATE(hw_tmp->state, HW_BP_OVERWRITTEN); diff --git a/src/tool/hpcrun/unwind/x86-family/x86-process-inst.c b/src/tool/hpcrun/unwind/x86-family/x86-process-inst.c index 5b0b7399ae..eaa039e2e6 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-process-inst.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-process-inst.c @@ -93,7 +93,7 @@ process_inst(xed_decoded_inst_t *xptr, interval_arg_t *iarg, mem_alloc m_alloc) dump_ui_stderr(ui); } // Fixup current intervals w.r.t. the warm code interval - hpcrun_cold_code_fixup(iarg->current, ui); + hpcrun_cold_code_fixup(iarg->first, iarg->current, ui); } break; diff --git a/src/tool/hpcrun/unwind/x86-family/x86-push.c b/src/tool/hpcrun/unwind/x86-family/x86-push.c index 96b2e83d07..2c82be11ab 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-push.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-push.c @@ -68,8 +68,10 @@ process_push(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar const xed_operand_t *op0 = xed_inst_operand(xi, 0); xed_operand_enum_t op0_name = xed_operand_name(op0); - bp_loc bp_status = UWI_RECIPE(iarg->current)->bp_status; - int sp_bp_pos, size; + x86recipe_t *xr = UWI_RECIPE(iarg->current); + x86registers_t reg = xr->reg; + bp_loc bp_status = reg.bp_status; + int size; switch(iclass(xptr)) { case XED_ICLASS_PUSH: size = sizeof(void*); break; @@ -79,18 +81,17 @@ process_push(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iar default: assert(0); } - sp_bp_pos = UWI_RECIPE(iarg->current)->sp_bp_pos + size; + reg.sp_ra_pos += size; + reg.sp_bp_pos += size; if (op0_name == XED_OPERAND_REG0) { xed_reg_enum_t regname = xed_decoded_inst_get_reg(xptr, op0_name); if (x86_isReg_BP(regname) && bp_status == BP_UNCHANGED) { - bp_status = BP_SAVED; - sp_bp_pos = 0; + reg.bp_status = BP_SAVED; + reg.sp_bp_pos = 0; } } - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), UWI_RECIPE(iarg->current)->ra_status, - UWI_RECIPE(iarg->current)->sp_ra_pos + size, UWI_RECIPE(iarg->current)->bp_ra_pos, bp_status, - sp_bp_pos, UWI_RECIPE(iarg->current)->bp_bp_pos, m_alloc); + next = new_ui(nextInsn(iarg, xptr), xr->ra_status, ®, m_alloc); return next; } @@ -104,7 +105,8 @@ process_pop(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg const xed_operand_t *op0 = xed_inst_operand(xi, 0); xed_operand_enum_t op0_name = xed_operand_name(op0); - bp_loc bp_status = UWI_RECIPE(iarg->current)->bp_status; + x86recipe_t *xr = UWI_RECIPE(iarg->current); + x86registers_t reg = xr->reg; int size; switch(iclass(xptr)) { @@ -115,14 +117,13 @@ process_pop(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg default: assert(0); } + reg.sp_ra_pos += size; + reg.sp_bp_pos += size; if (op0_name == XED_OPERAND_REG0) { xed_reg_enum_t regname = xed_decoded_inst_get_reg(xptr, op0_name); - if (x86_isReg_BP(regname)) bp_status = BP_UNCHANGED; + if (x86_isReg_BP(regname)) reg.bp_status = BP_UNCHANGED; } - next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), UWI_RECIPE(iarg->current)->ra_status, - UWI_RECIPE(iarg->current)->sp_ra_pos + size, UWI_RECIPE(iarg->current)->bp_ra_pos, bp_status, - UWI_RECIPE(iarg->current)->sp_bp_pos + size, UWI_RECIPE(iarg->current)->bp_bp_pos, - m_alloc); + next = new_ui(nextInsn(iarg, xptr), xr->ra_status, ®, m_alloc); return next; } diff --git a/src/tool/hpcrun/unwind/x86-family/x86-return.c b/src/tool/hpcrun/unwind/x86-family/x86-return.c index 8ce99508ad..60795f67d3 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-return.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-return.c @@ -69,53 +69,46 @@ process_return(xed_decoded_inst_t *xptr, bool irdebug, interval_arg_t *iarg, unwind_interval *next = iarg->current; if (UWI_RECIPE(iarg->current)->ra_status == RA_SP_RELATIVE) { - int offset = UWI_RECIPE(iarg->current)->sp_ra_pos; + int offset = UWI_RECIPE(iarg->current)->reg.sp_ra_pos; if (offset != 0) { - unwind_interval *u = iarg->current; - for (;;) { + unwind_interval *u = iarg->restored_canonical; + do { // fix offset - UWI_RECIPE(u)->sp_ra_pos -= offset; - UWI_RECIPE(u)->sp_bp_pos -= offset; - - if (UWI_RECIPE(u)->restored_canonical == 1) { - break; - } - u = UWI_PREV(u); - if (! u) { - break; - } - } + x86recipe_t *xr = UWI_RECIPE(u); + xr->reg.sp_ra_pos -= offset; + xr->reg.sp_bp_pos -= offset; + } while (u != iarg->current && (u = UWI_NEXT(u))); } - if (UWI_RECIPE(iarg->current)->bp_status == BP_HOSED) { + if (UWI_RECIPE(iarg->current)->reg.bp_status == BP_HOSED) { // invariant: when we reach a return, if the BP was overwritten, it // should have been restored. this must be incorrect. let's reset // the bp status for all intervals leading up to this one since // the last canonical restore. - unwind_interval *u = iarg->current; - for (;;) { - if (UWI_RECIPE(u)->bp_status != BP_HOSED) { - break; - } - UWI_RECIPE(u)->bp_status = BP_UNCHANGED; - if (UWI_RECIPE(u)->restored_canonical == 1) { - break; - } - u = UWI_PREV(u); - if (! u) { - break; - } - } + unwind_interval *start = iarg->restored_canonical; + unwind_interval *u = start; + do { + x86recipe_t *xr = UWI_RECIPE(u); + if (xr->reg.bp_status != BP_HOSED) { + start = NULL; + } else if (start == NULL) + start = u; + } while (u != iarg->current && (u = UWI_NEXT(u))); + u = start; + do { + x86recipe_t *xr = UWI_RECIPE(u); + xr->reg.bp_status = BP_UNCHANGED; + } while (u != iarg->current && (u = UWI_NEXT(u))); } } - if (UWI_RECIPE(iarg->current)->bp_status == BP_SAVED) { + if (UWI_RECIPE(iarg->current)->reg.bp_status == BP_SAVED) { suspicious_interval(iarg->ins); } - if (iarg->ins + xed_decoded_inst_get_length(xptr) < iarg->end) { + if ((void*)nextInsn(iarg, xptr) < iarg->end) { //------------------------------------------------------------------------- // the return is not the last instruction in the interval; // set up an interval for code after the return //------------------------------------------------------------------------- - if (plt_is_next(iarg->ins + xed_decoded_inst_get_length(xptr))) { + if (plt_is_next(nextInsn(iarg, xptr))) { //------------------------------------------------------------------------- // the code following the return is a program linkage table. each entry in // the program linkage table should be invoked with the return address at diff --git a/src/tool/hpcrun/unwind/x86-family/x86-unwind-interval.c b/src/tool/hpcrun/unwind/x86-family/x86-unwind-interval.c index 0feba2eb7a..2c3e685a5c 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-unwind-interval.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-unwind-interval.c @@ -79,9 +79,7 @@ suspicious_interval(void *pc) } unwind_interval* -new_ui(char *start, - ra_loc ra_status, unsigned int sp_ra_pos, int bp_ra_pos, - bp_loc bp_status, int sp_bp_pos, int bp_bp_pos, +new_ui(char *start, ra_loc ra_status, const x86registers_t *reg, mem_alloc m_alloc) { bitree_uwi_t *u = bitree_uwi_malloc(m_alloc, sizeof(x86recipe_t)); @@ -93,19 +91,13 @@ new_ui(char *start, uwi_t *uwi = bitree_uwi_rootval(u); - interval_t *interval = uwi->interval; - interval->start = (uintptr_t)start; + uwi->interval.start = (uintptr_t)start; x86recipe_t* x86recipe = (x86recipe_t*) uwi->recipe; x86recipe->ra_status = ra_status; - x86recipe->sp_ra_pos = sp_ra_pos; - x86recipe->bp_ra_pos = bp_ra_pos; - x86recipe->bp_status = bp_status; - x86recipe->sp_bp_pos = sp_bp_pos; - x86recipe->bp_bp_pos = bp_bp_pos; + x86recipe->reg = *reg; x86recipe->prev_canonical = NULL; - x86recipe->restored_canonical = 0; x86recipe->has_tail_calls = false; return u; @@ -118,34 +110,23 @@ set_ui_canonical(unwind_interval *u, unwind_interval *value) UWI_RECIPE(u)->prev_canonical = value; } -void -set_ui_restored_canonical(unwind_interval *u, unwind_interval *value) -{ - UWI_RECIPE(u)->prev_canonical = value; - UWI_RECIPE(u)->restored_canonical = 1; -} - - unwind_interval * fluke_ui(char *loc, unsigned int pos, mem_alloc m_alloc) { bitree_uwi_t *u = bitree_uwi_malloc(m_alloc, sizeof(x86recipe_t)); uwi_t *uwi = bitree_uwi_rootval(u); - interval_t *interval = uwi->interval; - interval->start = (uintptr_t)loc; - interval->end = (uintptr_t)loc; + uwi->interval.start = (uintptr_t)loc; + uwi->interval.end = (uintptr_t)loc; x86recipe_t* x86recipe = (x86recipe_t*) uwi->recipe; x86recipe->ra_status = RA_SP_RELATIVE; - x86recipe->sp_ra_pos = pos; - x86recipe->bp_ra_pos = 0; - x86recipe->bp_status = 0; - x86recipe->sp_bp_pos = 0; - x86recipe->bp_bp_pos = 0; - + x86recipe->reg.sp_ra_pos = pos; + x86recipe->reg.bp_ra_pos = 0; + x86recipe->reg.bp_status = 0; + x86recipe->reg.sp_bp_pos = 0; + x86recipe->reg.bp_bp_pos = 0; x86recipe->prev_canonical = NULL; - x86recipe->restored_canonical = 0; x86recipe->has_tail_calls = false; return u; @@ -156,22 +137,21 @@ link_ui(unwind_interval *current, unwind_interval *next) { UWI_END_ADDR(current) = UWI_START_ADDR(next); bitree_uwi_set_rightsubtree(current, next); - bitree_uwi_set_leftsubtree(next, current); } static void dump_ui_str(unwind_interval *u, char *buf, size_t len) { + x86recipe_t *xr = UWI_RECIPE(u); + x86registers_t reg = xr->reg; snprintf(buf, len, "UWI: [%8p, %8p) " "ra_status=%14s sp_ra_pos=%4d sp_bp_pos=%4d " "bp_status=%12s bp_ra_pos=%4d bp_bp_pos=%4d " - "prev=%14p next=%14p prev_canon=%14p rest_canon=%d " - "tail_call=%d\n", + "next=%14p prev_canon=%14p tail_call=%d\n", (void *) UWI_START_ADDR(u), (void *) UWI_END_ADDR(u), - ra_status_string(UWI_RECIPE(u)->ra_status), UWI_RECIPE(u)->sp_ra_pos, UWI_RECIPE(u)->sp_bp_pos, - bp_status_string(UWI_RECIPE(u)->bp_status), UWI_RECIPE(u)->bp_ra_pos, UWI_RECIPE(u)->bp_bp_pos, - UWI_PREV(u), UWI_NEXT(u), UWI_RECIPE(u)->prev_canonical, UWI_RECIPE(u)->restored_canonical, - UWI_RECIPE(u)->has_tail_calls); + ra_status_string(xr->ra_status), reg.sp_ra_pos, reg.sp_bp_pos, + bp_status_string(reg.bp_status), reg.bp_ra_pos, reg.bp_bp_pos, + UWI_NEXT(u), xr->prev_canonical, UWI_RECIPE(u)->has_tail_calls); } @@ -233,30 +213,13 @@ dump_ui_troll(unwind_interval *u) TMSG(TROLL,buf); } -x86recipe_t* -x86recipe_new(ra_loc ra_status, int sp_ra_pos, int bp_ra_pos, - bp_loc bp_status, int sp_bp_pos, int bp_bp_pos, mem_alloc m_alloc) -{ - x86recipe_t* recipe = (x86recipe_t*)m_alloc(sizeof(x86recipe_t)); - recipe->ra_status = ra_status; - recipe->sp_ra_pos = sp_ra_pos; - recipe->sp_bp_pos = sp_bp_pos; - recipe->bp_status = bp_status; - recipe->bp_bp_pos = bp_bp_pos; - recipe->bp_ra_pos = bp_ra_pos; - recipe->prev_canonical = NULL; - recipe->restored_canonical = 0; - recipe->has_tail_calls = false; - return recipe; -} - void x86recipe_tostr(void* recipe, char str[]) { // TODO x86recipe_t* x86recipe = (x86recipe_t*)recipe; snprintf(str, MAX_RECIPE_STR, "%s%d%s%s", - "x86recipe ", x86recipe->sp_ra_pos, + "x86recipe ", x86recipe->reg.sp_ra_pos, ": tail_call = ", x86recipe->has_tail_calls? "true": "false"); } diff --git a/src/tool/hpcrun/unwind/x86-family/x86-unwind-interval.h b/src/tool/hpcrun/unwind/x86-family/x86-unwind-interval.h index 7e941209ef..efb8ecf4a8 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-unwind-interval.h +++ b/src/tool/hpcrun/unwind/x86-family/x86-unwind-interval.h @@ -97,9 +97,7 @@ typedef enum { BP_UNCHANGED, BP_SAVED, BP_HOSED } bp_loc; -typedef struct x86recipe_s { - ra_loc ra_status; /* how to find the return address */ - +typedef struct x86registers_s { int sp_ra_pos; /* return address offset from sp */ int sp_bp_pos; /* BP offset from sp */ @@ -107,9 +105,13 @@ typedef struct x86recipe_s { int bp_ra_pos; /* return address offset from bp */ int bp_bp_pos; /* (caller's) BP offset from bp */ +} x86registers_t; + +typedef struct x86recipe_s { + ra_loc ra_status; /* how to find the return address */ + x86registers_t reg; bitree_uwi_t* prev_canonical; - int restored_canonical; bool has_tail_calls; } x86recipe_t; @@ -127,13 +129,8 @@ extern "C" { void set_ui_canonical(unwind_interval *u, unwind_interval *value); - void set_ui_restored_canonical(unwind_interval *u, unwind_interval *value); - - unwind_interval * - new_ui(char *startaddr, - ra_loc ra_status, unsigned int sp_ra_pos, int bp_ra_pos, - bp_loc bp_status, int sp_bp_pos, int bp_bp_pos, + new_ui(char *startaddr, ra_loc ra_status, const x86registers_t *reg, mem_alloc m_alloc); unwind_interval *fluke_ui(char *pc,unsigned int sp_ra_pos, mem_alloc m_alloc); @@ -147,10 +144,6 @@ extern "C" { void suspicious_interval(void *pc); - x86recipe_t * - x86recipe_new(ra_loc ra_status, int sp_ra_pos, int bp_ra_pos, - bp_loc bp_status, int sp_bp_pos, int bp_bp_pos, mem_alloc m_alloc); - /* * Concrete implementation of the abstract val_tostr function of the * generic_val class. diff --git a/src/tool/hpcrun/unwind/x86-family/x86-unwind.c b/src/tool/hpcrun/unwind/x86-family/x86-unwind.c index 740c9d2c6a..341a9e8b0f 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-unwind.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-unwind.c @@ -93,6 +93,7 @@ #include #include +#include #include #include "x86-unwind-interval.h" #include "x86-validate-retn-addr.h" @@ -103,7 +104,6 @@ #include #include -#include "main.h" //**************************************************************************** @@ -135,18 +135,6 @@ static int DEBUG_NO_LONGJMP = 0; static void update_cursor_with_troll(hpcrun_unw_cursor_t* cursor, int offset); -static fence_enum_t -hpcrun_check_fence(void* ip); - -static void -simulate_segv(void); - -static void -help_simulate_segv(bool no_backtrace); - -static int -unw_step_prefer_sp(void); - static step_state unw_step_sp(hpcrun_unw_cursor_t* cursor); @@ -166,8 +154,6 @@ t1_dbg_unw_step(hpcrun_unw_cursor_t* cursor); static step_state (*dbg_unw_step)(hpcrun_unw_cursor_t* cursor) = t1_dbg_unw_step; -extern void hpcrun_set_real_siglongjmp(void); - //************************************************ // private functions //************************************************ @@ -175,7 +161,7 @@ extern void hpcrun_set_real_siglongjmp(void); static void compute_normalized_ips(hpcrun_unw_cursor_t* cursor) { - void *func_start_pc = (void*) cursor->unwr_info.start; + void *func_start_pc = (void*) cursor->unwr_info.interval.start; load_module_t* lm = cursor->unwr_info.lm; cursor->pc_norm = hpcrun_normalize_ip(cursor->pc_unnorm, lm); @@ -193,7 +179,6 @@ hpcrun_unw_init(void) { x86_family_decoder_init(); uw_recipe_map_init(); - hpcrun_set_real_siglongjmp(); } @@ -247,7 +232,7 @@ hpcrun_unw_get_ip_norm_reg(hpcrun_unw_cursor_t* c, ip_normalized_t* reg_value) } int -hpcrun_unw_get_ip_unnorm_reg(hpcrun_unw_cursor_t* c, unw_word_t* reg_value) +hpcrun_unw_get_ip_unnorm_reg(hpcrun_unw_cursor_t* c, void** reg_value) { return hpcrun_unw_get_unnorm_reg(c, UNW_REG_IP, reg_value); } @@ -265,8 +250,6 @@ hpcrun_unw_set_cursor(hpcrun_unw_cursor_t* cursor, void **sp, void **bp, void *i TMSG(UNW, "unw_set_cursor: pc=%p, ra_loc=%p, sp=%p, bp=%p", cursor->pc_unnorm, cursor->ra_loc, cursor->sp, cursor->bp); - cursor->flags = 0; // trolling_used - load_module_t *lm; bool found = uw_recipe_map_lookup(cursor->pc_unnorm, &(cursor->unwr_info)); @@ -290,7 +273,6 @@ hpcrun_unw_init_cursor(hpcrun_unw_cursor_t* cursor, void* context) TMSG(UNW, "unw_init: pc=%p, ra_loc=%p, sp=%p, bp=%p", cursor->pc_unnorm, cursor->ra_loc, cursor->sp, cursor->bp); - cursor->flags = 0; // trolling_used bool found = uw_recipe_map_lookup(cursor->pc_unnorm, &(cursor->unwr_info)); if (!found) { @@ -320,35 +302,30 @@ hpcrun_unw_get_ra_loc(hpcrun_unw_cursor_t* cursor) return cursor->ra_loc; } -static bool -fence_stop(fence_enum_t fence) -{ - return (fence == FENCE_MAIN) || (fence == FENCE_THREAD); -} - static step_state hpcrun_unw_step_real(hpcrun_unw_cursor_t* cursor) { + void *pc = cursor->pc_unnorm; + cursor->fence = (monitor_unwind_process_bottom_frame(pc) ? FENCE_MAIN : + monitor_unwind_thread_bottom_frame(pc)? FENCE_THREAD : FENCE_NONE); + + if (cursor->fence != FENCE_NONE) { + if (ENABLED(FENCE_UNW)) + TMSG(FENCE_UNW, "%s", fence_enum_name(cursor->fence)); - cursor->fence = hpcrun_check_fence(cursor->pc_unnorm); - - //----------------------------------------------------------- - // check if we have reached the end of our unwind, which is - // demarcated with a fence. - //----------------------------------------------------------- - if (fence_stop(cursor->fence)) { - TMSG(UNW,"unw_step: STEP_STOP, current pc in monitor fence pc=%p\n", cursor->pc_unnorm); + //----------------------------------------------------------- + // check if we have reached the end of our unwind, which is + // demarcated with a fence. + //----------------------------------------------------------- + TMSG(UNW,"unw_step: STEP_STOP, current pc in monitor fence pc=%p\n", pc); return STEP_STOP; } // current frame void** bp = cursor->bp; void* sp = cursor->sp; - void* pc = cursor->pc_unnorm; unwind_interval* uw = cursor->unwr_info.btuwi; - step_state unw_res; - if (!uw){ TMSG(UNW, "unw_step: invalid unw interval for cursor, trolling ..."); TMSG(TROLL, "Troll due to Invalid interval for pc %p", pc); @@ -356,6 +333,7 @@ hpcrun_unw_step_real(hpcrun_unw_cursor_t* cursor) return STEP_TROLL; } + step_state unw_res; switch (UWI_RECIPE(uw)->ra_status){ case RA_SP_RELATIVE: unw_res = unw_step_sp(cursor); @@ -472,20 +450,6 @@ hpcrun_unw_step(hpcrun_unw_cursor_t *cursor) // hpcrun_unw_step helpers //**************************************************************************** -// FIXME: make this a selectable paramter, so that all manner of strategies -// can be selected -static int -unw_step_prefer_sp(void) -{ - if (ENABLED(PREFER_SP)){ - return 1; - } else { - return 0; - } - // return cursor->flags; // trolling_used -} - - static step_state unw_step_sp(hpcrun_unw_cursor_t* cursor) { @@ -498,19 +462,20 @@ unw_step_sp(hpcrun_unw_cursor_t* cursor) void* sp = cursor->sp; void* pc = cursor->pc_unnorm; unwind_interval* uw = cursor->unwr_info.btuwi; + x86recipe_t *xr = UWI_RECIPE(uw); TMSG(UNW,"step_sp: cursor { bp=%p, sp=%p, pc=%p }", bp, sp, pc); if (MYDBG) { dump_ui(uw, 0); } void** next_bp = NULL; - void** next_sp = (void **)(sp + UWI_RECIPE(uw)->sp_ra_pos); + void** next_sp = (void **)(sp + xr->reg.sp_ra_pos); void* ra_loc = (void*) next_sp; void* next_pc = *next_sp; TMSG(UNW," step_sp: potential next cursor next_sp=%p ==> next_pc = %p", next_sp, next_pc); - if (UWI_RECIPE(uw)->bp_status == BP_UNCHANGED){ + if (xr->reg.bp_status == BP_UNCHANGED){ next_bp = bp; TMSG(UNW," step_sp: unwind step has BP_UNCHANGED ==> next_bp=%p", next_bp); } @@ -520,7 +485,7 @@ unw_step_sp(hpcrun_unw_cursor_t* cursor) // save area in the activation frame according to the unwind // information produced by binary analysis //----------------------------------------------------------- - next_bp = (void **)(sp + UWI_RECIPE(uw)->sp_bp_pos); + next_bp = (void **)(sp + xr->reg.sp_bp_pos); TMSG(UNW," step_sp: unwind next_bp loc = %p", next_bp); next_bp = *next_bp; TMSG(UNW," step_sp: sp unwind next_bp val = %p", next_bp); @@ -550,9 +515,8 @@ unw_step_sp(hpcrun_unw_cursor_t* cursor) return STEP_ERROR; } - unwind_interval* uw = cursor->unwr_info.btuwi; - if ((RA_BP_FRAME == UWI_RECIPE(uw)->ra_status) || - (RA_STD_FRAME == UWI_RECIPE(uw)->ra_status)) { // Makes sense to sanity check BP, do it + if ((RA_BP_FRAME == xr->ra_status) || + (RA_STD_FRAME == xr->ra_status)) { // Makes sense to sanity check BP, do it //----------------------------------------------------------- // if value of BP reloaded from the save area does not point // into the stack, then it cannot possibly be useful as a frame @@ -592,17 +556,16 @@ unw_step_sp(hpcrun_unw_cursor_t* cursor) static step_state unw_step_bp(hpcrun_unw_cursor_t* cursor) { - void *sp, **bp, *pc; void **next_sp, **next_bp, *next_pc; - unwind_interval *uw; - TMSG(UNW_STRATEGY,"Using BP step"); // current frame - bp = cursor->bp; - sp = cursor->sp; - pc = cursor->pc_unnorm; - uw = cursor->unwr_info.btuwi; + void **bp = cursor->bp; + void *sp = cursor->sp; + void *pc = cursor->pc_unnorm; + unwind_interval *uw = cursor->unwr_info.btuwi; + x86recipe_t *xr = UWI_RECIPE(uw); + TMSG(UNW,"step_bp: cursor { bp=%p, sp=%p, pc=%p }", bp, sp, pc); if (MYDBG) { dump_ui(uw, 0); } @@ -621,9 +584,9 @@ unw_step_bp(hpcrun_unw_cursor_t* cursor) } } // bp relative - next_sp = (void **)((void *)bp + UWI_RECIPE(uw)->bp_bp_pos); + next_sp = (void **)((void *)bp + xr->reg.bp_bp_pos); next_bp = *next_sp; - next_sp = (void **)((void *)bp + UWI_RECIPE(uw)->bp_ra_pos); + next_sp = (void **)((void *)bp + xr->reg.bp_ra_pos); void* ra_loc = (void*) next_sp; next_pc = *next_sp; next_sp += 1; @@ -705,7 +668,7 @@ unw_step_std(hpcrun_unw_cursor_t* cursor) { int unw_res; - if (unw_step_prefer_sp()){ + if (ENABLED(PREFER_SP)) { TMSG(UNW_STRATEGY,"--STD_FRAME: STARTing with SP"); unw_res = unw_step_sp(cursor); if (unw_res == STEP_ERROR || unw_res == STEP_STOP_WEAK) { @@ -731,7 +694,17 @@ unw_step_std(hpcrun_unw_cursor_t* cursor) static step_state t1_dbg_unw_step(hpcrun_unw_cursor_t* cursor) { - simulate_segv(); + if (!DEBUG_NO_LONGJMP) { + + if (hpcrun_below_pmsg_threshold()) { + hpcrun_bt_dump(TD_GET(btbuf_cur), "DROP"); + } + + hpcrun_up_pmsg_count(); + + sigjmp_buf_t *it = &(TD_GET(bad_unwind)); + (*hpcrun_get_real_siglongjmp())(it->jb, 9); + } return STEP_ERROR; } @@ -758,32 +731,6 @@ t2_dbg_unw_step(hpcrun_unw_cursor_t* cursor) // private operations //**************************************************************************** -static void -help_simulate_segv(bool no_backtrace) -{ - if (DEBUG_NO_LONGJMP) return; - - if (no_backtrace) { - return; - } - if (hpcrun_below_pmsg_threshold()) { - hpcrun_bt_dump(TD_GET(btbuf_cur), "DROP"); - } - - hpcrun_up_pmsg_count(); - - sigjmp_buf_t *it = &(TD_GET(bad_unwind)); - (*hpcrun_get_real_siglongjmp())(it->jb, 9); -} - - -static void -simulate_segv(void) -{ - help_simulate_segv(false); -} - - static void update_cursor_with_troll(hpcrun_unw_cursor_t* cursor, int offset) { @@ -824,8 +771,6 @@ update_cursor_with_troll(hpcrun_unw_cursor_t* cursor, int offset) cursor->ra_loc = ra_loc; compute_normalized_ips(cursor); - cursor->flags = 1; // trolling_used - return; // success! } TMSG(TROLL, "No interval found for trolled pc, dropping sample," @@ -841,17 +786,3 @@ update_cursor_with_troll(hpcrun_unw_cursor_t* cursor, int offset) // assert(0); hpcrun_unw_throw(); } - -static fence_enum_t -hpcrun_check_fence(void* ip) -{ - fence_enum_t rv = FENCE_NONE; - if (monitor_unwind_process_bottom_frame(ip)) - rv = FENCE_MAIN; - else if (monitor_unwind_thread_bottom_frame(ip)) - rv = FENCE_THREAD; - - if (ENABLED(FENCE_UNW) && rv != FENCE_NONE) - TMSG(FENCE_UNW, "%s", fence_enum_name(rv)); - return rv; -} diff --git a/src/tool/hpcrun/unwind/x86-family/x86-validate-retn-addr.c b/src/tool/hpcrun/unwind/x86-family/x86-validate-retn-addr.c index 9f76a5fbd0..ec580ca99f 100644 --- a/src/tool/hpcrun/unwind/x86-family/x86-validate-retn-addr.c +++ b/src/tool/hpcrun/unwind/x86-family/x86-validate-retn-addr.c @@ -76,14 +76,6 @@ #include -//**************************************************************************** -// forward declarations -//**************************************************************************** - -extern void *x86_get_branch_target(void *ins, xed_decoded_inst_t *xptr); - - - //**************************************************************************** // local types //**************************************************************************** @@ -378,7 +370,7 @@ deep_validate_return_addr(void* addr, void* generic) if (!return_addr_valid(cursor->pc_unnorm, &unwr_info)) return status_is_wrong(); - void* callee = (void*)unwr_info.start; + void* callee = (void*)unwr_info.interval.start; TMSG(VALIDATE_UNW, "beginning of my routine = %p", callee); if (confirm_call(addr, callee)) { TMSG(VALIDATE_UNW, "Instruction preceeding %p is a call to this routine. Unwind confirmed", addr);