1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 #  include "config.h"
28 #endif
29 
30 #include "file-ops.h"
31 #include "oct-shlib.h"
32 
33 #include "defaults.h"
34 #include "dynamic-ld.h"
35 #include "error.h"
36 #include "interpreter-private.h"
37 #include "ovl.h"
38 #include "ov-dld-fcn.h"
39 #include "ov.h"
40 
41 
42 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_dld_function,
43                                      "dynamically-linked function",
44                                      "dynamically-linked function");
45 
octave_dld_function(octave_builtin::fcn ff,const octave::dynamic_library & shl,const std::string & nm,const std::string & ds)46 octave_dld_function::octave_dld_function
47   (octave_builtin::fcn ff, const octave::dynamic_library& shl,
48    const std::string& nm, const std::string& ds)
49   : octave_builtin (ff, nm, ds), sh_lib (shl)
50 {
51   mark_fcn_file_up_to_date (time_parsed ());
52 
53   std::string file_name = fcn_file_name ();
54 
55   static const std::string canonical_oct_file_dir
56     = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ());
57   static const std::string oct_file_dir
58     = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir ()
59                                       : canonical_oct_file_dir;
60 
61   system_fcn_file
62     = (! file_name.empty ()
63        && oct_file_dir == file_name.substr (0, oct_file_dir.length ()));
64 }
65 
octave_dld_function(octave_builtin::meth mm,const octave::dynamic_library & shl,const std::string & nm,const std::string & ds)66 octave_dld_function::octave_dld_function
67   (octave_builtin::meth mm, const octave::dynamic_library& shl,
68    const std::string& nm, const std::string& ds)
69   : octave_builtin (mm, nm, ds), sh_lib (shl)
70 {
71   mark_fcn_file_up_to_date (time_parsed ());
72 
73   std::string file_name = fcn_file_name ();
74 
75   static const std::string canonical_oct_file_dir
76     = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ());
77   static const std::string oct_file_dir
78     = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir ()
79                                       : canonical_oct_file_dir;
80 
81   system_fcn_file
82     = (! file_name.empty ()
83        && oct_file_dir == file_name.substr (0, oct_file_dir.length ()));
84 }
85 
~octave_dld_function(void)86 octave_dld_function::~octave_dld_function (void)
87 {
88   octave::dynamic_loader& dyn_loader
89     = octave::__get_dynamic_loader__ ("~octave_dld_function");
90 
91   dyn_loader.remove_oct (my_name, sh_lib);
92 }
93 
94 std::string
fcn_file_name(void) const95 octave_dld_function::fcn_file_name (void) const
96 {
97   return sh_lib.file_name ();
98 }
99 
100 octave::sys::time
time_parsed(void) const101 octave_dld_function::time_parsed (void) const
102 {
103   return sh_lib.time_loaded ();
104 }
105 
106 // Note: this wrapper around the octave_dld_function constructor is
107 //       necessary to work around a MSVC limitation handling in
108 //       virtual destructors that prevents unloading a dynamic module
109 //       before *all* objects (of class using a virtual dtor) have
110 //       been fully deleted; indeed, MSVC attaches auto-generated code
111 //       (scalar deleting destructor) to objects created in a dynamic
112 //       module, and this code will be executed in the dynamic module
113 //       context at object deletion; unloading the dynamic module
114 //       before objects have been deleted will make the "delete" code
115 //       of objects to point to an invalid code segment.
116 
117 octave_dld_function*
create(octave_builtin::fcn ff,const octave::dynamic_library & shl,const std::string & nm,const std::string & ds)118 octave_dld_function::create (octave_builtin::fcn ff,
119                              const octave::dynamic_library& shl,
120                              const std::string& nm, const std::string& ds)
121 {
122   return new octave_dld_function (ff, shl, nm, ds);
123 }
124 
125 octave_dld_function*
create(octave_builtin::meth mm,const octave::dynamic_library & shl,const std::string & nm,const std::string & ds)126 octave_dld_function::create (octave_builtin::meth mm,
127                              const octave::dynamic_library& shl,
128                              const std::string& nm, const std::string& ds)
129 {
130   return new octave_dld_function (mm, shl, nm, ds);
131 }
132