GCC target PE32+
GCC target PE32+
Is there a GCC cross compiler target PE32+ (64bit PE) ?
EDIT: I don't want the compiler readymade from someone else. I just want to know whether I can build a cross compiler for PE32+.
Greetings
Peter
EDIT: I don't want the compiler readymade from someone else. I just want to know whether I can build a cross compiler for PE32+.
Greetings
Peter
Re: GCC target PE32+
Yeah, sure. But you don't need a cross-compiler, the simple way out is to compile to ELF as usual and as a last step call objconv or objcopy to convert the output to PE.PeterX wrote:Is there a GCC cross compiler target PE32+ (64bit PE) ?
Otherwise you can compile gcc and binutils for PE target, pretty much the same way as you would with any other targets. There are many projects that already done this, MinGW for Linux pops into my mind. It is very likely that you can access it from your distro's standard repo, but if not, download it from the linked page. (FYI: MinGW is not the only one, there are others. It's just the simplest to use to my humble opinion.) Try
Code: Select all
sudo apt-get install gcc-mingw-w64
Cheers,
bzt
Re: GCC target PE32+
OK, maybe what I'm trying to do is not so smart. Let's see:
The whole thing I'm trying to do is producing an UEFI application.
I thought of producing PE32+ as an UEFI application.
EDK2 and GNU-EFI can do that. But it's a pain and I think I could reduce or replace the dependencies (for me and maybe for others).
I thought: Let's produce an normal object file from C source-code file using GCC. As it seems this could be a 64bit ELF or COFF (both should work).
And then link a little assembler object file with the object file from GCC together to a PE32+ UEFI application.
(The assembler object file would NOT replace a standard C library with main() etc.)
Is the whole thing obsolete? I managed to build EDK II and OVMF, but it still is difficult to produce a UEFI application with it, because you need to edit a DSC file and produce in inf file. And the GNU-EFI include file seems not very mature.
Greetings
Peter
The whole thing I'm trying to do is producing an UEFI application.
I thought of producing PE32+ as an UEFI application.
EDK2 and GNU-EFI can do that. But it's a pain and I think I could reduce or replace the dependencies (for me and maybe for others).
I thought: Let's produce an normal object file from C source-code file using GCC. As it seems this could be a 64bit ELF or COFF (both should work).
And then link a little assembler object file with the object file from GCC together to a PE32+ UEFI application.
(The assembler object file would NOT replace a standard C library with main() etc.)
Is the whole thing obsolete? I managed to build EDK II and OVMF, but it still is difficult to produce a UEFI application with it, because you need to edit a DSC file and produce in inf file. And the GNU-EFI include file seems not very mature.
Greetings
Peter
Re: GCC target PE32+
Have you looked at this tutorial?
Re: GCC target PE32+
Wow, thanks, I didn't see that.nexos wrote:Have you looked at this tutorial?
That gives me some stuff to read. Looks like it is what am asking about
Greetings
Peter
Re: GCC target PE32+
Let's not mix these two, they use different approach. For the EDK, it internally uses PE. For GNU-EFI, it always uses the native toolchain and convert to PE in the last step.PeterX wrote:I thought of producing PE32+ as an UEFI application.
EDK2 and GNU-EFI can do that.
Take a look at my boot loader. I've managed to shrink the build environment considerably: BOOTBOOT x86_64-efi. Here crt0 is what its look like. The lds file is a linker script. The files libefi.a provides mostly GUIDs and high level functions (like Print()) and libgnuefi.a the low level stuff (like uefi_call_wrapper()). That's all, no third party dependencies.PeterX wrote:But it's a pain and I think I could reduce or replace the dependencies (for me and maybe for others).
Check out my Makefile, it compiles everything into ELF (on Linux), and then uses objcopy convert it into PE. There are many gotchas during this process, see how many flags I had to use, but at the end of the day I can compile EFI applications with native GNU toolchain, without requiring anything special. So what you had in mind is perfectly doablePeterX wrote:I thought: Let's produce an normal object file from C source-code file using GCC. As it seems this could be a 64bit ELF or COFF (both should work).
And then link a little assembler object file with the object file from GCC together to a PE32+ UEFI application.
True, it is a real pain in the @ss.PeterX wrote:I managed to build EDK II and OVMF, but it still is difficult to produce a UEFI application with it,
Also true, however it has almost everything you need for a bootloader. And for those few things that it might lack, you can always add some structs and a GUID in you app, it is not a big deal.PeterX wrote:And the GNU-EFI include file seems not very mature.
Cheers,
bzt
Re: GCC target PE32+
just don't forget, that all these "converters" are snake oil and they in fact DON'T LET you use PE at full potential - import/export etc. for this, you need a compiler that DOES support PE targetting.
an easy example: no __declspec(dllimport). no IAT, bye. it's a compiler task, not some postprocessing mumbojumbo utility. you declare a function as dllimported and the compiler calls it differently, say
call [__imp_IsSh1tDone]
instead of
call IsSh1tDone
that symbol is a IAT residing pointer.
you see, it's a code generation thing - to make the former call instead of, a common, latter. not postprocessing. what all those converters do is crippled down PEs. for example neither edk (I guess, I am sure) nor UEFI applications don't make use import/export mechanism. but the fully fledged environment would want to use it.
an easy example: no __declspec(dllimport). no IAT, bye. it's a compiler task, not some postprocessing mumbojumbo utility. you declare a function as dllimported and the compiler calls it differently, say
call [__imp_IsSh1tDone]
instead of
call IsSh1tDone
that symbol is a IAT residing pointer.
you see, it's a code generation thing - to make the former call instead of, a common, latter. not postprocessing. what all those converters do is crippled down PEs. for example neither edk (I guess, I am sure) nor UEFI applications don't make use import/export mechanism. but the fully fledged environment would want to use it.
Re: GCC target PE32+
Ah, I see what you mean. I will keep that in mind if I ever write a PE32+ kernel. For now I stick to (simple) UEFI applications.zaval wrote:just don't forget, that all these "converters" are snake oil and they in fact DON'T LET you use PE at full potential - import/export etc. for this, you need a compiler that DOES support PE targetting.
an easy example: no __declspec(dllimport). no IAT, bye. it's a compiler task, not some postprocessing mumbojumbo utility. you declare a function as dllimported and the compiler calls it differently, say
call [__imp_IsSh1tDone]
instead of
call IsSh1tDone
that symbol is a IAT residing pointer.
you see, it's a code generation thing - to make the former call instead of, a common, latter. not postprocessing. what all those converters do is crippled down PEs. for example neither edk (I guess, I am sure) nor UEFI applications don't make use import/export mechanism. but the fully fledged environment would want to use it.
Re: GCC target PE32+
You should not use PE dll import/export function under UEFI at all! Your code will suck and will break on various firmware! UEFI was never designed to handle dlls!zaval wrote:just don't forget, that all these "converters" are snake oil and they in fact DON'T LET you use PE at full potential - import/export etc.
Under UEFI, PE is just a container format for a single (but relocateable) code image file. All the firmware provided interfaces are "dynamically linked" by querying their addresses using LocateHandle or OpenProtocol etc. If you want dynamic linking, you should register such handles in your modules too, and use LocateHandle and friends in your main app. To assure ABI compatibility, GNU EFI provides "uefi_call_wrapper" function, always use that, and any C compiler will do!
But more importantly, who does need complex infrastructure for pre-OS environment (other that rootkits and spyware I mean)?
Just make it load your kernel and get the hell out of there as soon as possible!
Cheers,
bzt
Re: GCC target PE32+
Yeah, after reading the several answers I come to the same conclusion. I intend to writebzt wrote:Just make it load your kernel and get the hell out of there as soon as possible!
1.) Hello World
2.) system info
3.) minimal kernel loader
All both for learning and for giving example code to other people.
Greetings
Peter
Re: GCC target PE32+
first of all, this topic has nothing to do with UEFI. its author asked this question:bzt wrote:You should not use PE dll import/export function under UEFI at all! Your code will suck and will break on various firmware! UEFI was never designed to handle dlls!zaval wrote:just don't forget, that all these "converters" are snake oil and they in fact DON'T LET you use PE at full potential - import/export etc.
Under UEFI, PE is just a container format for a single (but relocateable) code image file. All the firmware provided interfaces are "dynamically linked" by querying their addresses using LocateHandle or OpenProtocol etc. If you want dynamic linking, you should register such handles in your modules too, and use LocateHandle and friends in your main app. To assure ABI compatibility, GNU EFI provides "uefi_call_wrapper" function, always use that, and any C compiler will do!
But more importantly, who does need complex infrastructure for pre-OS environment (other that rootkits and spyware I mean)?
Just make it load your kernel and get the hell out of there as soon as possible!
Cheers,
bzt
kind of more general, than about UEFI, right?Is there a GCC cross compiler target PE32+ (64bit PE) ?
second, it's up to the implementation of the UEFI - using PE import/export or not, internally it can perfectly use it. where it's not used (unfortunately) - is with UEFI<->UEFI application interface. here, it's duplicated by numerous function pointers.
finally, "to assure ABI compatibility" one uses proper compiler. I use msvc, but I read some blog, where a guy used clang on linux and it worked perfectly fine for him without needless wrappers. however msvc can produce efi for x86, x64, arm and arm64.
Re: GCC target PE32+
Yeah, and two posts later, he added:zaval wrote:kind of more general, than about UEFI, right?
PeterX wrote:The whole thing I'm trying to do is producing an UEFI application.
Yeah, you can also just tell GCC which calling convention to use by default, or just mark all external functions with the required attribute. But apparently that would be too hard, so people use uefi_call_wrapper, which eliminates compiler type checking. Because I really wanted to get rid of assembler, and so here I am writing assembler in C. *sigh*zaval wrote:finally, "to assure ABI compatibility" one uses proper compiler. I use msvc, but I read some blog, where a guy used clang on linux and it worked perfectly fine for him without needless wrappers. however msvc can produce efi for x86, x64, arm and arm64.
Anyway, GCC can also be compiled for Windows, and will then generate PE32 or PE32+ executables. Even with the right calling convention. Of course, it is entirely up to taste which one to use. Except I can't use MSVC since I'm on Linux, but whatever blows your skirt up.
Carpe diem!
Re: GCC target PE32+
I prefer uefi_call_wrapper over other solutions not because others would be hard, but because it is a clean 100% portable solution. Compiler attributes are not, they tie you to a certain compiler. True, you have to do the type checking yourself, but I have no issues with that, I can do that for those few functions I use (it's not more complicated than using printf). I value more that my sources can be compiled with any standard ANSI C compiler, let's say with tcc too for example. I always use as few compiler specific things as possible. But maybe this is just my preference.nullplan wrote:just mark all external functions with the required attribute. But apparently that would be too hard, so people use uefi_call_wrapper, which eliminates compiler type checking.
Cheers,
bzt