2012-09-19 12 views
7

Sono interessato allo sviluppo di un tipo di debugger in modalità kernel ring0 per x86-64 in Common Lisp che verrebbe caricato come un modulo del kernel Linux e come preferisco Common Lisp a C nella programmazione generale, mi chiedo in che modo Common Lisp le implementazioni si adatterebbero a questo tipo di attività di programmazione.È possibile scrivere un debugger in modalità kernel Linux per Intel x86-64 in Common Lisp e con quale implementazione Common Lisp [s]?

Il debugger utilizzerà una libreria di disassemblaggio esterna, ad esempio udis86 tramite alcuni FFI. Mi sembra che sia più facile da scrivere moduli del kernel in C come hanno bisogno di contenere funzioni C int init_module(void) e void cleanup_module(void) (The Linux Kernel Module Programming Guide), in modo che il codice del modulo del kernel-terra sarebbe chiamare il codice Common Lisp da C utilizzando CFFI. L'idea sarebbe quella di creare un debugger ring0 per Linux a 64 bit ispirato all'idea di Rasta Ring 0 Debugger, che è disponibile solo per Linux a 32 bit e richiede la tastiera PS/2. Penso che la parte più difficile sarebbe il codice attuale del debugger con i breakpoint hardware e software e la gestione dei dispositivi di input video, tastiera o USB di basso livello. Inline assembly sarebbe di grande aiuto in questo, mi sembra che in SBCL l'assembly inline possa essere implementato utilizzando VOP (SBCL Internals: VOP) (SBCL Internals: Adding VOPs), e questo IRC log menziona che ACL (Allegro Common Lisp), CCL (Clozure Common Lisp) e CormanCL hanno LAP (Lisp Programmi di assemblaggio). Sia ACL che CormanCL sono proprietari e quindi scartati, ma CCL (Clozure Common Lisp) potrebbe essere un'opzione. Anche la capacità di creare file eseguibili standalone è un requisito; SBCL che sto usando attualmente ce l'ha, ma dato che sono immagini Lisp intere, le loro dimensioni sono abbastanza grandi.

La mia domanda è: è praticabile per creare un debugger del kernel-mode ring0 per Intel x86-64 in Common Lisp, con il codice di basso livello implementato in C e/o il montaggio, e se lo è, quali Common Implementazioni Lisp per Linux best-suit a 64 bit per questo tipo di attività, e quali sono i pro e i contro se esistono più di una implementazione Common Lisp adatta? Lo schema può essere anche una possibile opzione, se offre alcuni vantaggi rispetto a Common Lisp. Sono ben consapevole del fatto che la grande maggioranza dei moduli del kernel sono scritti in C, e conosco abbastanza bene l'assembly C e x86 per poter scrivere il codice di basso livello richiesto in C e/o assembly. Questo non è un tentativo di portare il kernel Linux in Lisp (vedi: https://stackoverflow.com/questions/1848029/why-not-port-linux-kernel-to-common-lisp), ma un piano per scrivere in Common Lisp un modulo del kernel Linux che verrebbe usato come un debugger ring0.

+3

Probabilmente si può eseguire la parte Lisp in un processo utente e solo comunicare con esso dal debugger.. –

+0

@AlexeyFrunze Questa potrebbe essere una buona idea, probabilmente rende le cose molto più semplici – nrz

+0

Un downvote, un upvote Mi piacerebbe sapere perché un downvote? – nrz

risposta

2

No, non sarebbe fattibile implementare un modulo del kernel in CL per l'ovvia ragione che solo per fare quel lavoro dovrai fare molti hack e finire per perdere tutti i benefici che il linguaggio Lisp fornisce e il tuo il codice Lisp sarà simile al codice C nelle espressioni S.

Scrivere il modulo del kernel per esportare qualsiasi funzionalità/dati necessari dal kernel e quindi utilizzare le operazioni ioctl o di lettura/scrittura qualsiasi programma in modalità utente in grado di comunicare con il modulo.

Non sono sicuro che ci sia un modulo del kernel che è abbastanza generico da implementare Lisp (o potrebbe essere il suo sottoinsieme) in modo tale da scrivere codice in Lisp e questo modulo generico legge il codice Lisp ed eseguirlo come componente secondario , in pratica Kernel -> Modulo lisp generico -> il tuo codice lisp (che verrà eseguito nel kernel).

+2

+1 Implementare il codice del modulo del kernel in C e il codice userland in Common Lisp sarebbe una buona alternativa. Tuttavia, ho scoperto che [ECL (Embedded Common-Lisp)] (http://ecls.sourceforge.net/) supporta inline C e compila in file eseguibili standalone, e questi sono i due requisiti più importanti qui per qualsiasi implementazione CL, quindi provo prima ECL con C inline. – nrz

+0

Dopo alcuni giorni di hacking del codice del modulo del kernel, sembra che incorporare Common Lisp (ECL) sarebbe un compito difficile. Nel codice del kernel è possibile solo un sottoinsieme di C, quindi anche se ECL produce codice C (che è una cosa molto buona), il codice C probabilmente non è un codice C del kernel valido. Modifica del codice C prodotto da ECL ad es. con regex creerebbe un altro livello di programmazione, prima che il codice possa essere compilato con 'gcc'. Così insted di '.lisp' ->' ecl' -> '.c' ->' gcc' -> '.o' ->' ld' -> '.ko' pipeline sarebbe eg. '.lisp' ->' ecl' -> '.c' ->' vim' o 'perl' ->' .c' -> 'gcc' ->' .o' -> 'ld' ->'. ko' pipeline. – nrz

+0

Mi sembra che scrivere codice del modulo del kernel in ECL possa essere possibile con alcune modifiche (maggiori?) In ECL, in modo che possa facoltativamente emettere un codice C valido per i moduli del kernel. È molto più facile scrivere il modulo del kernel in C e il codice userland in ECL, e fare la comunicazione tra loro tramite '/ dev' e/o porte. Questo è possibile già adesso, ed è la strada da percorrere per me. – nrz

3

Si potrebbe voler dare un'occhiata al discorso del 2 febbraio 2008 di Lispvan "Fare cose cattive con Common Lisp" di Brad Beveridge su come lavorare con un driver per filesystem di SBCL.

Talk description & files

In essa egli menzioni:

"A C/C++ Debugger scritto in CL ??

Totalmente torta in cielo in questo momento

Ma, quanto freddo sarebbe?

Non che un grande sforzo, solo bisogno di essere in grado di scrivere nella memoria in cui si trova la libreria di inserire punti di interruzione & poi segnali trappola sul lato Lisp

Potrebbe utilizzare sporchi trucchi per sostituire le funzioni C con le chiamate a funzioni Lisp

a parte alcuni dettagli, probabilmente non è così difficile - di certo nulla di “nuovo”

il trucco sporco comporterebbe sovrascrivendo il codice C con un altro salto (ramo senza link) in un callback Lisp . Quando viene restituito il codice Lisp, è possibile tornare direttamente alla funzione di chiamata originale tramite il registro dei collegamenti.

Inoltre, io sono totalmente sorvolare la vera difficoltà per iscritto un debugger - sarebbe in termini di tempo "

+1

+1 L'attività sembra essere possibile ma richiede molto tempo, anche se la decompilazione è molto più difficile del disassemblaggio. Il mio piano sarebbe quello di creare un debugger di assembly regolare nello stile di SoftIce, con le ricerche di memoria regex di Vim/Perl. Sembra che un debugger in modalità kernel scritto in una parte importante di Common Lisp sia possibile, soprattutto considerando il fatto che [ECL (Common-Lisp (Embeddable Common-Lisp)] (http://ecls.sourceforge.net/) supporta inline C con '(ffi: cline c-code *) 'e' (ffi: c-inline (lisp-value *)) 'forme speciali, quindi penso che ECL sarebbe una delle migliori implementazioni Common Lisp per un compito come questo. – nrz