How to convert a GNU linker Script ld to Scatter File (ARM) - gcc

I would like to migrate from GCC to the new ARM COMPILER 6.
But I'm not able to well convert the Gnu liker script (ld) to the equivalent of ARM Scatter file.
The Original Code is as following:
arm-none-eabi-ld -T link.ld test.o shared/bootcode.o shared/vertors.o -o test.elf
Where link.ld script is as following
ENTRY(bootcode)
SECTIONS
{
. = 0x00000000;
/* Code starts with vectors, then bootcode, then other code */
.text :
{
*vectors.o(vectors)
*bootcode.o(boot)
*(.text) /* remainder of code */
} =0
.data : { *(.data) }
.bss : { *(.bss) }
/* Notes section
* This is not used so we discard it. Although not used it needs to be
* explicitly mentioned in the linker script as some toolchains will place
* the notes section at adderss 0 if it is not explicitly mentioned*/
/DISCARD/ : { *(.note*) }
}
I would like to use armlink as a linker :
armlink --cpu=8-A.32 --entry=bootcode test.o shared/bootcode.o shared/vertors.o -o test.elf --scatter=ld.scat
But I did not succeed in Creating a valid scatter File. I tried to play with the armlink options (--first, --last, --ro_base, --rw_base) but nothing went as expected (I'm getting successful compilation but the test is not working).
Any Idea on that please?

I looked at the documentation here: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0803d/pge1362065973150.html
The GNU Linker Script you want to migrate can be rewritten as:
LOAD_ROM 0x0000
{
EXEC_ROM_1 0x0000 ; Name of first exec region (EXEC_ROM_1),
; Start address for exec region (0x0000)
{
vectors.o(VECTORS)
* (InRoot$$Sections) ; All library sections that must be in a
; root region, for example, __main.o,
; __scatter*.o, __dc*.o, and * Region$$Table
}
EXEC_ROM_2 +0 ; Name of second exec region (EXEC_ROM_2)
{
bootcode.o(BOOT, +FIRST)
* (+RO)
}
SRAM +0 ; Name of third exec region (SRAM)
{
* (+RW, +ZI) ; Place all RW and ZI data into
; this exec region
}
}
In order to specify the entry point of your image you can use the command line option --entry=bootcode as you already specified in your command line.
armlink --cpu=8-A.32 --entry=bootcode test.o shared/bootcode.o shared/vertors.o -o test.elf --scatter=ld.scat

armlink allows reading of GNU LD linker script, however, with restrictions.
The flag is "--linker_script=ld_script".

Related

How do i set up data memory address when using "riscv32/64-unknown-elf-gcc"?

I designed RISCV32IM processor, and i used "riscv32/64-unknown-elf-gcc" to generate code for test.
Instruction memory setting has been solved with the options below(-Ttext option), but data memory setting has not been solved yet.
riscv64-unknown-elf-gcc -v -march=rv32im -mabi=ilp32 -nostartfiles -x c -Ttext 40000000 -o main.o main.c
Can I know if I can set the data memory address I want?
looks like you need to link linker script, something like:
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = 0x40000000;
.text.init : { *(.text.init) }
. = ALIGN(0x1000);
.text : { *(.text) }
. = ALIGN(0x1000);
.data : { *(.data) }
.bss : { *(.bss) }
_end = .;
}
_start is a start symbol and 0x40000000 is a memory start address,
followed by the section names aligned by 0x1000.
text this is the program itself
data is a statically initialized variables
bss
is a statically allocated variables

Remove a section from ELF during linking stage

How can I remove a section from ELF during linking stage? Is there any linker option or flag for this? I'm mostly interested on how it can be done with LLVM, but any information about GCC will be appreciated as well.
Thanks!
If you want anything different from the default ELF construction--copy everything--then you will need to write a linker script. files can specify what to include and where to put it. So you would remove this section by not copying it. LLD supports GNU LD style linker scripts. They will look something like:
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
They are specified on the lld command line with something like:
ld.lld --script=../linker_script xxx.o -o xxx

GCC -T link option issue

I have compiled the project with arm-none-eabi-gcc to object with command
arm-none-eabi-gcc --specs=nosys.specs -mcpu=cortex-m7 -mtune=cortex-m7 -Os -g -gdwarf-2 -c $< -o $(#)
currently I got the object file when I try to link it with command in object foler
arm-none-eabi-gcc --specs=nosys.specs -mcpu=cortex-m7 -mtune=cortex-m7 -g -gdwarf-2 -nostartfiles -T ..\project.ld -o target *
However I got some strange error
arm-none-eabi/bin/ld.exe: error: no memory region specified for loadable section `.text.memcmp'
I understand that when I use -T option the link script file will be used instead of default link script. it looks like the section definitions for some builtin function are missing. I tried to fix that put
.text.memcmp : {*(.text.memcmp)}
in my ld file, it looks like this section is fixed however I got another error:
arm-none-eabi/bin/ld.exe: error: no memory region specified for loadable section `.text.memset'
so I don't think put .text.memset in the LD file is correct fix, because after I put `.text.memset' in ld file , I got another error :
arm-none-eabi/bin/ld.exe: error: no memory region specified for loadable section `.text._snprintf_r'
I think I missed some options in GCC to create these default sections for builtin functions
What is the root cause of this issue and how to fix that? Thank you so much!
Update: Add the LD file below :
MEMORY {
INIT_SRAM : ORIGIN = 0x34400000, LENGTH = 0x1FB000
INIT_SRAM_NO_CACHEABLE : ORIGIN = 0x3460A000, LENGTH = 0x1DF00
INIT_SRAM_STACK : ORIGIN = 0x34628000, LENGTH = 0x15000
RAM_RSVD : ORIGIN = ., LENGTH = 0
BOOT_TEST : ORIGIN = 0x43840000 LENGTH = 0x50
}
SECTIONS
{
.boot_test : {*(.boot_test)}> BOOT_TEST
.exception_table ALIGN(4) : > {*(.exception_table)}>INIT_SRAM
.startup ALIGN(4) : {*(.startup)}
.ramcode ALIGN(4) : > {*(.ramcode)}
.text ALIGN(4) : { *(.text) }
.ramcode ALIGN(4) : { *(.ramcode) }
.rodata ALIGN(4) : { *(.rodata) }
.data ALIGN(4) : { *(.data) }
.bss ALIGN(16) : { *(.bss) }
_TEST_SESSION_START = .;
.TEST_SESSION :{*(.TEST_SESSION)}
_TEST_SESSION_END = (. - 1);
_Stack_start = .;
__STACK_SIZE = SIZEOF(INIT_SRAM_STACK);
__RAM_NO_CACHEABLE_START = ADDR(INIT_SRAM_NO_CACHEABLE);
}
Changing
.text ALIGN(4) : { *(.text) }
to
.text ALIGN(4) : { *(.text) *(.text.*) }
can fix this .text.xxx missing issue.

GCC: how to tell GCC to put the 'main' function at the start of the .text section?

I've just started learning some ARM programming and I've got stuck in a slightly annoying problem. The toolchain I'm using to compile my sources is Sourcery CodeBench Lite 2013.05-23 (can be found here: https://sourcery.mentor.com/GNUToolchain/release2449)
What I would need is to tell GCC or LD or OBJCOPY to put the compiled bytecode of the 'main' function at the beginning of the .text section.
Is there any way to achieve this? (maybe through a linker script?)
Thank you
Solved the problem. For whoever faces it:
When compiling with GCC, add the -ffunction-sections option in the command-line. This will tell GCC to put each function in a separate section. The format of the section name will be .text.#function name#, without the # (that is, if the function belongs to the .text section [ which by default is true ]).
Secondly, use a linker script to order these "function-sections" into the final big .text section. As an example, putting the main function at the beginning of the .text section would result in an LD script that looks approximately like this:
ENTRY(main)
SECTIONS
{
.text :
{
*(.text.main);
*(.text*);
}
}
First, see how is the .text section defined in your gcc's default linker script (so you don't have to make your own), by calling it as:
gcc -Wl,-verbose
that will print out the default linker script. Mine shows this for the .text section:
/* text: Program code section */
.text :
{
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
}
So in order to have the "main" function be the first in the .text section (and the rest be contiguous), you have to set the "section" attribute for all other functions. For example:
void main(void);
void funct1(....) __attribute__ ((section (".text.A")));
void funct2(....) __attribute__ ((section (".text.A")));
void funct3(....) __attribute__ ((section (".text.A")));
It's enough with "attributing" the function prototypes. That way, when you compile now, the "main" function will be the first one in the ".text" section and all others will follow on the immediately consecutive addresses.
If you want to place the ".text" section (i.e. "main" function) at a specific address (for example 0x1000), remember to link with:
gcc .... -Wl,-Ttext=0x1000
You can also just put 'main' in its own section using an __attribute__:
int main (void) __attribute__ ((section ("entry")));
and then in the ld file:
ENTRY(main)
SECTIONS
{
.text :
{
*(main)
*(.text)
}
}
There are plenty of other interesting __attributes__, read more about them here: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

How to correctly use a simple linker script? Executable gets SIGKILL when run

I'm trying to understand deeper linking process and linker scripts...looking at binutils doc i found a simple linker script implementation that i've improved by adding some commands:
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
"elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(mymain)
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
My program is a very simple program:
void mymain(void)
{
int a;
a++;
}
Now i tried to build an executable:
gcc -c main.c
ld -o prog -T my_script.lds main.o
But if i try to run prog it receives a SIGKILL during startup. I know that when a program is compiled and linked with the command:
gcc prog.c -o prog
the final executable is the product also of other object files like crt1.o, crti.o and crtn.o but what about my case? Which is the correct way to use this linker scripts?
I suspect that your code is running just fine, and getting into trouble at the end: what do you expect to happen after the a++?
mymain() is just an ordinary C function, which will try to return to its caller.
But you've set it as the ELF entry point, which tells the ELF loader to jump to it once it has loaded the program segments in the right place - and it doesn't expect you to return.
Those "other object files like crt1.o, crti.o and crtn.o" normally handle this stuff for C programs. The ELF entry point for a C program isn't main() - instead, it's a wrapper which sets up an appropriate environment for main() (e.g. setting up the argc and argv arguments on the stack or in registers, depending on platform), calls main() (with the expectation that it may return), and then invokes the exit system call (with the return code from main()).
[Update following comments:]
When I try your example with gdb, I see that it does indeed fail on returning from mymain(): after setting a breakpoint on mymain, and then stepping through instructions, I see that it performs the increment, then gets into trouble in the function epilogue:
$ gcc -g -c main.c
$ ld -o prog -T my_script.lds main.o
$ gdb ./prog
...
(gdb) b mymain
Breakpoint 1 at 0x10006: file main.c, line 4.
(gdb) r
Starting program: /tmp/prog
Breakpoint 1, mymain () at main.c:4
4 a++;
(gdb) display/i $pc
1: x/i $pc
0x10006 <mymain+6>: addl $0x1,-0x4(%ebp)
(gdb) si
5 }
1: x/i $pc
0x1000a <mymain+10>: leave
(gdb) si
Cannot access memory at address 0x4
(gdb) si
0x00000001 in ?? ()
1: x/i $pc
Disabling display 1 to avoid infinite recursion.
0x1: Cannot access memory at address 0x1
(gdb) q
For i386 at least, the ELF loader sets up a sensible stack before entering the loaded code, so you can set the ELF entry point to a C function and get reasonable behaviour; however, as I mentioned above, you have to handle a clean process exit yourself. And if you're not using the C runtime, you'd better not be using any libraries that depend on the C runtime either.
So here is an example of that, using your original linker script - but with the C code modified to initialise a to a known value, and invoke an exit system call (using inline assembly) with the final value of a as the exit code. (Note: I've just realised that you haven't said exactly what platform you're using; I'm assuming Linux here.)
$ cat main2.c
void mymain(void)
{
int a = 42;
a++;
asm volatile("mov $1,%%eax; mov %0,%%ebx; int $0x80" : : "r"(a) : "%eax" );
}
$ gcc -c main2.c
$ ld -o prog2 -T my_script.lds main2.o
$ ./prog2 ; echo $?
43
$
yes to run on linux, we need to change .lds file
SECTIONS
{
. = 0x8048000;
.text : { *(.text)
}

Resources