Skip to content

Commit d0678bf

Browse files
committed
erts: Add asserts to verify trace stack frames
1 parent c78ec31 commit d0678bf

File tree

6 files changed

+52
-14
lines changed

6 files changed

+52
-14
lines changed

erts/emulator/beam/beam_bp.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,27 @@ do_session_breakpoint(Process *c_p, ErtsCodeInfo *info, Eterm *reg,
11011101
return bp_flags;
11021102
}
11031103

1104+
#ifdef DEBUG
1105+
void assert_return_trace_frame(const Eterm *frame)
1106+
{
1107+
ASSERT_MFA((ErtsCodeMFA*)cp_val(frame[0]));
1108+
ASSERT(IS_TRACER_VALID(frame[1]));
1109+
ASSERT(erts_is_trace_session_weak_id(frame[2]));
1110+
}
1111+
1112+
void assert_return_to_trace_frame(const Eterm *frame)
1113+
{
1114+
ASSERT(erts_is_trace_session_weak_id(frame[0]));
1115+
}
1116+
1117+
void assert_return_call_acc_trace_frame(const Eterm *frame)
1118+
{
1119+
ASSERT(is_CP(frame[0]) || is_nil(frame[0])); // prev_info
1120+
ASSERT((unsigned_val(frame[1]) & ~ERTS_BPF_ALL) == 0); // bp_flags
1121+
ASSERT(erts_is_trace_session_weak_id(frame[2]));
1122+
}
1123+
#endif
1124+
11041125
static ErtsTracer
11051126
do_call_trace(Process* c_p, ErtsCodeInfo* info, Eterm* reg,
11061127
int local, Binary* ms,

erts/emulator/beam/beam_bp.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,12 @@ Uint erts_line_breakpoint_hit__cleanup(Eterm *regs, UWord *stk);
208208

209209
const ErtsCodeInfo *erts_find_local_func(const ErtsCodeMFA *mfa);
210210

211+
#ifdef DEBUG
212+
void assert_return_trace_frame(const Eterm *frame);
213+
void assert_return_to_trace_frame(const Eterm *frame);
214+
void assert_return_call_acc_trace_frame(const Eterm *frame);
215+
#endif
216+
211217
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
212218

213219
ERTS_GLB_INLINE ErtsBpIndex erts_active_bp_ix(void)

erts/emulator/beam/erl_gc.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3839,7 +3839,7 @@ erts_max_heap_size(Eterm arg, Uint *max_heap_size, Uint *max_heap_flags)
38393839
return 1;
38403840
}
38413841

3842-
#ifdef DEBUG
3842+
#if defined(DEBUG) && defined(ERLANG_FRAME_POINTERS)
38433843
void erts_validate_stack(Process *p, Eterm *frame_ptr, Eterm *stack_top) {
38443844
Eterm *stack_bottom = HEAP_END(p);
38453845
Eterm *next_fp = frame_ptr;
@@ -3858,18 +3858,19 @@ void erts_validate_stack(Process *p, Eterm *frame_ptr, Eterm *stack_top) {
38583858
However the return trace intructions do update p->i after returning.
38593859
*/
38603860
if (BeamIsReturnTrace(p->i)) {
3861-
/* Skip MFA and tracer. */
3862-
ASSERT_MFA((ErtsCodeMFA*)cp_val(scanner[0]));
3863-
ASSERT(IS_TRACER_VALID(scanner[1]));
3861+
assert_return_trace_frame(scanner);
38643862
scanner += BEAM_RETURN_TRACE_FRAME_SZ;
38653863
} else if (BeamIsReturnCallAccTrace(p->i)) {
3866-
/* Skip prev_info. */
3864+
assert_return_call_acc_trace_frame(scanner);
38673865
scanner += BEAM_RETURN_CALL_ACC_TRACE_FRAME_SZ;
38683866
} else if (BeamIsReturnToTrace(p->i)) {
3867+
assert_return_to_trace_frame(scanner);
38693868
scanner += BEAM_RETURN_TO_TRACE_FRAME_SZ;
38703869
}
38713870

38723871
while (next_fp) {
3872+
ErtsCodePtr cp;
3873+
38733874
ASSERT(next_fp >= stack_top && next_fp <= stack_bottom);
38743875

38753876
/* We may not skip any frames. */
@@ -3879,24 +3880,24 @@ void erts_validate_stack(Process *p, Eterm *frame_ptr, Eterm *stack_top) {
38793880
}
38803881

38813882
/* {Next frame, Return address} or vice versa */
3882-
ASSERT(is_CP(scanner[0]) && is_CP(scanner[1]));
38833883
next_fp = (Eterm*)cp_val(scanner[0]);
3884+
cp = cp_val(scanner[1]);
3885+
3886+
scanner += CP_SIZE;
38843887

38853888
/* Call tracing may store raw pointers on the stack. This is explicitly
38863889
* handled in all routines that deal with the stack. */
3887-
if (BeamIsReturnTrace((ErtsCodePtr)scanner[1])) {
3888-
/* Skip MFA and tracer. */
3889-
ASSERT_MFA((ErtsCodeMFA*)cp_val(scanner[2]));
3890-
ASSERT(IS_TRACER_VALID(scanner[3]));
3890+
if (BeamIsReturnTrace(cp)) {
3891+
assert_return_trace_frame(scanner);
38913892
scanner += BEAM_RETURN_TRACE_FRAME_SZ;
3892-
} else if (BeamIsReturnCallAccTrace((ErtsCodePtr)scanner[1])) {
3893-
/* Skip prev_info. */
3893+
} else if (BeamIsReturnCallAccTrace(cp)) {
3894+
assert_return_call_acc_trace_frame(scanner);
38943895
scanner += BEAM_RETURN_CALL_ACC_TRACE_FRAME_SZ;
3895-
} else if (BeamIsReturnToTrace((ErtsCodePtr)scanner[1])) {
3896+
} else if (BeamIsReturnToTrace(cp)) {
3897+
assert_return_to_trace_frame(scanner);
38963898
scanner += BEAM_RETURN_TO_TRACE_FRAME_SZ;
38973899
}
38983900

3899-
scanner += CP_SIZE;
39003901
}
39013902
}
39023903
#endif

erts/emulator/beam/erl_gc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,13 @@ int erts_dbg_within_proc(Eterm *ptr, Process *p, Eterm* real_htop);
195195
#endif
196196

197197
#ifdef DEBUG
198+
199+
# ifdef ERLANG_FRAME_POINTERS
198200
/* Validates the frame chain, ensuring that it always points within the stack
199201
* and that no frames are skipped. */
200202
void erts_validate_stack(Process *p, Eterm *frame_ptr, Eterm *stack_top);
203+
# endif
204+
201205
int
202206
erts_dbg_check_heap_terms(int (*check_eterm)(Eterm),
203207
Process *p,

erts/emulator/beam/erl_trace.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3822,6 +3822,11 @@ void erts_change_proc_trace_session_flags(Process* p, ErtsTraceSession* session,
38223822
}
38233823

38243824
#ifdef DEBUG
3825+
bool erts_is_trace_session_weak_id(Eterm term)
3826+
{
3827+
return is_small(term) || term == am_default;
3828+
}
3829+
38253830
void erts_assert_tracer_refs(ErtsPTabElementCommon* t_p)
38263831
{
38273832
ErtsTracerRef *ref, *other;

erts/emulator/beam/erl_trace.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ Uint32 erts_sum_all_trace_flags(ErtsPTabElementCommon* t_p);
152152
void erts_change_proc_trace_session_flags(Process*, ErtsTraceSession*,
153153
Uint32 clear_flags, Uint32 set_flags);
154154
#ifdef DEBUG
155+
bool erts_is_trace_session_weak_id(Eterm);
155156
void erts_assert_tracer_refs(ErtsPTabElementCommon* t_p);
156157
# define ERTS_ASSERT_TRACER_REFS(TP) erts_assert_tracer_refs(TP)
157158
#else

0 commit comments

Comments
 (0)