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:

  • 00 = spakowany rozwijają się danych nieużywane; pozostałe bitów, wskaż polecenie .xdata rekordu.

  • 01 = spakowany rozwijają się danych.

  • 10 = spakowany rozwijają się danych, gdy funkcja przyjmuje się, że ma nie prologu.Jest to przydatne w przypadku opisujący fragmenty funkcji, będące nie sąsiadujących ze sobą z początek funkcji.

  • 11 = zastrzeżone.

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:

  • 00 = Wróć za pośrednictwem pop {pc} ( L bitu flagi musi mieć wartość 1 w takim przypadku).

  • 01 = wróć przy użyciu gałąź 16-bitowe.

  • 10 = wróć przy użyciu gałąź 32-bitowych.

  • 11 = w ogóle nie epilogu.Jest to przydatne w przypadku opisujący fragmentu nie sąsiadujących ze sobą funkcji, które mogą zawierać tylko prologu, ale którego epilogu znajduje się w innym.

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:

  • Bity 0-1 wskazuje liczbę wyrazów stosu korekty (1-4) minus 1.

  • Bit 2 jest równa 1, jeśli prologu połączone to dopasowanie do jego operacji push.

  • Bit 3 jest równa 1, jeśli epilogu połączone to dopasowanie do jego operacji pop.

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:

  1. 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

  2. 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.

  3. 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.

  4. 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ę:

  1. 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.

  2. 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.

  3. 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

Koncepcje

Overview of ARM ABI Conventions