Win32 PE executable with DJGPP GNU C/C++ compiller.
Small description of utilites.
The software described in this document is destributed under a
GNU General Public License.
GNU software is Copyright by the Free Software Foundation.
DJGPP is Copyright by DJ Delorie.
Windows is a trademark of Microsoft Corporation.
Windows NT is a trademark of Microsoft Corporation.
Windows 2000 is a trademark of Microsoft Corporation.
Other product names mentioned in this description may be trademarks
or registered trademarks of their respective companies and are hereby
acknowledged.
How to install?
To install your need:
- Unpack arhive. E.g. type:
pkunzip -p win_peb.zip c:\djgpp
(The good idea is to read
this document up to end beforhand)
- Make linkable libraries (.a files) for Win32 API DLL. As rule it's
nessesary to make libraries for user32.dll, kernel32.dll, gdi32.dll. As well
frequently advapi32.dll, comdlg32.dll, shell32.dll are nessesary too. To use
Socket your need library for wsock32.dll, to use PlaySound function your need
winmm.dll, etc.
To make library you can create temporary directory, the first, is good idea,
but it's dispensable.
Change curent directory to it and run dll2a.exe for each
DLL need you. E.g. type:
c:\>mkdir c:\lib_temp
c:\>cd c:\lib_temp
c:\lib_temp>dll2a.exe user32.dll
c:\lib_temp>ren user32.a c:\djgpp\lib\libuser.a
You can use next makefile and generate all automaticaly with DJGPP GNU MAKE.
#begin of 'makefile'
LIBDIR=$(DJDIR)/LIB/
DLLDIR=$(WINDIR)/SYSTEM/
# For Windows NT or 2000 DLLDIR must by
# DLLDIR=$(WINDIR)/SYSTEM32/
# WINDIR -- predefined Windows enviroment variable
# DJDIR -- DJGPP enviroment variable, must be defined
# in DJGPP.ENV
lib: libuser.a libuser.a libkern.a libgdi.a \
libshell.a libwadv.a lwinmm.a lwinmm.a lcdlg.a
libuser.a: user32.dll
dll2s.exe -o $@ $<
libkern.a: %(DLLDIR)kernel32.dll
dll2s.exe -o $(LIBDIR)$@ $<
libgdi.a: %(DLLDIR)gdi32.dll
dll2s.exe -o $(LIBDIR)$@ $<
libshell.a: %(DLLDIR)shell32.dll
dll2s.exe -o $(LIBDIR)$@ $<
libwadv.a: %(DLLDIR)advapi32.dll
dll2s.exe -o $(LIBDIR)$@ $<
libwinmm.a: %(DLLDIR)winmm.dll
dll2s.exe -o $(LIBDIR)$@ $<
libcdlg.a: %(DLLDIR)comdlg32.dll
dll2s.exe -o $(LIBDIR)$@ $<
libwsock.a: %(DLLDIR)wsock32.dll
dll2s.exe -o $(LIBDIR)$@ $<
#end of 'makefile'
It borrows some time, because for each function in each library assembler
file will be created, exec "as.exe" and exec "ar.exe". Up to ten minuit
per library for big library and slow machin.
- At last you must customize your "specs" file to run make_pe.exe
to convert a.out to Win32 PE. By default arhive contents valid "specs" file,
and by default it replase that file in DJGPP\LIB directory, but any GCC newer
then 2.8 find this file in DJGPP\LIB\GCC-LIB\DJGPP\2.952 for GNU C++ 2.952 or
DJGPP\LIB\GCC-LIB\DJGPP\EGCS-291.66 for EGCS C++ 2.91.66, etc. I don't know,
what version you use, I thing it's not a problem for you replase or
update using file by your own. The "specs" in my arhive add two key to GCC:
- -Zpe --to generate Win32 PE executable
- -Zcon --used only with -Zpe to generate Win32 console application.
You can define your own keys. To generate PE you must use "djgppe.djl" linker
script. "*startfile" for PE must be "crt0pe.o".
These files are also present in my arhive and be default placed to DJGPP\LIB.
- The big trouble it is header files, and description
of API functions. It is part of Microsoft Windows SDK, and I
can't destribute tham. Now you can found these files in diferent
location. It is included in any other Windows compiller, but
in many case they doesn't directly compilled with GNU.
To compile Microsoft's header with GNU compiller, easy changes
must be done. In the begining of the file
#define __stdcall __attribute__((stdcall))
must be inserted. In some case you must edit Microsoft's
function declaration, move "PASCAL" to the end of
declaration. E.g. if in SDK header present:
struct hostent* PASCAL gethostbyname(const char* name);
struct hostent* gethostbyname(const char* name) PASCAL;
If you have nothing, use header's generated by DLL2S. In this case
you must edit these files, insert argument in declaration of each
function or use "gw_api.h". This file contents next definetion:
inline void PUSH(int a)
{ asm volatile("pushl %0;": :"g" (a) ); };
inline void PUSH(void* a)
{ asm volatile("pushl %0;": :"g" (a) ); };
#define API1(f,a) ( PUSH(a),f())
#define API2(f,a1,a2) ( PUSH(a2),PUSH(a1),f())
...
And you can call to API e.g. this way:
#include "gw_api.h"
extern "C" {
#include <user32.h>
#include <kernel32.h>
};
...
API4( MessageBox, 0, &"Hello world !",&"Test", 0);
Warning! In this case you must use optimisation (keys -O1, -O2, -O#),
otherwise GNU compiller generate inline function as no inline, and
PUSH failure. In this case you can use #define instead inline.
This might be use only with GNU 2.8x or older.
DLL to .a convertor
This program read incomming DLL-file, get names of functions from it,
and for each function:
generate easy assembler file;
exec "as.exe" to compile this file;
exec "ar.exe" to add this file to output library;
add incomplete declaration of function to output header file.
At the last header file is stored.
Command line have next format:
dll2s.exe {[-keys]}[-o out_file_name][-n filename] file.dll
Next option's keys supported:
- -s -- store assembler source, otherwise temporary
assembler files are deleted.
- -a -- generate one AT&T assembler file only.
- -i -- generate one Intel assembler file only.
- -u -- add "unnamed" functions.
Some DLL-functions could have no name.
It might be linked by number. Program also could
add these functions to the library, but what's the reason ?
- -l -- always use number for link.
Default name of function is used, so it's possible. It is calculable.
To use number you must overwrite startup file "crt0pe.o".
- -d -- no generate header file.
- -j -- store objects, otherwise
temporary objects files are deleted.
- -n -- name for assembler file.
- -r -- generate header file only
- -f -- no generate #define for A-function.
All Windows API functions that recive string as argument
have ASCI and UNICODE versions.
Usually one DLL contents both functions. The last symbol
in the name of ASCI version is 'A'. The last symbol
in the name of UNICODE version is 'W'.
By default, for each ASCI function DLL2S add to header file
#define that define name without last 'A' as name with 'A'.
Make PE from COFF a.out
This program only adds DOS stub and first part of PE header.
Command line have next format:
make_pe [-c][-s Stack_Reserve_Size][-p Heap_Reserve_Size][-o out_file] input_file
Next option's keys supported:
- -c -- to generate Win32 console application.
- -s -- to define Stack Reserve Size. By default it is 64 Kb.
- -p -- to define Heap Reserve Size. By default it is 1 Mb.
- -o -- to define name of output file.
This program always setup Commit Heap Size and Commit Stack Size to 4 Kb.
Program will not use more memory until program doesn't requist it.
This program could convert only specifed COFF files, that begin
from the last part of PE header. This part is precent in the "crt0pe.o" --
startup file. It must be linked the first. It defines in "djgppe.djl"
-- linker script.
max (Shift-2) mf.inc.ru M. Feoktistov
|
|