2015-06-24 12 views
5

Khi chạy info registers trong gdb, chúng tôi nhận được một đầu ra tương tự như sau:thông tin GDB đăng ký lệnh - cột thứ hai của đầu ra

rax   0x1c 28 
rbx   0x0 0 
rcx   0x400a60 4196960 
rdx   0x7fffffffde88 140737488346760 
rsi   0x1 1 
rdi   0x400932 4196658 
rbp   0x0 0x0 
rsp   0x7fffffffde68 0x7fffffffde68 
r8    0x400ad0 4197072 
r9    0x7ffff7dea560 140737351951712 
r10   0x7fffffffdc30 140737488346160 
r11   0x7ffff7732dd0 140737344908752 
r12   0x4007f0 4196336 
r13   0x7fffffffde80 140737488346752 
r14   0x0 0 
r15   0x0 0 
rip   0x7ffff7732dd0 0x7ffff7732dd0 
eflags   0x202 [ IF ] 
cs    0x33 51 
ss    0x2b 43 
ds    0x0 0 
es    0x0 0 
fs    0x0 0 
gs    0x0 0 

Trong khi tôi hiểu được cho rax, rcx vv, GDB là chuyển đổi các giá trị để thập phân cho cột thứ hai, điều này dường như không nhất quán. Một số thanh ghi, cụ thể là rsprip hiển thị cùng một giá trị trong hex, ngay cả trong cột thứ hai. Mặt khác, eflags hiển thị các cờ trong cột thứ hai.

Lý do mà gdb thực hiện điều này là gì? Nếu nó sẽ hiển thị cùng một thông tin (trong trường hợp của rsprip), không phải là nó dư thừa? Ngoài ra, làm thế nào để khái quát hóa trên các kiến ​​trúc khác? (Đầu ra trên là dành cho x86-64).

Trả lời

4

Lệnh đăng ký thông tin in ra sổ đăng ký ở cả định dạng thô (hex) và định dạng tự nhiên.

Định dạng tự nhiên dựa trên loại sổ đăng ký, được khai báo trong tệp xml trong mã nguồn của gdb. Ví dụ, i386/64bit-core.xml chứa:

<reg name="rax" bitsize="64" type="int64"/> 
<reg name="rbx" bitsize="64" type="int64"/> 
<reg name="rcx" bitsize="64" type="int64"/> 
<reg name="rdx" bitsize="64" type="int64"/> 
<reg name="rsi" bitsize="64" type="int64"/> 
<reg name="rdi" bitsize="64" type="int64"/> 
<reg name="rbp" bitsize="64" type="data_ptr"/> 
<reg name="rsp" bitsize="64" type="data_ptr"/> 
<reg name="r8" bitsize="64" type="int64"/> 
<reg name="r9" bitsize="64" type="int64"/> 
<reg name="r10" bitsize="64" type="int64"/> 
<reg name="r11" bitsize="64" type="int64"/> 
<reg name="r12" bitsize="64" type="int64"/> 
<reg name="r13" bitsize="64" type="int64"/> 
<reg name="r14" bitsize="64" type="int64"/> 
<reg name="r15" bitsize="64" type="int64"/> 

<reg name="rip" bitsize="64" type="code_ptr"/> 
<reg name="eflags" bitsize="32" type="i386_eflags"/> 
<reg name="cs" bitsize="32" type="int32"/> 
<reg name="ss" bitsize="32" type="int32"/> 
<reg name="ds" bitsize="32" type="int32"/> 
<reg name="es" bitsize="32" type="int32"/> 
<reg name="fs" bitsize="32" type="int32"/> 
<reg name="gs" bitsize="32" type="int32"/> 

Bạn có thể thấy rằng các thanh ghi với type="int64"type="int32" được hiển thị như giá trị thập phân trong kết quả tự nhiên của chúng, vì chúng là đăng ký mục đích bình thường nói chung và có thể được sử dụng cho cả tham khảo bộ nhớ và gán giá trị.

Khi thanh ghi có type="data_ptr"type="code_ptr" có giá trị thập lục phân ở định dạng tự nhiên, vì chúng thường được sử dụng để tham chiếu địa chỉ bộ nhớ.

Đối với thanh ghi có type="i386_eflags" xuất ra cờ được đặt 'true', vì đối với thanh ghi này, đối với con người, điều đó có ý nghĩa hơn khi biết cờ nào được đặt 'Đúng' chứ không phải giá trị hex.

Đối với kiến ​​trúc khác, nó phụ thuộc vào cách các loại đăng ký được xác định trong mã nguồn của chúng. Bạn có thể nhìn vào mã nguồn của ARM, ARM-64, x86-32bit và nhiều người khác tại binutils-gdb/gdb/features/


EDIT:

Nguồn: @MarkPlotnick câu trả lời tại Why is "info register ebp" in gdb not displaying a decimal number? và trả lời @perror tại https://reverseengineering.stackexchange.com/questions/9221/output-of-gdb-info-registers/9222#9222.

Xin lỗi tôi quên đề cập đến nguồn.

+0

Tôi sẽ gọi đạo văn này ... khi bạn đặt câu hỏi [tại đây] (http://reverseengineering.stackexchange.com/questions/9221/output-of-gdb-info-registers) và bạn đã sao chép phần lớn câu trả lời của tôi ở đây mà không trích dẫn nguồn của bạn đúng ... Tôi mạnh mẽ không chấp nhận cách này! – perror

+0

@perror ở đó tôi đã đề cập đến câu hỏi này. Ngoài ra tôi đã thay đổi câu trả lời của tôi loại bỏ một phần của câu trả lời của bạn. –

0

Trong thực tế, trong lắp ráp, bạn có thể tìm thấy chỉ có ba loại giá trị:

  1. giá trị bằng số;
  2. Địa chỉ bộ nhớ;
  3. Hướng dẫn (mã).

thanh ghi mục đích chung, chẳng hạn như rax, rbx ..., được sử dụng để lưu trữ một trong hai giá trị số (sẽ kích hoạt hành vi của chương trình) hoặc địa chỉ bộ nhớ (để biết được nơi để đọc/ghi hoặc nhảy).Tất nhiên, vì hầu hết con người được sử dụng để định dạng thập phân cho các giá trị được sử dụng trong các chương trình, điều quan trọng là phải hiển thị định dạng thập phân khi thanh ghi có thể chứa các giá trị như vậy.

Bây giờ, điều quan trọng là phải biết rằng địa chỉ bộ nhớ thường được cung cấp ở định dạng thập lục phân (chủ yếu vì lý do nén). Và, mục đích chung đăng ký cũng có thể chứa địa chỉ bộ nhớ. Đó là lý do tại sao gdb hiển thị cả hai định dạng thập phân và thập lục phân chỉ trong trường hợp một hoặc khác là thích hợp nhất cho giá trị hiện tại.

Các thanh ghi rsp, rip (và rbp) là trường hợp đặc biệt vì họ được đặc biệt dùng để lưu trữ các địa chỉ (và chỉ này), do đó nó sẽ được sử dụng không để dịch nội dung của thanh ghi đó sang định dạng số thập phân. Đó là lý do tại sao gdb chỉ đưa ra một định dạng thập lục phân cho những thanh ghi này.

Cuối cùng, trường hợp của rflags/eflags là một chút đặc biệt vì thanh ghi này có nghĩa là phụ thuộc bit-bit (xem hình sau).

EFLAGS bit-per-bit details

Do đó, đưa ra các định dạng thập phân, thập lục phân hoặc nhị phân là không thực sự hữu ích cho người sử dụng (trừ khi bạn có thể liên hệ số điện thoại để những lá cờ ngay lập tức). Tuy nhiên, sẽ hữu ích hơn nếu bạn cung cấp danh sách các cờ được đặt là 'true' (đây là số [ IF ] mà bạn thấy trong ví dụ của mình). Tuy nhiên, gdb cho giá trị thập lục phân của eflags vì nó có thể được truy cập và được sử dụng như một giá trị trong các chương trình (tôi đã thấy điều này cho mục đích obfuscation).

Các vấn đề liên quan