diff options
Diffstat (limited to 'lib/kernel/src/erts_debug.erl')
-rw-r--r-- | lib/kernel/src/erts_debug.erl | 64 |
1 files changed, 34 insertions, 30 deletions
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index a69e74a3c1..9a03dd8d75 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -40,6 +40,15 @@ lc_graph/0, lc_graph_to_dot/2, lc_graph_merge/2, alloc_blocks_size/1]). +%% Reroutes calls to the given MFA to error_handler:breakpoint/3 +%% +%% Note that this is potentially unsafe as compiled code may assume that the +%% targeted function returns a specific type, triggering undefined behavior if +%% this function were to return something else. +%% +%% For reference, the debugger avoids the issue by purging the affected module +%% and interpreting all functions in the module, ensuring that no assumptions +%% are made with regard to return or argument types. -spec breakpoint(MFA, Flag) -> non_neg_integer() when MFA :: {Module :: module(), Function :: atom(), @@ -92,7 +101,7 @@ copy_shared(_) -> -spec get_internal_state(W) -> term() when W :: reds_left | node_and_dist_references | monitoring_nodes - | next_pid | 'DbTable_words' | check_io_debug + | next_pid | 'DbTable_words' | check_io_debug | lc_graph | process_info_args | processes | processes_bif_info | max_atom_out_cache_index | nbalance | available_internal_state | force_heap_frags | memory @@ -517,43 +526,38 @@ alloc_blocks_size_1([], _Type, 0) -> undefined; alloc_blocks_size_1([{_Type, false} | Rest], Type, Acc) -> alloc_blocks_size_1(Rest, Type, Acc); -alloc_blocks_size_1([{Type, Instances} | Rest], Type, Acc0) -> - F = fun ({instance, _, L}, Acc) -> +alloc_blocks_size_1([{_Type, Instances} | Rest], Type, Acc) -> + F = fun ({instance, _, L}, Acc0) -> MBCSPool = case lists:keyfind(mbcs_pool, 1, L) of {_, Pool} -> Pool; false -> [] end, {_,MBCS} = lists:keyfind(mbcs, 1, L), {_,SBCS} = lists:keyfind(sbcs, 1, L), - Acc + - sum_block_sizes(MBCSPool) + - sum_block_sizes(MBCS) + - sum_block_sizes(SBCS) + Acc1 = sum_block_sizes(MBCSPool, Type, Acc0), + Acc2 = sum_block_sizes(MBCS, Type, Acc1), + sum_block_sizes(SBCS, Type, Acc2) end, - alloc_blocks_size_1(Rest, Type, lists:foldl(F, Acc0, Instances)); -alloc_blocks_size_1([{_Type, Instances} | Rest], Type, Acc0) -> - F = fun ({instance, _, L}, Acc) -> - Acc + sum_foreign_sizes(Type, L) - end, - alloc_blocks_size_1(Rest, Type, lists:foldl(F, Acc0, Instances)); + alloc_blocks_size_1(Rest, Type, lists:foldl(F, Acc, Instances)); alloc_blocks_size_1([], _Type, Acc) -> Acc. -sum_foreign_sizes(Type, L) -> - case lists:keyfind(mbcs_pool, 1, L) of - {_,Pool} -> - {_,ForeignBlocks} = lists:keyfind(foreign_blocks, 1, Pool), - case lists:keyfind(Type, 1, ForeignBlocks) of - {_,TypeSizes} -> sum_block_sizes(TypeSizes); - false -> 0 - end; - _ -> - 0 - end. +sum_block_sizes([{blocks, List} | Rest], Type, Acc) -> + sum_block_sizes(Rest, Type, sum_block_sizes_1(List, Type, Acc)); +sum_block_sizes([_ | Rest], Type, Acc) -> + sum_block_sizes(Rest, Type, Acc); +sum_block_sizes([], _Type, Acc) -> + Acc. + +sum_block_sizes_1([{Type, L} | Rest], Type, Acc0) -> + Acc = lists:foldl(fun({size, Sz,_,_}, Sz0) -> Sz0+Sz; + ({size, Sz}, Sz0) -> Sz0+Sz; + (_, Sz) -> Sz + end, Acc0, L), + sum_block_sizes_1(Rest, Type, Acc); +sum_block_sizes_1([_ | Rest], Type, Acc) -> + sum_block_sizes_1(Rest, Type, Acc); +sum_block_sizes_1([], _Type, Acc) -> + Acc. + -sum_block_sizes(Blocks) -> - lists:foldl( - fun({blocks_size, Sz,_,_}, Sz0) -> Sz0+Sz; - ({blocks_size, Sz}, Sz0) -> Sz0+Sz; - (_, Sz) -> Sz - end, 0, Blocks). |