Skip to content

Commit

Permalink
change (internal) TclpLoadMemory() signature, backported from 9.0.
Browse files Browse the repository at this point in the history
Install headers before documentation. If documentation copying (which is slow) is aborted, it doesn't affect development work
  • Loading branch information
jan.nijtmans committed Jan 15, 2025
1 parent 94d4244 commit 1345a76
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 80 deletions.
28 changes: 14 additions & 14 deletions generic/tclIOUtil.c
Original file line number Diff line number Diff line change
Expand Up @@ -3262,10 +3262,11 @@ Tcl_LoadFile(
}

/*
* The filesystem doesn't support 'load', so we fall back on the following
* technique:
*
* First check if it is readable -- and exists!
* The filesystem doesn't support 'load'. Fall to the following:
*/

/*
* Make sure the file is accessible.
*/

if (Tcl_FSAccess(pathPtr, R_OK) != 0) {
Expand All @@ -3279,9 +3280,9 @@ Tcl_LoadFile(

#ifdef TCL_LOAD_FROM_MEMORY
/*
* The platform supports loading code from memory, so ask for a buffer of
* the appropriate size, read the file into it and load the code from the
* buffer:
* The platform supports loading a dynamic shared object from memory.
* Create a sufficiently large buffer, read the file into it, and then load
* the dynamic shared object from the buffer:
*/

{
Expand All @@ -3298,14 +3299,17 @@ Tcl_LoadFile(
size = statBuf.st_size;

/*
* Tcl_Read takes an int: check that file size isn't wide.
* Tcl_Read takes an int: Determine whether the file size <= INT_MAX
*/

if (size > INT_MAX) {
goto mustCopyToTempAnyway;
}
data = Tcl_FSOpenFileChannel(interp, pathPtr, "rb", 0666);
if (!data) {
if (interp) {
Tcl_ResetResult(interp);
}
goto mustCopyToTempAnyway;
}
buffer = TclpLoadMemoryGetBuffer(size);
Expand All @@ -3315,22 +3319,18 @@ Tcl_LoadFile(
}
ret = Tcl_Read(data, buffer, size);
Tcl_Close(interp, data);
ret = TclpLoadMemory(interp, buffer, size, ret, handlePtr,
ret = TclpLoadMemory(buffer, size, ret, TclGetString(pathPtr), handlePtr,
&unloadProcPtr, flags);
if (ret == TCL_OK && *handlePtr != NULL) {
goto resolveSymbols;
}
}

mustCopyToTempAnyway:
if (interp) {
Tcl_ResetResult(interp);
}
#endif /* TCL_LOAD_FROM_MEMORY */

/*
* Get a temporary filename to use, first to copy the file into, and then
* to load.
* Get a temporary filename, first to copy the file into, and then to load.
*/

copyToPtr = TclpTempFileNameForLibrary(interp, pathPtr);
Expand Down
4 changes: 2 additions & 2 deletions generic/tclInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -3196,8 +3196,8 @@ MODULE_SCOPE int TclpDlopen(Tcl_Interp *interp, Tcl_Obj *pathPtr,
MODULE_SCOPE int TclpUtime(Tcl_Obj *pathPtr, struct utimbuf *tval);
#ifdef TCL_LOAD_FROM_MEMORY
MODULE_SCOPE void * TclpLoadMemoryGetBuffer(size_t size);
MODULE_SCOPE int TclpLoadMemory(Tcl_Interp *interp, void *buffer,
size_t size, int codeSize, Tcl_LoadHandle *loadHandle,
MODULE_SCOPE int TclpLoadMemory(void *buffer, size_t size,
int codeSize, const char *path, Tcl_LoadHandle *loadHandle,
Tcl_FSUnloadFileProc **unloadProcPtr, int flags);
#endif
MODULE_SCOPE void TclInitThreadStorage(void);
Expand Down
8 changes: 2 additions & 6 deletions generic/tclLoadNone.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,27 +93,23 @@ TclGuessPackageName(

MODULE_SCOPE void *
TclpLoadMemoryGetBuffer(
int size) /* Dummy: unused by this implementation */
size_t size) /* Dummy: unused by this implementation */
{
return NULL;
}

MODULE_SCOPE int
TclpLoadMemory(
Tcl_Interp *interp, /* Used for error reporting. */
void *buffer, /* Dummy: unused by this implementation */
size_t size, /* Dummy: unused by this implementation */
int codeSize, /* Dummy: unused by this implementation */
const char *path, /* Dummy: unused by this implementation */
Tcl_LoadHandle *loadHandle, /* Dummy: unused by this implementation */
Tcl_FSUnloadFileProc **unloadProcPtr,
/* Dummy: unused by this implementation */
int flags)
/* Dummy: unused by this implementation */
{
if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("dynamic loading from memory "
"is not available on this system", -1));
}
return TCL_ERROR;
}

Expand Down
2 changes: 1 addition & 1 deletion unix/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ INSTALL_DOC_TARGETS = install-doc
INSTALL_PACKAGE_TARGETS = install-packages
INSTALL_DEV_TARGETS = install-headers
INSTALL_EXTRA_TARGETS = @EXTRA_INSTALL@
INSTALL_TARGETS = $(INSTALL_BASE_TARGETS) $(INSTALL_DOC_TARGETS) $(INSTALL_DEV_TARGETS) \
INSTALL_TARGETS = $(INSTALL_BASE_TARGETS) $(INSTALL_DEV_TARGETS) $(INSTALL_DOC_TARGETS) \
$(INSTALL_PACKAGE_TARGETS) $(INSTALL_EXTRA_TARGETS)

install: $(INSTALL_TARGETS)
Expand Down
57 changes: 44 additions & 13 deletions unix/tclLoadDl.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,19 @@ TclpDlopen(
* relative path.
*/

native = Tcl_FSGetNativePath(pathPtr);
native = (const char *)Tcl_FSGetNativePath(pathPtr);
/*
* Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
*/
if (flags & TCL_LOAD_GLOBAL) {
dlopenflags |= RTLD_GLOBAL;
dlopenflags |= RTLD_GLOBAL;
} else {
dlopenflags |= RTLD_LOCAL;
dlopenflags |= RTLD_LOCAL;
}
if (flags & TCL_LOAD_LAZY) {
dlopenflags |= RTLD_LAZY;
dlopenflags |= RTLD_LAZY;
} else {
dlopenflags |= RTLD_NOW;
dlopenflags |= RTLD_NOW;
}
handle = dlopen(native, dlopenflags);
if (handle == NULL) {
Expand All @@ -106,7 +106,7 @@ TclpDlopen(
*/

Tcl_DString ds;
const char *fileName = Tcl_GetString(pathPtr);
const char *fileName = TclGetString(pathPtr);

native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
/*
Expand All @@ -127,11 +127,11 @@ TclpDlopen(
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't load file \"%s\": %s",
Tcl_GetString(pathPtr), errorStr));
TclGetString(pathPtr), errorStr));
}
return TCL_ERROR;
}
newHandle = ckalloc(sizeof(*newHandle));
newHandle = (Tcl_LoadHandle)ckalloc(sizeof(*newHandle));
newHandle->clientData = handle;
newHandle->findSymbolProcPtr = &FindSymbol;
newHandle->unloadFileProcPtr = &UnloadFile;
Expand Down Expand Up @@ -168,7 +168,7 @@ FindSymbol(
Tcl_DString newName, ds; /* Buffers for converting the name to
* system encoding and prepending an
* underscore*/
void *handle = (void *) loadHandle->clientData;
void *handle = loadHandle->clientData;
/* Native handle to the loaded library */
void *proc; /* Address corresponding to the resolved
* symbol */
Expand Down Expand Up @@ -210,15 +210,14 @@ FindSymbol(
*
* UnloadFile --
*
* Unloads a dynamically loaded binary code file from memory. Code
* pointers in the formerly loaded file are no longer valid after calling
* this function.
* Unloads a dynamic shared object, after which all pointers to functions
* in the formerly-loaded object are no longer valid.
*
* Results:
* None.
*
* Side effects:
* Code removed from memory.
* Memory for the loaded object is deallocated.
*
*----------------------------------------------------------------------
*/
Expand Down Expand Up @@ -265,6 +264,38 @@ TclGuessPackageName(
return 0;
}

/*
* These functions are fallbacks if we somehow determine that the platform can
* do loading from memory but the user wishes to disable it. They just report
* (gracefully) that they fail.
*/

#ifdef TCL_LOAD_FROM_MEMORY

MODULE_SCOPE void *
TclpLoadMemoryGetBuffer(
size_t size) /* Dummy: unused by this implementation */
{
return NULL;
}

MODULE_SCOPE int
TclpLoadMemory(
void *buffer, /* Dummy: unused by this implementation */
size_t size, /* Dummy: unused by this implementation */
int codeSize, /* Dummy: unused by this implementation */
const char *path, /* Dummy: unused by this implementation */
Tcl_LoadHandle *loadHandle, /* Dummy: unused by this implementation */
Tcl_FSUnloadFileProc **unloadProcPtr,
/* Dummy: unused by this implementation */
int flags)
/* Dummy: unused by this implementation */
{
return TCL_ERROR;
}

#endif /* TCL_LOAD_FROM_MEMORY */

/*
* Local Variables:
* mode: c
Expand Down
16 changes: 2 additions & 14 deletions unix/tclLoadDyld.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,13 +562,13 @@ TclpLoadMemoryGetBuffer(
#ifdef TCL_LOAD_FROM_MEMORY
MODULE_SCOPE int
TclpLoadMemory(
Tcl_Interp *interp, /* Used for error reporting. */
void *buffer, /* Buffer containing the desired code
* (allocated with TclpLoadMemoryGetBuffer). */
size_t size, /* Allocation size of buffer. */
int codeSize, /* Size of code data read into buffer or -1 if
* an error occurred and the buffer should
* just be freed. */
const char *path,
Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
* file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
Expand All @@ -583,7 +583,6 @@ TclpLoadMemory(
NSObjectFileImage dyldObjFileImage = NULL;
Tcl_DyldModuleHandle *modulePtr;
NSModule module;
const char *objFileImageErrMsg = NULL;
int nsflags = NSLINKMODULE_OPTION_RETURN_ON_ERROR;

/*
Expand Down Expand Up @@ -652,26 +651,16 @@ TclpLoadMemory(
if (err == NSObjectFileImageSuccess) {
err = NSCreateObjectFileImageFromMemory(buffer, codeSize,
&dyldObjFileImage);
if (err != NSObjectFileImageSuccess) {
objFileImageErrMsg = DyldOFIErrorMsg(err);
}
} else {
objFileImageErrMsg = DyldOFIErrorMsg(err);
}
}

/*
* If it went wrong (or we were asked to just deallocate), get rid of the
* memory block and create an error message.
* memory block.
*/

if (dyldObjFileImage == NULL) {
vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
if (objFileImageErrMsg != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"NSCreateObjectFileImageFromMemory() error: %s",
objFileImageErrMsg));
}
return TCL_ERROR;
}

Expand All @@ -693,7 +682,6 @@ TclpLoadMemory(
const char *errorName, *errMsg;

NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
return TCL_ERROR;
}

Expand Down
Loading

0 comments on commit 1345a76

Please sign in to comment.