• Nenhum resultado encontrado

DLL s ligação estática na construção e dinâmica no carregamento

N/A
N/A
Protected

Academic year: 2021

Share "DLL s ligação estática na construção e dinâmica no carregamento"

Copied!
13
0
0

Texto

(1)

DLL´s –

ligação estática na construção e dinâmica no carregamento

28-04-2012 Sistemas Operativos 1

x.lib

app.obj

.text

.data

.text

.data

StaticLinker (Link.exe)

app.exe

x.dll

.text

.data

.reloc

.idata

.text

.data

.edata

Dynamic Linker (ntdll.dll)

app.exe process

virtual address space

.text

.data

.text

.bss

.data

.bss

x.dll

app.exe

import

stubs

.idata

(Import Table)

Construção do

Executável

(Ligação estática)

Ligação dinâmica

no carregamento do

executável

.idata

(2)

DLL´s –

Detalhe da ligação dinâmica

28-04-2012 Sistemas Operativos 2

.edata

.text

Export Address Table (RVAs)

.reloc

(RVA table)

Export Name Table

.data

.text

.idata

Import Address Table Import Name Table

.data

Dynamic Linker (ntdll.dll)

.text

.data

.text

.bss

.data

.bss

.idata

(Import Tables)

app.exe

x.dll

app.exe

x.dll

app.exe process

virtual address space

app base address PE header dll base address PE header

.reloc

(RVA table)

(3)

Produção e consumo de bibliotecas de ligação dinâmica(DLL’s)

#ifdef DLLMATH_EXPORTS

#define DLLMATH_API _declspec(dllexport) #else

#define DLLMATH_API _declspec(dllimport) #endif

#ifdef __cplusplus extern “C” {

#endif

DLLMATH_API int add(int op1, int op2);

#ifdef __cplusplus } #endif 28-04-2012 Sistemas Operativos 3 #include "stdafx.h" #include "dllmath.h"

int add(int oper1, int oper2) { return oper1 + oper2;

}

#include <stdafx.h> #include “dllmath.h”

int _tmain(int argc, _TCHAR* argv[]) { _tprintf(_T("%d\n"), add(3,5)); }

build

(compile and link)

build

(compile and link)

dllmath.dll

dllmath.lib

define DLLMATH_EXPORTS on DLL build

mathclient.exe

dllmath.h mathclient.c dllmath.c ficheiro de include, partilhado entre DLL e clientes que inclui as funções exportadas e tipos usados nos respectivos parâmetros.

other

libs & obs

other

(4)

Produção e consumo de Bibliotecas de Ligação Dinâmica(DLL’s)

all: dllmath.dll mathclient.exe

dllmath.dll: dllmath.obj dllmain.obj

link /DLL dllmath.obj dllmain.obj

dllmath.obj: dllmath.c

cl /c /D dllmath_EXPORTS dllmath.c

mathclient.exe: mathclient.obj

link mathclient.obj dllmath.lib

mathclient.obj: mathclient.c

cl /c /MD mathclient.c

28-04-2012 Sistemas Operativos 4

Exemplo de utilização do compilador e do

linker em comandos de linha para a

produção e consumo de dll´s. O

makefile

exemplifica os comandos necessários,

admitindo que as fontes estão na mesma

directoria.

Utilizar a import library (msvcrtd.lib) associada à versão dll do

runtime do C (msvcr100.dll). Na sua omissão é usada a biblioteca

estática com o runtime (libcmtd.lib). Notem a diferença de

tamanho do executável entre os dois casos.

(5)

dumpbin (exports & imports)

28-04-2012 Sistemas Operativos 5

Dump of file dllmath.dll File Type: DLL

Section contains the following exports for DLLMATH.dll 00000000 characteristics

4D9835A0 time date stamp Sun Apr 03 09:53:52 2011 0.00 version

1 ordinal base

1 number of functions 1 number of names

ordinal hint RVA name 1 0 00001000 add Summary 2000 .data 2000 .rdata 1000 .reloc 5000 .text

Dump of file mathclient.exe File Type: EXECUTABLE IMAGE

Section contains the following imports: dll2.dll

4020B4 Import Address Table 4022A8 Import Name Table …

0 add

MSVCR100.dll

402050 Import Address Table 402244 Import Name Table …

5D7 printf 573 exit 3C9 _onexit KERNEL32.dll

402000 Import Address Table 4021F4 Import Name Table … 1C0 GetCurrentProcess 4C0 TerminateProcess … Summary 1000 .data 1000 .rdata 1000 .reloc 1000 .text

dumpbin /exports dllmath.dll

dumpbin /imports mathclient.exe

Inicialmente os linkers colocavam a tabela de exports na secção .edata. Actualmente encontra-se na secção de dados constantes (.rdata).

Neste caso as tabelas de import também ficaram na secção .rdata

(6)

Convenções de chamada

Por omissão, na chamada de funções, na convenção usada por omissão pelo compilador de C

o chamador desempilha os argumentos (

add esp, n

).

No Windows é usada, por razões históricas, outra convenção de chamada. A função invocada

é que desempilha os argumentos (

ret n

). Usa-se o atributo do compilador

__stdcall

(ou a

macro equivalente

WINAPI

) a prefixar o nome da função, para especificar este

comportamento. Tal opção permite poupar algum código pois o ajuste do stack fica

centralizado.

– Usando a assinatura DLLMATH_API int WINAPI add(int op1, int op2) para a

função exportada, as tabelas de export da dll e import do executável sofrem as seguintes

modificações:

28-04-2012 Sistemas Operativos 6

Dump of file dllmath.dll

File Type: DLL

Section contains the following exports for DLLMATH.dll

ordinal hint RVA name

1 0 00001000 _add@8

Dump of file mathclient.exe

File Type: EXECUTABLE IMAGE

Section contains the following imports:

dll2.dll

4020B4 Import Address Table

4022A8 Import Name Table

0 _add@8

O nome passa a estar decorado com a inclusão da dimensão em bytes dos argumentos a passar à função

(7)

Ligação implícita e explícita

• A ligação com uma DLL pode ser feita em dois

tempos:

– Em tempo de carregamento do executável quando o executável

depende da DLL através de uma import table produzida pela ligação

estática com a import library associada à DLL. Neste caso, a ligação

diz-se automática ou implícita.

– Em tempo de execução a pedido explícito do programa. Neste caso a

ligação diz-se manual ou explícita. Desta forma é possível, por

exemplo, escolher a dll a usar em tempo de execução.

(8)

Ligação explícita – modelo computacional

• O Windows expõe as seguintes funções para tirar partido da

ligação explícita:

– HMODULE WINAPI LoadLibrary( LPCTSTR lpFileName );

– FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR lpProcName );

– BOOL WINAPI FreeLibrary(HMODULE hModule );

28-04-2012 Sistemas Operativos 8

O mesmo que TCHAR*

O mesmo que char*. É um dos raros casos em que na Windows API se utilizam forçosamente caracteres a 8 bits.

typedef int

(WINAPI * AddFuncPtr)(int i1, int i2); int _tmain(int argc, _TCHAR* argv[]) { HMODULE hLib;

AddFuncPtr addFunc;

hLib = LoadLibrary(_T("DLL2.DLL"));

addFunc = (AddFuncPtr) GetProcAddress(hLib, "_add@8" ); if (addFunc==NULL) { _tprintf(_T("GelastError=%d\n"), GetLastError()); return 1; } _tprintf(_T("%d\n"), addFunc(3,5)); FreeLibrary(hLib); … return 0; }

Notem a boa prática de especificar através de um typedef a assinatura da função a invocar.

Na versão da dll que expõe a função usando a convenção de chamada __stdcall (WINAPI) teremos de ter o cuidado de incluír a convenção ou naturalmente o stack é

incorrectamente ajustado. Notem também a utilização do nome decorado na função

(9)

dll entry point: DllMain

As dll´s podem ter um entry point (

DllMain

). O entry point é invocado nas seguintes

situações, entre outras que veremos adiante:

– Da primeira vez que a dll é carregada no espaço de endereçamento de um processo

(DLL_PROCESS_ATTACH), quer na ligação implícita quer na ligação explícita.

– Quando a dll for retirada do espaço de endereçamento (DLL_PROCESS_DETACH). Isto ocorre no

último FreeLibrary ou em fase de terminação do processo.

O código seguinte exemplifica a utilização:

28-04-2012 Sistemas Operativos 9

#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule, DWORD reason_for_call, LPVOID reserved){ switch (reason_for_call) { case DLL_PROCESS_ATTACH: _tprintf(_T("Starting Math DLL\n")); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: _tprintf(_T("Ending DLLW2\n")); break; } return TRUE; } sinónimo de WINAPI

(10)

dll – necessidade de relocalização

Por omissão o código e os dados da DLL são localizados na ligação estática a partir de

0x10000000. O código de acesso a variáveis globais (e às tabelas de import de outras dll´s de

que esta dependa) foi gerado tendo em conta essa base.

O que fazer se a dll não puder ser carregado nesse endereço?

28-04-2012 Sistemas Operativos 10

Dump of file dllmath.dll …

OPTIONAL HEADER VALUES 10B magic # (PE32) 10.00 linker version 3600 size of code

3600 size of initialized data 0 size of uninitialized data

110C8 entry point (100110C8) @ILT+195(__DllMainCRTStartup@12) 1000 base of code

1000 base of data

10000000 image base (10000000 to 1001AFFF)

1000 section alignment …

static int savedPageSize; int GetPageSize() { SYSTEM_INFO si; if (savedPageSize == 0) { GetSystemInfo(&si); savedPageSize=si.dwPageSize; } return savedPageSize; }

função para guardar em variável global (estática) a dimensão da página obtida

via GetSystemInfo

Excerto do código gerado para a função, localizado de

acordo com o link base

address por omissão

100113A4 call dword ptr [__imp__GetSystemInfo@4 (10018168h)] 100113B1 mov eax,dword ptr [ebp-24h]

(11)

Mecanismo de relocalização

Os ficheiros imagem (dlls e executáveis) contém uma secção (.reloc) que é essencialmente uma tabela

de RVAs que indica referência a endereços relocalizados. Em tempo de carregamento essas posições de

memória são modificadas de acordo com o novo endereço base.

Mas o que acontece se houver necessidade de relocalização da DLL no caso desta ser partilhada (como é

usual)?

Porque razão os executáveis também contêm uma secção .reloc se são sempre carregados no endereço

especificado em tempo de ligação?

28-04-2012 Sistemas Operativos 11

AE6 HIGHLOW 10018168 __imp__GetSystemInfo@4 AF5 HIGHLOW 10017130 _savedPageSize

Excerto da tabela de relocações referente ao código do slide anterior e obtida através da opção relocations do comando dumpbin. As colunas representam, respectivamente, o RVA , o tipos da relocação, o valor actual e o símbolo referido

(12)

Optimizações – DLL rebase e DLL bind

O utilitário rebase permite efectuar a relocalização antecipada de uma dll para o

endereço especificado de modo a evitar a recolocação em tempo de

carregamento. Deste modo consegue-se maior eficiência em tempo de

carregamento e utilização da memória.

As dll´s do windows estão todas rebased para endereços que evitam colisões.

Vantagens de um sistema operativo proprietário…

28-04-2012 Sistemas Operativos 12

REBASE –b newbase image-name

O comando bind permite efectuar a ligação dinâmica de forma antecipada, isto é,

iniciar as import address tables de acordo com os endereços base especificados

nas dll´s de que depende a imagem sobre a qual é efectuada o bind.

Evita a ligação dinâmica se as dll´s não forem alteradas e forem carregadas no

endereço pré-definido. Caso contrário a ligação dinâmica é efectuada.

(13)

Bibliografia

• Windows via C/C++, Fifth Edition, Jeffrey Richter e

Christophe Nasarre

– Cap.19 – DLL basics

– Cap.20 – DLL advanced techniques

Referências

Documentos relacionados

Files Allowed: wininet.dll, mlang.dll, Kernel32.dll, Wversion.dll, sensapi.dll, Com dlg32.dll, ipeditor.dll, Comctl32.dll, mso.dll, wShell32.Dll, msi.dll, xdnoship. dll,

Files Allowed: USER32.DLL, kernel32.dll, mscoree.dll, combase.dll, ADVAPI32.dll , OLEAUT32.dll, VERSION.dll, UxTheme.dll, WSOCK32.dll, SHELL32.dll, PSAPI.DLL, COMCTL32.dll,

ws2_32.dll ws2_32.dll olepro32.dll comctl32.dll comctl32.dll comctl32.dll comctl32.dll comctl32.dll wship6.dll version.dll WINMM.dll UxTheme.dll wininet.dll uxtheme.dll 0.0.0.0

Files Allowed: kernel32.dll, USER32.dll, mscoree.dll, GDI32.dll hasFiles:

Libraries Allowed: mapi32.dll, mtxex.dll, ws2_32.dll, user32.dll, uxtheme.dll, dwmap i.dll, wininet.dll, ole32.dll, imm32.dll, advapi32.dll, comctl32.dll, shfolder.dll,

Files Allowed: rarext64.dll, rarext.dll, riched20.dll, KERNEL32.DLL, cabinet.dll, U nAceV2.Dll, Wkernel32.dll, mscoree.dll, \SOFTWARE\Microsoft\Windows\Curr

Files Allowed: user32.dll, kernel32.dll, uxtheme.dll, gdi32.dll, crypt32.dll, coleto r.dll, vcltest3.dll, pstorec.dll, MAPI32.DLL, version.dll, comctl32.dll, shell32.d ll,

Files Allowed: 2ntdll.dll, WININET.dll, shlwapi.dll, MSVCR110.dll, CRYPT32.dll, SH ELL32.dll, user32.dll, ADVAPI32.dll, PSAPI.DLL, kernel32.dll, GDI32.dll, msvc rt.dll,