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
Post a Comment