implementation module SearchObject; /* problem: (from the perspective of the dynamic linker) assume a running application uses object from module x. The application uses a dynamic which in turn uses also a module y. If x <> y then there is no problem. But if x == y then, we have a problem. Are the running application and the dynamic using the same (object) module or are there two different but equally named (object) modules? To answer this question more information is needed. We cannot conclude soley from the modules whether the object module is shared or not. Here the type system comes in. Based on the type information available in each (object) module, the type system can decide whether a module is usable for the application and/or dynamic. If it decides that the module x can be shared between the application and its dynamic then there is no problem. But if not, there is a serious problem: we have two *equally* named (object) modules (e.g. both modules are named x) with differently typed objects. The linker can however not load two equally named object modules and consider them different. Somehow we have to load them both! Solution: for the moment it is assumed that all loaded modules have *different* names */ import ExtArray; import ExtString; import ObjectToMem; //1.3 from ReadObject import read_library_file,ReadXcoffM, ExtFileSystem, read_library_file_new; from SortSymbols import sort_modules; from ExtFile import ExtractPathFileAndExtension, ExtractPathAndFile, path_separator, FileExists, strip_abc_and_o_extension; //3.1 /*2.0 from ReadObject import read_library_file,ReadXcoffM, class ExtFileSystem, instance ExtFileSystem Files, read_library_file_new; from SortSymbols import sort_modules; from ExtFile import ExtractPathFileAndExtension, ExtractPathAndFile, path_separator, FileExists, strip_abc_and_o_extension; from deltaIOState import instance FileEnv (IOState s); 0.2*/ F a b :== b; /* ** Loads a module in memory. If necessary e.g. (size symbol_name) > 0 then it is ** checked if the module is its defining module. Accordingly to the result, the ** returned bool is set. If it is false, the module is not loaded e.g. integrated ** with existing modules. */ load_object :: !String !Int !String !*State !*DLClientState !*DLServerState !(IOState s) -> !(!Bool,![(!String,!Int,!Int)],!*State,!*DLClientState,!*DLServerState,!(IOState s)); load_object object_path_name_ext object_fp_in_library symbol_name state=:{one_pass_link,n_xcoff_files} dl_client_state dl_server_state io /* ** If symbol_name must be defined (length greater than zero), then create a ** new, empty names_table because it is unknown if the specified module ** actually defines the symbol. */ #! (names_table,state) = case (size symbol_name) of { 0 #! (names_table,state) = select_namestable state; #! (s_names_table,names_table) = usize names_table; | s_names_table == 0 -> abort "names table is zero" -> (names_table,state); //-> select_namestable state; _ -> (create_names_table,state); } // read object file #! (redirection_state,state) = get_redirection_state state; #! ((any_extra_sections,errors,xcoff_list,names_table,redirection_state),io) = accFiles (ReadXcoffM False object_path_name_ext object_fp_in_library names_table one_pass_link n_xcoff_files redirection_state) io; #! state = put_redirection_state redirection_state state; | not (isEmpty errors) #! state = { state & namestable = names_table }; #! messages = [LinkerError m \\ m <- errors]; = (False,[],SetLinkerMessages messages state,dl_client_state,dl_server_state,io); // if necessary, check if symbol_name is defined in this module #! (symbol_found,names_table,state) = case (size symbol_name) of { 0 // symbol_name needs not be defined -> (True,names_table,state); _ // symbol_name must be defined #! (names_table_element,names_table) = find_symbol_in_symbol_table symbol_name names_table -> case names_table_element of { NamesTableElement _ _ _ _ #! (old_namestable,state) = select_namestable state; -> (True, (MergeNamesTables old_namestable names_table),state); _ -> (False,names_table,state); } } | not symbol_found #! state = { state & namestable = names_table }; #! message = "module '" +++ object_path_name_ext +++ "' requires symbol " +++ symbol_name +++ "to be defined"; = (False,[],AddMessage (LinkerError message) state,dl_client_state,dl_server_state,io); // import as many symbols as can be resolved; sort on macos probably not needed #! map_function = sel_platform sort_modules // winos (\xcoff -> sort_modules (split_data_symbol_lists_without_removing_unmarked_symbols xcoff)) // macos ; #! (undefined_symbols,xcoff_list,names_table) = import_symbols_in_xcoff_files /*[sort_modules xcoff]*/ (map map_function xcoff_list) n_xcoff_files [] names_table; #! state = update_namestable names_table state; = (True,undefined_symbols,/*add_module (hd xcoffs) state*/ foldl (\state xcoff -> add_module xcoff state) state xcoff_list,dl_client_state,dl_server_state,io); // where { add_module :: !*Xcoff !State -> !State; add_module xcoff=:{n_symbols=n_new_xcoff_symbols} state=:{n_xcoff_files,n_xcoff_symbols,n_library_symbols} // HACK: see InitialLink2 in ObjectToMem.icl; it is a way to pass on the absolute address of the // qd symbol. // #! (qd_address,state) // = acc_pd_state (\pd_state=:{qd_address} -> (qd_address,pd_state)) state; #! (marked_bool_a,state) = select_marked_bool_a state; #! (marked_offset_a,state) = select_marked_offset_a state; #! (module_offset_a,state) = select_module_offset_a state; #! n_xcoff_files_plus_libraries = size marked_offset_a; #! n_symbols = n_xcoff_symbols + n_new_xcoff_symbols + n_library_symbols; # marked_bool_a2 = createArray n_symbols False; marked_bool_a2 = {marked_bool_a2 & [i]=marked_bool_a.[i] \\ i<-[0..n_xcoff_symbols-1]}; marked_bool_a2 = {marked_bool_a2 & [i]=marked_bool_a.[i-n_new_xcoff_symbols] \\ i<-[n_xcoff_symbols+n_new_xcoff_symbols..n_symbols-1]}; # marked_offset_a2 = createArray (n_xcoff_files_plus_libraries+1) 0; marked_offset_a2 = {marked_offset_a2 & [i]=marked_offset_a.[i] \\ i<-[0..n_xcoff_files-1]}; marked_offset_a2 = {marked_offset_a2 & [n_xcoff_files] = n_xcoff_symbols}; marked_offset_a2 = {marked_offset_a2 & [i]=marked_offset_a.[i-1]+n_new_xcoff_symbols \\ i<-[n_xcoff_files+1..n_xcoff_files_plus_libraries]}; # module_offset_a2 = createArray n_symbols 0; module_offset_a2 = {module_offset_a2 & [i]=module_offset_a.[i] \\ i<-[0..n_xcoff_symbols-1]}; module_offset_a2 = {module_offset_a2 & [i]=module_offset_a.[i-n_new_xcoff_symbols] \\ i<-[n_xcoff_symbols+n_new_xcoff_symbols..n_symbols-1]}; #! state = update_state_with_xcoff xcoff state; = { state & n_xcoff_files = n_xcoff_files + 1, n_xcoff_symbols = n_xcoff_symbols + n_new_xcoff_symbols, marked_bool_a = marked_bool_a2, marked_offset_a = marked_offset_a2, module_offset_a = module_offset_a2 }; add_module2 :: !*Xcoff !State -> !State; add_module2 xcoff=:{n_symbols=n_new_xcoff_symbols} state=:{n_xcoff_files,n_xcoff_symbols,n_library_symbols} // HACK: see InitialLink2 in ObjectToMem.icl; it is a way to pass on the absolute address of the // qd symbol. // #! (qd_address,state) // = acc_pd_state (\pd_state=:{qd_address} -> (qd_address,pd_state)) state; #! (marked_bool_a,state) = select_marked_bool_a state; #! (marked_offset_a,state) = select_marked_offset_a state; #! (module_offset_a,state) = select_module_offset_a state; #! n_xcoff_files_plus_libraries = size marked_offset_a; #! n_symbols = n_xcoff_symbols + n_new_xcoff_symbols + n_library_symbols; # marked_bool_a2 = createArray n_symbols False; marked_bool_a2 = {marked_bool_a2 & [i]=marked_bool_a.[i] \\ i<-[0..n_xcoff_symbols-1]}; marked_bool_a2 = {marked_bool_a2 & [i]=marked_bool_a.[i-n_new_xcoff_symbols] \\ i<-[n_xcoff_symbols+n_new_xcoff_symbols..n_symbols-1]}; # marked_offset_a2 = createArray (n_xcoff_files_plus_libraries+1) 0; marked_offset_a2 = {marked_offset_a2 & [i]=marked_offset_a.[i] \\ i<-[0..n_xcoff_files-1]}; marked_offset_a2 = {marked_offset_a2 & [n_xcoff_files] = n_xcoff_symbols}; marked_offset_a2 = {marked_offset_a2 & [i]=marked_offset_a.[i-1]+n_new_xcoff_symbols \\ i<-[n_xcoff_files+1..n_xcoff_files_plus_libraries]}; # module_offset_a2 = createArray n_symbols 0; module_offset_a2 = {module_offset_a2 & [i]=module_offset_a.[i] \\ i<-[0..n_xcoff_symbols-1]}; module_offset_a2 = {module_offset_a2 & [i]=module_offset_a.[i-n_new_xcoff_symbols] \\ i<-[n_xcoff_symbols+n_new_xcoff_symbols..n_symbols-1]}; #! state = update_state_with_xcoff xcoff state; = { state & n_xcoff_files = n_xcoff_files + 1, n_xcoff_symbols = n_xcoff_symbols + n_new_xcoff_symbols, // n_library_symbols, library_list, one_pass_link and namestable remain unaltered marked_bool_a = marked_bool_a2, marked_offset_a = marked_offset_a2, module_offset_a = module_offset_a2 }; add_library2 :: !Int !Int !LibraryList !State -> !State; add_library2 n_new_libraries n_new_library_symbols library_list state=:{n_libraries,n_xcoff_files,n_xcoff_symbols,n_library_symbols} #! (marked_bool_a,state) = select_marked_bool_a state; #! (marked_offset_a,state) = select_marked_offset_a state; #! (module_offset_a,state) = select_module_offset_a state; #! n_xcoff_files_plus_libraries = size marked_offset_a; #! n_symbols = n_xcoff_symbols + n_new_library_symbols + n_library_symbols; # marked_bool_a2 = createArray n_symbols False; marked_bool_a2 = {marked_bool_a2 & [i]=marked_bool_a.[i] \\ i<-[0..n_xcoff_symbols-1]}; marked_bool_a2 = {marked_bool_a2 & [i]=marked_bool_a.[i-n_new_library_symbols] \\ i<-[n_xcoff_symbols+n_new_library_symbols..n_symbols-1]}; # marked_offset_a2 = createArray (n_xcoff_files_plus_libraries+ n_new_libraries) 0; marked_offset_a2 = {marked_offset_a2 & [i]=marked_offset_a.[i] \\ i<-[0..n_xcoff_files-1]}; // copy old xcoff offsets # marked_offset_a2 = fill_library_offsets library_list n_xcoff_files n_xcoff_symbols marked_offset_a2; marked_offset_a2 = {marked_offset_a2 & [i]=marked_offset_a.[i-n_new_libraries]+n_new_library_symbols \\ i<-[n_xcoff_files+n_new_libraries..n_xcoff_files_plus_libraries+n_new_libraries - 1 ]}; # module_offset_a2 = createArray n_symbols 0; module_offset_a2 = {module_offset_a2 & [i]=module_offset_a.[i] \\ i<-[0..n_xcoff_symbols-1]}; module_offset_a2 = {module_offset_a2 & [i]=module_offset_a.[i-n_new_library_symbols] \\ i<-[n_xcoff_symbols+n_new_library_symbols..n_symbols-1]}; = { state & n_libraries = n_new_libraries + n_libraries, n_library_symbols = n_new_library_symbols + n_library_symbols, marked_bool_a = marked_bool_a2, marked_offset_a = marked_offset_a2, module_offset_a = module_offset_a2 }; split_data_symbol_lists_without_removing_unmarked_symbols // The Clean 1.3 compiler does check only when they are fully expanded. The Clean 2.0 compiler checks // before expansion. = abort "split_data_symbol_lists_without_removing_unmarked_symbols; look in source";