From bug-octave-request at bevo dot che dot wisc dot edu Wed Oct 15 03:32:35 1997 Subject: Fix for loading oct-files From: Michael Hanke To: bug-octave at bevo dot che dot wisc dot edu Date: Wed, 15 Oct 1997 10:31:52 +0200 Hallo, roughly one month ago I was reporting about a bug which is more related to the implementation of the loader library than to octave. Unfortunately, I dropped the description. You can find it at URL http://www.che.wisc.edu/octave/mailing-lists/bug-octave/1997/474. In short: If I write a .oct file containing two function definitions which share a common global object and make links under both names to the same .oct file, some versions of the dynamic loader (I found it in IRIX 6.2 and Linux) load two images with the same symbols. This means that the "shared" objects are no longer shared! So I introduced some new code into dynamic-ld.cc for some bookkeeping in order to avoid this situation. The new text is included below. Notes: 1. On some systems (e.g. OSF/1 4.0) this bookkeeping is done by the loader itself. 2. The code is only tested under Linux. I try to test it under IRIX, too. But I do not have time for more extensive tests. /* Copyright (C) 1996 John W. Eaton This file is part of Octave. Octave is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif #if defined (WITH_SHL) #include #include #endif #include extern "C" { #if defined (WITH_DL) #include #ifndef RTLD_LAZY #define RTLD_LAZY 1 #endif #elif defined (WITH_SHL) #include #endif } #include #include "dirfns.h" #include "dynamic-ld.h" #include "error.h" #include "toplev.h" #include "pathsearch.h" #include "ov.h" #include "utils.h" #include "variables.h" #if defined(WITH_DYNAMIC_LINKING) #include #include #if defined(WITH_DL) template class SLNode; template class SLList; static SLList oct_loaded; #elif defined(WITH_SHL) template class SLNode; template class SLList; static SLList oct_loaded; #endif #endif typedef builtin_function * (*Octave_builtin_fcn_struct_fcn)(void); #if defined (WITH_DYNAMIC_LINKING) // XXX FIXME XXX -- need to provide some way to ensure that functions // that we are going to use will use the same naming convention as // Octave's internal functions. It needs to be simpler than the // current DEFUN_DLD() macro, which assumes you know how to name the // function, the struct, and the helper function. static string mangle_octave_oct_file_name (const string& name) { string retval ("FS"); retval.append (name); retval.append ("__Fv"); return retval; } #if defined (WITH_DL) static void * dl_resolve_octave_reference (const string& name, const string& file) { void *retval = 0; // Dynamic linking with dlopen/dlsym doesn't require specification // of the libraries at runtime. Instead, they are specified when // the .oct file is created. void *handle = dlopen (file.c_str (), RTLD_LAZY); if (handle) { oct_loaded.prepend(handle); retval = dlsym (handle, name.c_str ()); if (! retval) // According to the Manpage this test is in error!! { const char *errmsg = dlerror (); if (errmsg) error("%s: `%s'", name.c_str (), errmsg); else error("unable to link function `%s'", name.c_str ()); // dlclose (handle); } } else error ("%s: %s `%s'", dlerror (), file.c_str (), name.c_str ()); return retval; } #elif defined (WITH_SHL) static void * shl_resolve_octave_reference (const string& name, const string& file) { void *retval = 0; // Dynamic linking with shl_load/shl_findsym doesn't require // specification of the libraries at runtime. Instead, they are // specified when the .oct file is created. shl_t handle = shl_load (file.c_str (), BIND_DEFERRED, 0L); const char *nm = name.c_str (); if (handle) { oct_loaded.prepend(handle); // Don't use TYPE_PROCEDURE here. The man page says that future // versions of HP-UX may not support it. int status = shl_findsym (&handle, nm, TYPE_UNDEFINED, &retval); if (status < 0) { const char *errmsg = strerror (errno); if (errmsg) error("%s: `%s'", nm, errmsg); else error("unable to link function `%s'", nm); retval = 0; } } else error ("%s: %s `%s'", strerror (errno), file.c_str (), nm); return retval; } #endif #endif #if defined (WITH_DYNAMIC_LINKING) static void * resolve_octave_reference (const string& name, const string& file) { #if defined (WITH_DL) return dl_resolve_octave_reference (name, file); #elif defined (WITH_SHL) return shl_resolve_octave_reference (name, file); #endif } #endif #if defined (WITH_DYNAMIC_LINKING) #if defined (WITH_DL) static void * dl_resolve_octave_reference (const string& name) { void *retval = 0; // Dynamic linking with dlopen/dlsym doesn't require specification // of the libraries at runtime. Instead, they are specified when // the .oct file is created. for (Pix i = oct_loaded.first(); i != 0; oct_loaded.next(i)) { retval = dlsym (oct_loaded(i), name.c_str ()); if (retval) break; } return retval; } #elif defined (WITH_SHL) static void * shl_resolve_octave_reference (const string& name) { void *retval = 0; for (Pix i = oct_loaded.first(); i != 0; oct_loaded.next(i)) { // Don't use TYPE_PROCEDURE here. The man page says that future // versions of HP-UX may not support it. int status = shl_findsym (&(oct_loaded(i)), name.c_str(), TYPE_UNDEFINED, &retval); if (status < 0) retval = 0; else break; } else error ("%s: %s `%s'", strerror (errno), file.c_str (), nm); return retval; } #endif #endif #if defined (WITH_DYNAMIC_LINKING) static void * resolve_octave_reference (const string& name) { #if defined (WITH_DL) return dl_resolve_octave_reference (name); #elif defined (WITH_SHL) return shl_resolve_octave_reference (name); #endif } #endif int load_octave_oct_file (const string& name) { int retval = 0; #if defined (WITH_DYNAMIC_LINKING) string mangled_name = mangle_octave_oct_file_name (name); Octave_builtin_fcn_struct_fcn f = (Octave_builtin_fcn_struct_fcn) resolve_octave_reference(mangled_name); if (!f) { string oct_file = oct_file_in_path (name); if (! oct_file.empty ()) { f = (Octave_builtin_fcn_struct_fcn) resolve_octave_reference (mangled_name, oct_file); } } if (f) { builtin_function *s = f (); if (s) { install_builtin_function (*s); retval = 1; } } #else (void) name; #endif return retval; } void init_dynamic_linker (void) { // Nothing to do anymore... } /* ;;; Local Variables: *** ;;; mode: C++ *** ;;; End: *** */