Flipping endianness di gdb?
Di gdbI'm a bix bingung mengapa kadang-kadang mencetak byte dari kiri ke kanan dan kadang dari kanan ke kiri. Berikut adalah contoh di mana tidak ada instruksi yang dijalankan di antaranya:
>>> x/4b $rbp-4 0x7fffffffe43c: 0x04 0x00 0x03 0x16 >>> x/2h $rbp-4
0x7fffffffe43c: 0x0004 0x1603
Mengapa ini dilakukan di gdb? Saya akan berpikir itu akan selalu mencetaknya sebagai:
04 00 03 16
Jawaban
GDB menggunakan endiannes asli mesin target (secara default 1 ) untuk menafsirkan potongan ukuran yang Anda minta sebagai bilangan bulat, dengan alamat yang meningkat dari kiri ke kanan di antara potongan. x86 adalah little-endian.
Dalam potongan, 04 00ditafsirkan sebagai integer little-endian 16-bit adalah 0x0004 . Ini membuat GDB membuang array shortseperti yang Anda harapkan, misalnya. Anda diminta GDB untuk 16-bit potongan integer, sehingga melakukan apa yang Anda diberitahu itu, menunjukkan integer nilai menggunakan notasi tempat-nilai standar dengan digit paling kiri yang paling signifikan. Itu tidak mencoba mencetak byte secara terpisah karena Anda meminta setengah kata.
Jika Anda ingin byte dalam urutan memori, gunakan b. Untuk itulah.
Catatan kaki 1 :
Anda dapat mengubah pengaturan endianness GDB; show endianmenunjukkan pengaturan saat ini. Namun, set endian bigmenyebabkan masalah, merusak nilai register. misal saat berhenti di _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
Register tidak memiliki endianness, dan membaliknya saat memperluas nilainya sebagai alamat untuk perintah lain benar-benar rusak.
Terkait bukan duplikat persis:
- Apakah GDB menafsirkan alamat memori dengan benar?
- Mengapa data yang disimpan dalam memori dibalik?
- Big Endian dan Little endian kebingungan
Peter memiliki jawaban yang benar dan diterima tetapi saya akan memberikan penjelasan singkat di sini juga yang telah membantu pemahaman saya.
Jadi katakanlah kita ingin menyimpan angka 22( 0x16dalam hex) sebagai nilai dua byte dalam memori.
Karena x86 adalah little-endian (menyimpan byte paling signifikan di alamat memori tertinggi), kami akan menyimpannya seperti ini:
0xAA1: 0x16 (LSB)
0xAA2: 0x00 (MSB)
Sekarang, jika kita mencetaknya byte-by-byte dalam urutan alamat memori yang meningkat, jelas terlihat seperti ini:
0xAA1: 0x16 0x00 (2 bytes, byte by byte in increasing memory address)
Tetapi kemudian jika kita menginginkan nilai asli 22kembali, kita perlu menafsirkan nilai dua byte sebagai little-endian sehingga mengembalikan nilai yang benar:
0xAA1: 0x0016 # 22 in decimal (bytes flipped back to interpret it properly in program