Nell’esempio di savefile descritto nel precedente post abbiamo analizzato solo la prima pagina contenente la intestazione del savefile. Seguono 3 pagine (da 4KB ciascuna) per cui la struttura complessiva è la seguente:
------------------------------------------------- | Header | PAGE 1 | ------------------------------------------------- | Load/dump object descriptor (0x19db) | PAGE 2 | ------------------------------------------------- | System Object Structure (0x19db) | PAGE 3 | | Associated space (IBM i work area) | PAGE 4 | -------------------------------------------------
Come dicevamo in precedenza la documentazione fornita da Frank Soltis ci è utile per comprendere la pagina 3 (System Object Structure).
I primi 32 byte della stessa contengono la Segment header e forniscono informazioni descrittive del segmento di memoria di cui è stato effettuato il dump. Le due pagine 3 e 4 sono esattamente la copia del contenuto di due pagine presenti in memoria (si tratta di un dump) anche se non si tratta di un oggetto utente ma di una entità di servizio ad uso del sistema operativo.
Questa è la segment header:
00 01 00 10 03 c0 00 90 3a aa 40 cc fa 00 00 00 00 01 00 00 00 00 00 00 3a aa 40 cc fa 00 10 00
Il valore 0x3aaa40ccfa
(ossia i primi 40 bit dei due indirizzi nelle posizioni 9-16 e 25-32) identificano univocamente un segmento di memoria IBM i. Il primo indirizzo è complessivamente un puntatore alla posizione iniziale del segmento (offset 0x000000
), il secondo è un puntatore alla pagina successiva (offset 0x001000
).
Un segmento si compone sempre di un multiplo intero di pagine di memoria (4KB) logicamente contigue ( ma non necessariamente contigue anche nella memoria fisica ).
Il secondo indirizzo ci dice che a partire dalla posizione 0x001000
(fatto 0
l’inizio della header) inizia il cosiddetto Associated Space che altro non è se non l’area di lavoro utilizzata dal sistema operativo IBM i. Il sistema operativo IBM i (ex OS/400 -e ancor prima ex CPF-) esiste ad un livello di architettura superiore al License Internal Code : “all users of the MI, including OS/400 itself, are not allowed below the MI” (op. cit. Soltis, page 129) .
Le informazioni che ci interessano, ossia quelle che descrivono gli oggetti come visti/gestiti dal sistema operativo, si trovano dunque all’inizio della pagina 4.
Sapendo che all’interno del segmento di memoria 0x3aaa40ccfa
la sola pagina gestita dal sistema operativo IBM i (e di nostro interesse) inizia all’indirizzo 0x1000
, decidiamo di far precedere al dump esadecimale un offset relativo partendo da 0x00000000
anziché dall’offset relativo al segmento:
000000000 02 49 c5 d4 d7 e3 e8 40 40 40 40 40 40 40 40 40 000000010 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 000000020 04 01 a6 d7 9a 5b 0d 5a e0 01 00 00 00 01 00 00 000000030 00 00 01 40 40 ** ** ** ** ** ** ** 00 00 5c e2 000000040 e8 e2 e5 c1 d3 40 40 40 00 00 00 00 d5 00 01 00 000000050 5c e2 e8 e2 c2 c1 e2 40 40 40 00 5c d5 d6 d5 c5 000000060 40 40 40 40 40 ** ** ** ** ** ** ** ** 00 00 00
La prima sezione (byte 1-112) ha dimensione fissa è descrive l’operazione di salvataggio (operazione, versione sistema operativo, nome libreria, tipo, sottotipo, timestamp, ecc.).
000000070 c5 d4 d7 e3 e8 40 40 40 40 40 40 40 40 40 40 40 000000080 40 40 40 40 40 40 40 40 40 40 40 40 40 40 04 01 000000090 c1 d5 c4 d9 c5 c1 d9 c9 c2 40 40 40 40 40 40 40 0000000a0 40 40 40 40 40 40 40 40 40 40 40 40 40 40 00 00 0000000b0 00 00 80 00 01 c0 00 00 00 01 10 00 00 01 60 00 0000000c0 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000d0 00 00 00 00 00 00 00 0000000d7 00 00 00 00 00 00 00 00 00
La seconda è costituita da una struttura di elementi che si ripete: una struct di lunghezza 151 byte (0xd7) per ogni oggetto salvato (nel nostro caso ne è presente una sola).
All’interno di questa struttura risiedono due riferimenti a posizioni successive che contengono dati addizionali relative all’elemento salvato.
I valori 0x00000110
e 0x00000160
fungono da puntatori locali all’interno della pagina.
000000110 00 00 00 00 00 00 00 40 00 00 00 00 02 e2 00 00 000000120 ff 1c 3f 10 60 00 00 00 40 00 00 00 00 00 00 00 000000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 *
Alla posizione 0x00000110
(in questo esempio) si trovano informazioni generali valide per ogni tipo di oggetto.
Mentre alla posizione 0x00000160
(sempre in questo esempio) troviamo una serie di strutture precedute dalla loro
lunghezza e che hanno un significato posizionale.
Espandiamo la sezione di dump seguente per facilitarne la comprensione:
000000160 00 00 00 00 00 00 00 a8 40 40 40 40 40 40 40 40 000000170 40 40 40 40 40 40 40 40 40 40 40 40 40 f1 40 40 000000180 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 000000190 40 40 40 e5 f7 d9 f4 d4 f0 f1 f2 f1 f0 f8 f2 f6 0000001a0 f1 f8 f5 f3 f0 f9 40 40 40 40 40 40 40 40 40 40 0000001b0 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 * 0000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 000000200 40 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000000210 00 00 00 1a c1 d5 c4 d9 c5 c1 d9 c9 c2 40 ** ** 000000220 ** ** ** ** ** ** 00 00 00 00 00 00 00 00 00 00 000000230 00 00 00 00 00 0b d7 d9 d6 c4 40 40 40 40 40 40 000000240 f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
interpretando 4 byte alla volta come lunghezza che precede ciascun elemento:
- Primo elemento (assente, lunghezza
0
)
000000160 00 00 00 00
- Secondo elemento
000000164 00 00 00 a8 000000168 40 40 40 40 40 40 40 40 000000170 40 40 40 40 40 40 40 40 40 40 40 40 40 f1 40 40 000000180 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 000000190 40 40 40 e5 f7 d9 f4 d4 f0 f1 f2 f1 f0 f8 f2 f6 0000001a0 f1 f8 f5 f3 f0 f9 40 40 40 40 40 40 40 40 40 40 0000001b0 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 0000001c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000000200 40 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- Terzo elemento
Avanzando di 0xa8
byte: 0x168 + 0xa8 = 0x210
000000210 00 00 00 1a 000000214 c1 d5 c4 d9 c5 c1 d9 c9 c2 40 ** ** 000000220 ** ** ** ** ** ** 00 00 00 00 00 00 00 00
Quarto elemento (assente, lunghezza 0
)
00000022e 00 00 000000230 00 00
Quinto elemento (attributo; valore “PROD”)
000000232 00 00 00 0b 000000236 d7 d9 d6 c4 40 40 40 40 40 40 000000240 f0
Sesto elemento (assente, lunghezza 0
)
000000241 00 00 00 00
Settimo elemento (assente, lunghezza 0
)
000000245 00 00 00 00
Mettendo a confronto il savefile con l’output del comando DMPOBJ OBJ(EMPTY) OBJTYPE(*LIB)
si potranno correlare i campi con la dicitura adottata nella stampa QPSRVDMP.