ARM Exception Handling
Ten sam wyjątek strukturalnego obsługi mechanizm asynchroniczne wyjątki generowane sprzętu i synchroniczne wyjątków generowanych przez oprogramowanie korzysta z systemu Windows za pośrednictwem ARM.Programy obsługi wyjątków specyficzny dla języka są rozszerzający Windows wyjątek strukturalnego obsługi za pomocą funkcji pomocnika języka.Ten dokument zawiera informacje obsługi wyjątków w systemu Windows za pośrednictwem ARM, a pomocników język używany przez kod, który jest generowany przez MASM i kompilatora Visual C++.
Obsługa wyjątków ARM
Używa systemu Windows za pośrednictwem ARM rozwijają się kody do kontrolowania stosu unwinding podczas structured exception handling (SEH).Rozwijają się kody są sekwencję bajtów zapisanych w sekcji .xdata pliku wykonywalnego obrazu.Odzwierciedlać operację kodu prologu i epilogu funkcji w sposób ogólny, aby skutki prologu funkcji można cofnąć w ramach przygotowania do unwinding do wywołującej ramki stosu.
EABI ARM (interfejs binarne osadzonych aplikacji) określa modelu unwinding wyjątek, który używa rozwijają się kody, ale nie jest wystarczająca do SEH unwinding w systemie Windows, który musi obsługiwać asynchroniczne przypadki, w którym procesor jest w trakcie prologu i epilogu funkcji.Windows również obramowań unwinding kontroli na poziomie funkcji unwinding i unwinding zakres specyficzny dla języka, który jest unified w ARM EABI.Z tego powodu systemu Windows za pośrednictwem ARM określa więcej szczegółów dla unwinding danych i procedury.
Założenia
Obrazy wykonywalne dla systemu Windows w imieniu formatu przenośnego pliku wykonywalnego (PE).Aby uzyskać więcej informacji, zobacz PE firmy Microsoft i specyfikacji COFF.Informacje o obsługi wyjątków są przechowywane w sekcjach .pdata i .xdata obrazu.
Mechanizm obsługi wyjątków powoduje, że pewne założenia dotyczące kodu, który jest zgodna z ABI dla systemu Windows na ARM:
Gdy wystąpi wyjątek w treści funkcji, nie ma znaczenia, czy operacje prologu są cofnąć lub epilogu operacje są wykonywane w sposób do przodu.Obie powinny być takie same wyniki.
Prologues i epilogues zwykle dublowanego siebie.To może służyć do zmniejszyć rozmiar niezbędnych do zapisania unwinding metadanych.
Funkcje zwykle jest niewielka.Wiele optymalizacji są oparte na to wydajne pakowania danych.
Jeśli warunek jest umieszczany na epilogu, dotyczy ona tak samo każdą instrukcję w epilogu.
Jeśli wskaźnik stosu (SP) jest zapisywany w innym rejestru w prologu, który rejestru musi pozostać bez zmian w całej funkcji, tak, aby oryginalny SP może odzyskać w dowolnym momencie.
O ile PS jest zapisywany w rejestrze innego manipulowania wszystkie jego musi wystąpić ściśle prologu i epilogu.
Rozwijają się wszelkie ramki stosu, te operacje są wymagane do:
Dostosuj r13 (SP) przyrost 4 bajtów.
POP jedną lub więcej całkowitą rejestruje.
Co najmniej jeden VFP POP (wirtualny zmiennoprzecinkowa) rejestruje.
Kopiuj wartości rejestru dowolnego do r13 (SP).
Ładowanie SP ze stosu za pomocą małych operacji zmniejszenia końcowe.
Jeden z kilku typów ramki dobrze zdefiniowany analizy.
.PData rekordów
Uporządkowana tablicy elementów stałej długości opisującej każdy funkcję manipulowania stosu są rekordy .pdata PE format obrazu.Funkcje typu liść, które są funkcje, które nie wymagają innych funkcji, nie wymagają .pdata rekordów podczas ich nie jest modyfikowany stosu.(Oznacza to, że ich nie wymagają jeden z magazynów lokalnych i nie musisz zapisać lub przywracanie rejestruje trwałej.).Rekordy dla tych funkcji można pominąć z sekcji .pdata, aby zapisać miejsca.Operacji unwind z jednej z tych funkcji po prostu skopiować adres zwrotny z łącza zarejestrować (LR) do licznik programu (PC) do obiektu wywołującego.
Każdy rekord .pdata dla ARM jest 8 bajtów.Ogólny format rekordu umieszcza względnych adresów wirtualnych (RVA) rozpoczęcia funkcji w pierwszym word 32-bitowy, następuje drugi wyraz, który zawiera wskaźnik do bloku .xdata zmiennej długości lub spakowany wyraz opisujący sekwencję unwinding kanonicznej funkcji, jak pokazano w tej tabeli:
Przesunięcie słowa |
Bity |
Przeznaczenie |
---|---|---|
0 |
0-31 |
Function Start RVAjest RVA 32-bitowy rozpoczęcia funkcji.Jeśli funkcja zawiera kod przycisku suwaka, należy ustawić niski bit ten adres. |
1 |
0-1 |
Flagjest polem 2-bitowe wskazuje sposób interpretowania pozostałe 30 bitów drugi słowa .pdata.Jeśli Flag jest równa 0, a następnie pozostałe bity formularza Exception Information RVA (o małej dwa bity niejawnie 0).Jeśli Flag jest równa zero, a następnie pozostałe bity formularza Packed Unwind Data struktury. |
1 |
2-31 |
Exception Information RVAor Packed Unwind Data. Exception Information RVAjest to adres wyjątku zmiennej długości struktury informacje przechowywane w sekcji .xdata.Dane te muszą być 4-bajty wyrównane. Packed Unwind Dataskompresowany opis operacji jest wymagany do rozwijają się od funkcji, zakładając, że formy kanonicznej.W takim przypadku nie odnaleziono rekordu .xdata jest wymagany. |
Pakowane rozwijają się danych
Dla rozwijają się funkcje, których kolejne prologues i epilogues pakowane formy kanonicznej opisane poniżej, można danych.To eliminuje konieczność użycia rekordu .xdata i znacząco redukuje przestrzeń obowiązkowa rozwijają się danych.Canonical prologues i epilogues są przeznaczone do wspólnych wymagań prosty funkcję, która nie wymaga program obsługi wyjątku, a następnie wykonuje jego operacje, konfigurowanie i usuwanie w standardowej kolejności.
W poniższej tabeli przedstawiono format z .pdata rekord, który ma pakowane rozwijają się danych:
Przesunięcie słowa |
Bity |
Przeznaczenie |
---|---|---|
0 |
0-31 |
Function Start RVAjest RVA 32-bitowy rozpoczęcia funkcji.Jeśli funkcja zawiera kod przycisku suwaka, należy ustawić niski bit ten adres. |
1 |
0-1 |
Flagto pole 2-bitowe zawierającej następujące znaczenie:
|
1 |
2-12 |
Function Lengthto pole 11-bitowe udostępniający długość całej funkcji w bajtach podzielona przez 2.Funkcja jest większy niż 4 KB, zamiast tego należy wykorzystać rekord pełną .xdata. |
1 |
13-14 |
Retjest polem 2-bitowe, która wskazuje, jak funkcja zwraca:
|
1 |
15 |
Hto 1-bitowe flagę wskazującą, czy funkcja "homes" parametr całkowitą rejestruje (r0-r3), przesyłając przy uruchamianiu funkcji i zwalnia 16 bajtów stosu przed zwróceniem.(0 = nie we własnym rejestrów, 1 = rejestruje domu.) |
1 |
16-18 |
Regpole 3-bitowy wskazujący indeks ostatniego zapisaniu trwałej rejestru.Jeśli R bit ma wartość 0, a następnie tylko rejestruje całkowitą są zapisywane i są uznawane w zakresie rN r4, gdzie N jest równy 4 + Reg.Jeśli R bit ma wartość 1, a następnie tylko rejestruje zmiennoprzecinkowe są zapisywane i są uznawane w zakresie d8 — nazwa wyróżniająca, gdzie N jest równy 8 + Reg.Kombinacja specjalne R = 1 i Reg = 7 wskazuje, że rejestruje nie zostaną zapisane. |
1 |
19 |
Rto 1-bitowe flagę wskazującą, czy zapisane rejestruje trwałej całkowitą rejestrów (0) lub zmiennoprzecinkowych rejestrów (1).Jeśli R jest równa 1 oraz Reg pole jest ustawione na 7, nie rejestruje trwałej zostały przekazane. |
1 |
20 |
Lto 1-bitowe flagę wskazującą, czy funkcja zapisywania/przywracania LR, wraz z innych rejestrów wskazywanym przez Reg pola.(0 = nie Zapisz/restore, 1 = czy zapisać/przywrócić.) |
1 |
21 |
Cjest flagą 1-bitowy, która wskazuje, czy funkcja zawiera dodatkowe instrukcje, aby skonfigurować łańcucha ramki stosu szybkie chodzenie (1) lub nie (0).Jeśli ten bit jest ustawiony, r11 niejawnie dodawanej do listy rejestruje trwałej całkowitą zapisane.(Zobacz ograniczenia poniżej if C flaga jest wykorzystywana.) |
1 |
22-31 |
Stack Adjustjest polem 10-bitowe, która wskazuje liczbę bajtów stosu, które są przydzielane dla tej funkcji, podzielona przez 4.Jednak tylko wartości pomiędzy 0x000 0x3F3 może bezpośrednio zakodowany.Funkcje, które przydzielić więcej niż 4044 bajtów stosu, należy użyć rekordu pełną .xdata.Jeśli Stack Adjust pole jest 0x3F4 lub większego dolnego 4 bity mają specjalne znaczenie, a następnie:
|
Z powodu możliwych zwolnienia w powyższych kodowania następujące ograniczenia:
Jeśli C flaga jest ustawiona na wartość 1:
L Flaga musi również można ustawić 1, ponieważ łańcuch ramki wymagany zarówno r11 i LR.
R11 nie musi być uwzględniona w zestawie rejestrów opisanego przez Reg.To znaczy, jeśli są usuwane, r4 r11, Reg tylko powinna opisać r4 r10, C flaga oznacza r11.
Jeśli Ret pole jest ustawione na 0, L Flaga musi być równa 1.
Naruszenie ograniczenia te powoduje nieobsługiwany sekwencji.
Na potrzeby poniższego omówienia, pochodzących z dwóch pseudo-flagi Stack Adjust:
PFlub "prologu składanie" wskazuje, że Stack Adjust 0x3F4 lub większe i bit 2 jest ustawiona.
EFlub "epilogu składanie" wskazuje, że Stack Adjust 0x3F4 lub większych i bit 3 jest ustawiona.
Prologues dla funkcji kanonicznej może mieć maksymalnie 5 instrukcje (powiadomienia, że 3a i 3b wzajemnie się wykluczają):
Instrukcja |
Kod operacji przyjęto, że obecne jeśli: |
Rozmiar |
Kod operacji |
Rozwijają się kodów |
---|---|---|---|---|
1 |
H==1 |
16 |
push {r0-r3} |
04 |
2 |
C== 1 lub L== 1 lub R== 0 lub PF == 1 |
16/32 |
push {registers} |
80-BF/D0-DF/WE ED |
3a |
C== 1 i (L== 0 i R== 1 i PF == 0) |
16 |
mov r11,sp |
C0-CF/FB |
3b |
C== 1 i (L== 1 lub R== 0 lub PF == 1) |
32 |
add r11,sp,#xx |
FC |
4 |
R== 1 i Reg ! = 7 |
32 |
vpush {d8-dE} |
E0 E7 |
5 |
Stack Adjust! = 0 i PF== 0 |
16/32 |
sub sp,sp,#xx |
00-7F/E8 EB |
Zawsze występuje instrukcja 1 Jeśli H bit jest ustawiony na wartość 1.
Aby skonfigurować łańcuch ramkę, instrukcji 3a lub 3b znajduje się Jeśli C bit jest ustawiony.Jest 16-bitowe mov Jeśli nie rejestruje innych niż r11 i LR są usuwane; w przeciwnym razie jest 32-bitowa add.
Jeśli określono korekty złożone, instrukcji 5 to dostosowywanie jawnego stosu.
Instrukcje 2 do 4 są ustawione w zależności od tego, czy wypychania jest wymagany.Ta tabela zawiera podsumowanie rejestrów są zapisywane na podstawie C, L, R, i PF pól.W każdym przypadku N jest taki sam, Reg + 4, E jest równa Reg + 8, i S jest równa (~Stack Adjust) & 3.
C |
L |
R |
PF |
Rejestruje całkowitą przypisany |
Rejestruje VFP przypisany |
---|---|---|---|---|---|
0 |
0 |
0 |
0 |
R4-rN |
brak |
0 |
0 |
0 |
1 |
rS-rN |
brak |
0 |
0 |
1 |
0 |
brak |
D8 dE |
0 |
0 |
1 |
1 |
rS-r3 |
D8 dE |
0 |
1 |
0 |
0 |
R4-rN, LR |
brak |
0 |
1 |
0 |
1 |
rS-rN, LR |
brak |
0 |
1 |
1 |
0 |
LR |
D8 dE |
0 |
1 |
1 |
1 |
rS-r3, LR |
D8 dE |
1 |
0 |
0 |
0 |
R4-rN, r11 |
brak |
1 |
0 |
0 |
1 |
rS-rN, r11 |
brak |
1 |
0 |
1 |
0 |
R11 |
D8 dE |
1 |
0 |
1 |
1 |
rS-r3, r11 |
D8 dE |
1 |
1 |
0 |
0 |
R4-rN, r11, LR |
brak |
1 |
1 |
0 |
1 |
rS- rN, r11, LR |
brak |
1 |
1 |
1 |
0 |
R11, LR |
D8 dE |
1 |
1 |
1 |
1 |
rS-r3 r11, LR |
D8 dE |
Epilogues dla funkcji kanonicznej przypomnienia podobne formularza, ale odwrotnie i pewne dodatkowe opcje.Epilogu może mieć maksymalnie 5 instrukcje długie, a jego formularza jest ściśle określonej przez formularz prologu.
Instrukcja |
Kod operacji przyjęto, że obecne jeśli: |
Rozmiar |
Kod operacji |
---|---|---|---|
6 |
Stack Adjust! = 0 i EF== 0 |
16/32 |
add sp,sp,#xx |
7 |
R== 1 i Reg ! = 7 |
32 |
vpop {d8-dE} |
8 |
C==1 or (L==1 and H==0) or R==0 or EF==1 |
16/32 |
pop {registers} |
9a |
H== 1 i L== 0 |
16 |
add sp,sp,#0x10 |
9b |
H== 1 i L== 1 |
32 |
ldr pc,[sp],#0x14 |
10a |
Ret==1 |
16 |
bx reg |
10b |
Ret==2 |
32 |
b address |
Instrukcja 6 to dostosowanie jawnego stosu, jeśli określono korekty złożone.Ponieważ PF jest niezależny od EF, istnieje możliwość instrukcji 5 obecny bez instrukcji 6 lub na odwrót.
Instrukcje 7 i 8 użyć tej samej logiki jako prologu do określenia, który rejestruje zostaną przywrócone ze stosu, ale z tych dwóch zmienia: pierwszy, EF jest używana zamiast właściwości PF; Jeśli drugi, Ret = 0, a następnie LR zostanie zastąpiony PC na liście rejestru i epilogu kończy się natychmiast.
Jeśli H jest ustawiona, a następnie instrukcji 9a lub 9b znajduje się.Instrukcja 9a jest używany podczas L ma wartość 0, aby wskazać, że LR nie znajduje się na stosie.W takim przypadku ręcznie jest dostosowywany stosu i Ret musi wynosić 1 lub 2, aby określić jawnego zwrotu.Instrukcja 9b jest używany podczas L wynosi 1, wskazania wczesnym zakończenie epilogu oraz do zwrócenia i Dostosuj stosu w tym samym czasie.
Jeśli epilogu nie została już zakończona, następnie albo instrukcji 10a lub 10b znajduje się, aby wskazać gałąź 16-bitowe i 32-bitowe, na podstawie wartości z Ret.
.xdata rekordów
Jeśli format spakowany unwind jest niewystarczająca do opisywania unwinding funkcji, zostać utworzony rekord .xdata zmiennej długości.Adres tego rekordu jest przechowywany w drugi wyraz rekordu .pdata.Format .xdata jest spakowany zmiennej długości zbiór słów, które ma cztery sekcje:
Nagłówek 1 lub 2 word opisuje całkowity rozmiar struktury .xdata, który dostarcza dane kluczowych funkcji.Drugie słowo jest obecnie tylko, jeśli Epilogue Count i Code Words pola są ustawione na 0.Pola są dzielone w tej tabeli:
Word
Bity
Przeznaczenie
0
0-17
Function Lengthto pole 18-bitowe wskazującą łączny czas funkcji w bajtach, podzielona przez 2.Jeśli funkcja jest większy niż 512 KB, to wielu rekordów .pdata i .xdata musi być używane do opisywania funkcji.Aby uzyskać szczegółowe informacje Zobacz sekcję długie funkcje, w tym dokumencie.
0
18-19
Versto pole 2-bitową, do którego odnosi się do wersji pozostałe xdata.Aktualnie zdefiniowano wersji 0; wartości 1-3 są zastrzeżone.
0
20
Xto pole 1-bitowe wskazującą (1) obecności lub braku (0) wyjątku.
0
21
Ejest 1-bitowe pole, wskazującą, czy informacje opisujące pojedynczy epilogu są pakowane w nagłówku (1), a nie wymaga dodatkowych zakres później słów (0).
0
22
Fto pole 1-bitowe wskazującą, czy ten rekord opisuje fragmentu funkcji (1) lub pełne funkcji (0).Fragment oznacza, że nie istnieje żadne prologu i przetwarzania prologu mają być ignorowane.
0
23-27
Epilogue CountPole 5-bitowe zawierającej dwie znaczenie, w zależności od stanu jest E bitowe:
Jeśli E wynosi 0, to pole jest liczba całkowita liczba zakresów wyjątek opisane w sekcji 3.Jeśli istnieje więcej niż 31 zakresów w funkcji, a następnie to pole i Code Words pole musi być wartości 0, aby wskazać, że word rozszerzenie jest wymagany.
Jeśli E wynosi 1, to pole określa indeks pierwszego kodu unwind opisujący tylko epilogu.
0
28-31
Code Wordspole 4-bitowy określająca liczbę wyrazów 32-bitowy jest wymagany do przechowywania wszystkich kodów unwind w sekcji 4.Jeśli więcej niż 15 wyrazy są wymagane do więcej niż 63 unwind bajtów kodu, to pole i Epilogue Count pole musi być wartości 0, aby wskazać, że word rozszerzenie jest wymagany.
1
0-15
Extended Epilogue Countto pole 16-bitowe, który zapewnia więcej miejsca do kodowania niezwykle dużą liczbę epilogues.Słowo rozszerzenia, które zawiera to pole jest obecnie tylko, jeśli Epilogue Count i Code Words pól w pierwszym słowem nagłówka są ustawione na 0.
1
16-23
Extended Code Wordsto pole 8-bitowe oferująca więcej miejsca do kodowania niezwykle dużą liczbę unwind wyrazów.Słowo rozszerzenia, które zawiera to pole jest obecnie tylko, jeśli Epilogue Count i Code Words pól w pierwszym słowem nagłówka są ustawione na 0.
1
24-31
Zastrzeżone
Po danych wyjątku — Jeśli E bit w nagłówku został ustawiony na wartość 0 — znajduje się lista informacji na temat zakresów epilogu, które są pakowane je, aby słowo i przechowywane w kolejności rosnącej początkowe przesunięcie.Każdy zakres zawiera następujące pola:
Bity
Przeznaczenie
0-17
Epilogue Start Offsetto pole 18-bitowe opisujący przesunięcie epilogu, w bajtach podzielona przez 2 względem początek funkcji.
18-19
Res2-bitowe pole jest zarezerwowane dla przyszłego rozszerzenia.Jego wartość musi być równa 0.
20-23
Conditionto pole 4-bitowe określające warunek, pod którym jest wykonywany epilogu.Dla epilogues bezwarunkowe go należy ustawić wartość 0xE, która oznacza "always".(Epilogu musi być całkowicie warunkowych lub bezwarunkowych całkowicie, a w trybie 2 przycisku suwaka epilogu zaczyna się od pierwszej instrukcji po kod operacji IT).
24-31
Epilogue Start Indexto pole 8-bitowy wskazujący indeks pierwszego kodu unwind opisujący ten epilogu bajtów.
Po liście epilogu zakresy powróci do tablicę bajtów, które zawierają kody unwind, których opisano szczegółowo w sekcji kodów rozwijają się w tym artykule.Ta tablica jest uzupełniana na końcu do najbliższej granicy pełnego wyrazu.Bajty są przechowywane w kolejności małoendiański tak, aby mogą być bezpośrednio pobierane w trybie małoendiański.
Jeśli X polu nagłówka wynosi 1, bajtów kodu unwind następują informacji obsługi wyjątków.Składa się z jednego Exception Handler RVA zawiera adres obsługi wyjątków, bezpośrednio po (zmiennej długości) ilość danych wymaganych przez program obsługi wyjątku.
Rekord .xdata zaprojektowano tak, aby można pobrać pierwsze 8 bajtów i obliczyć pełnego rozmiaru rekordu, z wyłączeniem długość danych o rozmiarze zmienna wyjątek, zgodną z.Ten fragment kodu oblicza rozmiar rekordu:
ULONG ComputeXdataSize(PULONG *Xdata)
{
ULONG EpilogueScopes;
ULONG Size;
ULONG UnwindWords;
if ((Xdata[0] >> 23) != 0) {
Size = 4;
EpilogueScopes = (Xdata[0] >> 23) & 0x1f;
UnwindWords = (Xdata[0] >> 28) & 0x0f;
} else {
Size = 8;
EpilogueScopes = Xdata[1] & 0xffff;
UnwindWords = (Xdata[1] >> 16) & 0xff;
}
if (!(Xdata[0] & (1 << 21))) {
Size += 4 * EpilogueScopes;
}
Size += 4 * UnwindWords;
if (Xdata[0] & (1 << 20)) {
Size += 4;
}
return Size;
}
Athough prologu i epilogu każdego ma indeks na kody unwind, tabeli jest udostępniana między nimi.Nie jest niezwykłym, że wszystkie udostępniają te same kody unwind.Zaleca się, że twórcom kompilatorów Optymalizacja pod kątem tym przypadku ponieważ największego indeksu, który może być określony wynosi 255 i, która ogranicza całkowitą liczbę kodów unwind możliwe dla danej funkcji.
Rozwijają się kodów
Tablica kody unwind jest pulą sekwencji instrukcji, opisujące dokładnie cofnąć skutki prologu, w kolejności, w którym musi być cofnąć operacji.Kody unwind to zestaw instrukcji podręczny zakodowane jako ciąg bajtów.Po zakończeniu wykonywania jest adres zwrotny do funkcji wywołującej w rejestrze LR, a wszystkie rejestry trwałej zostaną przywrócone do wartości w momencie, gdy została wywołana funkcja.
Jeśli wyjątki zostały gwarantowana tylko pojawiający się w treści funkcji i nie wolno w prologu i epilogu, następnie tylko jeden rozwijają się sekwencji byłoby.Jednak modelu unwinding systemu Windows wymaga możliwość rozwijają się od prologu częściowo wykonane lub epilogu.Aby spełnić to wymaganie, kody unwind zaplanowano dokładnie tak, aby mieć jednoznaczne mapowanie jeden do jednego do każdego odpowiedniego kodu w prologu i epilogu.Ma to wpływ kilka:
Istnieje możliwość do obliczenia długości prologu i epilogu liczbą kodów unwind.Jest to możliwe nawet w przypadku zmiennej długości instrukcje przycisku suwaka 2, ponieważ istnieją różne mapowania dla używa 16-bitowe i 32-bitowych.
Obliczając, ile instrukcji po uruchomieniu zakresu epilogu, istnieje możliwość pominąć równoważne liczbę kodów unwind i wykonania pozostałych sekwencji do ukończenia częściowo wykonać rozwijają się rejestrowano epilogu.
Obliczając, ile instrukcji przed upływem prologu, to można pominąć równoważne liczbę kodów unwind i wykonaj pozostałe sekwencji cofnąć tylko te prologu istotnych częściach po wykonaniu.
Poniższa tabela zawiera mapowanie kodów unwind kodów operacji.Najbardziej typowe kody są tylko jednego bajtu, a mniej typowe takich, które wymagają dwóch, trzech lub nawet czterech bajtów.Każdy kod jest przechowywany z najbardziej znaczące bajty do najmniej znaczące bajty.Struktura kodu unwind różni się od kodowanie opisane w ARM EABI, ponieważ te kody unwind mają na celu ma jeden mapowania do używa w prologu i epilogu mają być dozwolone podczas unwinding z częściowo wykonane prologues i epilogues.
Bajty 1 |
Bajty 2 |
Bajty 3 |
Bajty 4 |
Opsize |
Wyjaśnienie |
---|---|---|---|---|---|
00 7F |
16 |
add sp,sp,#X gdzie X jest (kod i 0x7F) * 4 |
|||
80 BF |
00-FF |
32 |
pop {r0-r12, lr} gdzie jest tam pojawi LR, jeśli kod & 0x2000 i r0 r12 są tam pojawi Jeśli odpowiadający mu bit jest ustawiana w & 0x1FFF kodu |
||
C0 CF |
16 |
mov sp,rX gdzie X jest 0x0F & kodu |
|||
D0 D7 |
16 |
pop {r4-rX,lr} gdzie X jest (kod i 0x03) + 4 i LR jest tam pojawi Jeśli 0x04 & kodu |
|||
D8 DF |
32 |
pop {r4-rX,lr} gdzie X jest (kod i 0x03) + 8 i LR jest tam pojawi Jeśli 0x04 & kodu |
|||
E0 E7 |
32 |
vpop {d8-dX} gdzie X jest (kod i 0x07) + 8 |
|||
E8 EB |
00-FF |
32 |
addw sp,sp,#X gdzie X jest (kod i 0x03FF) * 4 |
||
WE ED |
00-FF |
16 |
pop {r0-r7,lr} gdzie jest tam pojawi LR, jeśli kod & 0x0100 i r0 r7 są tam pojawi Jeśli odpowiadający mu bit jest ustawiana w & 0x00FF kodu |
||
EE |
00 0F |
16 |
specyficzne dla firmy Microsoft |
||
EE |
10-FF |
16 |
Dostępne |
||
EF |
00 0F |
32 |
ldr lr,[sp],#X gdzie X jest (kod i 0x000F) * 4 |
||
EF |
10-FF |
32 |
Dostępne |
||
F0 F4 |
- |
Dostępne |
|||
F5 |
00-FF |
32 |
vpop {dS-dE} gdzie jest (kod i 0x00F0) >> 4 i E jest 0x000F & kodu |
||
F6 |
00-FF |
32 |
vpop {dS-dE} gdzie jest ((Code & 0x00F0) >> 4) + 16 i E jest (kod i 0x000F) + 16 |
||
F7 |
00-FF |
00-FF |
16 |
add sp,sp,#X gdzie X jest (kod i 0x00FFFF) * 4 |
|
F8 |
00-FF |
00-FF |
00-FF |
16 |
add sp,sp,#X gdzie X jest (kod i 0x00FFFFFF) * 4 |
F9 |
00-FF |
00-FF |
32 |
add sp,sp,#X gdzie X jest (kod i 0x00FFFF) * 4 |
|
ŚRODKÓW TRWAŁYCH |
00-FF |
00-FF |
00-FF |
32 |
add sp,sp,#X gdzie X jest (kod i 0x00FFFFFF) * 4 |
FB |
16 |
NOP (16-bitowe) |
|||
FC |
32 |
NOP (32-bitowe) |
|||
DEMON FILTRU |
16 |
End + nop 16-bitowe w epilogu |
|||
FE |
32 |
End + nop 32-bitowe w epilogu |
|||
FF |
- |
end |
Ten element pokazuje zakres wartości szesnastkowych dla każdego bajtu kod unwind Code, wraz z rozmiarem kod operacji Opsize i odpowiadający mu oryginalny interpretacji instrukcji.Puste komórki wskazują mniej kody unwind.W instrukcji, które mają duże wartości obejmujące wiele bajtów najpierw są przechowywane najbardziej znaczących bitów.Opsize Pole zawiera rozmiar niejawne kod operacji skojarzony z każdej operacji 2 przycisku suwaka.Jawnego zduplikowanych wpisów w tabeli o różnych kodowania są używane do rozróżniania wielkości kod innej operacji.
Kody unwind zaprojektowano tak, aby pierwszego bajtu kodu informuje zarówno całkowity rozmiar w bajtach kodu i rozmiar odpowiedni kod operacji w strumieniu instrukcji.Do obliczenia rozmiaru prologu i epilogu, zapoznaj się z kodów unwind od początku sekwencji na końcu i umożliwia określenie, jak długo jest odpowiedni kod operacji do tabeli odnośników lub podobnego metody.
Rozwijają się kody 0xFD i 0xFE są równoważne kod zakończenia regularne 0xFF, ale konto dla jednego kodu nop dodatkowe w przypadku epilogu, 16-bitowe i 32-bitowych.Prologues 0xFD, 0xFE i 0xFF są równoważne.This accounts for the common epilogue endings bx lr or b <tailcall-target>, which don’t have an equivalent prologue instruction.Ta zwiększa, które rozwijają się sekwencje szanse może być współużytkowane między prologu i epilogues.
W wielu przypadkach powinno być możliwe używają tego samego zbioru kodów unwind prologu i wszystkie epilogues.Na potrzeby obsługi unwinding częściowo wykonane prologues i epilogues, może mieć ma wiele unwind sekwencji kodu, które różnią się w kolejności lub jego działania.Jest to, dlaczego każdego epilogu ma własny indeks w tablicy unwind wyświetlanych, gdzie można rozpocząć wykonywania.
Unwinding Prologues częściowe i Epilogues
Najbardziej typowe przypadku unwinding jest w przypadku wystąpienia wyjątku w treści funkcji, prologu i wszystkie epilogues.W takim przypadku unwinder wykonuje kody na początku tablicy unwind pod indeksem 0 i będzie nadal występował, dopóki nie zostanie wykryty kod zakończenia operacji.
Gdy wystąpi wyjątek podczas prologu lub wykonywania epilogu, ramki stosu jedynie częściowo jest tworzony i unwinder należy określić dokładnie co zostało wykonane aby można było ją poprawnie cofnąć.
Na przykład należy wziąć pod uwagę tej sekwencji prologu i epilogu:
0000: push {r0-r3} ; 0x04
0002: push {r4-r9, lr} ; 0xdd
0006: mov r7, sp ; 0xc7
...
0140: mov sp, r7 ; 0xc7
0142: pop {r4-r9, lr} ; 0xdd
0146: add sp, sp, #16 ; 0x04
0148: bx lr
Obok każdego kodu jest unwind odpowiedni kod do opisu tej operacji.Sekwencja kodów unwind prologu jest odbicie lustrzane kody unwind epilogu, z pominięciem końcowego instrukcji.Ta sprawa jest wspólne i przyczyny, dla której kody unwind prologu zawsze przyjmuje, że są przechowywane w odwrotnej kolejności z prologu kolejność wykonywania.Daje wspólny zestaw kodów unwind:
0xc7, 0xdd, 0x04, 0xfd
Kod 0xFD jest specjalny kod na końcu sekwencji, która oznacza, że epilogu jest dłuższy niż prologu jednej instrukcji 16-bitowe.Umożliwia udostępnianie większej unwind kodów.
W tym przykładzie Jeśli wystąpi wyjątek podczas wykonywania funkcji treści między prologu i epilogu, unwinding rozpoczyna się epilogu sprawa, przy przesunięciu 0 z kodem epilogu.Odpowiada to przesunięcie 0x140 w przykładzie.Unwinder wykonuje pełną unwind sekwencji, ponieważ nie oczyszczanie nie została wykonana.W przypadku zamiast tego wyjątku jednej instrukcji po rozpoczęciu kodu epilogu unwinder może pomyślnie rozwijają się przez pominięcie pierwszy kod unwind.Podane mapowanie jeden do jednego między używa i rozwijają się kody, jeśli unwinding z instrukcji n w epilogu unwinder powinien pominąć pierwszy n rozwijają się kody.
Działa podobnie logiki odwrotnie dla prologu.Jeśli unwinding się od przesunięcia 0 w prologu, nic nie ma do wykonania.Jeśli unwinding z jednej instrukcji w, sekwencja unwind należy uruchomić jeden kod unwind od końca, ponieważ prologu unwind kody są przechowywane w odwrotnej kolejności.W przypadku ogólnym, jeśli unwinding z instrukcji n w prologu, unwinding należy rozpocząć wykonywania na n rozwijają się kody od końca listę kodów.
Kody unwind prologu i epilogu nie zawsze jest zgodna dokładnie.W takim przypadku tablicy kodu unwind może musi zawierać kilka sekwencji kodów.Aby określić przesunięcie rozpoczęcie przetwarzania kody, należy użyć tę logikę:
Jeśli unwinding z w treści funkcji, Rozpocznij wykonywanie kody unwind pod indeksem 0 i przejdź do chwili osiągnięcia kod zakończenia operacji.
Jeśli unwinding z w ramach epilogu, należy użyć indeks początkowy określonych epilogu udostępnione przez zakres epilogu.Oblicza liczbę bajtów komputera jest od początku epilogu.Przejście do przodu za pomocą kodów unwind aż wszystkie już wykonane instrukcje stanowią.Wykonaj unwind sekwencji uruchamiania w tym momencie.
Jeżeli unwinding z w prologu, należy uruchomić z indeksu 0 w kodach unwind.Oblicz długość kodu prologu z sekwencji, a następnie obliczyć liczbę bajtów komputera od końca prologu.Przejście do przodu za pomocą kodów unwind aż wszystkie instrukcje cofnąć stanowią.Wykonaj unwind sekwencji uruchamiania w tym momencie.
Kody unwind prologu zawsze musi być pierwszym w tablicy.Są one również kody używany do rozwijają się w przypadku ogólne unwinding z w treści.Wszelkie sekwencje kodu określonych epilogu należy stosować się bezpośrednio po prologu sekwencji kodu.
Funkcja fragmenty
Dla optymalizacji kodu może to być przydatne dzielony funkcję na części nie sąsiadujących ze sobą.Gdy ta czynność jest wykonywana, każdy fragment funkcji wymaga własnej oddzielnych .pdata — i prawdopodobnie .xdata — rekordu.
Zakładając, że prologu funkcji na początku funkcji i nie można podzielić, istnieją cztery przypadków fragment funkcji:
Prologu. wszystkie epilogues w pozostałych fragmentów.
Prologu i co najmniej jeden epilogues; dodatkowe epilogues w pozostałych fragmentów.
Nie prologu lub epilogues; prologu i co najmniej jeden epilogues w pozostałych fragmentów.
Epilogues. prologu i prawdopodobnie dodatkowe epilogues w pozostałych fragmentów.
W przypadku pierwszego musi być opisany tylko prologu.Można to zrobić w formie compact .pdata normalnie opisujący prologu i określając Ret wartość 3, aby wskazać, nie epilogu.W formularzu pełną .xdata można to zrobić jak zwykle dostarczający kody unwind prologu pod indeksem 0 i określając epilogu liczba wynosi 0.
Drugim przypadku jest podobnie jak funkcja normalnego.Jeśli istnieje tylko jeden epilogu we fragmencie i jest na końcu fragment, następnie rekord compact .pdata może służyć.W przeciwnym razie należy użyć rekordu pełną .xdata.Należy pamiętać, będące przesunięcia określone dla początku epilogu względem początek fragmentu nie oryginalne rozpoczęcie funkcji.
Przypadków trzecim i czwartym są odpowiednio wariantów przypadków pierwszy i drugi, z wyjątkiem nie zawierają one prologu.W takim przypadku zakłada o kodzie przed rozpoczęciem epilogu i zostanie to uznane za część treści funkcję, która może być rozwiniętej zwykle cofając skutki prologu.Takich sytuacjach dlatego musi być zostały zakodowane za pomocą pseudo-prologu, która opisuje sposób rozwijają się od w treści, ale które ma być traktowane jako długość 0 podczas ustalania, czy należy przeprowadzić częściowego rozwijają się na początku fragmentu.Możesz też to pseudo-prologu mogą być opisane przy użyciu tych samych kodów unwind jako epilogu, ponieważ prawdopodobnie wykonują operacje równorzędne.
W przypadku trzecim i czwartym, obecności pseudo-prologu jest określona przez ustawienie Flag pola rekordu compact .pdata 2 lub przez ustawienie F flagi w nagłówku .xdata do 1.W obu przypadkach wyboru dla unwind prologu częściowe są ignorowane, a wszystkie bez epilogu unwinds są uważane za pełny.
Długie funkcje
Fragmenty może służyć do opisu większy niż 512 KB limitowi pól bitowych w nagłówku .xdata funkcji.Aby opisać bardzo dużych funkcji, po prostu podzielić je na fragmenty mniejszy niż 512 KB.Każdy fragment należy dostosować tak, aby nie dzieli epilogu na wielu części.
Tylko pierwszego fragmentu funkcji zawiera prologu; wszystkie inne fragmenty są oznaczone jako posiadające nie prologu.W zależności od liczby epilogues każdy fragment może zawierać zero lub więcej epilogues.Należy pamiętać, że każdy zakres epilogu w fragmentu określa jego początkowe przesunięcie względem początek fragmentu nie początek funkcji.
Jeśli fragmentu nie prologu i epilogu nie, nadal wymaga własnej .pdata — i prawdopodobnie .xdata — rekord celu opisania sposobu rozwijają się od w treści funkcji.
Shrink-wrapping
Jest bardziej złożonych specjalny przypadek fragmenty funkcji shrink-wrapping, technika odraczające rejestru zapisuje od początku funkcji do później w funkcji zoptymalizowane pod kątem proste przypadki, które nie wymagają zapisywania w rejestrze.Można to określić jako zewnętrzne region przydziela miejsce stosu, ale zapisuje minimalny zbiór rejestrów i wewnętrzny regionu, który zapisuje i przywraca dodatkowe rejestry.
ShrinkWrappedFunction
push {r4, lr} ; A: save minimal non-volatiles
sub sp, sp, #0x100 ; A: allocate all stack space up front
... ; A:
add r0, sp, #0xE4 ; A: prepare to do the inner save
stm r0, {r5-r11} ; A: save remaining non-volatiles
... ; B:
add r0, sp, #0xE4 ; B: prepare to do the inner restore
ldm r0, {r5-r11} ; B: restore remaining non-volatiles
... ; C:
pop {r4, pc} ; C:
Funkcje porządnie zapakowane zwykle powinny wstępnie przydzielić miejsca dla rejestru dodatkowe są zapisywane w regularnych prologu i wykonywać zapisywanie rejestru za pomocą str lub stm zamiast push.Pozwoli to na zachowanie wszystkich manipulowania wskaźnik stosu w prologu oryginalnego funkcji.
Funkcja porządnie zapakowane przykład musi podzielony na trzy regionach, które są oznaczone jako A, B i C w komentarzach.Najpierw region obejmuje początek funkcji do końca dodatkowe zapisuje trwałej.Rekord .pdata lub .xdata muszą być skonstruowane w celu opisania tym fragmencie jako posiadające prologu i nie epilogues.
Region środka B pobiera swój rekord .pdata lub .xdata opisujący fragmentu nie prologu i epilogu nie.Jednak nadal musi być obecny kody unwind dla tego obszaru, ponieważ uwzględniono treści funkcji.Kody musi zawierać opis prologu złożony, reprezentujący oryginalny rejestruje zapisane w prologu region A i dodatkowe rejestry zapisane przed wprowadzeniem regionu B, tak jakby były one utworzonej przez jedną sekwencję operacji.
Zapisuje rejestru dla regionu B nie mogą być uważane "prologu wewnętrznego", ponieważ złożony prologu opisane dla regionu B musi zawierać opis zarówno prologu region A i dodatkowe rejestry zapisane.Jeśli fragment B zostały opisane jako posiadające prologu, kody unwind również oznacza rozmiar tego prologu, a nie istnieje sposób opisujący złożony prologu w sposób umożliwiający mapuje jeden do jednego z kodów operacji, który tylko zapisać dodatkowe rejestry.
Zapisuje dodatkowe rejestru musi być uważane za część obszaru A, ponieważ dopóki nie zostaną one zakończone, złożony prologu niedokładnie opisuje stan stosu.
Ostatniego regionu C pobiera swój rekord .pdata lub .xdata, opisujący fragmentu, który ma nie prologu, a epilogu.
To może również działać, jeśli stosem wykonywane przed wprowadzeniem regionu B można zmniejszyć do jednej instrukcji:
ShrinkWrappedFunction
push {r4, lr} ; A: save minimal non-volatile registers
sub sp, sp, #0xE0 ; A: allocate minimal stack space up front
... ; A:
push {r4-r9} ; A: save remaining non-volatiles
... ; B:
pop {r4-r9} ; B: restore remaining non-volatiles
... ; C:
pop {r4, pc} ; C: restore non-volatile registers
W tym miejscu klucza jest w granicach każdej instrukcji, stosu w pełni zgodne z kodów unwind dla regionu.W przypadku unwind przed wewnętrzny wypychania w tym przykładzie zostanie to uznane za część obszaru A, a tylko obszar prologu jest oddzielić.W przypadku unwind po wewnętrzny wypychania jest uznawany za część obszaru B, który został nie prologu, ale ma unwind kodów, które opisują zarówno wewnętrzny wypychania, jak i pierwotny prologu z regionu A.Logika podobne odnosi się do wewnętrznego pop.
Kodowanie optymalizacji
Z powodu złożonością kodów unwind i wykorzystywanie CD oraz rozwiniętej formularzy danych istnieje wiele możliwości optymalizowania kodowanie, aby jeszcze bardziej ograniczyć miejsce.Z najwyższą użycie tych technik net przeciążenia opisujący funkcje i fragmenty za pomocą kodów unwind może być dosyć minimalne.
Najważniejsze optymalizacji ma na celu należy zachować ostrożność nie mylić prologu/epilogu granice do celów unwinding z logicznego prologu/epilogu granice z punktu widzenia kompilatora.Granice unwinding można zmniejszyć i wprowadzone większego w celu zwiększenia wydajności.Na przykład prologu może zawierać kod po sprawdza Instalatora stosu, aby wykonać dodatkowej weryfikacji.Jednak po ukończeniu wszystkich stosem, nie istnieje potrzeba do zakodowania dalszych czynności i niczego poza tym można usunąć z unwinding prologu.
Ta zasada dotyczy długość funkcji.Jeśli dane — na przykład literału pula — występujący epilogu w funkcji, nie należy dołączać jako część długość funkcji.Zmniejszając funkcji do właśnie kodu, który jest częścią funkcji, szanse jest większa konieczności epilogu na końcu i CD.można PData rekordu.
W prologu po zapisaniu wskaźnik stosu do innego rejestru jest zwykle niepotrzebna do rejestrowania wszelkich dalszych kodów operacji.Rozwijają się funkcja, najpierw, jaka została wykonana jest odzyskać SP z rejestru zapisanych, a więc dalszych operacji nie miały wpływu na unwind.
Epilogues pojedynczej instrukcji nie należy do zakodowania gwarancja jako zakresy lub jako rozwijają się kody.Jeśli unwind odbywa się przed wykonaniem tej instrukcji, następnie może być przyjmuje się z w treści funkcji, a po prostu wykonywania kody unwind prologu jest wystarczająca.Jeśli unwind odbywa się po wykonaniu pojedynczej instrukcji, następnie z definicji go odbywa się w innym regionie.
Epilogues wielu instrukcji nie należy do zakodowania pierwszy nauczania epilogu z tego samego powodu jako poprzedni punkt: Jeśli unwind jest wykonywana przed wykonaniem tej instrukcji, unwind pełną prologu jest wystarczająca.Jeśli unwind odbywa się po tej instrukcji, a następnie kolejne operacje powinny być traktowane.
Rozwijają się kod jest używany powinien być skuteczną.Określony indeks każdego punktami zakres epilogu do dowolnego punktu początkowego w tablicy unwind kodów.Nie ma wskaż polecenie uruchomienia poprzedniego sekwencji; może wskazywać na środku.W tym miejscu najlepiej do generowania sekwencji odpowiedni kod i następnie wyszukaj dopasowania dokładnego bajtów w tej puli już zakodowane w formacie sekwencji i używać dowolnego czego szukasz jako punkt początkowy do ponownego wykorzystywania.
W przypadku, po jednym instrukcji epilogues są ignorowane, nie epilogues pozostałe, warto rozważyć użycie formularza compact .pdata; staje się bardziej prawdopodobnie z powodu braku epilogu.
Przykłady
W tym przykładzie image base znajduje się 0x00400000.
Przykład 1: Funkcja liścia, nie zmienne lokalne
Prologue:
004535F8: B430 push {r4-r5}
Epilogue:
00453656: BC30 pop {r4-r5}
00453658: 4770 bx lr
.PData (stała, wyrazy 2):
Word 0
- Function Start RVA= 0x000535F8 (= 0x004535F8 — 0x00400000)
Word 1
Flag= 1 wskazujących canonical formaty prologu i epilogu
Function Length= 0x31 (= 0x62/2)
Ret= Zwraca 1 wskazujących gałąź 16-bitowe
H= 0, wskazującą parametry nie zostały podłączony.
R= 0 i Reg = 1 wskazujących wypychania/pop z r4 r5
L= 0, co oznacza nie LR Zapisz/przywracania
C= 0, co oznacza nie łańcuch ramki
Stack Adjust= 0, co oznacza nie dopasowania stos
Przykład 2: Funkcja zagnieżdżona z lokalnym alokacji
Prologue:
004533AC: B5F0 push {r4-r7, lr}
004533AE: B083 sub sp, sp, #0xC
Epilogue:
00453412: B003 add sp, sp, #0xC
00453414: BDF0 pop {r4-r7, pc}
.PData (stała, wyrazy 2):
Word 0
- Function Start RVA= 0x000533AC (= 0x004533AC — 0x00400000)
Word 1
Flag= 1 wskazujących canonical formaty prologu i epilogu
Function Length= 0x35 (= 0x6A/2)
Ret= 0, co oznacza pop {pc} zwrotny
H= 0, wskazującą parametry nie zostały podłączony.
R= 0 i Reg = 3, wskazującą wypychania/pop z r4 r7
L= 1, wskazując LR zostało zapisane/przywrócić
C= 0, co oznacza nie łańcuch ramki
Stack Adjust= 3 (= 0x0C/4)
Przykładzie 3: Funkcja Variadic zagnieżdżona
Prologue:
00453988: B40F push {r0-r3}
0045398A: B570 push {r4-r6, lr}
Epilogue:
004539D4: E8BD 4070 pop {r4-r6}
004539D8: F85D FB14 ldr pc, [sp], #0x14
.PData (stała, wyrazy 2):
Word 0
- Function Start RVA= 0x00053988 (= 0x00453988 — 0x00400000)
Word 1
Flag= 1 wskazujących canonical formaty prologu i epilogu
Function Length= 0x2A (= 0x54/2)
Ret= 0, co oznacza pop {pc} — styl zwrotu (w takim przypadku pc ldr, [sp], nr 0x14 powrót)
H= 1 wskazujących parametry zostały adresem IP.
R= 0 i Reg = 2, wskazującą wypychania/pop z r4 r6
L= 1, wskazując LR zostało zapisane/przywrócić
C= 0, co oznacza nie łańcuch ramki
Stack Adjust= 0, co oznacza nie dopasowania stos
Przykład 4: Funkcja z wielu Epilogues
Prologue:
004592F4: E92D 47F0 stmdb sp!, {r4-r10, lr}
004592F8: B086 sub sp, sp, #0x18
Epilogues:
00459316: B006 add sp, sp, #0x18
00459318: E8BD 87F0 ldm sp!, {r4-r10, pc}
...
0045943E: B006 add sp, sp, #0x18
00459440: E8BD 87F0 ldm sp!, {r4-r10, pc}
...
004595D4: B006 add sp, sp, #0x18
004595D6: E8BD 87F0 ldm sp!, {r4-r10, pc}
...
00459606: B006 add sp, sp, #0x18
00459608: E8BD 87F0 ldm sp!, {r4-r10, pc}
...
00459636: F028 FF0F bl KeBugCheckEx ; end of function
.PData (stała, wyrazy 2):
Word 0
- Function Start RVA= 0x000592F4 (= 0x004592F4 — 0x00400000)
Word 1
Flag= 0, wskazującą istniejącego rekordu .xdata (wymagane z powodu wielu epilogues)
.xdata address-0x00400000
.xdata (zmiennej, słów 6):
Word 0
Function Length= 0x0001A3 (= 0x000346/2)
Vers= 0, co oznacza pierwszą wersję xdata
X= 0, co oznacza brak danych wyjątku
E= 0, co oznacza listą zakresów epilogu
F= 0, co oznacza opis funkcji pełną, w tym prologu
Epilogue Count= 0x04 wskazujący 4 zakresy epilogu całkowita
Code Words= 0x01 wskazujący jedno słowo 32-bitowy unwind kodów
Słowa opisujące 4 epilogu zakresów w lokalizacjach 4 1-4.Każdy zakres ma wspólny zestaw kodów unwind, udostępniane prologu, offset 0x00 i bezwarunkowe określający warunek 0x0E (zawsze).
Rozwijają się kody, począwszy od 5 słowa: (udostępniane między prologu/epilogu)
Rozwijają się kod 0 = wartość 0x06: sp += (6 << 2)
Rozwijają się kod 1 = 0xDE: pop {r4 r10, lr}
Rozwijają się kod 2 = 0xFF: zakończenia
Przykład 5: Funkcja dynamiczne stosu i epilogu wewnętrzny
Prologue:
00485A20: B40F push {r0-r3}
00485A22: E92D 41F0 stmdb sp!, {r4-r8, lr}
00485A26: 466E mov r6, sp
00485A28: 0934 lsrs r4, r6, #4
00485A2A: 0124 lsls r4, r4, #4
00485A2C: 46A5 mov sp, r4
00485A2E: F2AD 2D90 subw sp, sp, #0x290
Epilogue:
00485BAC: 46B5 mov sp, r6
00485BAE: E8BD 41F0 ldm sp!, {r4-r8, lr}
00485BB2: B004 add sp, sp, #0x10
00485BB4: 4770 bx lr
...
00485E2A: F7FF BE7D b #0x485B28 ; end of function
.PData (stała, wyrazy 2):
Word 0
- Function Start RVA= 0x00085A20 (= 0x00485A20 — 0x00400000)
Word 1
Flag= 0, wskazującą istniejącego rekordu .xdata (niezbędne z powodu wielu epilogues)
.xdata address-0x00400000
.xdata (zmiennej, słów 3):
Word 0
Function Length= 0x0001A3 (= 0x000346/2)
Vers= 0, co oznacza pierwszą wersję xdata
X= 0, co oznacza brak danych wyjątku
E= 0, co oznacza listą zakresów epilogu
F= 0, co oznacza opis funkcji pełną, w tym prologu
Epilogue Count= 0x001 1 zakres epilogu całkowita wskazująca
Code Words= 0x01 wskazujący jedno słowo 32-bitowy unwind kodów
Word 1: Epilogu zakresu na przesunięcie 0xC6 (= 0x18C/2), rozpoczęcie unwind kodu indeksu na 0x00 oraz z jednym z warunków 0x0E (zawsze)
Rozwijają się kody, począwszy od 2 słowa: (udostępniane między prologu/epilogu)
Rozwijają się kod 0 = 0xC6: sp = r6
Rozwijają się kod 1 = 0xDC: pop {r4 r8, lr}
Rozwijają się kod 2 = 0x04: sp += (4 << 2)
Rozwijają się kod 3 = 0xFD: zakończenia, liczby jako 16-bitowe instrukcję epilogu
Przykład 6: Funkcja z obsługi wyjątków
Prologue:
00488C1C: 0059 A7ED dc.w 0x0059A7ED
00488C20: 005A 8ED0 dc.w 0x005A8ED0
FunctionStart:
00488C24: B590 push {r4, r7, lr}
00488C26: B085 sub sp, sp, #0x14
00488C28: 466F mov r7, sp
Epilogue:
00488C6C: 46BD mov sp, r7
00488C6E: B005 add sp, sp, #0x14
00488C70: BD90 pop {r4, r7, pc}
.PData (stała, wyrazy 2):
Word 0
- Function Start RVA= 0x00088C24 (= 0x00488C24 — 0x00400000)
Word 1
Flag= 0, wskazującą istniejącego rekordu .xdata (niezbędne z powodu wielu epilogues)
.xdata address-0x00400000
.xdata (zmiennej, słów 5):
Word 0
Function Length= 0x000027 (= 0x00004E/2)
Vers= 0, co oznacza pierwszą wersję xdata
X= 1 wskazujących obecny wyjątku
E= 1 wskazujących pojedynczy epilogu
F= 0, co oznacza opis funkcji pełną, w tym prologu
Epilogue Count= 0x00, wskazującą epilogu unwind kody start na przesunięcie 0x00
Code Words= 0x02 wskazujący dwa słowa 32-bitowy unwind kodów
Rozwijają się kody, począwszy od 1 do słowa:
Rozwijają się kod 0 = 0xC7: sp = r7
Rozwijają się kod 1 = 0x05: sp += (5 << (2).
Rozwijają się kod 2 = 0xED/0x90: pop {r4, r7, lr}
Rozwijają się kod 4 = 0xFF: zakończenia
Określa program obsługi wyjątku, Word 3 = 0x0019A7ED (= 0x0059A7ED — 0x00400000)
Wyrazy 4 i nowszych są inlined wyjątku.
Przykład 7: Funclet
Function:
00488C72: B500 push {lr}
00488C74: B081 sub sp, sp, #4
00488C76: 3F20 subs r7, #0x20
00488C78: F117 0308 adds r3, r7, #8
00488C7C: 1D3A adds r2, r7, #4
00488C7E: 1C39 adds r1, r7, #0
00488C80: F7FF FFAC bl target
00488C84: B001 add sp, sp, #4
00488C86: BD00 pop {pc}
.PData (stała, wyrazy 2):
Word 0
- Function Start RVA= 0x00088C72 (= 0x00488C72 — 0x00400000)
Word 1
Flag= 1 wskazujących canonical formaty prologu i epilogu
Function Length= 0x0B (= 0x16/2)
Ret= 0, co oznacza pop {pc} zwrotny
H= 0, wskazującą parametry nie zostały podłączony.
R= 0 i Reg = 7, wskazującą nie rejestruje zapisane przywrócić
L= 1, wskazując LR zostało zapisane/przywrócić
C= 0, co oznacza nie łańcuch ramki
Stack Adjust= 1 wskazujących korekty stosu bajtów 1 x 4
Zobacz też
Informacje
Typowe problemy przy migracji Visual C++ ARM