简体   繁体   中英

How to link object files into a raw binary file with gcc/ld?

UPDATE 2 December 2019:

I'm having trouble with the m68k-elf toolchain. What I want to do is to translate a simple 68k-assembly file source.s like this:

    .text 
    move.w %d0,%d1

Into an object file, then use a linker script memmap.ldscript :

MEMORY 
{
    ROM1 (rx) : ORIGIN = 0x00, LENGTH = 16
    ROM2 (rx) : ORIGIN = 0x10, LENGTH = 16
}

SECTIONS 
{
    .text : 
    {
       *(.text)
    } >ROM2
}

OUTPUT_FORMAT(binary)

to link this object file into a raw binary file. The final file should look like this (viewed in a hex editor):

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00

If I build it like this

m68k-elf-as -o source.o source.s 
m68k-elf-ld -T memmap.ldscript -o final.rom source.o 

Then final.rom only contains:

30 01

So the code of the section is placed at 0x00 instead 0x05.

I need "raw" machine code to burn onto a E(E)PROM. But I'd like to use a linker and linker script to be able to assemble sections from several source files into objects files, then link them into one final ROM with the section placement controlled by a linker script. Is this possible with m68k-elf?

You need to force the linker to emit the ROM1 region by creating an output section with some content. The manual says :

Other link script directives that allocate space in an output section will also create the output section. So too will assignments to dot even if the assignment does not create space, except for '. = 0', '. =. + 0', '. = sym', '. =. + sym' and '. = ALIGN (. ,= 0, expr. 1)' when 'sym' is an absolute symbol of value 0 defined in the script. This allows you to force output of an empty section with '. =.'.

So this should work:

MEMORY 
{
    ROM1 (rx) : ORIGIN = 0x00, LENGTH = 16
    ROM2 (rx) : ORIGIN = 0x10, LENGTH = 16
}

SECTIONS
{
    .dummy :
    {
       . = ORIGIN(ROM1) + LENGTH(ROM1);
    } >ROM1

    .text : 
    {
       *(.text)
       . = ORIGIN(ROM2) + LENGTH(ROM2);
    } >ROM2
}

OUTPUT_FORMAT(binary)

However, at least with my binutils version 2.33.1, it doesn't. .=. doesn't work either. If you only need the region for padding, you can emit some data into it, eg by a BYTE(0) directive and that works:

MEMORY 
{
    ROM1 (rx) : ORIGIN = 0x00, LENGTH = 16
    ROM2 (rx) : ORIGIN = 0x10, LENGTH = 16
}

SECTIONS
{
    .dummy :
    {
       BYTE(0);
       . = ORIGIN(ROM1) + LENGTH(ROM1);
    } >ROM1

    .text : 
    {
       *(.text)
       . = ORIGIN(ROM2) + LENGTH(ROM2);
    } >ROM2
}

OUTPUT_FORMAT(binary)

If you do have some content for ROM1 then of course just create input section for it but make sure it always exists otherwise the linker will remove it. Strangely enough, even a zero sized section works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM