From fdb350a4c98f070c264b8bd4ea9eca2513352f21 Mon Sep 17 00:00:00 2001
From: Richard Carlsson
Date: Wed, 14 May 2014 14:46:46 +0200
Subject: Add 'md5' entry for module_info/0/1 functions.
---
erts/emulator/beam/atom.names | 1 +
erts/emulator/beam/beam_load.c | 56 ++++++++++++++++++++++++++++----
erts/emulator/beam/beam_load.h | 8 +++--
erts/emulator/test/module_info_SUITE.erl | 21 ++++++++++--
erts/preloaded/src/erlang.erl | 2 +-
system/doc/reference_manual/modules.xml | 7 +++-
6 files changed, 81 insertions(+), 14 deletions(-)
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index d28e519ae1..7d11f7f956 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -333,6 +333,7 @@ atom max
atom maximum
atom max_tables max_processes
atom mbuf_size
+atom md5
atom memory
atom memory_internal
atom memory_types
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index e96177cfd9..5c98d5c0b5 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -245,7 +245,7 @@ typedef struct {
/*
* This structure contains all information about the module being loaded.
*/
-
+#define MD5_SIZE 16
typedef struct LoaderState {
/*
* The current logical file within the binary.
@@ -292,7 +292,7 @@ typedef struct LoaderState {
StringPatch* string_patches; /* Linked list of position into string table to patch. */
BeamInstr catches; /* Linked list of catch_yf instructions. */
unsigned loaded_size; /* Final size of code when loaded. */
- byte mod_md5[16]; /* MD5 for module code. */
+ byte mod_md5[MD5_SIZE]; /* MD5 for module code. */
int may_load_nif; /* true if NIFs may later be loaded for this module */
int on_load; /* Index in the code for the on_load function
* (or 0 if there is no on_load function)
@@ -528,6 +528,7 @@ static Eterm exported_from_module(Process* p, Eterm mod);
static Eterm functions_in_module(Process* p, Eterm mod);
static Eterm attributes_for_module(Process* p, Eterm mod);
static Eterm compilation_info_for_module(Process* p, Eterm mod);
+static Eterm md5_of_module(Process* p, Eterm mod);
static Eterm native_addresses(Process* p, Eterm mod);
int patch_funentries(Eterm Patchlist);
int patch(Eterm Addresses, Uint fe);
@@ -648,6 +649,7 @@ erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
stp->code[MI_COMPILE_PTR] = 0;
stp->code[MI_COMPILE_SIZE] = 0;
stp->code[MI_COMPILE_SIZE_ON_HEAP] = 0;
+ stp->code[MI_MD5_PTR] = 0;
/*
* Read the atom table.
@@ -4038,7 +4040,7 @@ freeze_code(LoaderState* stp)
}
size = (stp->ci * sizeof(BeamInstr)) +
(stp->total_literal_size * sizeof(Eterm)) +
- strtab_size + attr_size + compile_size + line_size;
+ strtab_size + attr_size + compile_size + MD5_SIZE + line_size;
/*
* Move the code to its final location.
@@ -4247,11 +4249,20 @@ freeze_code(LoaderState* stp)
code[MI_COMPILE_SIZE_ON_HEAP] = decoded_size;
}
CHKBLK(ERTS_ALC_T_CODE,code);
+ {
+ byte* md5_sum = str_table + strtab_size + attr_size + compile_size;
+ CHKBLK(ERTS_ALC_T_CODE,code);
+ sys_memcpy(md5_sum, stp->mod_md5, MD5_SIZE);
+ CHKBLK(ERTS_ALC_T_CODE,code);
+ code[MI_MD5_PTR] = (BeamInstr) md5_sum;
+ CHKBLK(ERTS_ALC_T_CODE,code);
+ }
+ CHKBLK(ERTS_ALC_T_CODE,code);
/*
* Make sure that we have not overflowed the allocated code space.
*/
- ASSERT(str_table + strtab_size + attr_size + compile_size ==
+ ASSERT(str_table + strtab_size + attr_size + compile_size + MD5_SIZE ==
((byte *) code) + size);
/*
@@ -5103,6 +5114,7 @@ erts_module_info_0(Process* p, Eterm module)
hp += 3; \
list = CONS(hp, tup, list)
+ BUILD_INFO(am_md5);
BUILD_INFO(am_compile);
BUILD_INFO(am_attributes);
BUILD_INFO(am_imports);
@@ -5118,6 +5130,8 @@ erts_module_info_1(Process* p, Eterm module, Eterm what)
return module;
} else if (what == am_imports) {
return NIL;
+ } else if (what == am_md5) {
+ return md5_of_module(p, module);
} else if (what == am_exports) {
return exported_from_module(p, module);
} else if (what == am_functions) {
@@ -5306,7 +5320,7 @@ attributes_for_module(Process* p, /* Process whose heap to use. */
Eterm result = NIL;
Eterm* end;
- if (is_not_atom(mod) || (is_not_list(result) && is_not_nil(result))) {
+ if (is_not_atom(mod)) {
return THE_NON_VALUE;
}
@@ -5345,7 +5359,7 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */
Eterm result = NIL;
Eterm* end;
- if (is_not_atom(mod) || (is_not_list(result) && is_not_nil(result))) {
+ if (is_not_atom(mod)) {
return THE_NON_VALUE;
}
@@ -5367,6 +5381,33 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */
return result;
}
+/*
+ * Returns the MD5 checksum for a module
+ *
+ * Returns a tagged term, or 0 on error.
+ */
+
+Eterm
+md5_of_module(Process* p, /* Process whose heap to use. */
+ Eterm mod) /* Tagged atom for module. */
+{
+ Module* modp;
+ BeamInstr* code;
+ Eterm res = NIL;
+
+ if (is_not_atom(mod)) {
+ return THE_NON_VALUE;
+ }
+
+ modp = erts_get_module(mod, erts_active_code_ix());
+ if (modp == NULL) {
+ return THE_NON_VALUE;
+ }
+ code = modp->curr.code;
+ res = new_binary(p, (byte *) code[MI_MD5_PTR], MD5_SIZE);
+ return res;
+}
+
/*
* Build a single {M,F,A,Loction} item to be part of
* a stack trace.
@@ -5543,7 +5584,7 @@ code_module_md5_1(BIF_ALIST_1)
res = am_undefined;
goto done;
}
- res = new_binary(p, stp->mod_md5, sizeof(stp->mod_md5));
+ res = new_binary(p, stp->mod_md5, MD5_SIZE);
done:
erts_free_aligned_binary_bytes(temp_alloc);
@@ -5939,6 +5980,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
code[MI_LITERALS_END] = 0;
code[MI_LITERALS_OFF_HEAP] = 0;
code[MI_ON_LOAD_FUNCTION_PTR] = 0;
+ code[MI_MD5_PTR] = 0;
ci = MI_FUNCTIONS + n + 1;
/*
diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h
index bd22b0c4de..0e3ca0bdb0 100644
--- a/erts/emulator/beam/beam_load.h
+++ b/erts/emulator/beam/beam_load.h
@@ -91,7 +91,6 @@ extern Uint erts_total_code_size;
#define MI_LITERALS_END 8
#define MI_LITERALS_OFF_HEAP 9
-
/*
* Pointer to the on_load function (or NULL if none).
*/
@@ -102,6 +101,11 @@ extern Uint erts_total_code_size;
*/
#define MI_LINE_TABLE 11
+/*
+ * Pointer to the module MD5 sum (16 bytes)
+ */
+#define MI_MD5_PTR 12
+
/*
* Start of function pointer table. This table contains pointers to
* all functions in the module plus an additional pointer just beyond
@@ -111,7 +115,7 @@ extern Uint erts_total_code_size;
* this table.
*/
-#define MI_FUNCTIONS 12
+#define MI_FUNCTIONS 13
/*
* Layout of the line table.
diff --git a/erts/emulator/test/module_info_SUITE.erl b/erts/emulator/test/module_info_SUITE.erl
index 8a63d9fe3e..06cd2a9b9a 100644
--- a/erts/emulator/test/module_info_SUITE.erl
+++ b/erts/emulator/test/module_info_SUITE.erl
@@ -24,7 +24,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
- exports/1,functions/1,native/1]).
+ exports/1,functions/1,native/1,info/1]).
%%-compile(native).
@@ -52,8 +52,8 @@ end_per_group(_GroupName, Config) ->
Config.
-modules() ->
- [exports, functions, native].
+modules() ->
+ [exports, functions, native, info].
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
Dog = ?t:timetrap(?t:minutes(3)),
@@ -122,6 +122,21 @@ native_proj({Name,Arity,Addr}) ->
native_filter(Set) ->
sofs:no_elements(Set) =/= 1.
+%% Test that the module info of this module is correct. Use
+%% erlang:get_module_info(?MODULE) to avoid compiler optimization tricks.
+info(Config) when is_list(Config) ->
+ Info = erlang:get_module_info(?MODULE),
+ All = all_exported(),
+ {ok,{?MODULE,MD5}} = beam_lib:md5(code:which(?MODULE)),
+ {md5, MD5} = lists:keyfind(md5, 1, Info),
+ {exports, Exports} = lists:keyfind(exports, 1, Info),
+ All = lists:sort(Exports),
+ {attributes, Attrs} = lists:keyfind(attributes, 1, Info),
+ {vsn,_} = lists:keyfind(vsn, 1, Attrs),
+ {compile, Compile} = lists:keyfind(compile, 1, Info),
+ {options,_} = lists:keyfind(options, 1, Compile),
+ ok.
+
%% Helper functions (local).
add_arity(L) ->
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index cabbbd191f..bcc1250abd 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -1664,7 +1664,7 @@ element(_N, _Tuple) ->
%% Not documented
-spec erlang:get_module_info(Module, Item) -> ModuleInfo when
Module :: atom(),
- Item :: module | imports | exports | functions | attributes | compile | native_addresses,
+ Item :: module | imports | exports | functions | attributes | compile | native_addresses | md5,
ModuleInfo :: atom() | [] | [{atom(), arity()}] | [{atom(), term()}] | [{atom(), arity(), integer()}].
get_module_info(_Module, _Item) ->
erlang:nif_error(undefined).
diff --git a/system/doc/reference_manual/modules.xml b/system/doc/reference_manual/modules.xml
index f0ec7ef165..c8f443d9dd 100644
--- a/system/doc/reference_manual/modules.xml
+++ b/system/doc/reference_manual/modules.xml
@@ -230,7 +230,7 @@ behaviour_info(callbacks) -> Callbacks.
a list of {Key,Value} tuples with information about
the module. Currently, the list contain tuples with the following
Keys: attributes, compile,
- exports, and imports. The order and number of tuples
+ exports, imports and md5. The order and number of tuples
may change without prior notice.
The {imports,Value} tuple may be removed in a future
@@ -273,6 +273,11 @@ behaviour_info(callbacks) -> Callbacks.
be supported in future release.
+ md5
+ -
+
Return a binary representing the MD5 checksum of the module.
+
+
exports
-
Return a list of {Name,Arity} tuples with
--
cgit v1.2.3
From 4ad572a8b66df8174d92157411326aab95ee8124 Mon Sep 17 00:00:00 2001
From: Richard Carlsson
Date: Wed, 14 May 2014 14:49:10 +0200
Subject: Add 'module' entry for module_info/0 function for completeness
as it exist in module_info/1.
---
erts/emulator/beam/beam_load.c | 1 +
erts/emulator/test/module_info_SUITE.erl | 1 +
system/doc/reference_manual/modules.xml | 7 ++++++-
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 5c98d5c0b5..8b3fc90826 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -5119,6 +5119,7 @@ erts_module_info_0(Process* p, Eterm module)
BUILD_INFO(am_attributes);
BUILD_INFO(am_imports);
BUILD_INFO(am_exports);
+ BUILD_INFO(am_module);
#undef BUILD_INFO
return list;
}
diff --git a/erts/emulator/test/module_info_SUITE.erl b/erts/emulator/test/module_info_SUITE.erl
index 06cd2a9b9a..f3986f0c4f 100644
--- a/erts/emulator/test/module_info_SUITE.erl
+++ b/erts/emulator/test/module_info_SUITE.erl
@@ -128,6 +128,7 @@ info(Config) when is_list(Config) ->
Info = erlang:get_module_info(?MODULE),
All = all_exported(),
{ok,{?MODULE,MD5}} = beam_lib:md5(code:which(?MODULE)),
+ {module, ?MODULE} = lists:keyfind(module, 1, Info),
{md5, MD5} = lists:keyfind(md5, 1, Info),
{exports, Exports} = lists:keyfind(exports, 1, Info),
All = lists:sort(Exports),
diff --git a/system/doc/reference_manual/modules.xml b/system/doc/reference_manual/modules.xml
index c8f443d9dd..ac778805fe 100644
--- a/system/doc/reference_manual/modules.xml
+++ b/system/doc/reference_manual/modules.xml
@@ -229,7 +229,7 @@ behaviour_info(callbacks) -> Callbacks.
The module_info/0 function in each module returns
a list of {Key,Value} tuples with information about
the module. Currently, the list contain tuples with the following
- Keys: attributes, compile,
+ Keys: module, attributes, compile,
exports, imports and md5. The order and number of tuples
may change without prior notice.
@@ -246,6 +246,11 @@ behaviour_info(callbacks) -> Callbacks.
The following values are allowed for Key:
+ module
+ -
+
Return an atom representing the module name.
+
+
attributes
-
Return a list of {AttributeName,ValueList} tuples,
--
cgit v1.2.3
From 0dbcbea0cf52672ef1cf051c3cd7640eb7ff728e Mon Sep 17 00:00:00 2001
From: Richard Carlsson
Date: Wed, 14 May 2014 14:54:16 +0200
Subject: Remove obsolete 'imports' entry from module_info/1/2 functions
It previously always returned an empty list
and was documented to be removed.
---
erts/emulator/beam/atom.names | 1 -
erts/emulator/beam/beam_load.c | 3 ---
system/doc/reference_manual/modules.xml | 12 +-----------
3 files changed, 1 insertion(+), 15 deletions(-)
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 7d11f7f956..dc930f2d38 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -278,7 +278,6 @@ atom http httph https http_response http_request http_header http_eoh http_error
atom id
atom if_clause
atom ignore
-atom imports
atom in
atom in_exiting
atom inactive
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 8b3fc90826..a4e72a130a 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -5117,7 +5117,6 @@ erts_module_info_0(Process* p, Eterm module)
BUILD_INFO(am_md5);
BUILD_INFO(am_compile);
BUILD_INFO(am_attributes);
- BUILD_INFO(am_imports);
BUILD_INFO(am_exports);
BUILD_INFO(am_module);
#undef BUILD_INFO
@@ -5129,8 +5128,6 @@ erts_module_info_1(Process* p, Eterm module, Eterm what)
{
if (what == am_module) {
return module;
- } else if (what == am_imports) {
- return NIL;
} else if (what == am_md5) {
return md5_of_module(p, module);
} else if (what == am_exports) {
diff --git a/system/doc/reference_manual/modules.xml b/system/doc/reference_manual/modules.xml
index ac778805fe..5fc8b363f8 100644
--- a/system/doc/reference_manual/modules.xml
+++ b/system/doc/reference_manual/modules.xml
@@ -230,12 +230,8 @@ behaviour_info(callbacks) -> Callbacks.
a list of {Key,Value} tuples with information about
the module. Currently, the list contain tuples with the following
Keys: module, attributes, compile,
- exports, imports and md5. The order and number of tuples
+ exports and md5. The order and number of tuples
may change without prior notice.
-
- The {imports,Value} tuple may be removed in a future
- release because Value is always an empty list.
- Do not write code that depends on it being present.
@@ -272,12 +268,6 @@ behaviour_info(callbacks) -> Callbacks.
beam_lib(3).
- imports
- -
-
Always return an empty list. The imports key may not
- be supported in future release.
-
-
md5
-
Return a binary representing the MD5 checksum of the module.
--
cgit v1.2.3