Newsgroup: it.comp.lang.c++
Titolo: caricamento da ram

ciao a tutti,
 ho un problema per cui richiedo il vostro aiuto,
 vorrei lanciare un programma ,diciamo prg1 direttamente dalla ram senza 
copiarlo su disco,prg1 è incluso in un altro programma come risorsa,
pensavo si potesse copiare la risorsa contente il file eseguibile ,allocare 
la memoria per accoglierlo copiarlo dentro e poi lanciarlo,
ma ho un problema: tutte le funzioni che conosco per lanciare un programma 
hanno bisogno di puntare ad un file su disco 
(createProcess,system,winexec,execle....) come fare o dove trovare 
informazioni al riguardo???,
ho girato un bel pò su internet ma nulla di rilevante al riguardo,
dovrei risolvere il problema in ambiente windows.
Grazie anticipatamente.

 la memoria per accoglierlo copiarlo dentro e poi lanciarlo,
il problema che sollevi è molto interessante anche se di certo 
un purista storcerebbe il naso poiché non è un modo molto pulito 
di procedere.
Intanto penso che già a priori non si possa trovare una 
soluzione molto portabile, dato che è richiesta una interazione 
molto stretta con l'OS.
Imho dovresti cercare prima di capire come l'OS assegna e 
gestisce gli accessi ai tipi diversi di RAM.
Mi spiego, un segmento assegnato come codice solitamente non è 
scrivibile, e quando lo può essere, non lo è certo da processi 
diversi.
Pure sotto sistemi permissivi che nn proteggano l'area codice da 
accessi esterni, potrebbero essere attive utility tipo antivirus 
che ti cazziano, poiché modificare segmenti di codice era un 
tipico comportamento di alcuni tipi di virus.
Pensa nei termini del OS : è come se il programam di tizio vuole 
caricare un pezzo di disco dentro una procedura di M$-WORD. 
Detta così suona male, no ?
Ammettendo di bypassare in qualche modo (o di farsi autorizzare 
dall'OS) il controllo dell'accesso in scrittura della ram in 
questione, ti suggerisco per sommi capi un'idea che potrebbe 
fungere (nota che tutto questo potrebbe essere evitato 
ricorrendo al caricamento e scaricamento dinamico delle DLL, che 
servono proprio a evitare che un processo risieda interamente in 
ram, ma sorvoliamo).
N.B. il suggerimento è molto sporco (ma proprio tanto) e 
rischioso, e cmq non funziona se non convinci l'O.S. a darti 
accesso in scrittura ad una zona di memoria con codice eseguibile.
Cmq
ammettiamo che tu abbia svariate procedure su disco che non vuoi 
tenere in ram tutte insieme (in pratica vuoi swappare del codice 
a mano). Ottieni in qualche maniera le dimensioni di ciascuna 
routine compilata e scegli la più grossa di tali routine. PEr 
cautela potresti aggiungerci un altra percentuale che lascio a 
te scegliere (io aggiungerei un 50 % di cautela).
Diciamo che arrivi a XXX byte di ingombro di memoria di solo codice.
dichiari nel programma da caricare in ram una funzione piuttosto 
assurda, SILLY, ad esempio piena di codici assembly NOP (no 
operation, occupano un solo byte) e ne copyincolli tanti per 
arrivare a XXX byte di codice. Ora questa funzione non esegue 
nessuna operazione. Puoi anche usare __emit e scrivere 
l'esadecimale di NOP, se lo sai. Invece non allocare spazio 
usando costanti literal, tipo stringhe o numeri, perché il 
compilatore potrebbe metterle in un diverso segmento (dati) e 
nel codice soltanto l'indirizzo. Coi numeri non so cosa trovi 
conveniente. Con le stringhe sicuramente fa così.
Inizializzi un puntatore a funzione che punti a SILLY, poi fai 
anche un cast a void *.
A quel punto passi ad una funzione di lettura da file in ram il 
puntatore void * che in verità punta alla funzione ospitante, 
carichi in ram il contenuto del disco (nota, devi sapere con 
esattezza le dimensioni corrette del codice della funzione voluta).
Poi invochi la funzione tramite il puntatore.
(o persino col nome direttamente)
Stop
alcune cautele e limiti
1) non è previsto passaggio di parametri o se si, tutte le varie 
funzioni alias devono attendersi lo stesso set di parametri 
fissi per numero e tipo.
2) chiamare silly() prima dello swap non produce effetti eccetto 
che spreco di tempo macchina. i NOP sono esenti da effetti 
collaterali.
2a) chiamare silly pensando che contenga la funzione A mentre 
contiene la funzione B produce risultati indefiniti. In altre 
parole ti consiglio di lasciare qualche traccia, statica ed 
esterna, con la stessa visibilità di Silly, per sapere cosa 
cavolo contiene realmente in un dato istante. Ovviamente la 
sicurezza è tutta delegata al programmatore e non c'è vera 
garanzia di niente
3) io non lo ricordo nel dettaglio, ma ripassati il protocollo 
di chiamata/ritorno da uan qualsiasi funzione.
Questo per evitare che A) la copia da disco della funzione vada 
a sovrascrivere l'indirizzo di ritorno ... ok, dovrebbe stare 
sullo stack e non nel codice, quindi altrove, ma controlla ! ! 
B) controlla che succede quando finisce il codice voluto di una 
routine copiata (e finisce prima del corpo della funzione Silly) 
: non dovrebbe succedere nulla, dato che ci sono dei NOP, e 
soprattutto non dovrebbero nemmeno venire raggiunti. Il problema 
è che NOP è una istruzione completa (che non fa nulla) ma che 
potrebbe anche essere interpretata in modo diverso se fusa 
insieme a qualche altro byte della routine precedente. Questione 
di allineamento nella lettura delle istruzioni. Controlla in 
particolare se RET seguito da NOP può assumere un significato 
differente. RET era solitamente l'ultima istruzione compilata 
della procedura ... ai vecchi tempi. Ora non so. Devi avere un 
buon debugger per osservare la dinamica x filo e x segno
In linea di principio il basic arcaico da dos faceva una cosa 
simile con BLOAD / CALL ABSOLUTE
BLOAD caricava un programma dentro una matrice globale, pensa te !
CALL ABSOLUTE passava il controllo di esecuzione a quell'indirizzo.
Ma il DOS ti lasciava fare tutto, i sistemi evoluti arbitrano e 
vincolano l'accesso alal memoria, quindi il tuo principale 
problema resta quello.
ciao
Soviet-Mario
