2010-09-07 13 views
28

Farz edelim ki open() sistem çağrısını tamamen devralmak, belki de gerçek sistem çağrısı yapmak ve bazı günlük işlemleri yapmak istiyorum. Open() giriş noktasını ele alan bir (kullanıcı tarafından oluşturulmuş) paylaşılan nesne kitaplığını yüklemek için One way to do this is to use LD_PRELOAD.Linux'ta bir syscall işlevini nasıl yeniden (veya sarma) yaparım?

Kullanıcı tarafından oluşturulan open() rutini, işaretçiyi open() glibc işlevinin dlsym() tarafından almasını ve çağırmasını sağlar. Bununla birlikte, yukarıda önerilen çözüm dinamik bir çözümdür. Kendi open() sarmalayıcımı statik olarak bağlamak istediğimi varsayalım. Bunu nasıl yaparım? Sanırım mekanizma aynı, ama aynı zamanda kullanıcı tanımlı open() ve libc open() arasında bir sembol çatışması olacağını tahmin ediyorum.

Aynı amaca ulaşmak için lütfen başka teknikleri paylaşın.

+0

Kodunuza yalnızca bir sarıcı işlevi/makro yapıştırıyorsunuz? –

+0

@Seamus: Makroları kullanmamayı tercih ediyorum. Gerçekten bir sorunum yok. Sadece SO bilgisini arttırmak ve yeni bir hile öğrenmek istiyorum. –

cevap

56

Sen ld tarafından sağlanan sarma özelliğini kullanabilirsiniz. man ld:

--wrap symbol Sembol için bir sarıcı işlevini kullanın. symbol için tanımsız herhangi bir başvuru, __wrap_symbol olarak çözülecektir.

__real_symbol için tanımsız bir referans symbol için çözülecektir.

Yani sadece gerçek işlevi çağırmak istediğinizde, sarıcı fonksiyonu ve __real_ için önek __wrap_ kullanmak zorunda. Basit bir örnek aşağıda verilmiştir:

malloc_wrapper.c:

#include <stdio.h> 
void *__real_malloc (size_t); 

/* This function wraps the real malloc */ 
void * __wrap_malloc (size_t size) 
{ 
    void *lptr = __real_malloc(size); 
    printf("Malloc: %lu bytes @%p\n", size, lptr); 
    return lptr; 
} 

test uygulama testapp.c:

gcc -c malloc_wrapper.c 
gcc -c testapp.c 
gcc -Wl,-wrap,malloc testapp.o malloc_wrapper.o -o testapp 

elde edilen uygulamanın çıkışı olacaktır:

#include <stdio.h> 
#include <stdlib.h> 
int main() 
{ 
    free(malloc(1024)); // malloc will resolve to __wrap_malloc 
    return 0; 
} 

sonra uygulama derleme:

$ ./testapp 
Malloc: 1024 bytes @0x20d8010 
+3

+1 bu, soooo cool: D –

+1

Bu, malloc çağıran işlevin dinamik olarak bağlanmış görünmüyor. Örneğin, malloc çağıran perform_alloc() işlevini içeren bir tools.c yazdım. Sonra bir libtools.so yaparsam ve bunu dinamik olarak '-ltools' ile bağlarsam, -Wl, -wrap, malloc işe ​​yaramaz. – xanpeng

+1

http: // stackoverflow'de yanıtlandığı gibi.com/questions/3826108/var-bir-için-sarma-bir-function-in-c için-var-bu C++ programında bu kodu kullanırken extern "C" ile fonksiyon tanımları öneki için gereklidir. – MKroehnert

2

Semboller, linker tarafından komut satırında listelediğiniz sırayla çözülür; böylece kitaplığınızı standart kitaplıktan önce girdiğinizde, önceliğiniz var demektir. Gcc için

belirtmeniz gerekir. Bu şekilde kütüphaneleriniz önce aranır ve bulunur.