int.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 690 行 · 第 1/2 页
ERL
690 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(int).%% External exports-export([i/1, i/2, ni/1, ni/2, n/1, nn/1, interpreted/0, file/1, interpretable/1]).-export([auto_attach/0, auto_attach/1, auto_attach/2, stack_trace/0, stack_trace/1]).-export([break/2, delete_break/2, break_in/3, del_break_in/3, no_break/0, no_break/1, disable_break/2, enable_break/2, action_at_break/3, test_at_break/3, get_binding/2, all_breaks/0, all_breaks/1]).-export([snapshot/0, clear/0]).-export([continue/1, continue/3]).%% External exports only to be used by Debugger-export([start/0, stop/0, subscribe/0]).-export([attach/2, step/1, next/1, finish/1]).%% External exports only to be used by an attached process-export([attached/1, meta/2, meta/3, contents/2, functions/1]).%% External export only to be used by error_handler-export([eval/3]).%%==Erlang Interpreter================================================%%%% int%% ---%% Interface module.%%%% i%% -%% Interface module to int, retained for backwards compatibility only.%%%% dbg_debugged%% ------------%% Contains the message loops for a debugged process and is the main%% entry point from the breakpoint handler in the error_handler module%% (via the int module).%%%% When a process is debugged, most code is executed in another%% process, called the meta process. When the meta process is%% interpreting code, the process being debugged just waits in a%% receive loop in dbg_debugged. However the debugged process itself%% calls any BIFs that must execute in the correct process (such as%% link/1 and spawn_link/1), and external code which is not%% interpreted.%%%% dbg_icmd, dbg_ieval%% -------------------%% Code for the meta process.%%%% dbg_iserver%% -----------%% Interpreter main process, keeping and distributing information%% about interpreted modules and debugged processes.%%%% dbg_idb%% -------%% ETS wrapper, allowing transparent access to tables at a remote node.%%%% dbg_iload%% ---------%% Code for interpreting a module.%%==================================================================== %%====================================================================%% External exports%%====================================================================%%--------------------------------------------------------------------%% i(AbsMods) -> {module,Mod} | error | ok%% ni(AbsMods) -> {module,Mod} | error | ok%% AbsMods = AbsMod | [AbsMod]%% AbsMod = atom() | string()%% Mod = atom()%% Options = term() ignored%%--------------------------------------------------------------------i(AbsMods) -> i2(AbsMods, local).i(AbsMods, _Options) -> i2(AbsMods, local).ni(AbsMods) -> i2(AbsMods, distributed).ni(AbsMods, _Options) -> i2(AbsMods, distributed). i2([AbsMod|AbsMods], Dist) when is_atom(AbsMod); is_list(AbsMod) -> int_mod(AbsMod, Dist), i2(AbsMods, Dist);i2([AbsMod], Dist) when is_atom(AbsMod); is_list(AbsMod) -> int_mod(AbsMod, Dist);i2([], _Dist) -> ok;i2(AbsMod, Dist) when is_atom(AbsMod); is_list(AbsMod) -> int_mod(AbsMod, Dist).%%--------------------------------------------------------------------%% n(AbsMods) -> ok%% nn(AbsMods) -> ok%%--------------------------------------------------------------------n(AbsMods) -> n2(AbsMods, local).nn(AbsMods) -> n2(AbsMods, distributed).n2([AbsMod|AbsMods], Dist) when is_atom(AbsMod); is_list(AbsMod) -> del_mod(AbsMod, Dist), n2(AbsMods, Dist);n2([AbsMod], Dist) when is_atom(AbsMod); is_list(AbsMod) -> del_mod(AbsMod, Dist);n2([], _Dist) -> ok;n2(AbsMod, Dist) when is_atom(AbsMod); is_list(AbsMod) -> del_mod(AbsMod, Dist).%%--------------------------------------------------------------------%% interpreted() -> [Mod]%%--------------------------------------------------------------------interpreted() -> dbg_iserver:safe_call(all_interpreted).%%--------------------------------------------------------------------%% file(Mod) -> File | {error, not_loaded}%% Mod = atom()%% File = string()%%--------------------------------------------------------------------file(Mod) when is_atom(Mod) -> dbg_iserver:safe_call({file, Mod}).%%--------------------------------------------------------------------%% interpretable(AbsMod) -> true | {error, Reason}%% AbsMod = Mod | File%% Reason = no_src | no_beam | no_debug_info | badarg | {app, App}%%--------------------------------------------------------------------interpretable(AbsMod) -> case check(AbsMod) of {ok, _Res} -> true; Error -> Error end.%%--------------------------------------------------------------------%% auto_attach() -> false | {Flags, Function}%% auto_attach(false)%% auto_attach(false|Flags, Function)%% Flags = Flag | [Flag]%% Flag = init | break | exit%% Function = {Mod, Func} | {Mod, Func, Args}%% Will result in calling:%% spawn(Mod, Func, [Dist, Pid, Meta | Args]) (living process) or%% spawn(Mod, Func, [Dist, Pid, Reason, Info | Args]) (dead process)%%--------------------------------------------------------------------auto_attach() -> dbg_iserver:safe_call(get_auto_attach).auto_attach(false) -> dbg_iserver:safe_cast({set_auto_attach, false}).auto_attach([], _Function) -> auto_attach(false);auto_attach(Flags, {Mod, Func}) -> auto_attach(Flags, {Mod, Func, []});auto_attach(Flags, {Mod, Func, Args}) when is_atom(Mod),is_atom(Func),is_list(Args) -> check_flags(Flags), dbg_iserver:safe_cast({set_auto_attach, Flags, {Mod, Func, Args}}).check_flags([init|Flags]) -> check_flags(Flags);check_flags([break|Flags]) -> check_flags(Flags);check_flags([exit|Flags]) -> check_flags(Flags);check_flags([]) -> true.%%--------------------------------------------------------------------%% stack_trace() -> Flag%% stack_trace(Flag)%% Flag = all | true | no_tail | false%%--------------------------------------------------------------------stack_trace() -> dbg_iserver:safe_call(get_stack_trace).stack_trace(true) -> stack_trace(all);stack_trace(Flag) -> check_flag(Flag), dbg_iserver:safe_cast({set_stack_trace, Flag}).check_flag(all) -> true;check_flag(no_tail) -> true;check_flag(false) -> true.%%--------------------------------------------------------------------%% break(Mod, Line) -> ok | {error, break_exists}%% delete_break(Mod, Line) -> ok%% break_in(Mod, Func, Arity) -> ok | {error, function_not_found}%% del_break_in(Mod, Function, Arity) -> ok | {error, function_not_found}%% no_break()%% no_break(Mod)%% disable_break(Mod, Line) -> ok%% enable_break(Mod, Line) -> ok%% action_at_break(Mod, Line, Action) -> ok%% test_at_break(Mod, Line, Function) -> ok%% get_binding(Var, Bindings) -> {value, Value} | unbound%% all_breaks() -> [Break]%% all_breaks(Mod) -> [Break]%% Mod = atom()%% Line = integer()%% Func = atom() function name%% Arity = integer()%% Action = enable | disable | delete%% Function = {Mod, Func} must have arity 1 (Bindings)%% Var = atom()%% Bindings = Value = term()%% Break = {Point, Options}%% Point = {Mod, Line}%% Options = [Status, Action, null, Cond]%% Status = active | inactive%% Cond = null | Function%%--------------------------------------------------------------------break(Mod, Line) when is_atom(Mod), is_integer(Line) -> dbg_iserver:safe_call({new_break, {Mod, Line}, [active, enable, null, null]}).delete_break(Mod, Line) when is_atom(Mod), is_integer(Line) -> dbg_iserver:safe_cast({delete_break, {Mod, Line}}).break_in(Mod, Func, Arity) when is_atom(Mod), is_atom(Func), is_integer(Arity) -> case dbg_iserver:safe_call({is_interpreted, Mod, Func, Arity}) of {true, Clauses} -> Lines = first_lines(Clauses), lists:foreach(fun(Line) -> break(Mod, Line) end, Lines); false -> {error, function_not_found} end.del_break_in(Mod, Func, Arity) when is_atom(Mod), is_atom(Func), is_integer(Arity) -> case dbg_iserver:safe_call({is_interpreted, Mod, Func, Arity}) of {true, Clauses} -> Lines = first_lines(Clauses), lists:foreach(fun(Line) -> delete_break(Mod, Line) end, Lines); false -> {error, function_not_found} end.first_lines(Clauses) -> lists:map(fun(Clause) -> element(2, hd(element(5, Clause))) end, Clauses).no_break() -> dbg_iserver:safe_cast(no_break).no_break(Mod) when is_atom(Mod) -> dbg_iserver:safe_cast({no_break, Mod}).disable_break(Mod, Line) when is_atom(Mod), is_integer(Line) -> dbg_iserver:safe_cast({break_option, {Mod, Line}, status, inactive}). enable_break(Mod, Line) when is_atom(Mod), is_integer(Line) -> dbg_iserver:safe_cast({break_option, {Mod, Line}, status, active}).action_at_break(Mod, Line, Action) when is_atom(Mod), is_integer(Line) -> check_action(Action), dbg_iserver:safe_cast({break_option, {Mod, Line}, action, Action}).check_action(enable) -> true;check_action(disable) -> true;check_action(delete) -> true.test_at_break(Mod, Line, Function) when is_atom(Mod), is_integer(Line) -> check_function(Function), dbg_iserver:safe_cast({break_option, {Mod, Line}, condition, Function}).check_function({Mod, Func}) when is_atom(Mod), is_atom(Func) -> true.get_binding(Var, Bs) -> dbg_icmd:get_binding(Var, Bs).all_breaks() -> dbg_iserver:safe_call(all_breaks).all_breaks(Mod) when is_atom(Mod) -> dbg_iserver:safe_call({all_breaks, Mod}).%%--------------------------------------------------------------------%% snapshot() -> [{Pid, Init, Status, Info}]%% Pid = pid()%% Init = atom() First interpreted function%% Status = idle | running | waiting | break | exit%% Info = {} | {Mod, Line} | ExitReason%% Mod = atom()%% Line = integer()%% ExitReason = term()%%--------------------------------------------------------------------snapshot() -> dbg_iserver:safe_call(snapshot).%%--------------------------------------------------------------------%% clear()%%--------------------------------------------------------------------clear() -> dbg_iserver:safe_cast(clear). %%--------------------------------------------------------------------%% continue(Pid) -> ok | {error, not_interpreted}%% continue(X, Y, Z) -> ok | {error, not_interpreted}%%--------------------------------------------------------------------continue(Pid) when is_pid(Pid) -> case dbg_iserver:safe_call({get_meta, Pid}) of {ok, Meta} when is_pid(Meta) -> dbg_icmd:continue(Meta), ok; Error -> Error end. continue(X, Y, Z) when is_integer(X), is_integer(Y), is_integer(Z) -> continue(c:pid(X, Y, Z)).%%====================================================================%% External exports only to be used by Debugger%%====================================================================%%--------------------------------------------------------------------%% start()%% stop()%% Functions for starting and stopping dbg_iserver explicitly.%%--------------------------------------------------------------------start() -> dbg_iserver:start().stop() -> lists:foreach( fun(Mod) -> everywhere(distributed, fun() -> erts_debug:breakpoint({Mod,'_','_'}, false)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?