Binary files and GCC

Programming, for all ages and all languages.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Binary files and GCC

Post by XCHG »

Suppose I have a C program like this:

Code: Select all

void SomeProcedure (void){
  return;
}

int __attribute__((stdcall)) SomeFunction (int Param1){
  return(Param1);
}
I want to make GCC produce a simple Object file for me where [SomeProcedure] has the entry at the 0x00000000 offset of the object file so that I can simply call it. When I compile the project with this command line to get the Assembly output file:

Code: Select all

GCC -S -O3 -masm=intel c1.c -o c1.asm
I get a bunch of code that are unnecessarily put into my program. Like stack frames for procedures that do not have local variables/parameters.

My question is: is there a way to make GCC produce a simple OBJ file like the output of NASM (NASM -f bin)?
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Post by Brynet-Inc »

The output file is still going to be ELF, unless you have a custom binutils setup..

As for the other thing.. you could try -fomit-frame-pointer.

Perhaps you should read GCC's documentation?
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

Re: Binary files and GCC

Post by bluecode »

XCHG wrote:I get a bunch of code that are unnecessarily put into my program. Like stack frames for procedures that do not have local variables/parameters.
These stackframes are not unnecessary. They are for debugging purpose. You can turn that of via -fomit-frame-pointer.
My question is: is there a way to make GCC produce a simple OBJ file like the output of NASM (NASM -f bin)?
That would normally be the job of a linker. You have to pass some of LDs options as a command-line argument for GCC (I don't know how that works though).
Or you could compile/assemble your files independent into object code and then link them together explicitly with LD.
I want to make GCC produce a simple Object file for me where [SomeProcedure] has the entry at the 0x00000000 offset of the object file so that I can simply call it.
I don't really understand that... Why not just declare SomeProcedure extern in your assembler file and then do "call SomeProcedure" (be carefull, perhaps the name got mangled, nm/objdump will tell ya)?
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Brynet-Inc wrote: As for the other thing.. you could try -fomit-frame-pointer.

Perhaps you should read GCC's documentation?
Thanks.

bluecode wrote:That would normally be the job of a linker. You have to pass some of LDs options as a command-line argument for GCC (I don't know how that works though).
Or you could compile/assemble your files independent into object code and then link them together explicitly with LD.
So I will write the program and then compile it into an object file then link it together with my other object files and produce the final flat binary file eh?

bluecode wrote:I don't really understand that... Why not just declare SomeProcedure extern in your assembler file and then do "call SomeProcedure" (be carefull, perhaps the name got mangled, nm/objdump will tell ya)?
For example, in NASM; when I write a procedure/function at the top of the source code, I will be sure that the first instruction in that procedure is the first assembled instruction in the binary file. So if I load that file into memory in my OS and CALL the offset 0x00000000 in that file, I would know that the first procedure is called. Is that possible in C or should I create jump tables and etc?

The reason I want to do this is to, for example, write a device driver for mice and then load that dynamically in my Operating System. I want the "init()" method of any device driver to start at the first instruction in the flat binary file.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

Post by bluecode »

XCHG wrote:So I will write the program and then compile it into an object file then link it together with my other object files and produce the final flat binary file eh?
right.
XCHG wrote:So if I load that file into memory in my OS and CALL the offset 0x00000000 in that file, I would know that the first procedure is called. Is that possible in C or should I create jump tables and etc?
iirc you can put a function into a different section via __attribute__((something_here)). Then you could specify in the linkerscript, that this section goes first in the final binary. Or of course you could use a jump-table.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Thank you [bluecode]. I'm on it right now. I will post back here if something goes wrong.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Alright, I read GCC's documentation and found some useful command line switches. This is my source file:

Code: Select all

void __attribute__((stdcall)) WriteX (void){
  char* VideoPointer = (void*) 0x000B8000;
  *VideoPointer = 'x';
  return;
}
I compile this program with this command:

Code: Select all

gcc -O3 -fomit-frame-pointer -finline-functions -nostdinc -c c1.c -o c1.o
Then I will get the "c1.o" file. I have this linker script:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(4096);
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(4096);
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    . = ALIGN(4096);
  }
  end = .;
}
Then when I try to link the "c1.o" and make a flat binary file, I get this error:

Code: Select all

C:\c>ld -T link.ld c1.o -o c1.bin
ld: cannot perform PE operations on non PE output file 'c1.bin'.
Could anybody tell me what I am doing wrong, please?
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Post by Brynet-Inc »

There are hundreds of posts on the forum with that specific error...

You're using Cygwin's port of GCC/binutils, which is highly modified for that platform. (And emits PE files..)

It's time to start considering an ELF Cross Compiler.

Good luck..
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

I was using MinGW :shock: I am downloading Cygwin now. Why should this process be so complicated? Is it too hard for the compiler to give me a simple binary output?
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Okay I don't think I have any more time to play with this. Could anyone tell me straight away what compiler options and switches you use to compile this program into a flat binary file?

Code: Select all

void __attribute__((stdcall)) WriteX (void){
  char* VideoPointer = (void*) 0x000B8000;
  *VideoPointer = 'x';
  return;
}
Thanks guys.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

I would use. This is with a cygwin gcc cross compiler targeting ELF.

Code: Select all

gcc -fno-builtin -nostdlib -ffreestanding -o file.o file.c
ld file.o --oformat binary -T ldscr.ld - o file.bin
User avatar
os64dev
Member
Member
Posts: 553
Joined: Sat Jan 27, 2007 3:21 pm
Location: Best, Netherlands

Post by os64dev »

What i do with respect to the binary file. I compile my program to an elf executable and use objcopy to convert it to binary. I think that could even be done with PE executables. I do use a cross compiler but that should be no different then a regular compiler.
Author of COBOS
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Thanks guys. One big problem. How am I actually supposed to set up my C development environment? I have downloaded the Cygwin setup.exe file and it is unstructured with millions of packages in front of me. I searched for GCC in those and I couldn't find the. God these are some of the reasons I never liked to use C for OS Development :lol: So could someone "give me a hand" with this. Suppose I don't have GCC/Cygwin/MinGW and etc. What should I download now? From where? Why is Cygwin is using a list-view inaccurately? lol
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Alright, never mind. I found a way to download Cygwin's GCC package and etc. I will ask more questions here (if any). Thanks guys.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Wow I'm impressed. Cygwin sucks too :lol:

Code: Select all

C:\c>gcc -fno-builtin -nostdlib -ffreestanding -o c1.o c1.c

C:\c>ld c1.o --oformat binary -T link.ld -o c1.bin
ld: cannot perform PE operations on non PE output file 'c1.bin'.
Or is there something that I am doing wrong? By the way, I just looked at the output object file that GCC produced and it is clearly a Win32 PE file.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
Post Reply