gcc - MinGW's ld cannot perform PE operations on non PE output file -


i know there other similar questions out there, stackoverflow or not. i've researched lot this, , still didn't find single solution. i'm doing operative system side project. i've been doing in assembly, wanna join c code. test, made assembly code file (called test.asm):

[bits 32]  global _a  section .text  _a:     jmp $ 

then made c file (called main.c):

extern void a(void); int main(void) {     a(); } 

to link, used file (called make.bat):

"c:\mingw\bin\gcc.exe"  -ffreestanding -c -o c.o main.c nasm -f coff -o asm.o test.asm "c:\mingw\bin\ld.exe" -ttext 0x100000 --oformat binary -o out.bin c.o asm.o  pause 

i've been researching ages, , i'm still struggling find answer. hope won't flagged duplicate. acknowledge existence of similar questions, have different answers, , none work me.

question: what doing wrong?

old mingw versions had problem "ld" not able create non-pe files @ all.

maybe current versions have same problem.

the work-around creating pe file "ld" , transform pe file binary, hex or s19 using "objcopy".

--- edit ---

thinking question again see 2 problems:

as said versions of "ld" have problems creating "binary" output (instead of "pe", "elf" or whatever format used).

instead of:

ld.exe --oformat binary -o file.bin c.o asm.o 

you should use following sequence create binary file:

ld.exe -o file.tmp c.o asm.o objcopy -o binary file.tmp file.bin 

this create ".exe" file named "binary.tmp"; "objcopy" create raw data ".exe" file.

the second problem linking itself:

"ld" assumes ".exe"-like file format - if output file binary file. means ...

  • ... cannot sure if object code of "main.o" placed @ first address of resulting object code. "ld" allowed put code of "a()" before "main()" or put "internal" code before "a()" , "main()".
  • ... addressing works bit differently means lot of padding bytes created (maybe @ start of file!) if wrong.

the possibility see create "linker script" (sometimes called "linker command file") , create special section in assembler code (because use assembler "nasm" not know if syntax here correct):

[bits 32] global _a section .entry     jmp _main section .text _a:     jmp $ 

in linker script can specify sections appear in order. specify ".entry" first section of file can sure first instruction of file.

in linker script may multiple sections (e.g. ".entry", ".text" , ".data") should combined single section. useful because sections 0x1000-byte-aligned in pe files! if not combine multiple sections 1 you'll lot of stub bytes between sections!

unfortunately i'm not expert linker scripts cannot that.

using "-ttext" problematic:

in pe files actual address of section calculated "image base" + "relative address". "-ttext" argument influence "relative address" only. because "relative address" of first section typically fixed 0x1000 in windows "-ttext 0x2000" nothing filling 0x1000 stub bytes @ start of first section. not influence start address of ".text" @ - fill stub bytes @ start of ".text" section first useful byte located @ 0x2000. (maybe "ld" versions behave differently.)

if wish first section of file located @ address 0x100000 should use equivalent of "-ttext 0x1000" in linker script (-ttext not used if linker script used) , define "image base" 0xff000:

ld.exe -t linkerscript.ld --image-base 0xff000 -o binary.tmp a.o main.o 

the memory address of ".text" section 0xff000 + 0x1000 = 0x100000.

(and first byte of binary file generated "objcopy" first byte of first section - representing memory address 0x100000.)


Comments

Popular posts from this blog

powershell Start-Process exit code -1073741502 when used with Credential from a windows service environment -

twig - Using Twigbridge in a Laravel 5.1 Package -

c# - LINQ join Entities from HashSet's, Join vs Dictionary vs HashSet performance -