- •Архитектура современной вычислительной системы (обзор)
- •Кэши ассоциативные, с прямым отображением и множественно-ассоциативные
- •Представление бинарных данных
- •Режимы работы процессоров семейства i8086+
- •Регистры i8086+
- •Формат инструкции
- •Некоторые инструкции ЦПУ (не включая инструкции FPU, MMX, SSEn и пр.)
- •Формирование кодов основных инструкций i8086+
- •Соответствие мнемоники машинным кодам на примере инструкции пересылки (mov)
- •Режим реальных адресов i8086 (real mode)
- •Синтаксис основных ассемблеров (Intel и AT&T) семейства процессоров i8086+
- •Адреса: короткие, ближние, дальние; перемещаемые записи
- •Сегменты, секции, модели памяти, страницы
- •Переходы, вызовы процедур
- •Символы и макросы
- •Структура физического адресного пространства режима реальных адресов
- •Простейший пример BIOS
- •Некоторое оборудование IBM PC
- •Инициализация контроллера прерываний
- •Инициализация контроллеров клавиатуры PS/2
- •Инициализация PS/2 мыши
- •Инициализация таймера 8253/8254
- •Работа с последовательным интерфейсом UART
- •Программирование контроллера DMA 8257/8237
- •Прерывания в SMP системе; измерение времени
- •Инициализация локального контроллера прерываний (LAPIC)
- •Инициализация контроллера прерываний ввода-вывода (IO APIC)
- •Сегментная модель защищенных режимов i286...x64
- •Общая структура дескриптора
- •Cегмент состояния задачи; переключение стеков
- •«Нереальный 8086»
- •Системные вызовы
- •Структура адресного пространства многопоточного приложения (C, расширение MSVC) с обработкой исключений (Win32).
- •Структура адресного пространства многопоточного приложения (C++) с обработкой исключений (Posix Threads (NPTL); Linux; IA-32)
- •Страничная модель защищенных режимов i386...x64
- •Соглашения о вызовах C/C++ (платформы IA-32, x64)
- •Пример программы, демонстрирующей различные соглашения о вызовах.
- •Основные средства управления адресным пространством, основанные на страничном механизме
- •Запрет на исполнение данных
- •Пример использования уязвимости типа «переполнение буфера в стеке»
- •Проецирование файлов.
- •Императивный способ управления проецированием.
- •Пример создания разделяемого проецирования для межпроцессного взаимодействия
- •Исполняемые файлы и динамические библиотеки
- •Построение динамических библиотек
- •Загрузка библиотек на этапе исполнения.
- •Экспорт, импорт, перемещаемые записи в Windows
- •Экспорт, импорт, перемещаемые записи в Posix
- •POSIX. Позиционно-независимый код в архитектуре IA-32.
- •Построение и использование статических библиотек объектных файлов
- •Встроенный ассемблер; понятие барьеров оптимизации и барьеров памяти.
- •Пример измерения коротких интервалов времени
- •SMP, критические секции и взаимные блокировки
- •Литература
Структура адресного пространства многопоточного приложения (C, расширение MSVC) с обработкой исключений (Win32). |
|
|
|
|
|
|||||||||||||||||||||||||
0001 #include <process.h> |
|
|
0015 unsigned __stdcall proc( void* arg ) |
0028 int main( void ) |
|
|
|
|
||||||||||||||||||||||
0002 #include <windows.h> |
|
|
0016 { |
|
|
|
|
|
|
|
|
|
|
0029 { |
|
|
|
|
|
|
|
|
||||||||
0003 #include <intrin.h> |
|
|
0017 |
|
|
unsigned r = 0; |
|
|
|
|
0030 |
|
HANDLE |
th[2]; |
|
|
|
|||||||||||||
0004 |
|
|
|
|
|
|
0018 |
|
|
|
|
|
|
|
|
|
|
|
0031 |
|
unsigned |
tid[2]; |
|
|
||||||
0005 long |
|
|
|
global; |
|
0019 |
|
|
__try { |
|
|
|
|
|
|
0032 |
|
|
|
|
|
|
|
|
||||||
0006 long __declspec(thread) local; |
|
0020 |
|
|
|
|
while ( !flag ) {} |
|
0033 |
|
th[0] = (HANDLE)_beginthreadex( |
|||||||||||||||||||
0007 int volatile |
flag = 0; |
|
0021 |
|
|
|
|
proc2(); |
|
|
|
|
0034 |
|
(void*)0, 0, proc, tid, 0, tid |
|||||||||||||||
0008 |
|
|
|
|
|
|
0022 |
|
|
} __finally { |
|
|
|
|
|
0035 |
|
); |
|
|
|
|
|
|
||||||
0009 static void proc2( void ) |
|
|
0023 |
|
|
|
|
r = 1; |
|
|
|
|
|
0036 |
|
th[1] = (HANDLE)_beginthreadex( |
||||||||||||||
0010 { |
|
|
|
|
|
|
0024 |
|
|
} |
|
|
|
|
|
|
|
|
0037 |
|
(void*)0, 0, proc,tid+1,0,tid+1 |
|||||||||
0011 |
_InterlockedIncrement( &global ); |
|
0025 |
|
|
return r; |
|
|
|
|
|
|
0038 |
|
); |
|
|
|
|
|
|
|||||||||
0012 |
local++; |
|
|
|
0026 } |
|
|
|
|
|
|
|
|
|
|
0039 |
|
flag = 1; |
|
|
|
|
||||||||
0013 } |
|
|
|
|
|
|
0027 |
|
|
|
|
|
|
|
|
|
|
|
0040 |
|
WaitForMultipleObjects( |
|
|
|
||||||
0014 |
|
|
GlobalAlloc(), … GlobalFree() |
секции указателей |
секция указателей |
|
|
|
|
|
|
|
|
0041 |
|
2, th, TRUE, INFINITE |
|
|
||||||||||||
|
|
|
|
на конструкторы и |
|
на обработчики |
секция экспорта |
|
|
|
|
0042 |
|
); |
|
|
|
|
|
|
||||||||||
|
секции данных, |
|
LocalAlloc(), … LocalFree() |
деструкторы |
|
исключений |
|
|
|
|
|
|
блок |
|
|
|
return 0; |
|
|
|
|
|||||||||
|
специфичных для |
HeapAlloc(), … HeapFree() |
статических |
|
|
|
|
|
|
|
секция |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
секции импорта |
|
|
|
описания |
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
потока |
|
|
|
объектов |
|
|
|
перемещаемых |
|
|
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
|
i-того потока |
|
7FFE 0300: .dword 7C828608h |
|
|
|
|
|||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
записей |
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
Щитовая область (64K) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
продолжение кучи |
|
|
|
|
#i |
#0 |
void(*)())syscall Щитовая область (64K) |
Область системы |
|
|
||||
|
|
... ... |
|
|
|
|
... |
|
|
|
... |
|
... |
|
|
|
|
... ... |
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(2G) |
|
|
|
|||||||||||||
Стек первичного потока |
экземпляр секции.tls |
экземпляр секции.tls#i системная куча процесса |
runtime куча процесса |
|
.text |
.CRT$X* |
|
.xdata$x .idata$* .edata .reloc |
.data .bss |
.tls |
|
экземпляр стека#i |
|
|
Область размещения DLL NTDLL.DLL |
|
PEB TEB |
TEB |
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||
0000 |
0000 |
0000 |
0000 |
0000 |
malloc(), calloc(), |
секция кода |
0000 |
|
|
|
|
|
|
секция |
|
|
|
блок |
|
|
|
F000 |
|
|
блок описания |
|
|
|
FFFF |
|
realloc(), free(), |
|
|
секция |
|
|
|
|
описания |
|
|
|
|
|
|
|
|||||||||||||||
new, delete |
приложения |
инициализированных |
неинициализированных |
процесса |
|
|
|
|
первичного потока |
|
|
|
||||||||||||||||||
0000 |
0001 |
0012 |
0013 |
0014 |
0030 |
0040 |
данных приложения |
|
данных приложения |
|
|
|
7FFD 7FFD |
7FFD 7FFE 7FFF 7FFF |
8000 |
|
|
|
|
FFFF |
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
CreateFile: ; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
потока |
|
|
адреса |
|
TEB #i |
|
|
|
|
||
|
|
|
|
... |
|
|
|
|
|
|
|
|
|
KiFastSystemCall: |
|
|
|
|
|
|
FS:0000 указатель на фрейм исключений |
|||||||||
|
CS=001B |
|
|
call |
|
секция .text |
|
|
|
|
ESP |
|
|
|
||||||||||||||||
|
|
|
... |
|
|
|
|
7C828608:mov edx, esp |
|
|
|
|
... |
|
|
|
|
|||||||||||||
|
DS=0023 |
|
|
ret |
NtCreateFile: |
|
… |
|
|
|
|
|
|
7C82860A:sysenter |
|
|
|
того |
фрейм процедуры |
|
FS:0018 указатель на себя (в DS:) |
|
||||||||
|
ES=0023 |
|
|
|
|
void proc(void) |
|
|
7C82860C:ret |
|
|
|
EBP |
|
|
|
|
... |
|
|
|
|
||||||||
|
SS=0023 |
|
|
|
7C826DFD:mov eax, 27h |
|
|
… |
|
|
|
|
|
фрейм процедуры |
|
|
|
|
|
|||||||||||
|
FS=003B |
|
|
|
7C826E02:mov edx, 7FFE0300h |
{ |
|
|
|
|
|
|
KiIntSystemCall: |
|
|
|
стекi- |
|
FS:002C указатель на TLS вектор |
адреса |
||||||||||
|
GS=0000 |
|
|
|
7C826E07:call dword ptr [edx] |
|
__try { |
|
|
7C828618:lea edx, [esp+8] |
|
фрейм |
|
|
FS:0030 указатель на PEB |
|
||||||||||||||
|
|
|
|
7C826E09:ret 2Ch |
|
|
|
|
|
|
|
|
||||||||||||||||||
|
|
|
|
|
|
|
|
__try { |
|
|
7C82861C:int 2Eh |
|
|
|
обработчика |
|
... |
|
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||
|
Глобальная таблица дескрипторов |
|
|
|
h=CreateFile(...) |
7C82861E:ret |
|
|
|
|
|
исключений |
|
|
|
|
|
|
||||||||||||
|
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
int TlsAlloc(); |
|
|
|
|
||||||||||
|
#0000 |
|
|
|
|
|
|
|
} __except( ... ) { |
|
секция .xdata$x |
адреса |
|
|
|
|
|
void TlsFree( long ); |
|
|
|
|||||||||
|
#0008 |
|
|
|
|
|
|
|
... |
|
|
… |
|
фрейм процедуры |
|
long TlsGetValue( long |
|
|
|
|||||||||||
|
#0010 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long TlsSetValue( int, long |
|
|
|
|||
|
#0018 Code/Read, DPL=3, Base=0 Limit=FFFFFFFF |
|
|
|
|
|
|
|
|
|
|
|
|
|
фрейм процедуры |
|
|
|
|
|||||||||||
|
|
|
} __finally { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
#0020 Data/Write, DPL=3, Base=0, Limit=FFFFFFFF |
|
|
|
... |
|
|
|
|
указатель на фильтр |
|
|
|
фрейм |
|
|
|
[0] |
[1] ... |
[j] |
... [N] |
|||||||||
|
#0028 |
|
|
|
|
|
|
} |
|
|
|
|
|
указатель на обработчик except |
|
|
|
поток: |
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
обработчика |
|
||||||||||||||||
|
#0030 |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
исключений |
|
|
|
|
|
|
||||
|
#0038 Data/Write, DPL=3, Base=7FFD?000, Limit=00000FFF |
|
|
|
|
|
|
|
указатель на обработчик finally |
|
|
i-тый поток: |
[0] |
[1] ... |
[j] |
... [N] |
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||
|
#0040 |
|
|
|
|
|
... |
|
|
|
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[0] |
[1] ... |
[j] |
... [N] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Код приведенного выше многопоточного приложения на ассемблере:
Жирным выделены обращения к блоку описания потока (TEB/TCB), сегментный регистр FS содержит селектор сегмента, база которого смещена относительно базы сегмента данных таким образом, что с адреса FS:0 начинается блок описания текущего потока; при перепланировании потока дескриптор обновляется.
|
.686P |
|
|
|
xdata$x |
SEGMENT |
|
|
адреса __except и |
|
_TEXT |
SEGMENT |
|
|
.XMM |
|
|
|
__sehtable$_proc@4 DD 0ffffffffH |
|
_tid$ = -16 |
||||||
|
|
|
|
__finally обработчиков |
|
||||||||
|
.model |
flat |
_proc@4: |
|
|
DD |
00H |
|
|
||||
|
|
|
|
|
|
_th$ = -8 |
|||||||
|
|
|
функция proc |
|
|
DD |
FLAT:$LN7@proc |
|
|
||||
PUBLIC |
_local |
|
|
|
|
|
_main |
PROC |
|||||
использует соглашение __stdcall, |
|
xdata$x |
ENDS |
|
|
|
|
||||||
PUBLIC |
_flag |
|
|
|
|
|
; Line 29 |
||||||
|
аргументы занимают 4 байта |
|
|
|
|
|
|
|
|||||
PUBLIC |
_proc@4 |
|
|
_TEXT |
SEGMENT |
|
|
|
|
|
sub |
||
|
|
|
|
|
|
|
|
||||||
PUBLIC |
_main |
|
|
|
__$SEHRec$ = -24 |
|
Формирование во фрейме вызова |
|
; Line 33 |
||||
|
|
|
|
|
|
вложенного фрейма обработчика |
|
|
lea |
||||
EXTRN |
__tls_index:DWORD |
|
|
_arg$ = 8 |
|
|
|
||||||
|
|
|
исключений __try {...} |
|
|
push |
|||||||
EXTRN |
__except_handler3:PROC |
|
_proc@4 |
PROC |
|
|
|
||||||
|
|
|
|
|
|
push |
|||||||
EXTRN |
__beginthreadex:PROC |
|
; Line 16 |
|
|
|
|
|
|||||
|
|
|
|
|
|
mov |
|||||||
EXTRN |
__imp__WaitForMultipleObjects@16:PROC |
|
|
push |
ebp |
|
|
|
|
||||
|
|
|
|
|
|
push |
|||||||
|
|
|
|
|
|
mov |
ebp, |
|
|
|
|
||
_DATA |
SEGMENT |
|
Атомарная операция с |
|
|
|
|
|
|
push |
|||
|
|
|
push |
-1 |
|
|
|
|
|||||
COMM |
_global:DWORD |
блокировкой шины для |
|
|
|
|
|
|
push |
||||
|
|
push |
OFFSET __sehtable$_proc@4 |
|
|
||||||||
_DATA |
ENDS |
|
модификации разделяемой |
|
|
|
|
push |
|||||
|
|
|
push |
OFFSET __except_handler3 |
|
|
|||||||
|
|
|
переменной «global» |
|
|
|
|
call |
|||||
_TLS |
SEGMENT |
|
|
|
mov |
eax, DWORD PTR fs:0 |
|
|
|||||
|
|
|
|
|
; Line 36 |
||||||||
_local |
DD |
01H DUP |
обращение к специфичной |
push |
eax |
|
|
|
|||||
|
Включение |
фрейма |
lea |
||||||||||
_TLS |
ENDS |
|
для потока памяти — через |
mov |
DWORD PTR fs:0, |
||||||||
|
обработчика |
исключений |
push |
||||||||||
|
|
|
вектор TLS памяти определяется |
sub |
esp, 8 |
|
|||||||
_BSS |
SEGMENT |
|
|
в односвязный |
список |
push |
|||||||
|
адрес экземляра секции TLS |
push |
ebx |
|
|||||||||
_flag |
DD |
01H DUP |
|
|
|
|
mov |
||||||
|
|
|
push |
esi |
>=0 : маркер активного __try |
блока |
|||||||
_BSS |
ENDS |
|
|
|
|
mov |
|||||||
|
|
|
|
push |
edi |
||||||||
|
|
|
|
|
|
__$SEHRec$[ebp+20] := -24[ebp+20] |
:= [ebp-4] |
push |
|||||
_TEXT |
SEGMENT |
|
|
|
|
|
__try { |
||||||
|
|
|
|
|
|
|
|
|
push |
||||
|
|
|
|
|
|
mov |
DWORD PTR __$SEHRec$[ebp+20], 0 |
|
|
||||
_proc2 |
PROC |
|
|
|
|
|
|
push |
|||||
|
|
|
|
npad |
6 |
|
|
|
|
||||
; Line 11 |
|
|
|
|
|
|
|
|
push |
||||
|
|
|
|
|
|
|
|
|
|
||||
|
_InterlockedIncrement(&global); |
|
|
|
while (!flag ) {} |
|
|
call |
|||||
|
|
|
|
|
|
|
|
|
|
add |
|||
|
|
|
|
|
|
mov |
eax, DWORD PTR _flag |
|
|
||||
|
|
|
|
|
|
|
; Line 39 |
||||||
|
|
|
|
|
|
test |
eax, eax |
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
mov |
|||
|
|
|
|
|
|
je |
SHORT $LL2@proc |
|
|
|
|||
|
|
|
|
|
|
|
|
; Line 40 |
|||||
|
|
|
|
|
|
|
|
proc2(); |
|
|
|||
|
|
|
|
|
|
call |
_proc2 |
покидаем __try блок |
push |
||||
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
push |
||||||
|
|
|
|
|
|
|
} __finally { |
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
lea |
|||
|
|
|
|
|
|
mov |
DWORD PTR __$SEHRec$[ebp+20], -1 |
|
|||||
|
|
|
|
|
|
|
push |
||||||
|
|
|
|
|
|
call |
$LN9@proc |
|
|
|
|||
|
|
|
|
|
|
|
|
|
mov |
||||
|
|
|
|
|
|
|
|
|
присвоение «r=1» |
|
|||
|
|
|
|
|
|
|
} |
|
|
push |
|||
|
|
|
|
|
|
|
|
вынесено из __finaly |
|
call |
|||
|
|
|
|
|
|
mov |
eax, 1 |
|
|
||||
|
|
|
|
|
|
|
оптимизатором |
; Line 43 |
|||||
|
|
|
|
|
|
|
return r; |
||||||
|
|
|
|
|
|
|
|
|
|
xor |
|||
Существует несколько форм записи инструкции mov eax, xx[ebp] |
mov |
ecx, DWORD PTR __$SEHRec$[ebp+8] |
|
||||||||||
; Line 44 |
|||||||||||||
- со смещеннием в виде байта «8B 45 xx» (если xx<0x100) |
|
mov |
DWORD PTR fs:0, ecx |
||||||||||
|
|
add |
|||||||||||
(mod — r/m: 01...101: [ebp+byte]) |
|
|
|
pop |
edi |
|
|
|
|
||||
|
|
|
|
|
|
|
ret |
||||||
- со смещением в виде 32х разрядного слова «8B 85 xx 00 00 00» |
|
pop |
esi |
|
|
|
_main |
||||||
(mod-r/m: 10...101: [ebp+long]) |
|
|
|
pop |
ebx |
|
|
|
ENDP |
||||
- с SIB и смещением в виде 32х разрядного слова «8B 04 2D xx 00 00 00» |
mov |
esp, ebp |
|
|
|
_TEXT |
ENDS |
||||||
(mod-r/m: 00...100: см SIB; SIB: 00 101 101: [ebp+long]) |
|
|
|
|
|||||||||
|
pop |
ebp |
|
|
|
END |
|
||||||
- если xx кратно 2, 4 или 8, то возможны еще 3 формы с SIB той же длины |
|
|
|
|
|||||||||
ret |
|
|
__finally обработчик |
|
|
||||||||
запись npad 6 подсказывает, что для выравнивания адреса выбрана форма |
|
|
|
|
|||||||||
|
|
|
|
|
|||||||||
длиной 6 байт |
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
ret |
0 |
|
|
|
|
|
|
|
|
|
|
|
_proc@4 |
ENDP |
|
|
|
|
|
|
|
|
|
|
|
|
_TEXT |
ENDS |
|
|
|
|
|
|
|
; size = 8 |
|
; size = 8 |
esp, 16 |
; 00000010H |
eax, DWORD PTR _tid$[esp+16] |
|
eax |
|
0 |
|
ecx, eax |
__beginthreadex: |
ecx |
функция _beginthreadex |
OFFSET _proc@4 |
использует соглашение __cdecl |
0 |
|
0 __beginthreadex
edx, DWORD PTR _tid$[esp+44] edx
0
DWORD PTR _th$[esp+48], eax eax, edx
eax |
|
OFFSET _proc@4 |
|
0 |
|
0 |
|
__beginthreadex |
|
esp, 48 |
; 00000030H |
DWORD PTR _flag, 1
-1
1
ecx, DWORD PTR _th$[esp+24] ecx
DWORD PTR _th$[esp+32], eax
2
DWORD PTR __imp__WaitForMultipleObjects@16
eax, eax
esp, 16
0
__imp__WaitForMultipleObjects@16:
функция WaitForMultipleObjects: использует соглашение __stdcall,
аргументы занимают 16 байт (4 двойных слова) импортирована из DLL
Структура адресного пространства многопоточного приложения (C++) с обработкой исключений (Posix Threads (NPTL); Linux; IA-32) |
|
|
|
|
|
||||||||||||||||||||||
0001 #include <pthread.h> |
|
|
0014 void* proc( void* arg ) |
|
|
|
0025 int main( void ) |
|
|
|
|
|
|
||||||||||||||
0002 #define ZEROATTR |
(pthread_attr_t*)0 |
0015 { |
|
|
|
|
|
|
|
|
0026 { |
|
|
|
|
|
|
|
|
|
|||||||
0003 |
|
|
|
|
|
|
|
0016 |
try { |
|
|
|
|
|
|
|
0027 |
|
pthread_t tid[2]; |
|
|
|
|
||||
0004 long |
|
global; |
|
|
0017 |
while ( !flag ) {} |
|
|
0028 |
|
|
|
|
|
|
|
|
|
|
||||||||
0005 long __thread local; |
|
|
0018 |
proc2(); |
|
|
|
|
|
|
0029 |
|
pthread_create( |
|
|
|
|
|
|||||||||
0006 int volatile |
flag = 0; |
|
0019 |
} catch(...) { |
|
|
|
|
|
0030 |
|
|
tid+0, ZEROATTR, proc, tid+0 |
||||||||||||||
0007 |
|
|
|
|
|
|
|
0020 |
return (void*)1; |
|
|
0031 |
|
); |
|
|
|
|
|
|
|
|
|||||
0008 void proc2( void ) |
|
|
|
0021 |
} |
|
|
|
|
|
|
|
0032 |
|
pthread_create( |
|
|
|
|
|
|||||||
0009 { |
|
|
|
|
|
|
|
0022 |
return (void*)0; |
|
|
|
|
|
0033 |
|
|
tid+1, ZEROATTR, proc, tid+1 |
|||||||||
0010 |
__sync_fetch_and_add(&global, 1); |
0023 } |
|
|
|
|
|
|
|
|
0034 |
|
); |
|
|
|
|
|
|
|
|
||||||
0011 |
local++; |
|
TLS данные |
секции указателей |
0024 |
|
|
|
|
|
|
|
|
0035 |
|
flag = 1; |
|
|
|
|
|
|
|
||||
0012 } |
|
|
|
|
|
|
на конструкторы |
Секция |
блок |
секции данных, |
|
|
0036 |
|
pthread_join(tid[1], (void**)0); |
|
|||||||||||
|
Структуры, |
|
|
|
|
деструкторы |
|
|
|
|
|||||||||||||||||
0013 |
|
|
|
|
|
перемещаемых |
описания |
|
|
0037 |
|
pthread_join(tid[0], (void**)0); |
|
||||||||||||||
|
|
|
|
|
статических |
специфичных для |
|
|
|
|
|||||||||||||||||
секции |
|
(семантика |
|
|
|
объектов |
записей |
i-того потока |
первичного потока |
блок описания0038 |
|
return 0; |
|
|
|
|
|
|
|
||||||||
определения |
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
символов |
|
|
|
|
|
|
|
|
|
|
|
|
|
первичного потока |
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0039 } |
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
... |
|
|
|
... |
|
|
|
... |
|
|
|
|
Динамический загрузчик LD.SO |
|
Область системы |
|
|
|||||
Щитовая область(4K) |
|
.rel* .plt |
.text |
.rodata |
.ehframe .gcc excepttable |
.tbss .tdata .ctors .dtors .got .got.plt .data .bss |
общаякуча процесса |
экземпляр стека |
экземпляр .tbss.tdataи |
TCB #i |
секции .tbss.tdataи TCB |
LIBC.SO |
Область размещения SO |
Стек первичного потока |
|
|
(~1G) |
linux-gate(4K) [vdso] Щитовая область(4K) |
|||||||||
|
|
|
|
|
|
||||||||||||||||||||||
|
|
|
|
|
|
|
|
||||||||||||||||||||
0000 |
|
секция кода |
|
|
секция |
секция .text |
|
|
|
|
0000 |
|
|
B000 |
B000 |
|
8000 0000 |
|
|
|
E000 |
F000 |
FFFF |
||||
|
приложения |
|
инициализированных |
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
|
|
|
данных приложения |
… |
|
|
|
|
|
|
|
|
__kernel_vsyscall: |
||||||||||||
0000 |
|
|
|
|
|
|
|
void proc(void) |
|
|
|
|
B7CF |
|
|
B7FB |
B7FD |
|
BFFE C000 |
|
push |
%ecx |
FFFF |
FFFF |
FFFF |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
push |
%edx |
|||||||||||
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
|
секция |
|
|
|
|
|
|
|
|
|
push |
%ebp |
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
open: push %ebx |
|
|
1: |
|
|
|
|||||||
_dl_sysinfo: |
|
|
|
неинициализированных |
try { |
|
|
|
|
|
|
|
|
|
mov |
%esp,%ebp |
|
|
|||||||||
|
|
|
... |
|
|
|
|
|
|
|
|
mov |
|
0x10(%esp), %edx |
|
|
sysenter |
|
|
|
|||||||
|
.long __kernel_vsyscall |
|
данных приложения |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
mov |
|
0x0C(%esp), %ecx |
|
|
nop |
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
h=open(...) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mov |
|
0x08(%esp), %ebx |
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
|
|
... |
|
|
|
|
|
|
|
1: |
mov |
|
$5, %eax |
|
|
|
jmp |
1b |
|
|
|
|
|
|
|
секция .gcc_except_table |
|
|
|
|
|
|
|
|
call *_dl_sysinfo # %gs:0x10 |
|
pop |
%ebp |
|
|
|
||||||||
|
|
|
|
} catch (...) { |
|
того потока |
|
|
|
адреса |
|
pop |
|
%ebx |
|
|
|
pop |
%edx |
|
|
|
|||||
CS=0073 |
|
|
|
… |
|
|
|
... |
|
|
|
|
|
|
ret |
|
|
|
|
|
pop |
%ecx |
|
|
|
||
|
|
|
|
|
|
|
} |
|
|
|
|
|
адреса |
|
|
|
|
|
ret |
|
|
|
|
||||
DS=007B |
|
|
|
try-блок |
|
} |
|
|
|
|
|
|
|
|
Обращение к TLS данным |
|
|
||||||||||
ES=007B |
|
|
|
|
защищаемый код |
... |
|
ESP |
|
|
|
|
|
|
|
|
|
||||||||||
SS=007B |
|
|
|
|
обработчик ошибок |
|
EBP |
фрейм процедуры |
|
стек потока |
|
осуществляется с |
|
|
|
||||||||||||
FS=0000 |
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
экземпляр |
|
отрицательными смещениями |
|
|||||||||
GS=0033 |
|
|
|
|
|
|
|
|
|
фрейм процедуры |
|
|
к TCB: |
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
стек i- |
|
TCB#i |
|
.tbss |
|
mov %gs:0, %ebx |
|
|
|
|||||||
Глобальная таблица дескрипторов |
|
секция .eh_frame |
EIP |
|
локальные переменные |
|
|
экземпляр |
|
mov -xxx(%ebx), %eax |
|
|
|||||||||||||||
#0000 |
|
|
|
|
|
|
|
|
|
сохраненные регистры |
|
|
.tdata |
|
|
первичный |
|
|
|
|
|||||||
… |
|
|
|
|
|
|
|
… |
|
|
|
|
ук. на фрейм (ebp) |
|
GS:0000 указатель на себя (DS:) |
|
поток |
вектор 1го уровня |
|
||||||||
#0030 Data/Write, DPL=3, Base=B7???000, Limit=FFFFFFFF |
|
|
|
|
|
|
адрес возврата |
|
[0] [1] ... [j%32] ...[31] |
|
|
||||||||||||||||
… |
|
|
|
|
|
|
|
процедура xxx |
|
|
|
|
|
|
… |
|
|
|
|
|
[1] |
%32 |
[31] |
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
аргумент 1 |
|
|
|
|
|
|
|
вектор 2го уровня |
|
|
|
||||
#0070 Code/Read, DPL=3, Base=0, Limit=FFFFFFFF |
диапазон адресов |
|
|
|
|
|
|
GS:000C флаг асинхронного i/o |
|
|
|
|
|
||||||||||||||
|
|
|
|
… |
|
|
[0] |
|
|
|
|
||||||||||||||||
#0078 Data/Write, DPL=3, Base=0, Limit=FFFFFFFF |
|
|
|
|
|
|
|
|
GS:0010 |
адрес __kernel_vsyscall |
[1] ... [j/32] ... [31] |
|
|
|
|||||||||||||
try-блок |
|
|
|
|
|
аргумент N |
|
|
|
|
|
|
|
|
|
||||||||||||
... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
… |
|
|
|
i-тый поток:вектор 1го уровня |
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
... |
|
|
|
|
|
|
|
|
GS:006C TLS вектор 1го уровня |
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
фрейм процедуры |
|
… |
|
|
|
|
[0] [1] ... [j%32] ...[31] |
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[1] |
%32 |
[31] |
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GS:016C TLS вектор 2го уровня |
|
|
вектор 2го уровня |
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
… |
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[0] |
[1] ... [j/32] ... [31] |
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Код приведенного выше многопоточного приложения на ассемблере:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
.text |
|
|
|
.globl _Z4procPv |
|
|
.text |
|
||||||||
.globl main |
|
|
|
|
.type |
_Z4procPv, @function |
|
|
.globl global |
|
||||||
|
.type |
main, @function |
|
_Z4procPv: |
|
|
|
|
|
|
|
|
.bss |
|
||
main: |
|
|
|
|
.LFB12: |
# void* proc( void* arg) { |
|
|
|
|
.align 4 |
|
||||
|
|
|
|
|
|
|
|
|
||||||||
.LFB13: |
leal |
4(%esp), %ecx |
|
.LEHB0: |
subl |
$28, %esp |
|
|
|
|
.type |
global, @object |
||||
|
|
|
|
|
||||||||||||
.LCFI0: |
|
|
|
|
.LCFI4: |
|
|
|
|
|
|
|
|
|
.size |
global, 4 |
|
andl |
$-16, %esp |
|
.LEHE0: |
# |
try { |
|
|
|
|
|
global: |
|
|||
|
|
|
|
|
|
|
|
|||||||||
|
pushl |
-4(%ecx) |
|
|
.L6: |
movl |
flag, %eax |
|
|
|
|
|
.zero |
4 |
||
|
|
|
|
|
|
|
|
|||||||||
.LCFI1: |
|
|
|
|
|
testl |
%eax, %eax |
|
|
|
|
|
.globl local |
|
||
|
pushl |
%ecx |
|
|
|
je |
.L6 |
|
|
|
|
|
.section .tbss,"awT",@nobits |
|||
.LCFI2: |
|
|
|
|
.LEHB1: |
|
|
|
|
|
|
|
|
|
.align 4 |
|
|
subl |
$40, %esp |
|
|
call |
_Z5proc2v |
|
|
|
|
|
.type |
local, @object |
|||
|
|
|
|
|
|
|
|
|||||||||
.LCFI3: |
|
|
|
|
.LEHE1: |
|
|
|
|
|
|
|
|
|
.size |
local, 4 |
|
leal |
32(%esp), %eax |
|
|
xorl |
%eax, %eax |
|
|
|
|
local: |
|
||||
|
movl |
%eax, 12(%esp) |
|
|
jmp |
.L7 |
|
|
|
|
.zero |
4 |
||||
|
movl |
$_Z4procPv, 8(%esp) |
|
.L11: |
# |
} catch (…) { |
|
|
|
|
.globl flag |
|
||||
|
movl |
$0, 4(%esp) |
|
.L8: |
movl |
%eax, (%esp) |
|
|
|
|
.bss |
|
||||
|
movl |
%eax, (%esp) |
|
|
call |
__cxa_begin_catch |
|
|
|
|
.align 4 |
|
||||
|
|
|
|
|
|
|
|
|||||||||
|
call |
pthread_create |
|
.LEHB2: |
|
|
|
|
|
|
|
|
|
.type |
flag, @object |
|
|
leal |
36(%esp), %eax |
|
|
call |
__cxa_end_catch |
|
|
|
|
|
.size |
flag, 4 |
|||
|
|
|
|
|
|
|
|
|||||||||
|
movl |
%eax, 12(%esp) |
|
|
# |
return 1; |
|
|
|
|
flag: |
|
||||
|
movl |
$_Z4procPv, 8(%esp) |
|
|
movl |
$1, %eax |
|
|
|
|
.zero |
4 |
||||
|
movl |
$0, 4(%esp) |
|
.L7: |
# |
} |
|
|
|
|
|
|
|
.section .eh_frame,"a",@progbits |
||
|
movl |
%eax, (%esp) |
|
|
addl |
$28, %esp |
|
|
|
|
||||||
|
call |
pthread_create |
|
.LEHE2: |
# } |
|
|
|
|
|
|
|
|
.Lframe1: |
|
|
|
movl |
36(%esp), %eax |
|
|
ret |
|
|
|
|
|
|
|
|
.long |
.LECIE1-.LSCIE1 |
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
movl |
$1, flag |
|
|
.LFE12: |
|
|
|
|
|
|
|
|
|
.LSCIE1: |
|
|
movl |
$0, 4(%esp) |
|
|
.size |
_Z4procPv, .-_Z4procPv |
|
|
.long |
0x0 |
||||||
|
movl |
%eax, (%esp) |
|
.globl __gxx_personality_v0 |
|
|
|
|
.byte |
0x1 |
||||||
|
call |
pthread_join |
|
.section .gcc_except_table,"a",@progbits |
|
|
.string |
"zPL" |
||||||||
|
movl |
32(%esp), %eax |
|
|
|
.uleb128 0x1 |
||||||||||
|
|
|
.align 4 |
|
|
|
|
|||||||||
|
movl |
$0, 4(%esp) |
|
|
|
|
|
|
.sleb128 -4 |
|||||||
|
|
.LLSDA12: |
|
|
|
|
|
|
|
|
||||||
|
movl |
%eax, (%esp) |
|
|
|
|
|
|
|
|
|
.byte |
0x8 |
|||
|
|
|
.byte |
0xff |
|
|
|
|
||||||||
|
call |
pthread_join |
|
|
|
|
|
|
.uleb128 0x6 |
|||||||
|
|
|
.byte |
0x0 |
|
|
|
|
||||||||
|
xorl |
%eax, %eax |
|
|
|
|
|
|
.byte |
0x0 |
||||||
|
|
|
.uleb128 .LLSDATT12-.LLSDATTD12 |
|
|
|||||||||||
|
addl |
$40, %esp |
|
|
|
|
.long |
__gxx_personality_v0 |
||||||||
|
|
.LLSDATTD12: |
|
|
|
|
|
|
|
|
||||||
|
popl |
%ecx |
|
|
|
|
|
|
|
|
|
|
.byte |
0x0 |
||
|
|
|
|
.byte |
0x1 |
|
|
|
|
|||||||
|
leal |
-4(%ecx), %esp |
|
|
|
|
|
|
.byte |
0xc |
||||||
|
|
|
.uleb128 .LLSDACSE12-.LLSDACSB12 |
|
|
|||||||||||
|
ret |
|
|
|
|
|
|
.uleb128 0x4 |
||||||||
|
|
|
|
.LLSDACSB12: |
|
|
|
|
|
|
|
|
||||
.LFE13: |
|
|
|
|
|
|
|
|
|
|
|
|
.uleb128 0x4 |
|||
|
|
|
|
|
.uleb128 .LEHB0-.LFB12 |
|
|
|
|
|||||||
|
.size |
main, .-main |
|
|
|
|
|
|
.byte |
0x88 |
||||||
|
|
|
.uleb128 .LEHE0-.LEHB0 # try { |
|
|
|||||||||||
|
|
|
|
|
|
|
|
.uleb128 0x1 |
||||||||
|
|
функция |
|
|
.uleb128 0x0 |
|
|
|
|
|||||||
|
|
void proc2(void) |
|
|
.uleb128 0x0 |
|
|
|
|
.align 4 |
|
|||||
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
использует соглашение C++ |
|
|
.uleb128 .LEHB1-.LFB12 # } |
catch |
|
|
|
|
||||||
|
|
|
|
|
|
.uleb128 .LEHE1-.LEHB1 |
|
|
|
|
|
|
||||
.globl _Z5proc2v |
|
|
|
.uleb128 .L11-.LFB12 # |
... |
|
|
|
|
|||||||
|
.type |
|
|
|
|
.uleb128 0x1 |
|
|
|
|
|
|
||||
_Z5proc2v: |
|
|
|
|
.uleb128 .LEHB2-.LFB12 |
|
|
|
|
|
|
|||||
.LFB11: |
lock addl |
$1, global |
|
|
.uleb128 .LEHE2-.LEHB2 # } |
|
|
|
|
|
|
|||||
|
movl |
%gs:0, %eax |
|
|
.uleb128 0x0 |
|
|
|
|
|
|
|||||
|
incl |
local@NTPOFF(%eax) |
|
|
.uleb128 0x0 |
|
|
|
|
|
|
|||||
|
ret |
|
|
|
.LLSDACSE12: |
|
|
|
|
|
|
|
|
|
|
|
.LFE11: |
|
|
|
|
|
.byte |
0x1 |
|
|
|
|
|
|
|||
|
.size |
_Z5proc2v, |
|
|
.byte |
0x0 |
|
|
|
|
|
|
||||
.-_Z5proc2v |
|
|
|
|
.align 4 |
|
|
|
|
|
|
|||||
.globl _Unwind_Resume |
|
|
|
.long |
0 |
|
|
|
|
|
|
|
|
|
||
|
|
.LLSDATT12: |
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.LECIE1: |
|
.LSFDE1: .long |
.LEFDE1-.LASFDE1 |
.LASFDE1: |
|
.long |
.LASFDE1-.Lframe1 |
.long |
.LFB13 |
.long |
.LFE13-.LFB13 |
.uleb128 0x4 |
|
.long |
0x0 |
.byte |
0x4 |
.long |
.LCFI0-.LFB13 |
.byte |
0xc |
.uleb128 |
0x1 |
.uleb128 |
0x0 |
.byte 0x9
.uleb128 0x4
.uleb128 0x1
.byte 0x4
.long .LCFI1-.LCFI0
.byte 0xc
.uleb128 |
0x4 |
.uleb128 |
0x4 |
.byte |
0x4 |
.long |
.LCFI2-.LCFI1 |
.byte |
0xe |
.uleb128 0x8 |
|
.byte |
0x84 |
.uleb128 0x2 |
|
.byte |
0x4 |
.long |
.LCFI3-.LCFI2 |
.byte |
0xe |
.uleb128 0x30 |
|
.align 4 |
|
.LEFDE1: |
|
.LSFDE3: |
|
.long |
.LEFDE3-.LASFDE3 |
.LASFDE3: |
|
.long |
.LASFDE3-.Lframe1 |
.long |
.LFB11 |
.long |
.LFE11-.LFB11 |
.uleb128 0x4 |
|
.long |
0x0 |
.align 4 |
|
.LEFDE3: |
|
.LSFDE5: |
|
.long |
.LEFDE5-.LASFDE5 |
.LASFDE5: |
|
.long |
.LASFDE5-.Lframe1 |
.long |
.LFB12 |
.long |
.LFE12-.LFB12 |
.uleb128 0x4 |
|
.long |
.LLSDA12 |
.byte |
0x4 |
.long |
.LCFI4-.LFB12 |
.byte |
0xe |
.uleb128 0x20
.align 4
.LEFDE5: