@@ -870,18 +870,24 @@ ftrace_graph_get_ret_stack(struct task_struct *task, int idx)
870
870
}
871
871
872
872
/**
873
- * ftrace_graph_ret_addr - convert a potentially modified stack return address
874
- * to its original value
873
+ * ftrace_graph_ret_addr - return the original value of the return address
874
+ * @task: The task the unwinder is being executed on
875
+ * @idx: An initialized pointer to the next stack index to use
876
+ * @ret: The current return address (likely pointing to return_handler)
877
+ * @retp: The address on the stack of the current return location
875
878
*
876
879
* This function can be called by stack unwinding code to convert a found stack
877
- * return address (' ret' ) to its original value, in case the function graph
880
+ * return address (@ ret) to its original value, in case the function graph
878
881
* tracer has modified it to be 'return_to_handler'. If the address hasn't
879
- * been modified, the unchanged value of ' ret' is returned.
882
+ * been modified, the unchanged value of @ ret is returned.
880
883
*
881
- * 'idx' is a state variable which should be initialized by the caller to zero
882
- * before the first call.
884
+ * @idx holds the last index used to know where to start from. It should be
885
+ * initialized to zero for the first iteration as that will mean to start
886
+ * at the top of the shadow stack. If the location is found, this pointer
887
+ * will be assigned that location so that if called again, it will continue
888
+ * where it left off.
883
889
*
884
- * ' retp' is a pointer to the return address on the stack. It's ignored if
890
+ * @ retp is a pointer to the return address on the stack. It's ignored if
885
891
* the arch doesn't have HAVE_FUNCTION_GRAPH_RET_ADDR_PTR defined.
886
892
*/
887
893
#ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
@@ -895,6 +901,10 @@ unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
895
901
if (ret != return_handler )
896
902
return ret ;
897
903
904
+ if (!idx )
905
+ return ret ;
906
+
907
+ i = * idx ? : task -> curr_ret_stack ;
898
908
while (i > 0 ) {
899
909
ret_stack = get_ret_stack (current , i , & i );
900
910
if (!ret_stack )
@@ -908,8 +918,10 @@ unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
908
918
* Thus we will continue to find real return address.
909
919
*/
910
920
if (ret_stack -> retp == retp &&
911
- ret_stack -> ret != return_handler )
921
+ ret_stack -> ret != return_handler ) {
922
+ * idx = i ;
912
923
return ret_stack -> ret ;
924
+ }
913
925
}
914
926
915
927
return ret ;
0 commit comments