Capovolgere endianness in gdb?
In gdb
Sono un bix perplesso sul motivo per cui a volte stampa byte da sinistra a destra e talvolta da destra a sinistra. Ecco un esempio in cui nessuna istruzione è stata eseguita tra:
>>> x/4b $rbp-4 0x7fffffffe43c: 0x04 0x00 0x03 0x16 >>> x/2h $rbp-4
0x7fffffffe43c: 0x0004 0x1603
Perché questo viene fatto in gdb? Penso che li stamperebbe sempre come:
04 00 03 16
Risposte
GDB utilizza l'endiannes nativo della macchina di destinazione (per impostazione predefinita 1 ) per interpretare blocchi della dimensione richiesta come numeri interi, con indirizzi che aumentano da sinistra a destra tra i blocchi. x86 è little endian.
All'interno di un blocco, 04 00
interpretato come un intero little endian a 16 bit è 0x0004
. Questo fa sì che GDB dump un array short
nel modo in cui ti aspetteresti, ad esempio. Hai chiesto a GDB blocchi interi a 16 bit, quindi fa quello che gli hai detto, mostrando il valore intero utilizzando la notazione del valore di posizione standard con la cifra più a sinistra la più significativa. Non sta cercando di stampare i byte separatamente perché hai chiesto mezze parole.
Se vuoi byte in ordine di memoria, usa b
. Ecco a cosa serve.
Nota 1 :
Puoi modificare l'impostazione endianness di GDB; show endian
mostra l'impostazione corrente. Tuttavia, set endian big
causa problemi, danneggiando i valori di registro. ad es. quando ci si ferma a _start
:
(gdb) p /x $rsp $1 = 0x7fffffffe6d0 # this is normal for x86-64
(gdb) set endian big
The target is assumed to be big endian
(gdb) x /16xw $rsp 0xd0e6ffffff7f0000: Cannot access memory at address 0xd0e6ffffff7f0000 (gdb) p /x $rsp
$2 = 0xd0e6ffffff7f0000 # this is obviously broken, byte-reversed
I registri non hanno un endian e capovolgerli quando si espande il loro valore come indirizzo per un altro comando è completamente rotto.
Duplicati non esatti correlati:
- GDB interpreta correttamente l'indirizzo di memoria?
- Perché i dati archiviati in memoria vengono invertiti?
- Big Endian e Little Endian poca confusione
Peter ha la risposta corretta e accettata, ma inserirò anche una breve spiegazione che ha aiutato la mia comprensione.
Quindi supponiamo di voler memorizzare il numero 22
( 0x16
in esadecimale) come valore a due byte in memoria.
Poiché x86 è little-endian (memorizza il byte più significativo all'indirizzo di memoria più alto), lo memorizzeremo in questo modo:
0xAA1: 0x16 (LSB)
0xAA2: 0x00 (MSB)
Ora, se lo stampiamo byte per byte in ordine crescente di indirizzo di memoria, ovviamente ha questo aspetto:
0xAA1: 0x16 0x00 (2 bytes, byte by byte in increasing memory address)
Ma poi se vogliamo il valore originale di 22
back dobbiamo interpretare il valore a due byte come little-endian in modo che restituisca il valore corretto:
0xAA1: 0x0016 # 22 in decimal (bytes flipped back to interpret it properly in program