From d8d07a7593d811a6adad060951bc425ee0d81446 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 19 Oct 2017 14:50:50 +0200 Subject: compiler: Add +to_dis option that dumps loaded asm --- lib/compiler/src/beam_listing.erl | 14 ++++++++++++++ lib/compiler/src/compile.erl | 6 ++++-- lib/compiler/test/compile_SUITE.erl | 2 ++ lib/kernel/src/erts_debug.erl | 26 +++++++++++++++++--------- 4 files changed, 37 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_listing.erl b/lib/compiler/src/beam_listing.erl index 94b47cf568..836378727b 100644 --- a/lib/compiler/src/beam_listing.erl +++ b/lib/compiler/src/beam_listing.erl @@ -24,6 +24,7 @@ -include("core_parse.hrl"). -include("v3_kernel.hrl"). -include("v3_life.hrl"). +-include("beam_disasm.hrl"). -import(lists, [foreach/2]). @@ -59,6 +60,19 @@ module(Stream, {Mod,Exp,Attr,Code,NumLabels}) -> [Name, Arity, Entry]), io:put_chars(Stream, format_asm(Asm)) end, Code); +module(Stream, Code) when is_binary(Code) -> + #beam_file{ module = Module, compile_info = CInfo } = beam_disasm:file(Code), + Loaded = code:is_loaded(Module), + Sticky = code:is_sticky(Module), + [code:unstick_mod(Module) || Sticky], + + {module, Module} = code:load_binary(Module, proplists:get_value(source, CInfo), Code), + ok = erts_debug:df(Stream, Module), + + %% Restore loaded module + _ = [{module, Module} = code:load_file(Module) || Loaded =/= false], + [code:stick_mod(Module) || Sticky], + ok; module(Stream, [_|_]=Fs) -> %% Form-based abstract format. foreach(fun (F) -> io:format(Stream, "~p.\n", [F]) end, Fs). diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index aa2d224bb4..50b0ba76f8 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -787,8 +787,10 @@ asm_passes() -> | binary_passes()]. binary_passes() -> - [{native_compile,fun test_native/1,fun native_compile/2}, - {unless,binary,?pass(save_binary,not_werror)}]. + [{iff,'to_dis',{listing,"dis"}}, + {native_compile,fun test_native/1,fun native_compile/2}, + {unless,binary,?pass(save_binary,not_werror)} + ]. %%% %%% Compiler passes. diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index f647a4030d..98a77ea2b2 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -398,6 +398,7 @@ do_file_listings(DataDir, PrivDir, [File|Files]) -> ok = file:delete(filename:join(Listings, File ++ ".core")), do_listing(Simple, TargetDir, to_core, ".core"), do_listing(Simple, TargetDir, to_kernel, ".kernel"), + do_listing(Simple, TargetDir, to_dis, ".dis"), %% Final clean up. lists:foreach(fun(F) -> ok = file:delete(F) end, @@ -413,6 +414,7 @@ listings_big(Config) when is_list(Config) -> do_listing(Big, TargetDir, 'E'), do_listing(Big, TargetDir, 'P'), do_listing(Big, TargetDir, dkern, ".kernel"), + do_listing(Big, TargetDir, to_dis, ".dis"), TargetNoext = filename:rootname(Target, code:objfile_extension()), {ok,big} = compile:file(TargetNoext, [from_asm,{outdir,TargetDir}]), diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index 480db6814e..9662f8fa90 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -21,7 +21,7 @@ %% Low-level debugging support. EXPERIMENTAL! --export([size/1,df/1,df/2,df/3,ic/1]). +-export([size/1,df/1,df/2,df/3,df/4,ic/1]). %% This module contains the following *experimental* BIFs: %% disassemble/1 @@ -347,31 +347,39 @@ is_term_seen(_, []) -> false. -spec df(module()) -> df_ret(). df(Mod) when is_atom(Mod) -> + df(lists:concat([Mod, ".dis"]), Mod). + +-spec df(module(), atom()) -> df_ret(); + (file:io_device() | file:filename(), module()) -> df_ret(). + +df(Mod, Func) when is_atom(Mod), is_atom(Func) -> + df(lists:concat([Mod, "_", Func, ".dis"]), Mod, Func); +df(Name, Mod) when is_atom(Mod) -> try Mod:module_info(functions) of Fs0 when is_list(Fs0) -> - Name = lists:concat([Mod, ".dis"]), Fs = [{Mod,Func,Arity} || {Func,Arity} <- Fs0], dff(Name, Fs) catch _:_ -> {undef,Mod} end. --spec df(module(), atom()) -> df_ret(). -df(Mod, Func) when is_atom(Mod), is_atom(Func) -> +-spec df(module(), atom(), arity()) -> df_ret(); + (file:io_device() | file:filename(), module(), atom()) -> df_ret(). + +df(Mod, Func, Arity) when is_atom(Mod), is_atom(Func), is_integer(Arity) -> + df(lists:concat([Mod, "_", Func, "_", Arity, ".dis"]), Mod, Func, Arity); +df(Name, Mod, Func) when is_atom(Mod), is_atom(Func) -> try Mod:module_info(functions) of Fs0 when is_list(Fs0) -> - Name = lists:concat([Mod, "_", Func, ".dis"]), Fs = [{Mod,Func1,Arity} || {Func1,Arity} <- Fs0, Func1 =:= Func], dff(Name, Fs) catch _:_ -> {undef,Mod} end. --spec df(module(), atom(), arity()) -> df_ret(). - -df(Mod, Func, Arity) when is_atom(Mod), is_atom(Func) -> +-spec df(file:io_device() | file:filename(), module(), atom(), arity()) -> df_ret(). +df(Name, Mod, Func, Arity) when is_atom(Mod), is_atom(Func), is_integer(Arity) -> try Mod:module_info(functions) of Fs0 when is_list(Fs0) -> - Name = lists:concat([Mod, "_", Func, "_", Arity, ".dis"]), Fs = [{Mod,Func1,Arity1} || {Func1,Arity1} <- Fs0, Func1 =:= Func, Arity1 =:= Arity], dff(Name, Fs) -- cgit v1.2.3