mirror of
https://github.com/deadw00d/AROS.git
synced 2025-12-10 00:14:36 +00:00
Add code for implementing dynamic module support in executables (primarily game ports). Implements the interface between executable & module, management code, and API calls to resolve symbols.
This commit is contained in:
40
compiler/dynmodule/dynmodule_export.c
Normal file
40
compiler/dynmodule/dynmodule_export.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file implements the runtime module function, Export.
|
||||
*/
|
||||
|
||||
//#define DEBUG 1
|
||||
#include <aros/debug.h>
|
||||
|
||||
#include "dynmodule_modules.h"
|
||||
|
||||
#include <dynmod/dynmodstack.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// module provided symbols...
|
||||
extern dynmod_export_t DYNMODULE_Exports[];
|
||||
|
||||
BOOL dynmodule__InternalMatchSymbol(const char *sym1, const char *sym2)
|
||||
{
|
||||
return (strcmp(sym1, sym2) == 0);
|
||||
}
|
||||
|
||||
int dynmoduleExport(dynmod_sym_t *sym)
|
||||
{
|
||||
D(bug("[DynLink] %s(0x%p)\n", __func__, sym));
|
||||
|
||||
if (sym->SymPtr) {
|
||||
dynmod_export_t *symtable = DYNMODULE_Exports;
|
||||
while (symtable->ExportAddress) {
|
||||
if(dynmodule__InternalMatchSymbol(symtable->ExportName, sym->SymName)) {
|
||||
*sym->SymPtr = symtable->ExportAddress;
|
||||
return 1;
|
||||
}
|
||||
symtable++;
|
||||
}
|
||||
|
||||
*sym->SymPtr = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
82
compiler/dynmodule/dynmodule_freemodule.c
Normal file
82
compiler/dynmodule/dynmodule_freemodule.c
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file implements the runtime module function, FreeModule.
|
||||
*/
|
||||
|
||||
//#define DEBUG 1
|
||||
#include <aros/debug.h>
|
||||
|
||||
#include "dynmodule_modules.h"
|
||||
|
||||
#include <proto/dos.h>
|
||||
#include <proto/exec.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void dynmodule__InternalFreeModule(int slotid)
|
||||
{
|
||||
__dynmodulemsg_t msg,*reply;
|
||||
struct MsgPort *replyport, *dmmport;
|
||||
__dynmoduleinstance_t *dynmod = (__dynmoduleinstance_t *) dynmoduleslots[slotid].mhandle;
|
||||
|
||||
D(bug("[DynLink] %s(%u)\n", __func__, slotid));
|
||||
|
||||
if (!dynmod)
|
||||
return;
|
||||
|
||||
if (!(replyport = CreateMsgPort()))
|
||||
DYNMODULE_Exit(0);
|
||||
|
||||
memset(&msg.Message, 0, sizeof(struct Message));
|
||||
msg.Message.mn_ReplyPort = replyport;
|
||||
msg.IFMsgType = DMIFMSG_Close;
|
||||
|
||||
if ((dmmport = FindPort((CONST_STRPTR)dynmoduleslots[slotid].pnam)) == dynmod->dmi_IFMsgPort) {
|
||||
D(bug("[DynLink] %s: Sending IF Close Msg to Port @ 0x%p\n", __func__, dmmport));
|
||||
PutMsg(dmmport, (struct Message *)&msg);
|
||||
while ((reply = (__dynmodulemsg_t *)GetMsg(replyport)) == NULL) {
|
||||
Delay(2);
|
||||
if (FindPort((CONST_STRPTR)dynmoduleslots[slotid].pnam) != dynmod->dmi_IFMsgPort)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
D(bug("[DynLink] %s: deleting module\n", __func__, slotid));
|
||||
dynmodule__InternalDestroyDynModEntry(dynmod, replyport);
|
||||
|
||||
memset((APTR)&dynmoduleslots[slotid], 0, sizeof(__dynmoduleentry_t));
|
||||
dynmodopncnt--;
|
||||
return;
|
||||
}
|
||||
|
||||
void dynmodule__InternalCleanup()
|
||||
{
|
||||
int slotid;
|
||||
|
||||
D(bug("[DynLink] %s()\n", __func__));
|
||||
|
||||
for (slotid = 0; slotid< DYNMODULE_MAX; slotid++)
|
||||
if (dynmoduleslots[slotid].mhandle)
|
||||
dynmodule__InternalFreeModule(slotid);
|
||||
|
||||
D(bug("[DynLink] %s: done\n", __func__));
|
||||
}
|
||||
|
||||
void dynmoduleFreeModule(void *mhandle)
|
||||
{
|
||||
int slotid;
|
||||
|
||||
D(bug("[DynLink] %s(0x%p)\n", __func__, mhandle));
|
||||
|
||||
for (slotid = 0; slotid < DYNMODULE_MAX; slotid++)
|
||||
if (dynmoduleslots[slotid].mhandle == mhandle)
|
||||
break;
|
||||
|
||||
if (slotid < DYNMODULE_MAX) {
|
||||
dynmoduleslots[slotid].opencnt--;
|
||||
|
||||
if (dynmoduleslots[slotid].opencnt <= 0)
|
||||
dynmodule__InternalFreeModule(slotid);
|
||||
}
|
||||
}
|
||||
47
compiler/dynmodule/dynmodule_getprocaddr.c
Normal file
47
compiler/dynmodule/dynmodule_getprocaddr.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file implements the runtime module function, GetProcAddress.
|
||||
*/
|
||||
|
||||
//#define DEBUG 1
|
||||
#include <aros/debug.h>
|
||||
|
||||
#include "dynmodule_modules.h"
|
||||
|
||||
#include <dos/dos.h>
|
||||
#include <dos/dostags.h>
|
||||
|
||||
#include <proto/exec.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void *dynmoduleGetProcAddress(void *mhandle, const char *name)
|
||||
{
|
||||
void *sym = NULL;
|
||||
__dynmoduleinstance_t *dynmod;
|
||||
|
||||
D(bug("[DynLink] %s(0x%p, '%s')\n", __func__, mhandle, name));
|
||||
|
||||
if((dynmod = (__dynmoduleinstance_t *) mhandle) != NULL) {
|
||||
struct MsgPort *replyport;
|
||||
if((replyport = CreateMsgPort())) {
|
||||
__dynmodulemsg_t msg, *reply;
|
||||
|
||||
memset(&msg.Message, 0, sizeof(struct Message));
|
||||
msg.Message.mn_ReplyPort = replyport;
|
||||
msg.IFMsgType = DMIFMSG_Resolve;
|
||||
msg.IFResolveRequest.StackFType = dynmod->dmi_StackFType;
|
||||
msg.IFResolveRequest.SymName = name;
|
||||
msg.IFResolveRequest.SymPtr = &sym;
|
||||
|
||||
PutMsg(dynmod->dmi_IFMsgPort, (struct Message *)&msg);
|
||||
|
||||
WaitPort(replyport);
|
||||
reply = (__dynmodulemsg_t *)GetMsg(replyport);
|
||||
DeleteMsgPort(replyport);
|
||||
|
||||
if (!reply)
|
||||
sym = NULL;
|
||||
}
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
176
compiler/dynmodule/dynmodule_glue.c
Normal file
176
compiler/dynmodule/dynmodule_glue.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* This file contains glue linked into the dynamic-module
|
||||
*/
|
||||
|
||||
//#define DEBUG 1
|
||||
#include <aros/debug.h>
|
||||
|
||||
#include <exec/exec.h>
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dynmodule_intern.h"
|
||||
|
||||
/*
|
||||
* symbols provided by the linked module ...
|
||||
*/
|
||||
__attribute__((weak)) const char *DYNMODULE_Name = NULL;
|
||||
extern int DYNMODULE_Setup(APTR);
|
||||
extern void DYNMODULE_Cleanup(void);
|
||||
|
||||
/*
|
||||
* glue function implementations ...
|
||||
*/
|
||||
APTR __dynglue_FindResource(int id, const char *pType)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
APTR __dynglue_LoadResource(APTR handle)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void __dynglue_FreeResource(APTR handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* internal glue functions ...
|
||||
*/
|
||||
struct MsgPort *__dynglue_InitIFPort(char *name)
|
||||
{
|
||||
struct MsgPort *ifMPort = NULL;
|
||||
|
||||
ifMPort = CreatePort(name, 0);
|
||||
|
||||
return ifMPort;
|
||||
}
|
||||
|
||||
__dynmodulemsg_t *__dynglue_GetIFMSg(struct MsgPort *dmmport, BOOL inuse)
|
||||
{
|
||||
__dynmodulemsg_t *ifMsg = NULL;
|
||||
if (inuse) {
|
||||
WaitPort(dmmport);
|
||||
ifMsg = (__dynmodulemsg_t *)GetMsg(dmmport);
|
||||
}
|
||||
return ifMsg;
|
||||
}
|
||||
|
||||
__dynmodulemsg_t *__dynglue_DisposeIFPort(struct MsgPort *dmmport)
|
||||
{
|
||||
__dynmodulemsg_t *ifMsg;
|
||||
while((ifMsg = (__dynmodulemsg_t *)GetMsg(dmmport))) {
|
||||
ifMsg->IFOpenRequest.Error = DMIFERR_Closing;
|
||||
ReplyMsg((struct Message *)ifMsg);
|
||||
}
|
||||
DeletePort(dmmport);
|
||||
}
|
||||
|
||||
/*
|
||||
* Module entry point ...
|
||||
*/
|
||||
|
||||
#define ARG_TEMPLATE "PORT/A"
|
||||
enum
|
||||
{
|
||||
ARG_PORT = 0,
|
||||
NOOFARGS
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
IPTR args[NOOFARGS + 1] = { (IPTR)NULL, (IPTR)0 };
|
||||
struct RDArgs *rda;
|
||||
|
||||
struct MsgPort *dmmport;
|
||||
__dynmodulemsg_t *ifMsg;
|
||||
char *pname;
|
||||
|
||||
int opencnt = 0;
|
||||
BOOL inuse = TRUE;
|
||||
|
||||
D(
|
||||
const char *dbgname;
|
||||
if ((&DYNMODULE_Name == NULL) || (DYNMODULE_Name == NULL))
|
||||
dbgname = argv[0];
|
||||
else
|
||||
dbgname = DYNMODULE_Name;
|
||||
bug("[%s] %s('%s')\n", dbgname, __func__, argv[0]);
|
||||
)
|
||||
|
||||
if ((rda = ReadArgs(ARG_TEMPLATE, args, NULL)) != NULL) {
|
||||
char *argpname = (char *)args[ARG_PORT];
|
||||
if (*argpname == '"') {
|
||||
char prttmp[255];
|
||||
int prtlen = strlen(argpname) - 2;
|
||||
strncpy(prttmp, &argpname[1], prtlen);
|
||||
prttmp[prtlen] = 0;
|
||||
pname = StrDup((CONST_STRPTR)prttmp);
|
||||
}
|
||||
else
|
||||
pname = StrDup((CONST_STRPTR)args[ARG_PORT]);
|
||||
FreeArgs(rda);
|
||||
}
|
||||
if (!pname) {
|
||||
if ((&DYNMODULE_Name == NULL) || (DYNMODULE_Name == NULL))
|
||||
pname = StrDup((CONST_STRPTR)argv[0]);
|
||||
else
|
||||
pname = StrDup(DYNMODULE_Name);
|
||||
}
|
||||
|
||||
dmmport = __dynglue_InitIFPort(pname);
|
||||
FreeVec(pname);
|
||||
if (!dmmport)
|
||||
DYNMODULE_Exit(0);
|
||||
|
||||
D(bug("[%s] %s: port @ 0x%p\n", dbgname, __func__, dmmport));
|
||||
|
||||
if(!DYNMODULE_Setup(dmmport)) {
|
||||
__dynglue_DisposeIFPort(dmmport);
|
||||
DYNMODULE_Exit(0);
|
||||
}
|
||||
|
||||
D(bug("[%s] %s: initialised\n", dbgname, __func__));
|
||||
|
||||
while((ifMsg = __dynglue_GetIFMSg(dmmport, inuse))) {
|
||||
if (ifMsg) {
|
||||
switch(ifMsg->IFMsgType) {
|
||||
case DMIFMSG_Open:
|
||||
D(bug("[%s] %s: DMIFMSG_Open\n", dbgname, __func__));
|
||||
if (++opencnt > 0)
|
||||
inuse = TRUE;
|
||||
ifMsg->IFOpenRequest.Error = DMIFERR_Ok;
|
||||
break;
|
||||
|
||||
case DMIFMSG_Close:
|
||||
D(bug("[%s] %s: DMIFMSG_Close\n", dbgname, __func__));
|
||||
if (--opencnt <= 0)
|
||||
inuse = FALSE;
|
||||
break;
|
||||
|
||||
case DMIFMSG_Dispose:
|
||||
D(bug("[%s] %s: DMIFMSG_Dispose\n", dbgname, __func__));
|
||||
inuse = FALSE;
|
||||
break;
|
||||
|
||||
case DMIFMSG_Resolve:
|
||||
D(bug("[%s] %s: DMIFMSG_Resolve\n", dbgname, __func__));
|
||||
dynmoduleExport(&ifMsg->IFResolveRequest);
|
||||
break;
|
||||
|
||||
default:
|
||||
D(bug("[%s] %s: Unknown Msg type received!\n", dbgname, __func__));
|
||||
break;
|
||||
}
|
||||
ReplyMsg((struct Message *)ifMsg);
|
||||
}
|
||||
}
|
||||
|
||||
__dynglue_DisposeIFPort(dmmport);
|
||||
DYNMODULE_Cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
compiler/dynmodule/dynmodule_import.c
Normal file
41
compiler/dynmodule/dynmodule_import.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file implements the runtime module function, Import.
|
||||
*/
|
||||
|
||||
//#define DEBUG 1
|
||||
#include <aros/debug.h>
|
||||
|
||||
#include "dynmodule_modules.h"
|
||||
|
||||
#include <dynmod/dynmodstack.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// module needed symbols...
|
||||
extern dynmod_import_t DYNMODULE_Imports[];
|
||||
|
||||
int dynmoduleImport()
|
||||
{
|
||||
int cnt = 0;
|
||||
dynmod_import_t *symtable = DYNMODULE_Imports;
|
||||
|
||||
D(bug("[DynLink] %s()\n", __func__));
|
||||
|
||||
while (symtable->ImportPtr) {
|
||||
void *mhandle;
|
||||
void *ptr;
|
||||
|
||||
if (((mhandle = dynmodule__InternalLoadModule(symtable->ImportModule.Name, symtable->ImportModule.Port, 0)) == NULL) ||
|
||||
((ptr = dynmoduleGetProcAddress(mhandle, symtable->ImportName)) == NULL))
|
||||
return 0;
|
||||
|
||||
*symtable->ImportPtr = ptr;
|
||||
symtable++;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
D(bug("[DynLink] %s: imported %u symbols\n", __func__, cnt));
|
||||
|
||||
return cnt;
|
||||
}
|
||||
68
compiler/dynmodule/dynmodule_intern.h
Normal file
68
compiler/dynmodule/dynmodule_intern.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef __DYNMODULE_INTERN_H
|
||||
#define __DYNMODULE_INTERN_H
|
||||
|
||||
/*
|
||||
* Internal definitions used to implement the dynamic module support
|
||||
*/
|
||||
|
||||
#include <exec/exec.h>
|
||||
#include <dynmod/dynmodule.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMIFERR_Ok = 0,
|
||||
DMIFERR_Closing,
|
||||
DMIFERR_StackNotSupported,
|
||||
DMIFERR_OutOfMemory
|
||||
} __dynmoduleiferror_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMIFMSG_Open = 0,
|
||||
DMIFMSG_Close,
|
||||
DMIFMSG_Dispose,
|
||||
DMIFMSG_Resolve,
|
||||
DMIFMSG_TYPEMAX
|
||||
} __dynmodulemsgtype_t;
|
||||
|
||||
typedef struct {
|
||||
dynmod_stackf_t StackType;
|
||||
__dynmoduleiferror_t Error;
|
||||
} dynmodi_ifopenmsg_t;
|
||||
|
||||
typedef struct {
|
||||
} dynmodi_ifclosemsg_t;
|
||||
|
||||
/*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
struct Message Message;
|
||||
__dynmodulemsgtype_t IFMsgType;
|
||||
union
|
||||
{
|
||||
dynmodi_ifopenmsg_t IFOpenRequest;
|
||||
dynmodi_ifclosemsg_t IFCloseRequest;
|
||||
dynmod_sym_t IFResolveRequest;
|
||||
};
|
||||
// ... Might grow
|
||||
} __dynmodulemsg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct MsgPort *dmi_IFMsgPort;
|
||||
dynmod_stackf_t dmi_StackFType;
|
||||
dynmoduleLoadResourceFn_t dmi_LoadResFunc;
|
||||
dynmoduleFreeResourceFn_t dmi_FreeResFunc;
|
||||
dynmoduleFindResourceFn_t dmi_FindResFunc;
|
||||
} __dynmoduleinstance_t;
|
||||
|
||||
/************************************************************
|
||||
* Misc
|
||||
************************************************************/
|
||||
|
||||
extern void *dynmodule__InternalLoadModule(const char *, const char *, BOOL);
|
||||
extern void dynmodule__InternalFreeModule(int);
|
||||
extern void dynmodule__InternalCleanup();
|
||||
|
||||
#endif
|
||||
144
compiler/dynmodule/dynmodule_loadmodule.c
Normal file
144
compiler/dynmodule/dynmodule_loadmodule.c
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file implements the runtime module function, LoadModule.
|
||||
*/
|
||||
|
||||
//#define DEBUG 1
|
||||
#include <aros/debug.h>
|
||||
|
||||
#include "dynmodule_modules.h"
|
||||
#include <dos/dos.h>
|
||||
#include <dos/dostags.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
|
||||
extern const char *DYNMODULE_EntryPoint_Sym;
|
||||
extern const char *DYNMODULE_FindResource_Sym;
|
||||
extern const char *DYNMODULE_LoadResource_Sym;
|
||||
extern const char *DYNMODULE_FreeResource_Sym;
|
||||
|
||||
void *dynmoduleLoadModule(const char *modname, const char *port)
|
||||
{
|
||||
int (*EntryPFn)(void *, long, void *);
|
||||
void *mhandle;
|
||||
|
||||
D(bug("[DynLink] %s('%s','%s')\n", __func__, modname, port));
|
||||
|
||||
if ((mhandle = dynmodule__InternalLoadModule(modname, port, TRUE)) != NULL) {
|
||||
EntryPFn = dynmoduleGetProcAddress(mhandle, DYNMODULE_EntryPoint_Sym);
|
||||
if (EntryPFn) {
|
||||
if (!EntryPFn(mhandle, 0, NULL)) {
|
||||
dynmoduleFreeModule(mhandle);
|
||||
mhandle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mhandle;
|
||||
}
|
||||
|
||||
BOOL dynmodule__InternalHandleOpenMsg(__dynmoduleinstance_t *dynmod, int slotid, __dynmodulemsg_t *msg)
|
||||
{
|
||||
D(bug("[DynLink] %s()\n", __func__));
|
||||
if (msg->IFOpenRequest.Error != DMIFERR_Ok) {
|
||||
D(bug("[DynLink] %s: Open error %08x\n", __func__, msg->IFOpenRequest.Error));
|
||||
dynmodule__InternalDestroyDynModEntry(dynmod, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((dynmod->dmi_FindResFunc = dynmoduleGetProcAddress(dynmod, DYNMODULE_FindResource_Sym)) != NULL)
|
||||
if ((dynmod->dmi_LoadResFunc = dynmoduleGetProcAddress(dynmod, DYNMODULE_LoadResource_Sym)) != NULL)
|
||||
if ((dynmod->dmi_FreeResFunc = dynmoduleGetProcAddress(dynmod, DYNMODULE_FreeResource_Sym)) != NULL)
|
||||
return TRUE;
|
||||
|
||||
dynmoduleslots[slotid].mhandle = dynmod;
|
||||
dynmodule__InternalFreeModule(slotid);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL dynmodule__InternalValidModuleFile(const char *modname)
|
||||
{
|
||||
BPTR modf;
|
||||
if ((!modname) || !(modf = Open(modname, MODE_OLDFILE)))
|
||||
return FALSE;
|
||||
Close(modf);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void *dynmodule__InternalLoadModule(const char *modname, const char *port, BOOL registeropen)
|
||||
{
|
||||
__dynmoduleinstance_t *dynmod;
|
||||
struct MsgPort *dmodport;
|
||||
struct MsgPort *replyport;
|
||||
__dynmodulemsg_t msg,*reply;
|
||||
int slotid;
|
||||
|
||||
D(bug("[DynLink] %s('%s','%s')\n", __func__, modname, port));
|
||||
|
||||
if (!DYNMODULE_Init(&dynmoduleslots,
|
||||
sizeof(__dynmoduleentry_t) * DYNMODULE_MAX,
|
||||
(stdexitfunc_t)dynmodule__InternalCleanup))
|
||||
return NULL;
|
||||
|
||||
if (!dynmodule__InternalValidModuleFile(modname))
|
||||
return NULL;
|
||||
|
||||
if (!port)
|
||||
port = modname;
|
||||
|
||||
if ((dynmod = dynmodule__InternalOpenPortEntry(port, registeropen)) != NULL)
|
||||
return dynmod;
|
||||
|
||||
D(bug("[DynLink] %s: first open ..\n", __func__));
|
||||
if (!dynmodule__InternalFindFreeSlot(&slotid))
|
||||
return NULL;
|
||||
D(bug("[DynLink] %s: using slot %u\n", __func__, slotid));
|
||||
|
||||
if ((dynmod = dynmodule__InternalAllocDynModEntry(&replyport)) == NULL)
|
||||
return NULL;
|
||||
|
||||
D(bug("[DynLink] %s: dynamicmodule instance @ 0x%p\n", __func__, dynmod));
|
||||
D(bug("[DynLink] %s: ifport @ 0x%p\n", __func__, replyport));
|
||||
|
||||
if (!(dmodport = FindPort(port)))
|
||||
dmodport = dynmodule__InternalBootstrapDynMod(modname, port, 10);
|
||||
|
||||
if (!dmodport) {
|
||||
dynmodule__InternalDestroyDynModEntry(dynmod, replyport);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D(bug("[DynLink] %s: found port for '%s' @ 0x%p\n", __func__, port, dmodport));
|
||||
|
||||
memset(&msg.Message, 0, sizeof(struct Message));
|
||||
msg.Message.mn_ReplyPort = replyport;
|
||||
msg.IFMsgType = DMIFMSG_Open;
|
||||
msg.IFOpenRequest.Error = DMIFERR_Ok;
|
||||
msg.IFOpenRequest.StackType = DYNMOD_STACKF_DEFAULT;
|
||||
|
||||
dynmod->dmi_StackFType = DYNMOD_STACKF_DEFAULT;
|
||||
dynmod->dmi_IFMsgPort = dmodport;
|
||||
PutMsg(dynmod->dmi_IFMsgPort, (struct Message *)&msg);
|
||||
|
||||
WaitPort(replyport);
|
||||
|
||||
if (((reply = (__dynmodulemsg_t *)GetMsg(replyport)) != NULL) &&
|
||||
(reply->IFMsgType == DMIFMSG_Open)) {
|
||||
D(bug("[DynLink] %s: Open reply @ 0x%p\n", __func__, reply));
|
||||
if (!dynmodule__InternalHandleOpenMsg(dynmod, slotid, reply)) {
|
||||
dynmod = NULL;
|
||||
}
|
||||
} else {
|
||||
D(bug("[DynLink] %s: no reply from IF port\n", __func__));
|
||||
dynmodule__InternalDestroyDynModEntry(dynmod, NULL);
|
||||
dynmod = NULL;
|
||||
}
|
||||
DeleteMsgPort(replyport);
|
||||
if (dynmod)
|
||||
dynmodule__InternalInitDynModEntry(slotid, dynmod, port);
|
||||
|
||||
D(bug("[DynLink] %s: returning 0x%p\n", __func__, dynmod));
|
||||
|
||||
return dynmod;
|
||||
}
|
||||
146
compiler/dynmodule/dynmodule_modules.c
Normal file
146
compiler/dynmodule/dynmodule_modules.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Suppport functions and structures for the internal module entries
|
||||
*/
|
||||
|
||||
//#define DEBUG 1
|
||||
#include <aros/debug.h>
|
||||
|
||||
#include "dynmodule_modules.h"
|
||||
|
||||
#include <dos/dos.h>
|
||||
#include <dos/dostags.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
|
||||
struct dynmodulesupport {
|
||||
int dms_opencnt;
|
||||
int dms_flags;
|
||||
__dynmoduleentry_t *dms_modules;
|
||||
};
|
||||
|
||||
int dynmodopncnt = 0;
|
||||
__dynmoduleentry_t dynmoduleslots[DYNMODULE_MAX];
|
||||
|
||||
static const char *dynmodule_output_str = "CON:0/0/800/600/%s/AUTO/CLOSE/WAIT";
|
||||
static const char *dynmodule_cmd_template = "\"%s\" \"%s\"";
|
||||
|
||||
void dynmodule__InternalInitDynModEntry(int slotid, __dynmoduleinstance_t *dynmod, const char *port)
|
||||
{
|
||||
dynmodopncnt++;
|
||||
dynmoduleslots[slotid].mhandle = dynmod;
|
||||
dynmoduleslots[slotid].opencnt = 1;
|
||||
strcpy((char *)dynmoduleslots[slotid].pnam, port);
|
||||
}
|
||||
|
||||
int dynmodule__InternalFindFreeSlot(int *slotid)
|
||||
{
|
||||
int slotcur;
|
||||
for (slotcur = 0; slotcur < DYNMODULE_MAX; slotcur++)
|
||||
if(!dynmoduleslots[slotcur].mhandle)
|
||||
break;
|
||||
if (slotcur == DYNMODULE_MAX)
|
||||
return 0;
|
||||
*slotid = slotcur;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__dynmoduleinstance_t *dynmodule__InternalAllocDynModEntry(struct MsgPort **dmifport)
|
||||
{
|
||||
__dynmoduleinstance_t *dynmod;
|
||||
|
||||
if ((!dmifport) || ((dynmod = malloc(sizeof(__dynmoduleinstance_t))) == NULL))
|
||||
return NULL;
|
||||
|
||||
D(bug("[DynLink] %s: entry @ 0x%p\n", __func__, dynmod));
|
||||
|
||||
if (!(*dmifport = CreateMsgPort())) {
|
||||
free(dynmod);
|
||||
return NULL;
|
||||
}
|
||||
return dynmod;
|
||||
}
|
||||
|
||||
__dynmoduleinstance_t *dynmodule__InternalOpenPortEntry(const char *port, BOOL registeropen)
|
||||
{
|
||||
int slotcur;
|
||||
for (slotcur = 0; slotcur < DYNMODULE_MAX; slotcur++) {
|
||||
if(dynmoduleslots[slotcur].mhandle) {
|
||||
if(strcmp((const char *)dynmoduleslots[slotcur].pnam, port) == 0) {
|
||||
if(registeropen)
|
||||
dynmoduleslots[slotcur].opencnt++;
|
||||
return dynmoduleslots[slotcur].mhandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct MsgPort *dynmodule__InternalBootstrapDynMod(const char *modname, const char *port, int timeout)
|
||||
{
|
||||
char *outputfmt;
|
||||
char *commandline;
|
||||
BPTR input = BNULL, output = BNULL;
|
||||
|
||||
if ((outputfmt = AllocVec(strlen(port) + strlen(dynmodule_output_str) - 1, MEMF_PUBLIC)) != NULL) {
|
||||
sprintf(outputfmt, dynmodule_output_str, port);
|
||||
output = Open(outputfmt, MODE_NEWFILE);
|
||||
}
|
||||
|
||||
commandline = AllocVec(strlen(modname) + strlen(port) + 6, MEMF_PUBLIC);
|
||||
if (commandline) {
|
||||
struct TagItem cmdTags[] = {
|
||||
{ NP_StackSize, AROS_STACKSIZE },
|
||||
{ SYS_Input, (IPTR)input },
|
||||
{ SYS_Output, (IPTR)output },
|
||||
{ SYS_Asynch, TRUE },
|
||||
{ TAG_DONE, 0 }
|
||||
};
|
||||
struct MsgPort *dmifport = NULL;
|
||||
#if !defined(__AMIGA__)
|
||||
#define TICKSPERSEC 50
|
||||
#else
|
||||
int TICKSPERSEC;
|
||||
if ((SysBase->AttnFlags & AFB_NTSC) != 0)
|
||||
TICKSPERSEC = 60;
|
||||
else
|
||||
TICKSPERSEC = 50;
|
||||
#endif
|
||||
int iter, itermax, to = TICKSPERSEC/2;
|
||||
if (timeout > 1)
|
||||
itermax = (timeout * TICKSPERSEC) / to;
|
||||
else
|
||||
itermax = 1;
|
||||
sprintf(commandline, dynmodule_cmd_template, modname, port);
|
||||
|
||||
D(
|
||||
bug("[DynLink] %s: bootstrapping '%s'\n", __func__, commandline);
|
||||
bug("[DynLink] %s: input @ 0x%p\n", __func__, commandline, input);
|
||||
bug("[DynLink] %s: output @ 0x%p\n", __func__, commandline, output);
|
||||
)
|
||||
SystemTagList(commandline, cmdTags);
|
||||
|
||||
D(bug("[DynLink] %s: waiting %usecs for module to load ...\n", __func__, ((itermax * to)/TICKSPERSEC)));
|
||||
for (iter = 0; iter < itermax; iter++) {
|
||||
if ((dmifport = FindPort(port)) != NULL)
|
||||
break;
|
||||
Delay(to);
|
||||
}
|
||||
FreeVec(commandline);
|
||||
D(bug("[DynLink] %s: returning 0x%p\n", __func__, dmifport));
|
||||
return dmifport;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dynmodule__InternalDestroyDynModEntry(__dynmoduleinstance_t *dynmod, struct MsgPort *dmifport)
|
||||
{
|
||||
if (dmifport)
|
||||
DeleteMsgPort(dmifport);
|
||||
free(dynmod);
|
||||
}
|
||||
|
||||
29
compiler/dynmodule/dynmodule_modules.h
Normal file
29
compiler/dynmodule/dynmodule_modules.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef __DYNMODULE_MODULES_H
|
||||
#define __DYNMODULE_MODULES_H
|
||||
|
||||
/*
|
||||
* Definitions for the internal module entries
|
||||
*/
|
||||
|
||||
#include "dynmodule_intern.h"
|
||||
|
||||
#define DYNMODULE_MAX 20
|
||||
|
||||
typedef struct dynModuleEntry
|
||||
{
|
||||
__dynmoduleinstance_t *mhandle;
|
||||
int opencnt;
|
||||
char pnam[100];
|
||||
} __dynmoduleentry_t;
|
||||
|
||||
extern __dynmoduleentry_t dynmoduleslots[];
|
||||
extern int dynmodopncnt;
|
||||
|
||||
int dynmodule__InternalFindFreeSlot(int *);
|
||||
__dynmoduleinstance_t *dynmodule__InternalAllocDynModEntry(struct MsgPort **);
|
||||
void dynmodule__InternalInitDynModEntry(int, __dynmoduleinstance_t *, const char *);
|
||||
void dynmodule__InternalDestroyDynModEntry(__dynmoduleinstance_t *, struct MsgPort *);
|
||||
__dynmoduleinstance_t *dynmodule__InternalOpenPortEntry(const char *, BOOL);
|
||||
struct MsgPort *dynmodule__InternalBootstrapDynMod(const char *, const char *, int);
|
||||
|
||||
#endif
|
||||
45
compiler/dynmodule/dynmodule_removemodule.c
Normal file
45
compiler/dynmodule/dynmodule_removemodule.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file implements the runtime module function, RemoveModule.
|
||||
*/
|
||||
|
||||
//#define DEBUG 1
|
||||
#include <aros/debug.h>
|
||||
|
||||
#include "dynmodule_modules.h"
|
||||
|
||||
#include <proto/dos.h>
|
||||
#include <proto/exec.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int dynmoduleRemoveModule(const char *ifport)
|
||||
{
|
||||
struct MsgPort *replyport;
|
||||
struct MsgPort *dmmport;
|
||||
|
||||
D(bug("[DynLink] %s('%s')\n", __func__, ifport));
|
||||
|
||||
if (!(replyport = CreateMsgPort())) {
|
||||
if ((dmmport = FindPort(ifport))) {
|
||||
__dynmodulemsg_t msg, *reply;
|
||||
|
||||
memset(&msg.Message, 0, sizeof(struct Message));
|
||||
msg.Message.mn_ReplyPort = replyport;
|
||||
msg.IFMsgType = DMIFMSG_Dispose;
|
||||
|
||||
PutMsg(dmmport, (struct Message *)&msg);
|
||||
while ((reply = (__dynmodulemsg_t *)GetMsg(replyport)) == NULL) {
|
||||
Delay(2);
|
||||
if(FindPort(ifport) != dmmport)
|
||||
break;
|
||||
}
|
||||
}
|
||||
DeleteMsgPort(replyport);
|
||||
}
|
||||
else
|
||||
DYNMODULE_Exit(0);
|
||||
|
||||
return (dmmport ? 1 : 0);
|
||||
}
|
||||
55
compiler/dynmodule/include/dynmodstack.h
Normal file
55
compiler/dynmodule/include/dynmodstack.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef DYNMODULE_DYNMODSTACK_H
|
||||
#define DYNMODULE_DYNMODSTACK_H
|
||||
|
||||
/*
|
||||
* Definitions used to handle the correct stack frame format
|
||||
* on supported targets/toolchains. These are to define the stack
|
||||
* used by the module opener.
|
||||
*
|
||||
* the glue code will patch in the correct function pointer based
|
||||
* the requested stack frame type.
|
||||
*/
|
||||
|
||||
// "Generic" Targets.
|
||||
#define DYNMOD_STACKB_GCC 0
|
||||
#define DYNMOD_STACKB_SYSV 1
|
||||
|
||||
// M68k Targets
|
||||
#define DYNMOD_STACKB_EGCS DYNMOD_STACKB_GCC
|
||||
#define DYNMOD_STACKB_VBCC 2 /* vbcc */
|
||||
#define DYNMOD_STACKB_STORM 3 /* StormC */
|
||||
#define DYNMOD_STACKB_SAS 4 /* SAS/C */
|
||||
|
||||
// PPC targets
|
||||
#define DYNMOD_STACKB_EGCSPPC DYNMOD_STACKB_SYSV
|
||||
#define DYNMOD_STACKB_POWEROPEN 5 /* StormC/vbcc */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DYNMOD_STACKF_STORM = (1 << DYNMOD_STACKB_STORM),
|
||||
DYNMOD_STACKF_GCC = (1 << DYNMOD_STACKB_GCC),
|
||||
DYNMOD_STACKF_SAS = (1 << DYNMOD_STACKB_SAS),
|
||||
DYNMOD_STACKF_VBCC = (1 << DYNMOD_STACKB_VBCC),
|
||||
DYNMOD_STACKF_POWEROPEN = (1 << DYNMOD_STACKB_POWEROPEN),
|
||||
DYNMOD_STACKF_SYSV = (1 << DYNMOD_STACKB_SYSV)
|
||||
} dynmod_stackf_t;
|
||||
|
||||
#ifdef __PPC
|
||||
#if (defined __STORM__) || (defined __VBCC__)
|
||||
# define DYNMOD_STACKF_DEFAULT DYNMOD_STACKF_POWEROPEN
|
||||
#elif (defined __GNUC__)
|
||||
# define DYNMOD_STACKF_DEFAULT DYNMOD_STACKF_SYSV
|
||||
#endif
|
||||
#else
|
||||
#if (defined __VBCC__)
|
||||
# define DYNMOD_STACKF_DEFAULT DYNMOD_STACKF_VBCC
|
||||
#elif (defined __STORM__)
|
||||
# define DYNMOD_STACKF_DEFAULT DYNMOD_STACKF_STORM
|
||||
#elif (defined __SASC__)
|
||||
# define DYNMOD_STACKF_DEFAULT DYNMOD_STACKF_SAS
|
||||
#elif (defined __GNUC__)
|
||||
# define DYNMOD_STACKF_DEFAULT DYNMOD_STACKF_GCC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
79
compiler/dynmodule/include/dynmodule.h
Normal file
79
compiler/dynmodule/include/dynmodule.h
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef DYNMODULE_DYNMODULE_H
|
||||
#define DYNMODULE_DYNMODULE_H
|
||||
|
||||
/*
|
||||
* Public definitions for dynmodule support
|
||||
*/
|
||||
|
||||
#include <dynmod/dynmodstack.h>
|
||||
|
||||
typedef struct dynmodModule
|
||||
{
|
||||
const char *Name;
|
||||
const char *Port;
|
||||
} dynmod_mod_t;
|
||||
|
||||
typedef struct dynmodSymbol
|
||||
{
|
||||
dynmod_stackf_t StackFType;
|
||||
const char * SymName;
|
||||
void ** SymPtr;
|
||||
} dynmod_sym_t;
|
||||
|
||||
typedef struct dynmodImport
|
||||
{
|
||||
void **ImportPtr;
|
||||
const char *ImportName;
|
||||
dynmod_mod_t ImportModule;
|
||||
} dynmod_import_t;
|
||||
|
||||
typedef struct dynmodExport
|
||||
{
|
||||
void *ExportAddress;
|
||||
const char *ExportName;
|
||||
} dynmod_export_t;
|
||||
|
||||
/*
|
||||
* Typedefs for standard function vectors, implemented in module.
|
||||
*/
|
||||
typedef void *(*dynmoduleFindResourceFn_t)(int, const char *);
|
||||
typedef void *(*dynmoduleLoadResourceFn_t)(void *);
|
||||
typedef void (*dynmoduleFreeResourceFn_t)(void *);
|
||||
|
||||
typedef void (*stdexitfunc_t)(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *dynmoduleLoadModule(const char *, const char *);
|
||||
void dynmoduleFreeModule(void *);
|
||||
int dynmoduleImport(void);
|
||||
int dynmoduleExport(dynmod_sym_t *);
|
||||
void *dynmoduleGetProcAddress(void *, const char *);
|
||||
int dynmoduleRemoveModule(const char *);
|
||||
|
||||
/*
|
||||
* Prototypes for module provided structures/implementations
|
||||
*/
|
||||
extern const char *DYNMODULE_Name;
|
||||
extern dynmod_export_t DYNMODULE_Exports[];
|
||||
extern dynmod_import_t DYNMODULE_Imports[];
|
||||
|
||||
extern int DYNMODULE_Init(void *, unsigned long int, stdexitfunc_t);
|
||||
extern int DYNMODULE_Setup(void *);
|
||||
extern void DYNMODULE_Cleanup(void);
|
||||
extern void DYNMODULE_Exit(int);
|
||||
|
||||
/*
|
||||
* Prototypes for standard implementations exposed by the glue
|
||||
*/
|
||||
extern void *__dynglue_FindResource(int, const char *);
|
||||
extern void *__dynglue_LoadResource(void *);
|
||||
extern void __dynglue_FreeResource(void *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
33
compiler/dynmodule/mmakefile.src
Normal file
33
compiler/dynmodule/mmakefile.src
Normal file
@ -0,0 +1,33 @@
|
||||
include $(SRCDIR)/config/aros.cfg
|
||||
|
||||
#MM- core-linklibs : linklibs-dynmod linklibs-dynmodglue
|
||||
#MM linklibs-dynmod : includes
|
||||
#MM linklibs-dynmodglue : includes
|
||||
|
||||
#MM- includes-copy : dynmod-includes-copy
|
||||
#MM- compiler-includes : dynmod-includes-copy
|
||||
|
||||
%copy_includes mmake=dynmod-includes-copy dir=include path=dynmod includes="dynmodule.h dynmodstack.h"
|
||||
|
||||
DYNMODULEGLUEFILES := \
|
||||
dynmodule_glue
|
||||
|
||||
DYNMODULEFILES := \
|
||||
dynmodule_modules \
|
||||
dynmodule_loadmodule \
|
||||
dynmodule_freemodule \
|
||||
dynmodule_removemodule \
|
||||
dynmodule_export \
|
||||
dynmodule_import \
|
||||
dynmodule_getprocaddr
|
||||
|
||||
OLD := \
|
||||
dynmodule
|
||||
|
||||
%build_linklib mmake=linklibs-dynmod \
|
||||
libname=dynmod \
|
||||
files="$(DYNMODULEFILES)"
|
||||
|
||||
%build_linklib mmake=linklibs-dynmodglue \
|
||||
libname=dynmodglue \
|
||||
files="$(DYNMODULEGLUEFILES)"
|
||||
Reference in New Issue
Block a user