Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion edb/src/edb_dap.erl
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ decode_frames(Data) ->

-spec decode_frames(binary(), [frame()]) -> {[frame()], binary()}.
decode_frames(Data, Messages) ->
case binary:split(Data, <<"\r\n\r\n">>) of
Separator = case os:type() of
{win32, _} -> [<<"\r\n\r\n">>, <<"\n\n">>];
_ -> <<"\r\n\r\n">>
end,
case binary:split(Data, Separator) of
[<<"Content-Length: ", BinLength/binary>>, Rest] when is_binary(Rest) ->
Length = binary_to_integer(BinLength),
case byte_size(Rest) < Length of
Expand Down
12 changes: 10 additions & 2 deletions edb/test/edb_dap_test_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
handle_info/2
]).

-define(ESCRIPT, "escript").

-type awaitable_key() :: {event, edb_dap:event_type()} | {reverse_request, edb_dap:command()}.
-type awaitable() :: edb_dap:event() | edb_dap:request().

Expand Down Expand Up @@ -185,8 +187,14 @@ respond_success(Client, ReverseRequest, ResponseBody) ->

-spec init(#{executable := file:filename_all(), args := [string()]}) -> {ok, state()}.
init(#{executable := Executable, args := Args}) ->
Opts = [{args, Args}, exit_status, eof, binary, stream, use_stdio],
Port = open_port({spawn_executable, Executable}, Opts),
{Opts, SpawnExec} = case os:type() of
{win32, _} ->
CmdArgs = [Executable | Args],
{[{args, CmdArgs}, exit_status, eof, binary, stream, use_stdio], ?ESCRIPT};
_ ->
{[{args, Args}, exit_status, eof, binary, stream, use_stdio], Executable}
end,
Port = open_port({spawn_executable, os:find_executable(SpawnExec)}, Opts),
State = #{
io => Port,
buffer => <<>>,
Expand Down
11 changes: 8 additions & 3 deletions edb/test/edb_main_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,14 @@ escript_executable(Config) ->
Escript = filename:join([DataDir, ?EDB]),
?assert(filelib:is_file(Escript), "Escript should exists"),
{ok, FileInfo} = file:read_file_info(Escript),
case FileInfo#file_info.mode of
Mode when is_integer(Mode) ->
?assertEqual(8#111, Mode band 8#111, "Escript should be executable")
case os:type() of
{win32, _} ->
ok;
_ ->
case FileInfo#file_info.mode of
Mode when is_integer(Mode) ->
?assertEqual(8#111, Mode band 8#111, "Escript should be executable")
end
end.

escript_dap(Config) ->
Expand Down
12 changes: 11 additions & 1 deletion edb_core/src/edb.erl
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@ maybe_start_epmd() ->
case erl_epmd:names("localhost") of
{error, address} ->
% not running, let's start it ourselves
EpmdPath = filename:join([code:root_dir(), "bin", "epmd"]),
EpmdPath = epmd_path(),
Cmd = lists:flatten(io_lib:format("~s -daemon", [EpmdPath])),
[] = os:cmd(Cmd),
ok;
Expand All @@ -804,6 +804,16 @@ maybe_start_epmd() ->
end
end.

-spec epmd_path() -> file:filename().
epmd_path() ->
case os:type() of
{win32, nt} ->
ErtsVersion = erlang:system_info(version),
filename:join([code:root_dir(), "erts-" ++ ErtsVersion, "bin", "epmd.exe"]);
_ ->
filename:join([code:root_dir(), "bin", "epmd"])
end.

-spec debugger_node(NameDomain) -> node() when
NameDomain :: longnames | shortnames.
debugger_node(NameDomain) ->
Expand Down
16 changes: 16 additions & 0 deletions edb_core/src/edb_bootstrap.erl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ bootstrap_debuggee(Debugger, Subscribers, ReverseAttachCode, PauseAction) ->
check_vm_support(),
inject_edb_modules(Debugger),
start_edb_server(),
add_project_paths(),
subscribe_to_events(Subscribers),
case PauseAction of
keep_running ->
Expand All @@ -65,6 +66,21 @@ bootstrap_debuggee(Debugger, Subscribers, ReverseAttachCode, PauseAction) ->
end
end.

-spec add_project_paths() -> ok.
add_project_paths() ->
Cwd = filename:absname(""),
case filelib:is_file("rebar.config") of
true ->
code:add_pathsa(filelib:wildcard(filename:join(Cwd, "_build/default/lib/*/ebin")));
false ->
case filelib:is_file("erlang.mk") of
true ->
code:add_patha(filename:join(Cwd, "ebin"));
false ->
code:add_patha(filename:join(Cwd, "ebin"))
end
end.

-spec check_vm_support() -> ok.
check_vm_support() ->
try erl_debugger:supported() of
Expand Down
40 changes: 28 additions & 12 deletions edb_core/src/edb_gatekeeper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -65,29 +65,45 @@ new(Options) when node() /= 'nonode@nohost' ->

#{name_domain := NameDomain} = net_kernel:get_state(),

NameDomainStr = atom_to_list(NameDomain),
NodeStr = atom_to_list(node()),
CookieStr = atom_to_list(erlang:get_cookie()),
GatekeeperNameStr = atom_to_list(GatekeeperName),

EscNameDomain = build_esc(NameDomainStr),
EscNode = build_esc(NodeStr),
EscCookie = build_esc(CookieStr),
EscGatekeeper = build_esc(GatekeeperNameStr),

CallGatekeeperCode = io_lib:format(
~"""
case net_kernel:get_state() of
#{started := no} -> {ok, _} = net_kernel:start(undefined, #{name_domain => ~p});
#{started := no} -> {ok, _} = net_kernel:start(undefined, #{name_domain => list_to_atom(binary_to_list(~s))});
_ -> ok
end,
erlang:set_cookie(~p, ~p),
true = net_kernel:connect_node(~p),
ok = gen_server:call({~p, ~p}, [])
erlang:set_cookie(list_to_atom(binary_to_list(~s)), list_to_atom(binary_to_list(~s))),
true = net_kernel:connect_node(list_to_atom(binary_to_list(~s))),
ok = gen_server:call({list_to_atom(binary_to_list(~s)), list_to_atom(binary_to_list(~s))}, [])
""",
[
NameDomain,
node(),
erlang:get_cookie(),
node(),
GatekeeperName,
node()
EscNameDomain,
EscNode,
EscCookie,
EscNode,
EscGatekeeper,
EscNode
]
),

SingleLine = iolist_to_binary(re:replace(CallGatekeeperCode, "\\n", " ", [global])),
CallGatekeeperCodeNoCR = re:replace(CallGatekeeperCode, "\\r", "", [global]),
SingleLine = iolist_to_binary(re:replace(CallGatekeeperCodeNoCR, "\\n", " ", [global])),
{ok, Id, SingleLine}.

-spec build_esc(string()) -> string().
build_esc(Str) ->
IntStrs = [integer_to_list(C) || C <- Str],
Joined = lists:flatten(lists:join(",", IntStrs)),
"<<" ++ Joined ++ ">>".

%% -------------------------------------------------------------------
%% gen_server callbacks
%% -------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions edb_core/src/edb_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,7 @@ suspend_all_processes(Universe, Unsuspendable, State0) ->
Pid => []
|| Pid <- Universe,
not MustIgnore(Pid),
erlang:is_process_alive(Pid),
edb_server_process:try_suspend_process(Pid)
},
AllSuspended = maps:merge(AlreadySuspended, JustSuspended),
Expand Down
10 changes: 9 additions & 1 deletion edb_core/src/edb_server_code.erl
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,21 @@ get_debug_info(Module, Line) when is_atom(Module) ->
case lists:keyfind(Line, 1, DebugInfo) of
false ->
{error, line_not_found};
{Line, LineDebugInfo} ->
{Line, LineDebugInfo} when is_map(LineDebugInfo) ->
Vars =
#{
Var => assert_is_var_debug_info(Val)
|| {Var, Val} <- maps:get(vars, LineDebugInfo, []), is_binary(Var)
},
Calls = maps:get(calls, LineDebugInfo, []),
{ok, #{vars => Vars, calls => Calls}};
{Line, {_, Bindings}} ->
Vars =
#{
Var => assert_is_var_debug_info(Val)
|| {Var, Val} <- Bindings, is_binary(Var)
},
Calls = [],
{ok, #{vars => Vars, calls => Calls}}
end
catch
Expand Down
98 changes: 70 additions & 28 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -76,32 +76,74 @@
% SUITES THAT NEED ESCRIPT
{pre_hooks, [
{ct, "rebar3 escriptize"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_attach_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_attach_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_configuration_phase_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_configuration_phase_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_evaluate_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_evaluate_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_id_mappings_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_id_mappings_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_launch_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_launch_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_parse_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_parse_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_pause_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_pause_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_request_launch_arguments_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_request_launch_arguments_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_scopes_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_scopes_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_session_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_session_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_set_breakpoints_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_set_breakpoints_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_steps_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_steps_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_utils_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_utils_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_main_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_main_SUITE_data"}

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_attach_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_attach_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_attach_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_attach_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_attach_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_configuration_phase_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_configuration_phase_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_configuration_phase_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_configuration_phase_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_configuration_phase_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_evaluate_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_evaluate_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_evaluate_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_evaluate_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_evaluate_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_id_mappings_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_id_mappings_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_id_mappings_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_id_mappings_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_id_mappings_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_launch_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_launch_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_launch_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_launch_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_launch_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_parse_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_parse_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_parse_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_parse_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_parse_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_pause_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_pause_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_pause_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_pause_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_pause_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_request_launch_arguments_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_request_launch_arguments_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_request_launch_arguments_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_request_launch_arguments_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_request_launch_arguments_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_scopes_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_scopes_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_scopes_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_scopes_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_scopes_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_session_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_session_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_session_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_session_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_session_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_set_breakpoints_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_set_breakpoints_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_set_breakpoints_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_set_breakpoints_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_set_breakpoints_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_steps_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_steps_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_steps_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_steps_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_steps_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_dap_utils_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_dap_utils_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_dap_utils_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_dap_utils_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_dap_utils_SUITE_data\\edb _build\\default\\bin\\edb"},

{"(linux|darwin|solaris|freebsd)", ct, "mkdir -p _build/test/lib/edb/test/edb_main_SUITE_data"},
{"win32", ct, "if not exist _build\\test\\lib\\edb\\test\\edb_main_SUITE_data mkdir _build\\test\\lib\\edb\\test\\edb_main_SUITE_data"},
{"(linux|darwin|solaris|freebsd)", ct, "ln -f _build/default/bin/edb _build/test/lib/edb/test/edb_main_SUITE_data/edb"},
{"win32", ct, "mklink /H _build\\test\\lib\\edb\\test\\edb_main_SUITE_data\\edb _build\\default\\bin\\edb"}
]}.