Flipping endianness trong gdb?
Trong gdbtôi là một bix bối rối tại sao đôi khi nó in các byte từ trái sang phải và đôi khi từ phải sang trái. Đây là một ví dụ mà không có hướng dẫn nào được chạy ở giữa:
>>> x/4b $rbp-4 0x7fffffffe43c: 0x04 0x00 0x03 0x16 >>> x/2h $rbp-4
0x7fffffffe43c: 0x0004 0x1603
Tại sao điều này được thực hiện trong gdb? Tôi nghĩ nó sẽ luôn in chúng dưới dạng:
04 00 03 16
Trả lời
GDB sử dụng endiannes gốc của máy mục tiêu (theo mặc định là 1 ) để diễn giải các phần có kích thước bạn yêu cầu dưới dạng số nguyên, với các địa chỉ tăng từ trái sang phải giữa các phần. x86 là phiên bản nhỏ.
Trong một đoạn, được 04 00hiểu là số nguyên cuối cùng nhỏ 16 bit là 0x0004 . shortVí dụ, điều này làm cho GDB kết xuất một mảng theo cách bạn mong đợi. Bạn đã yêu cầu GDB cung cấp các khối số nguyên 16 bit, vì vậy nó thực hiện những gì bạn đã nói, hiển thị giá trị số nguyên bằng cách sử dụng ký hiệu giá trị vị trí tiêu chuẩn với chữ số ngoài cùng bên trái là chữ số quan trọng nhất. Nó không cố gắng in các byte riêng biệt bởi vì bạn đã yêu cầu nửa từ.
Nếu bạn muốn byte theo thứ tự bộ nhớ, hãy sử dụng b. Đó là những gì nó dành cho.
Chú thích 1 :
Bạn có thể thay đổi cài đặt độ bền của GDB; show endianhiển thị cài đặt hiện tại. Tuy nhiên, set endian biggây ra sự cố, làm hỏng giá trị thanh ghi. ví dụ: khi dừng lại ở _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
Các thanh ghi không có giá trị cuối cùng và việc lật chúng khi mở rộng giá trị của chúng làm địa chỉ cho một lệnh khác hoàn toàn bị hỏng.
Các bản sao không chính xác có liên quan:
- GDB có đang diễn giải địa chỉ bộ nhớ một cách chính xác không?
- Tại sao dữ liệu được lưu trữ trong bộ nhớ bị đảo ngược?
- Big Endian và Little endian nhầm lẫn nhỏ
Peter có câu trả lời chính xác và được chấp nhận nhưng tôi sẽ đưa ra một lời giải thích rất ngắn gọn ở đây để giúp tôi hiểu hơn.
Vì vậy, giả sử chúng ta muốn lưu trữ số 22( 0x16trong hệ lục phân) dưới dạng giá trị hai byte trong bộ nhớ.
Vì x86 là little-endian (lưu trữ byte quan trọng nhất ở địa chỉ bộ nhớ cao nhất), chúng tôi sẽ lưu trữ nó như sau:
0xAA1: 0x16 (LSB)
0xAA2: 0x00 (MSB)
Bây giờ, nếu chúng ta in nó từng byte theo thứ tự tăng dần của địa chỉ bộ nhớ, thì rõ ràng nó sẽ như thế này:
0xAA1: 0x16 0x00 (2 bytes, byte by byte in increasing memory address)
Nhưng sau đó, nếu chúng ta muốn giá trị ban đầu của 22trở lại, chúng ta cần phải diễn giải giá trị hai byte là giá trị nhỏ để nó trả về giá trị chính xác:
0xAA1: 0x0016 # 22 in decimal (bytes flipped back to interpret it properly in program