GeirGrusom Skrevet 21. september 2005 Del Skrevet 21. september 2005 Problemet mitt består i at jeg skal skrive noen assembly funksjoner, og jeg har skrevet en C++ versjon av alle sammen, men istedet for å bruke dumpbin e.l. for å finne dekorerte navn på en funksjon, hadde det vært hendig med et verktøy som kunne dekorere en C++ funksjon, som jeg bare limte inn i .asm fila, noen som vet om noen? jeg søkte, men fant bare linker til UndName.exe, men den går jo feil vei.... En ting til: er det noen som vet om et api kall e.l. for å finne ut alle funksjoner en dll eksporterer? hadde vært kjekt hvis man vil lage et verktøy som automatisk lager en .h fil for en dll Lenke til kommentar
A_N_K Skrevet 21. september 2005 Del Skrevet 21. september 2005 Spørs om Microsoft eksponerer noe grensesnitt til kompilatoren sin for å dekorere funksjoner, da. En mulighet kunne være å skrive en slags front-end til kompilator + dumpbin? Når det gjelder eksporterte kall googlet jeg litt og fant i alle fall en forklaring om formatet. Du ser ut til å like å gjøre ting selv, så hvorfor ikke skrive API'et :_) Lenke til kommentar
Gjest Slettet+6132 Skrevet 21. september 2005 Del Skrevet 21. september 2005 (endret) Spørsmålet er vel egentlig: Hvorfor vil du "mangle" navn på en gitt funksjon? Vil du styre/overstyre kompilator? (Som typisk "hekter på" en @nn på hvert "entry" i en .dll). Når det gjelder det andre spørsmålet er det mer relevant... I tidlegere? versjoner av Windows/NT fantes den en "viewer" som man kunne se alle "entry-points" i en .dll. Det brukte jeg ofte for å skrive program (C/C++, MF Cobol) for å kalle funksjoner dynamisk i en dll... f.eks. Kernel32.dll.. SLikt er jo ikke pent da.., men "må man så må man".. Endret 21. september 2005 av Slettet+6132 Lenke til kommentar
Peter Skrevet 21. september 2005 Del Skrevet 21. september 2005 En ting til: er det noen som vet om et api kall e.l. for å finne ut alle funksjoner en dll eksporterer? hadde vært kjekt hvis man vil lage et verktøy som automatisk lager en .h fil for en dll Enig i den, hadde vært kjekt å ha. Er ikke så veldig vanskelig å skrive en basic greie en som bare løper gjennom alle .h filene i en mappe og lager deklarasjoner da, som den til slutt legger i en .h fil. Lenke til kommentar
kjetil7 Skrevet 22. september 2005 Del Skrevet 22. september 2005 (endret) Den vanlige framgangsmåten er å definere funksjonene med extern "C". Du vil da slippe problemet med dekorerte navn i C++. Nesten alle DLL-filer i Windows blir laget på denne måten og eksporterer sjelden dekorerte C++ navn. #ifdef __cplusplus extern "C" { #endif /* dine funksjoner her */ #ifdef __cplusplus } /* extern "C" */ #endif Hvis du likevel av en eller annen grunn ønsker å hente ut symboler i en DLL-fil har en fyr som heter Matt Pietrek skrevet noen artikler om temaet. De tar for seg PE (Portable Executable) og viser et eksempel på en DUMPBIN lignende sak. Peering Inside the PE: A Tour of the Win32 Portable Executable File Format An In-Depth Look into the Win32 Portable Executable File Format Endret 22. september 2005 av kjetil7 Lenke til kommentar
GeirGrusom Skrevet 22. september 2005 Forfatter Del Skrevet 22. september 2005 Takker for alle innlegg, det var veldig nyttig. hvis jeg skriver den .dlll->.h saken, så skal jeg si ifra Grunnen til at jeg trenger dette, er fordi jeg tenkte jeg skulle skrive matrix og vertex funksjoner i ASM, for å frigjøre noen hertz til annet bruk, men jeg skal beholde de gamle som de er, slik at enginen skal la seg compile under andre compilere og OS. Lenke til kommentar
GeirGrusom Skrevet 23. september 2005 Forfatter Del Skrevet 23. september 2005 (endret) Hmm, dette virker ikke så vanskelig, når en exe fil lastes, lages det en tabell over pekere til alle funksjoner, så alle 'CALL' instruskjoner byttes ut med JMP DWORD PTR (og offset til hver enkel funksjon som skal kalles) Tabellen over dette står det at skal ligge i .edata seksjonen, men jeg kan ikke finne noen .edata i noen dll filer..... Har også funnet ut at en kan lete fram hvor export table ligger, ved å bruke OptionalHeader.DataDirectory Så hvis jeg skal lage et program som laget .lib og .h filer, må jeg først liste alle eksporterte funksjoner, deretter lage en del som skriver en .lib fil med alle .dll funksjoner eksportert, og en del som lager header fil... virker ganske enkelt men vi får se. Det jeg har fått til hitill, er at jeg klarer å liste alle sections, men ikke noe særlig mer en det, jeg klarer ikke å lese importerte dll-er og funksjoner engang....... Jeg har også funnet ut at du kan bruke ImageHlp til dette (<Imagehlp.h>, Imagehlp.lib) int _tmain(int argc, _TCHAR* argv[]) { register int x; FILE *fp; IMAGE_DOS_HEADER dhdr; IMAGE_NT_HEADERS nhdr; IMAGE_SECTION_HEADER *sec_hdr; if(!(fp = fopen(argv[0], "rb"))) return 1; //fread(&dhdr, sizeof(dhdr), 1, fp); fread(&dhdr, sizeof(dhdr), 1, fp); fseek(fp, dhdr.e_lfanew, SEEK_SET); fread(&nhdr, sizeof(nhdr), 1, fp); //fread(&fhdr, sizeof(fhdr), 1, fp); cout << "Machine:"; switch(nhdr.FileHeader.Machine) { case IMAGE_FILE_MACHINE_I386: cout << "Intel 32-bit processor"; break; case IMAGE_FILE_MACHINE_ALPHA: cout << "Alpha processor"; break; case IMAGE_FILE_MACHINE_AMD64: cout << "AMD 64 Processor"; break; case IMAGE_FILE_MACHINE_IA64: cout << "Intel Itanium 64 bit processsor"; break; default: cout << "Unknown processor"; } cout << "\nNumber of sections:" << nhdr.FileHeader.NumberOfSections << "\n"; sec_hdr = new IMAGE_SECTION_HEADER[nhdr.FileHeader.NumberOfSections]; fread(sec_hdr, sizeof(IMAGE_SECTION_HEADER), nhdr.FileHeader.NumberOfSections, fp); for(x = 0; x < nhdr.FileHeader.NumberOfSections;x++) { cout << "\t" << sec_hdr[x].Name << "\t\t " << sec_hdr[x].VirtualAddress; if(!strcmp((char*)&sec_hdr[x].Name, ".idata")) cout << " (import table)"; if(!strcmp((char*)&sec_hdr[x].Name, ".rdata")) cout << " (export table)"; cout << "\n"; } cout << "Number of symbols:" << nhdr.FileHeader.NumberOfSymbols << "\n\n"; cout << "Imported functions:"; if(!nhdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) cout << " None\n\n"; else { unsigned long address; unsigned long size; cout << "\n"; char *str; IMAGE_IMPORT_DESCRIPTOR imp; memset(&imp, 0, sizeof(imp)); imp.TimeDateStamp = 0; size = nhdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; address = nhdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; fseek(fp, address, SEEK_SET); for(;;) { fread(&imp, sizeof(IMAGE_IMPORT_DESCRIPTOR), 1, fp); if(!imp.TimeDateStamp) break; //str = read_string(sec_hdr[idata_section].Misc.PhysicalAddress + imp.Name, fp); cout << str << "\n"; free(str); } } cout << "Number of exports:"; if(!nhdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) cout << "None\n"; else { IMAGE_EXPORT_DIRECTORY expdir; fseek(fp, nhdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, SEEK_SET); fread(&expdir, sizeof(expdir), 1, fp); cout << expdir.NumberOfFunctions << "\n"; char **fn_names = new char*[expdir.NumberOfFunctions]; fseek(fp, expdir.AddressOfFunctions, SEEK_SET); for(x= 0;x<expdir.NumberOfFunctions;x++) { unsigned long str_ptr; fn_names[x] = read_string(str_ptr, fp); cout << " " << fn_names[x]; } } fclose(fp); cin.get(); delete [] sec_hdr; return 0; } Endret 23. september 2005 av GeirGrusom Lenke til kommentar
kjetil7 Skrevet 24. september 2005 Del Skrevet 24. september 2005 Nå har jeg ikke studert PE, men vil du ikke få problem med å hente ut riktige parametre til funksjonene du ønsker å skrive til header-filen din? Eventuelle C++ typer og lignende er det vel heller tvilsomt at blir bevart... Skjønner at det er interessant å studere PE og gå litt inn i dybden, men jeg tror du ender opp med å eksportere extern "C" funksjoner. Det er en veldig elegant løsning etter min mening. Og du kan jo fortsatt bruke C++ internt i funksjonene. MS har noen kompilatortillegg som lar deg eksportere klasser og lignende. Men du blir da bundet til at alle komponenter bruker samme kompilator og standardbibliotek hvis du bruker elementer derfra. Dette er vel en av hovedårsakene til at COM så dagens lys... Lenke til kommentar
Gjest Slettet+6132 Skrevet 24. september 2005 Del Skrevet 24. september 2005 Enhver funksjon som er "bundlet" i en såkalt "extension-DLL" har ett sett med funksjoner/entrypoints med tilhørende parametre.. Som Kjetil7 antyder her.. dukket COM opp bl.a. for å støtte runtime mulighet for å sjekke ut parametre.. Så gjentar jeg spørsmålet..: Hvorfor ønsker man å vite navn på funksjoenr i en DLL? Jo.. normalt for å kunne kallle disse fra et-eller-annet gr.snitt/progr.språk.. Dette er "teknisk" kode og kan løses uten å blande inn kompilatorer/verktøy annet enn det man bruker for å kalle en gitt funksjon dynamisk i en gitt .DLL. Det man må ha er selvsagt header-file/dokumentajon på API'et..dvs. paramtre inn/ut til en gitt funksjon.. Så kaller man den enkelt og greit fra sitt program.. I C/C++ ved LoadLibrary() og GetProcAddress(), i f.ek.s MF Cobol ved å CALL'e 'myDLL.dll'.. I Java ved å bruke JNI.. Dette er "stygt", men noen ganger nødvendig av ulike årsaker.. særlig i miljø der ulike språk/compiler/RTS (Run-Time-SYstems) skal "mixes". Når man av performance-hensyn ønsker å "speede" koden sin.. kan man jo likegodt kode maskinkode (ASM). Uleselig, men funksjonell kode.. og så "hardware-bound" som man kan komme.. Lenke til kommentar
GeirGrusom Skrevet 25. september 2005 Forfatter Del Skrevet 25. september 2005 (endret) Jeg skriver alltid én C++ funksjon først, som jeg legger inn i en #ifdef EXTERN_FUNCTION som bare betyr at koden er blitt kompilert av et annet verktøry, MASM, og C++ koden skal ikke brukes. SSE og SSE2 er veldig enkelt å sjekk om prosessoren støtter, det er gjort ved å kalle mov eax, 1 cpuid og det ligger da som flags i EDX registeret, og kan sjekkes da med (EDX & 0x2000000 (SSE)) og deretter kalle SSE kode, hvis det er støttet, elle binde den med en funksjonspeker. deretter, sparer man masse CPU! forresten, med PE formatet, har jeg kokt ihop et foreløpig litt uferdig program i C#, det er mer eller en hex editor for PE filer, en kan velge en header i en listbox, høyreklikke og velge "Jump to offset" så går hex editoren til det området i hex dumpen, man kan også velge felt i property viewer, og gjøre samme saken, alle objekter arver IFileEntry som inneholder hvor i filen strukturen ligger, og hvis noen feil har det interface, kan hex editoren hoppe dit, dere kan prøve dere frem hvis dere gidder. hadde håpet på å legge inn disassembler, men tror det kan bli litt mye jobb... har ikke helt fått fram exports enda, mye fordi jeg fortsatt har hangover... Enjoy! takk for alle inspill! dere har vært til uvurdelig hjelp, jeg skal legge noe av dette jeg har laget inn i spill motoren, for å bedre "modul" støtte, slik at det skal bli letter å utvikle, ved at enginen stort sett finner ut av hvordan biblioteket er laget, uten noe store "export" klasse typer, den kikker etter en funksjon som heter "GetImplementedInterface" og lister alle klasser som har dem i dll fila, for deretter å lage en komplett liste med klasser som kan instansieres i prosjektet. :edit ville legge til at jeg begynner å få inn en disassembler nå alt ble litt enklere når jeg skjønte hva RVA (Relative Virtual Address) var, og hvordan en gjorde de om til filpekere. PEdit.zip Endret 27. september 2005 av GeirGrusom Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå