2015-06-24 15 views
5

Po uruchomieniu info registers w gdb, możemy uzyskać wynik podobny do następującego:GDB informacji rejestruje polecenia - druga kolumna wyjścia

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 

Choć rozumiem for rax, rcx etc, GDB jest przeliczania wartości do dziesiętnego dla drugiej kolumny, nie wydaje się to spójne. Niektóre rejestry, a mianowicie rsp i rip, pokazują tę samą wartość w heksie, nawet w drugiej kolumnie. eflags z drugiej strony pokazuje flagi w drugiej kolumnie.

Jaki jest powód, dla którego gdb to robi? Jeśli ma wyświetlać te same informacje (w przypadku rsp i rip), czy nie jest to zbędne? A jak to się uogólnia na innych architekturach? (Powyższe wyjście jest dla x86-64).

Odpowiedz

4

Polecenie info register służy do wypisywania rejestrów zarówno w formacie raw (hex), jak i naturalnym.

Format naturalny jest oparty na typie rejestru zadeklarowanego w plikach xml w kodzie źródłowym gdb. Na przykład, i386/64bit-core.xml zawiera:

<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"/> 

Widać, że rejestry z type="int64" i type="int32" są wyświetlane jako wartości dziesiętnych w ich naturalnym wyjściem, ponieważ są one rejestr normalnie ogólnego przeznaczenia i może być używany zarówno odwołującego pamięci i przypisywanie wartość.

Podczas gdy rejestry z type="data_ptr" i type="code_ptr" mają wartości szesnastkowe w ich naturalnym formacie, ponieważ są zwykle używane do adresowania adresu pamięci.

Dla rejestrów z type="i386_eflags" wyprowadza flagę, która jest ustawiona na "true", ponieważ dla tego rejestru, dla ludzi ma to więcej sensu, gdy wiadomo, która flaga ma ustawioną wartość "True", a nie wartości heksadecymalne.

Dla innych architektur zależy to od sposobu zdefiniowania typów rejestrów w ich kodzie źródłowym. Możesz zajrzeć na kodzie źródłowym ARM, ARM-64, x86-32bit i wiele innych w binutils-gdb/gdb/features/


EDIT:

Źródło: @MarkPlotnick odpowiedź na Why is "info register ebp" in gdb not displaying a decimal number? i @perror odpowiedź na https://reverseengineering.stackexchange.com/questions/9221/output-of-gdb-info-registers/9222#9222.

Przepraszam, że zapomniałem wspomnieć o źródle.

+0

Nazwałbym ten plagiat ... gdy zadałeś pytanie [tutaj] (http://reverseengineering.stackexchange.com/questions/9221/output-of-gdb-info-registers) i skopiowałeś duże części moja odpowiedź tutaj bez zacytowania twoich źródeł ... Mocno potępiam ten sposób robienia! – perror

+0

@perror tam i odniosłem się do tego pytania. Zmieniłem też moją odpowiedź, usuwając część twojej odpowiedzi. –

0

W rzeczywistości, w zespole można znaleźć tylko trzy rodzaje wartości:

  1. wartości liczbowych;
  2. Adresy pamięci;
  3. Instrukcje (opcodes).

rejestrów ogólnego przeznaczenia, takich jak rax, rbx, ..., służą do przechowywania zarówno wartości liczbowe (który wywoła zachowanie programu) lub adresy pamięci (aby wiedzieć, gdzie do odczytu/zapisu lub do skok).

Oczywiście, ponieważ większość ludzi jest używana do formatu dziesiętnego dla wartości używanych w programach, ważne jest, aby wyświetlać format dziesiętny, gdy rejestr może zawierać takie wartości.

Teraz ważne jest, aby wiedzieć, że adresy pamięci są zwykle podawane w formacie szesnastkowym (głównie ze względu na zwartość). Rejestry ogólnego przeznaczenia mogą również zawierać adresy pamięci. Z tego powodu gdb wyświetla zarówno format dziesiętny, jak i szesnastkowy, na wypadek gdyby jeden lub drugi był najlepiej dostosowany do bieżącej wartości.

Rejestry rsp, rip (i rbp) to przypadki szczególne, ponieważ są one wykorzystywane specjalnie do przechowywania adresów (i tylko to), co byłoby bezużyteczne tłumaczyć treści takich rejestrów w formacie dziesiętnym. Z tego powodu gdb podaje tylko te formaty w formacie szesnastkowym.

Wreszcie przypadek rflags/eflags jest nieco wyjątkowy, ponieważ ten rejestr ma znaczenie zależne od bitów (patrz poniższy rysunek).

EFLAGS bit-per-bit details

Dlatego podając format dziesiętny, szesnastkowy lub binarny nie jest bardzo przydatne dla użytkownika (z wyjątkiem jeśli można odnosić numery do flag od razu). Ale znacznie lepiej jest podać listę flag, które są ustawione jako "true" (jest to [ IF ], które widzisz w twoim przykładzie). Jednak gdb podaje wartość szesnastkową parametru eflags, ponieważ może być dostępna i używana jako wartość w programach (widziałem to w celu zaciemniania).

Powiązane problemy