@@ -193,6 +193,7 @@ static term nif_code_all_loaded(Context *ctx, int argc, term argv[]);
193193static term nif_code_load_abs (Context * ctx , int argc , term argv []);
194194static term nif_code_load_binary (Context * ctx , int argc , term argv []);
195195static term nif_code_ensure_loaded (Context * ctx , int argc , term argv []);
196+ static term nif_code_get_object_code (Context * ctx , int argc , term argv []);
196197static term nif_erlang_module_loaded (Context * ctx , int argc , term argv []);
197198static term nif_erlang_nif_error (Context * ctx , int argc , term argv []);
198199static term nif_lists_reverse (Context * ctx , int argc , term argv []);
@@ -826,6 +827,11 @@ static const struct Nif code_ensure_loaded_nif =
826827 .nif_ptr = nif_code_ensure_loaded
827828};
828829
830+ static const struct Nif code_get_object_code_nif = {
831+ .base .type = NIFFunctionType ,
832+ .nif_ptr = nif_code_get_object_code
833+ };
834+
829835static const struct Nif module_loaded_nif =
830836{
831837 .base .type = NIFFunctionType ,
@@ -5408,6 +5414,52 @@ static term nif_code_ensure_loaded(Context *ctx, int argc, term argv[])
54085414 return result ;
54095415}
54105416
5417+ static term nif_code_get_object_code (Context * ctx , int argc , term argv [])
5418+ {
5419+ UNUSED (argc );
5420+ term module_atom = argv [0 ];
5421+ VALIDATE_VALUE (module_atom , term_is_atom );
5422+
5423+ size_t module_name_len ;
5424+ const uint8_t * module_name = atom_table_get_atom_string (ctx -> global -> atom_table , term_to_atom_index (module_atom ), & module_name_len );
5425+
5426+ size_t filename_len = module_name_len + 6 ;
5427+ char * module_file_name = malloc (filename_len );
5428+ if (IS_NULL_PTR (module_file_name )) {
5429+ return ERROR_ATOM ;
5430+ }
5431+ memcpy (module_file_name , module_name , module_name_len );
5432+ memcpy (module_file_name + module_name_len , ".beam" , 6 );
5433+ Module * module = globalcontext_load_module_from_avm (ctx -> global , module_file_name );
5434+
5435+ if (IS_NULL_PTR (module )) {
5436+ module = sys_load_module_from_file (ctx -> global , module_file_name );
5437+ }
5438+ if (UNLIKELY (!module )) {
5439+ free (module_file_name );
5440+ return ERROR_ATOM ;
5441+ }
5442+
5443+ size_t result_size = TUPLE_SIZE (3 ) + term_binary_heap_size (module -> binary_size ) + LIST_SIZE (filename_len , 1 );
5444+ if (UNLIKELY (memory_ensure_free_with_roots (ctx , result_size , 1 , & module_atom , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK )) {
5445+ free (module_file_name );
5446+ RAISE_ERROR (OUT_OF_MEMORY_ATOM );
5447+ }
5448+ // Note: this assumes constness of module->binary and could be use-after-free if we allowed changing module bitcode at runtime.
5449+ // TODO: update this code when module unloading will be supported.
5450+ term binary = term_from_literal_binary ((void * ) module -> binary , module -> binary_size , & ctx -> heap , ctx -> global );
5451+ // TODO: this code has to be changed to return the complete path
5452+ term filename_term = term_from_string ((const uint8_t * ) module_file_name , filename_len , & ctx -> heap );
5453+ term result = term_alloc_tuple (3 , & ctx -> heap );
5454+
5455+ term_put_tuple_element (result , 0 , module_atom );
5456+ term_put_tuple_element (result , 1 , binary );
5457+ term_put_tuple_element (result , 2 , filename_term );
5458+
5459+ free (module_file_name );
5460+ return result ;
5461+ }
5462+
54115463static term nif_erlang_module_loaded (Context * ctx , int argc , term argv [])
54125464{
54135465 UNUSED (argc );
0 commit comments