aboutsummaryrefslogtreecommitdiffstats
path: root/lib/runtime_tools
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2013-07-11 17:10:16 +0200
committerBjörn-Egil Dahlberg <[email protected]>2013-07-15 17:01:36 +0200
commitc250cec28d4cd5dbe68abd8835730eaf81aba086 (patch)
tree710f1196773799e0a481390d8b24d2f6447cafac /lib/runtime_tools
parent5e768c8765bc70d70599dd9a6e5d27875de490e3 (diff)
downloadotp-c250cec28d4cd5dbe68abd8835730eaf81aba086.tar.gz
otp-c250cec28d4cd5dbe68abd8835730eaf81aba086.tar.bz2
otp-c250cec28d4cd5dbe68abd8835730eaf81aba086.zip
Check for native code without loading module
Diffstat (limited to 'lib/runtime_tools')
-rw-r--r--lib/runtime_tools/src/system_information.erl89
-rw-r--r--lib/runtime_tools/test/system_information_SUITE.erl1
2 files changed, 83 insertions, 7 deletions
diff --git a/lib/runtime_tools/src/system_information.erl b/lib/runtime_tools/src/system_information.erl
index b0f03126b9..1d4b878d79 100644
--- a/lib/runtime_tools/src/system_information.erl
+++ b/lib/runtime_tools/src/system_information.erl
@@ -38,7 +38,8 @@
applications/0, applications/1,
application/1, application/2,
environment/0, environment/1,
- module/1, module/2
+ module/1, module/2,
+ modules/1
]).
%% gen_server callbacks
@@ -126,6 +127,8 @@ module(M) when is_atom(M) -> module(M, []).
module(M, Opts) when is_atom(M), is_list(Opts) ->
gen_server:call(?SERVER, {module, M, Opts}).
+modules(Opt) when is_atom(Opt) ->
+ gen_server:call(?SERVER, {modules, Opt}).
%%===================================================================
%% gen_server callbacks
@@ -169,6 +172,11 @@ handle_call({module, M, Opts}, _From, #state{ report = Report } = S) ->
print_modules_from_code(M, Mods, Opts),
{reply, ok, S};
+handle_call({modules, native}, _From, #state{ report = Report } = S) ->
+ Codes = get_native_modules_from_code(get_value([code],Report)),
+ io:format("~p~n", [Codes]),
+ {reply, ok, S};
+
handle_call(_Request, _From, State) ->
{reply, ok, State}.
@@ -216,6 +224,31 @@ find_modules(M, [{M, _}=Info|Ms]) -> [Info|find_modules(M,Ms)];
find_modules(M, [_|Ms]) -> find_modules(M, Ms);
find_modules(_, []) -> [].
+get_native_modules_from_code([{application, {App, Info}}|Cs]) ->
+ case get_native_modules(get_value([modules], Info)) of
+ [] -> get_native_modules_from_code(Cs);
+ Mods ->
+ Path = get_value([path], Info),
+ Vsn = get_value([vsn], Info),
+ [{App, Vsn, Path, Mods}|get_native_modules_from_code(Cs)]
+ end;
+get_native_modules_from_code([{code, Info}|Cs]) ->
+ case get_native_modules(get_value([modules], Info)) of
+ [] -> get_native_modules_from_code(Cs);
+ Mods ->
+ Path = get_value([path], Info),
+ [{Path, Mods}|get_native_modules_from_code(Cs)]
+ end;
+get_native_modules_from_code([]) -> [].
+
+get_native_modules([]) -> [];
+get_native_modules([{Mod, Info}|Ms]) ->
+ case proplists:get_value(native, Info) of
+ false -> get_native_modules(Ms);
+ _ -> [Mod|get_native_modules(Ms)]
+ end.
+
+
%% print information
print_applications([{application, App}|Apps], Opts) ->
@@ -437,10 +470,10 @@ get_modules_from_path(Path) ->
_ -> true
end,
{Mod, [
- {loaded, Loaded},
- {native, code:is_module_native(Mod)},
+ {loaded, Loaded},
+ {native, beam_is_native_compiled(Beam)},
{compiler, get_compiler_version(Beam)},
- {md5, hexstring(Md5)}
+ {md5, hexstring(Md5)}
]}
end || Beam <- filelib:wildcard(filename:join(Path, "*.beam"))
].
@@ -448,14 +481,56 @@ get_modules_from_path(Path) ->
hexstring(Bin) when is_binary(Bin) ->
lists:flatten([io_lib:format("~2.16.0b", [V]) || <<V>> <= Bin]).
-get_compiler_version(B) ->
- {ok, Bin} = file:read_file(B),
- case beam_lib:chunks(Bin, [compile_info]) of
+%% inspect beam files for information
+
+get_compiler_version(Beam) ->
+ case beam_lib:chunks(Beam, [compile_info]) of
{ok,{_,[{compile_info, Info}]}} ->
proplists:get_value(version, Info);
_ -> undefined
end.
+%% we don't know the specific chunk names of native code
+%% we don't want to load the code to check it
+beam_is_native_compiled(Beam) ->
+ Chunks = get_value([chunks], beam_lib:info(Beam)),
+ case check_known_hipe_chunks(Chunks) of
+ [] -> false;
+ [Arch] -> {true, Arch};
+ Archs -> {true, Archs}
+ end.
+
+
+check_known_hipe_chunks([{Tag,_,_}|Cs]) ->
+ case is_chunk_tag_hipe_arch(Tag) of
+ false -> check_known_hipe_chunks(Cs);
+ {true, Arch} -> [Arch|check_known_hipe_chunks(Cs)]
+ end;
+check_known_hipe_chunks([]) -> [].
+
+%% these values are taken from hipe_unified_loader
+%% perhaps these should be exported in that module?
+
+-define(HS8P_TAG,"HS8P").
+-define(HPPC_TAG,"HPPC").
+-define(HP64_TAG,"HP64").
+-define(HARM_TAG,"HARM").
+-define(HX86_TAG,"HX86").
+-define(HA64_TAG,"HA64").
+
+is_chunk_tag_hipe_arch(Tag) ->
+ case Tag of
+ ?HA64_TAG -> {true, amd64}; %% HiPE, x86_64, (implicit: 64-bit, Unix)
+ ?HARM_TAG -> {true, arm}; %% HiPE, arm, v5 (implicit: 32-bit, Linux)
+ ?HPPC_TAG -> {true, powerpc}; %% HiPE, PowerPC (implicit: 32-bit, Linux)
+ ?HP64_TAG -> {true, ppc64}; %% HiPE, ppc64 (implicit: 64-bit, Linux)
+ ?HS8P_TAG -> {true, ultrasparc}; %% HiPE, SPARC, V8+ (implicit: 32-bit)
+ %% Future: HSV9 %% HiPE, SPARC, V9 (implicit: 64-bit)
+ %% HW32 %% HiPE, x86, Win32
+ _ -> false
+ end.
+
+
get_dynamic_libraries() ->
Beam = filename:join([os:getenv("BINDIR"),get_beam_name()]),
case os:type() of
diff --git a/lib/runtime_tools/test/system_information_SUITE.erl b/lib/runtime_tools/test/system_information_SUITE.erl
index 9dd4e67efc..fb9455a30f 100644
--- a/lib/runtime_tools/test/system_information_SUITE.erl
+++ b/lib/runtime_tools/test/system_information_SUITE.erl
@@ -274,6 +274,7 @@ validate_loaded_report() ->
ok = system_information:application(kernel,[full]),
ok = system_information:module(gen_server),
ok = system_information:module(gen_server,[full]),
+ ok = system_information:modules(native),
ok.