Forum: Projeler Rhodeus Script RSS
Runtime DLL çağırma
Sayfa:  1  2  sonraki 
Avatar
zekeriyadurmus #1
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Runtime DLL çağırma
Daha önce burada ( http://ddili.org/forum/thread/1136 ) ve burada ( http://ddili.org/forum/thread/1131 ) bahsetmiş olduğumuz dinamik olarak runtime esnasında dll çağırıp işleve erişme işlemleri için az önce kafamda şimşekler çaktı diyebilirim :)

Tek bilmem gereken şey şu; fonksiyon çağırma işlemleri nasıl gerçekleşiyor?

Zekeriya
Bilgi meraktan gelir...
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4391 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Soruyu doğru anladım mı? İşlev göstergesine dll içindeki işlevin adresi verilir ve işlev göstergesi bir işlev gibi çağrılır.

Ek: Bundan sonra çıkacak olan DConf konuşması Martin Nowak'ın "Shared libraries in D" konuşması. Pazartesi günü hazır olacak.

Ali
Bu mesaj acehreli tarafından değiştirildi; zaman: 2013-05-25, 07:21.
Avatar
zekeriyadurmus #3
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Ali hocam yapacağım şey şu aslında.

Fonksiyona alacağı tüm verileri türsüz olarak byte olarak veya int olarak göndereceğim. Yani fonksiyonun yine hangi parametreleri aldığını script dili üzerinden belirtecekler ama int olarak belirtti ya 4 baytlık veri göndereceğim. Sonuç olarak fonksiyon ona int olarak davranacak ve zaten eğer script içerisinde string olarak belirtilirse bu sefer de haliyle hata verecek ama sonuç olarak fonksiyonu çağırabilecek ve statik olarak fonksiyon parametreleri tanımlanmamış olacak.

Sanırsam bu olayı yapabilmek için iasm kullanmak gerekecek. D dili buna müsaade etmiyordur gibime geliyor, iasm ile yapılabilir.

Zekeriya
Bilgi meraktan gelir...
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4391 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
C ailesinden olan sistem dilleri buna izin verir.
import std.stdio;
 
void foo(void * baytlar)
{
    int * gösterge = cast(int*)(baytlar);
    int değer = *gösterge;
 
    // ... burada 'değer' kullanılır ...
 
    writeln("aldığım parametre: ", değer);
}
 
void main()
{
    int i = 42;
    int * p = &i;
    foo(p);
}
void* yerine biraz daha güvenli olan void[] de kullanılabilir. Ayrıca variadic parameter olanağı da var.

Ali
Avatar
zekeriyadurmus #5
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bilmiyorum sanırsam ya tam anlayamadım yada anlatamadım ama http://ddili.org/forum/post/9108 adresindeki MessageBoxA, ClipCursor gibi işlevleri bu şekilde çalıştırmayı istiyorum. Yani bu şekilde fonksiyonu void* olarak tanımlamayacağım fonksiyon zaten var ve int alır, string alır ama ben onun int aldığını script dili üzerinden bilerek çağırma işlemi yapacağım.

Zekeriya
Bilgi meraktan gelir...
acehreli (Moderatör) #6
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4391 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
aracıİşlev, sana ait bir işlev. Sen hangi asıl işlevi çağıracağını ve parametrenin aslında ne türde olduğunu biliyorsun:
void asılİşlev(string s)
{
    assert(s == "merhaba");
}
 
void aracıİşlev(void * parametre)
{
    // Sen bu noktada asılİşlev()'i çağırman gerektiğini ve onun string
    // aldığını biliyorsun. Onun için bize verilmiş olan void* parametresinin
    // bir string göstergesi olduğuna inanıyoruz:
    string s = *cast(string*)parametre;
 
    // ve çağırıyoruz:
    asılİşlev(s);
}
 
void main()
{
    // Çağıran tarafta aslında bir string var:
    string s = "merhaba";
 
    // Bir noktada bu bilgiyi kaybediyoruz:
    void * p = &s;
 
    // aracıİşlev'in doğru türü bildiğine güvenerek tür bilgisini kaybetmiş
    // olan parametremizi gönderiyoruz:
    aracıİşlev(p);
}

Ali
Avatar
zekeriyadurmus #7
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Hocam demek istediğim bu değil bu işlevi ben tanımlamıyorum zaten tanımlanmış. Şöyle bir şey yaptım.

module main;
 
import std.stdio;
 
void x(int z, int z2){
    writeln(z," -- ", z2);
}
 
int main(string[] argv){
 
    asm{
        mov EAX, 2;
        push EAX;
        mov EAX,3;
        call x;
    }
   return 0;
}

Ama string işlemlerini beceremedim...

Zekeriya
Bilgi meraktan gelir...
acehreli (Moderatör) #8
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4391 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
İşlevi senin tanımladığı düşünmedim.

Örnekteki foo, sana ait olmayan ama bildirimini senin bildiğin bir işlev olsun. Ben kod içine yazdım ama bir DLL içinde de tanımlı olabilir. Sen yalnızca onun string aldığını biliyorsun.

Örnekteki aracıİşlev sensin. Elinde yalnızca void* diye bir parametre var. Onun aslında ne olduğunu bilemezsin ama anlaşmalara uygun olarak onun foo'yu çağırırken kullanılacağını bildiğin için buna güvenerek onu bir string* gibi kullanıyor ve foo'yu o string ile çağırıyorsun.

Bu, C'de de çok uygulanan bir yöntemdir. İşlev çağrısı perde arkasında senin assembly'den farklı olmayacaktır. D'de daha temiz ve güvenli çözümler de bulunabilir.

Ali
Avatar
zekeriyadurmus #9
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Evet onun string aldığını biliyorum ama,
(int, string, int, bir struct) gibi daha kompleks ve çeşitli yapılar gelebilir bu noktada string s gibi tanımlamam doğru olmayacaktır.

Biraz asm boyutunu inceledim ve her şey push metodu ile stacka atılıyor. String gönderildiğinde ise string içerisinde int ve ptr bulunduğu için ikisini ayrı ayrı push ediyoruz. Bu şekilde fonksiyon çağırılacak, yapıyı çözdüm ve ilerleyen zamanlarda kodları burada paylaşacağım...


Zekeriya
Bilgi meraktan gelir...
Avatar
zekeriyadurmus #10
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Ali hocam an itibariyle istediğimi gerçekleştirmiş bulunmaktayım...

Ama http://ddili.org/forum/post/9108 adresindeki GetProcAddress komutunu kullanarak compiled time işlevi tanımlamadan yapabilirim inşallah. Belki dll çağırmalarında asm boyutunda farklı kodlar çalışıyor ama eğer çalışmıyorsa şu anda doğrudan bu sisteme uygulayabilirim.

module main;
 
import std.stdio;
import core.memory;
 
void xx(int a, int b, string x){
    writeln(x, a+b);
}
struct adata{
    uint typ;
    void* veri;
}
enum{
    INT, STRING
}
int main(string[] argv){
    int sayi1 = 40;
    xx();
    int sayi2 = 20;
    string metin = "toplam = ";
    adata[] dizi = [adata(INT, &sayi1), adata(INT, &sayi1), adata(STRING, &metin)];
 
    foreach(d; dizi){
        final switch(d.typ){
            case INT:
                int x = *cast(int*) d.veri;
                asm{push x;}
            case STRING:
                string x = *cast(string*) d.veri;
                auto l= x.length;
                auto c = x.ptr;
                asm{
                    push c;
                    push l;
                }
                break;
        }
    }
    asm{
        call xx;
    }
 
 
    while(1){}
   return 0;
}

Zekeriya
Bilgi meraktan gelir...
Avatar
Salih Dinçer #11
Üye Ock 2012 tarihinden beri · 1880 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Merhaba Zekeriya,

Biz main() içinde şu işlevi parametre vermeden doğal yollardan ve assembly kümesi içinde çağırmışız. Peki nasıl derlenecek?
void xx(int a, int b, string x){
    writeln(x, a+b);
}
Başarılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
zekeriyadurmus #12
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Neyin derleneceğini sorduğunuzu anlayamadım ama o kodların tamamı çok rahat derlenebiliyor. Önceki başlıkta çalıştırılacak olan fonsiyonu GetProcAddress ile runtime çağırabiliyoruz ama parametrelerini bilmiyoruz compile time tanımlamak gerekiyor ama bu uyguladığım yapı sayesinde runtime esnada parametreleri tanımlayarak çağırabilmeye imkan tanıyoruz mesela;

dll = dll.load("Kernel32.dll)"
SizeofResource = dll.define("DWORD","SizeofResource","ptr","ptr")
SizeofResource(HModule, HRSRC) // bu 2 değişken de önceden tanımlanıyor. 

Buradaki olay şu dll yüklemesi yapılıyor daha sonra SizeofResource değişkenine dll fonksiyonu aldığı parametre türleri belirtilerek yerleştiriliyor ve istenilen yerde SizeofResource fonksiyonu o paramtreler belirtilerek çağırılıyor.

Zekeriya
Bilgi meraktan gelir...
acehreli (Moderatör) #13
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4391 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Sanırım Salih main'in ikinci satırındaki xx() çağrısının derlenemediğini söylüyor.

Ali
Avatar
zekeriyadurmus #14
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Hocam şu an tek çözülmesi gereken şey şu;

    85: 
    86:     auto adres = &talha;
0040222C B8 CC 21 40 00       mov         eax,4021CCh  
00402231 89 45 EC             mov         dword ptr [adres],eax  
    87:     asm{
    88: //        push adres;
    89: //        mov ECX, 
    90:     }
    91: 
    92:     integral(&talha);
00402234 50                   push        eax  
    87:     asm{
    88: //        push adres;
    89: //        mov ECX, 
    90:     }
    91: 
    92:     integral(&talha);
00402235 8B 0D 00 C1 42 00    mov         ecx,dword ptr ds:[42C100h]  
0040223B 64 8B 15 2C 00 00 00 mov         edx,dword ptr fs:[2Ch]  
00402242 8B 1C 8A             mov         ebx,dword ptr [edx+ecx*4]  
00402245 FF 93 1C 00 00 00    call        dword ptr [ebx+1Ch]  
0040224B DD D8                fstp        st(0)
Buradaki asm kodlarını iasm üzerinden yazabilirsek eğer bu yeni sistemi uygulamak için hiçbir engel kalmaz inşallah :)

Zekeriya
Bilgi meraktan gelir...
Avatar
zekeriyadurmus #15
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
ASM boyutuna girmeden bu işlemleri hallettim. CSS de falan bu gibi işlemlere CSS Hack deniliyor. Sanırsam benim de bu işleme d hack dememde sakınca olmaz?

    void function() dllcall;
Olarak tanımladım sonra da
    auto adres = &talha;
    asm{
        mov EAX, adres;
        push EAX;
    }
    dllcall();
    float x;
    asm{
        fstp dword ptr [x];
    }
Yaptım aslında fonksiyonun return değeri de var parametreleri de var ama ben yokmuş gibi çağırdım :)

Zekeriya
Bilgi meraktan gelir...
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  1  2  sonraki 
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-04-26, 12:40:08 (UTC -07:00)