La prima volta che si scrive un motore di scripting

0

Quindi ho deciso di creare una macchina virtuale basata sullo stack e il risultato è venuto fuori piuttosto bene (secondo me!). La prima iterazione è stata una macchina virtuale di base.

Ho effettuato una riscrittura per rendere la VM un lavoro più realistico fornendo memoria e stack di dati orientati ai byte e opcode orientati ai byte n. Dopo molti test, incluso un test Fibonacci in opcode, il risultato si è rivelato bellissimo, completo e mi è davvero piaciuto farlo.

Ora ho deciso di eseguire un'altra riscrittura, ma di estenderla a un motore di scripting. Ho preso un libro intitolato "Game scripting mastery" che parlava della creazione di un intero motore di scripting con un linguaggio di scripting personalizzato da zero.

È stato un po 'eccessivo per quello che volevo fare, ma le idee erano utili, ma spero di prendere alcuni approcci migliori di quello che il libro mostra.

Come motore di scripting, la mia intenzione con questo motore è di eseguire bytecode creato da un normale compilatore C modificando il backend. Il mio obiettivo finale è che il motore di script possa supportare ogni parte di C.

In termini di script, ho già implementato un formato di file di intestazione per ogni script e ogni script ha un sandbox permettendo di avere la propria memoria e lo stack allocato durante il caricamento. Il layout dei dati dello script è ...

typedef struct __script {
    uchar       *pMemory, *pStack, *pInstrStream;
    uint64_t            ip, sp, bp;     // 24 bytes

    uint        uiMemSize;      // how much memory does script need?
    uint        uiStkSize;      // how large of a stack does script need?
    uint        ipstart;        // where does 'main' begin?
    uint        uiInstrCount;   // how many instructions does the code have?
    uint16_t    magic;          // verify bytecode
} Script_t;

In termini di tutto ciò, ho solo due domande reali.

Q1: Considerando che ogni script è in modalità sandbox, come posso ottenerlo in modo che i singoli script possano condividere dati tra loro?

Ho pensato in due modi per risolvere questo problema: 1 modo è che posso creare un link bytecode e collegare più script bytecode compilati in uno grande e usarli come librerie statiche

un altro metodo che ho ideato è che gli script compilati senza main() possono fungere da DLL (caricati dinamicamente), quindi uno script può caricare in un dllscript e quindi utilizzare dati specifici se funzione o variabile simile a dlopen e dlsym utilizzato in linux.

Q2: Qual è il modo migliore per collegare un'API pubblica tra la VM e l'applicazione host? (in modo che gli script possano chiamare il codice C nativo dal lato dell'applicazione host)

Poiché questa VM deve eseguire bytecode fatto da un compilatore C, sono abbastanza sicuro che ogni script dovrà includere un file di intestazione che contiene i prototipi di funzione esportati dall'host per gli script da usare anche se non sono sicuro di come che funzionerebbe.

Poi c'è il problema con l'esportazione di variabili lato host come struct, unions, globals, ecc. Non ho pensato a questa parte perché sto ancora pensando di risolvere il problema della domanda n. 1.

Cosa suggerisci?

    
posta Nergal 20.07.2017 - 08:23
fonte

1 risposta

0

Q1: Considering that each script is sandboxed, how can I have it so individual scripts can share data between one another?

Un software costituito da diversi .c file è progettato per funzionare insieme, non ha senso provare l'esecuzione di un sottoinsieme di essi e sono progettati per funzionare in collaborazione.

Una sandbox ha lo scopo opposto: intende dividere e proteggere le persone, evitando che abbiano un impatto sugli altri, evitando le comunicazioni ed evitando la collaborazione.

Cercando di rendere ogni file .c sandboxed, IMO è un concetto errato sin dall'inizio e quindi qualsiasi soluzione sarebbe una patch, un problema di sicurezza o entrambi.

La soluzione probabilmente è considerare questa interazione da vicino dalla prospettiva sandbox: una sandbox incapsulerebbe un software e non più un singolo file .c . Potremmo immaginare questa sandbox per incapsulare diversi file, qualche gestione della memoria, qualche interfaccia per dispositivi, ecc. Avrebbe anche bisogno di un modo per definire quali file appartengono allo stesso software, forse un file meta-dati?

Q2: What is the best way to bridge a public API between the VM and host application? (so that scripts can call native C code from host application side)

Supponendo di avere il tuo albero sintattico fuori dal codice oggetto, sembra possibile rilevare librerie esterne: solitamente una tabella indica le firme delle funzioni esterne previste. È quindi possibile chiamare la funzione C specifica in caso di una firma conosciuta (e.i. chiamate di libreria standard).

    
risposta data 20.07.2017 - 13:14
fonte

Leggi altre domande sui tag