I'm trying to debug a program on LH75401 device with ARM7TDMI core using GDB. When I invoke "load" command, GDB loads only ".text" output section. How do I make it so that it loads not only the ".text" section but some other sections too? I tried to use PHDRS command in the linker script to make some sections loadable but it did not help. Here is my linker script:
USR_STACK_SIZE = 0x100;
IRQ_STACK_SIZE = 0x100;
MEMORY
{
EXTROM(wx) : ORIGIN = 0x44000000, LENGTH = 0x100000
EXTRAM(wx) : ORIGIN = 0x48000000, LENGTH = 0x100000
INTRAM(wx) : ORIGIN = 0x60000000, LENGTH = 0x4000
TCMRAM(wx) : ORIGIN = 0x80000000, LENGTH = 0x4000
}
PHDRS
{
EXTROM PT_LOAD;
EXTRAM PT_LOAD;
INTRAM PT_LOAD;
TCMRAM PT_LOAD;
}
ENTRY(rst_handler)
SECTIONS
{
.vect :
{
*(.vect)
}
> TCMRAM AT
> TCMRAM
: TCMRAM
.text :
{
*(.text)
*(.rodata)
}
> EXTROM AT
> EXTROM
: EXTROM
.data :
{
*(.data)
}
> EXTRAM AT
> EXTRAM
: EXTRAM
.bss :
{
*(.bss)
}
> EXTRAM AT
> EXTRAM
: EXTRAM
.usr_stack :
{
. += USR_STACK_SIZE;
. = ALIGN(8);
}
> EXTRAM AT
> EXTRAM
: EXTRAM
.irq_stack :
{
. += IRQ_STACK_SIZE;
. = ALIGN(8);
}
> EXTRAM AT
> EXTRAM
: EXTRAM
}
Fortunately I solved this problem. It was necessary to add a special section attribute in the source file. The attribute is "a", meaning that the section is allocatable. That's all.
Related
I'm working on the Upsilon Project (https://github.com/UpsilonNumworks/Upsilon) and I have some trouble to implement sram data retention after reset (using nrst pin).
I want to preserve the data on the staticStorageArea, so I did this:
extern "C" {
extern char _bss_records_section_start;
}
static volatile uint32_t * staticStorageArea[sizeof(Storage)/sizeof(uint32_t)] __attribute__((section(".noinit"))) ;
And there is my linker script:
MEMORY {
INTERNAL_FLASH (rx) : ORIGIN = 0x00200000, LENGTH = 64K
SRAM (rw) : ORIGIN = 0x20000000, LENGTH = 256K - 0xfa20
NOINIT (rwx) : ORIGIN = 0x20000000 + 256K - 0xfa20, LENGTH = 0xfa20
EXTERNAL_FLASH (rx) : ORIGIN = 0x90000000, LENGTH = 8M
}
STACK_SIZE = 32K;
FIRST_EXTERNAL_FLASH_SECTOR_SIZE = 4K;
SECTIONS {
.isr_vector_table ORIGIN(INTERNAL_FLASH) : {
KEEP(*(.isr_vector_table))
} >INTERNAL_FLASH
.header : {
KEEP(*(.header))
} >INTERNAL_FLASH
.text.internal_to_external : {
...
} >INTERNAL_FLASH
...
} >INTERNAL_FLASH
.rodata.internal : {
...
} >INTERNAL_FLASH
.exam_mode_buffer ORIGIN(EXTERNAL_FLASH) : {
...
} >EXTERNAL_FLASH
/* External flash memory */
.text.external : {
. = ALIGN(4);
*(.text)
*(.text.*)
} >EXTERNAL_FLASH
.rodata.external : {
*(.rodata)
*(.rodata.*)
} >EXTERNAL_FLASH
.init_array : {
...
} >INTERNAL_FLASH
.data : {
...
} >SRAM AT> INTERNAL_FLASH
.bss : {
...
} >SRAM
.heap : {
...
} >SRAM
.stack : {
...
} >SRAM
.noinit (NOLOAD) : ALIGN(4) {
_bss_records_section_start = .;
KEEP(*(.noinit))
KEEP(*(.noinit*))
_bss_records_section_end = .;
} >NOINIT
/DISCARD/ : {
...
}
}
NOCROSSREFS_TO(.text.external .text.internal);
NOCROSSREFS_TO(.rodata.external .text.internal);
NOCROSSREFS_TO(.text.external .rodata.internal);
NOCROSSREFS_TO(.rodata.external .rodata.internal);
NOCROSSREFS_TO(.text.external .isr_vector_table);
NOCROSSREFS_TO(.rodata.external .isr_vector_table);
NOCROSSREFS_TO(.text.external .header);
NOCROSSREFS_TO(.rodata.external .header);
NOCROSSREFS_TO(.exam_mode_buffer .text.internal);
NOCROSSREFS_TO(.exam_mode_buffer .rodata.internal);
NOCROSSREFS_TO(.exam_mode_buffer .isr_vector_table);
NOCROSSREFS_TO(.exam_mode_buffer .header);
I noticed that after every reset the data in the .noinit section is like corrupted, and I do not understand why... maybe I didn't understand correctly what nrst does in fact ? (on the website it's wrote that the power is "virtually disconnected")
I have written a startup and liker script for my C++ application, running on STM32F407VG.
The problem is i have an array of structure, where the structure field str is always zero despite the initialization. The other field in the struct are correctly initialized. I can-t understand what I'm doing wrong, I guess some part of initialization in the startup script is missing.
The array is declared like the following:
struct elem{
uint32_t str;
uint32_t value;
uint32_t value2;
};
const struct elem array[]{
{(uint32_t)(*(uint32_t*)"CM1"), 1, 1},
{(uint32_t)(*(uint32_t*)"CM2"), 2, 2},
{(uint32_t)(*(uint32_t*)"CM3"), 3, 3}
};
relevant section of startup script:
inline void static_init()
{
for (void (**p)() = __preinit_array_start; p < __preinit_array_end; ++p)
(*p)();
for (void (**p)() = __init_array_start; p < __init_array_end; ++p)
(*p)();
}
void reset_handler(void)
{
unsigned long *source;
unsigned long *destination;
// Copying data from Flash to RAM
source = &_data_flash;
for (destination = &_data_begin; destination < &_data_end;)
{
*(destination++) = *(source++);
}
// default zero to undefined variables
for (destination = &_bss_begin; destination < &_bss_end;)
{
*(destination++) = 0;
}
static_init();
#ifndef __NO_SYSTEM_INIT
SystemInit();
#endif
// starting main program
main();
}
and the linker script:
/* Entry Point */
ENTRY(reset_handler)
_estack = 0x20010000; /* end of 128K RAM */
/* Specify the memory areas */
/*
0x08000000 until 0x08010000 is reserved for BOOTLOADER! (64k)
*/
MEMORY
{
EEPROM (rwx) : ORIGIN = 0x08010000, LENGTH = 64K /*fake EEPROM!*/
FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 896K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
RAM2 (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
__intvec_start__ = .;
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
_text = .;
*(.text) /* .text sections (code) */
_text2 = .;
*(.text*) /* .text* sections (code) */
_rodata = .;
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
_init_data = .;
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} > FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* used by the startup to initialize data */
_data_flash = _sidata;
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_data_begin = .;
*(.data)
*(.data*)
. = ALIGN(4);
_data_end = .;
} >RAM AT> FLASH
.bss (NOLOAD) :
{
. = ALIGN(4);
_bss_begin = .;
__bss_start__ = _bss_begin;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_bss_end = .;
__bss_end__ = _bss_end;
} > RAM
stack_size = 1024;
__stack_end__ = ORIGIN(RAM)+LENGTH(RAM);
__stack_start__ = __stack_end__ - stack_size;
heap_size = 0;
__heap_end__ = __stack_start__;
__heap_start__ = __heap_end__ - heap_size;
. = __stack_start__;
._stack :
{
PROVIDE ( end = . );
. = . + stack_size;
. = . + heap_size;
. = ALIGN(4);
} > RAM
_siccmram = LOADADDR(.ram2);
.ram2 (NOLOAD) :
{
. = ALIGN(4);
*(.ram2);
*(.ram2*);
. = ALIGN(4);
} > RAM2 AT> FLASH
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
This should work and have no UB.
However, it's endian dependent.
#include <iostream>
#include <cstdint>
#include <cstring>
using namespace std;
struct elem {
uint32_t str;
uint32_t value;
uint32_t value2;
};
uint32_t makeint(const char str[4])
{
uint32_t val;
memcpy( &val, str, 4 );
return val;
}
const elem arr[] = {
{makeint("CM1"), 1, 1},
{makeint("CM2"), 2, 2},
{makeint("CM3"), 3, 3}
};
int main()
{
for (auto& e : arr)
cout << e.str << endl;
cout << "\ndone\n";
}
See it here
You might use multicharacter literal: see (6.) of character_literal.
Notice single quotes:
const struct elem array[]{
{'CM1', 1, 1},
{'CM2', 2, 2},
{'CM3', 3, 3}
};
You can see how gcc evaluate multicharacter literal:
https://gcc.gnu.org/onlinedocs/cpp/Implementation-defined-behavior.html#Implementation-defined-behavior
The compiler evaluates a multi-character character constant a character at a time, shifting the previous value left by the number of bits per target character, and then or-ing in the bit-pattern of the new character truncated to the width of a target character. The final bit-pattern is given type int, and is therefore signed, regardless of whether single characters are signed or not. If there are more characters in the constant than would fit in the target int the compiler issues a warning, and the excess leading characters are ignored.
I have a linker script like this:
OUTPUT_FORMAT(binary)
SECTIONS
{
. = 0xFFFF800000000000 ;
.startup_text : { processor.o(.text) }
.text : { *(EXCLUDE_FILE (processor.o) .text) }
.data : { *(.data) }
.rodata : { *(.rodata) }
linker_first_free_page = ALIGN(4096);
}
A piece of code loads the executable generated by this script, printing these infos:
size of executable (pages) 3
first free page 0xffff800000003000
And the executable itself prints:
&(linker_first_free_page) 0xffff800000003000
So everything works good so far. Now my executable needs a .bss section. Note that I don't have a loader capable of loading elf files, so I need a flat binary that can be just read and used, with all sections inside.
First attempt
OUTPUT_FORMAT(binary)
SECTIONS
{
. = 0xFFFF800000000000 ;
.startup_text : { processor.o(.text) }
.text : { *(EXCLUDE_FILE (processor.o) .text) }
.data : { *(.data) }
.rodata : { *(.rodata) }
.bss : { *(.bss) }
linker_first_free_page = ALIGN(4096);
}
That is, simply adding a .bss section. This is the output:
size of executable (pages) 3
first free page 0xffff800000003000
&(linker_first_free_page) 0xffff800000004000
That is, the linker variable is correctly updated, but the section is not allocated (I guess this is pretty normal for a .bss section).
Second attempt
OUTPUT_FORMAT(binary)
SECTIONS
{
. = 0xFFFF800000000000 ;
.startup_text : { processor.o(.text) }
.text : { *(EXCLUDE_FILE (processor.o) .text) }
.data : { *(.data) *(.bss) }
.rodata : { *(.rodata) }
linker_first_free_page = ALIGN(4096);
}
That is, putting .bss section inside the .data one. This is the output:
size of executable (pages) 4
first free page 0xffff800000004000
&(linker_first_free_page) 0xffff800000003000
That is, the .bss is allocated, but the linker variable is not updated (and I can't understand why...)
Short question
So, given all above, how can I embed the .bss section in a flat binary, so that it can be loaded in memory like a "standard" file and used directly, without a specific loader?
Now, I make a new OS which is written in C++.
I want to place the main function at the first location in the image, but I could not.
If I do not use class, the main is first .
If I use class, the class is located at the first location of the image.
Disassembly of section .text:
00010200 <_ZN4test4initEv>:
_ZN4test4initEv():
/home/xaliver/WorkSpace/kOdin/kernel32/./test.hpp:11
public:
void init(void);
};
void test::init(void)
{
10200: 55 push %ebp
10201: 89 e5 mov %esp,%ebp
/home/xaliver/WorkSpace/kOdin/kernel32/./test.hpp:12
m = 10;
10203: 8b 45 08 mov 0x8(%ebp),%eax
10206: c7 00 0a 00 00 00 movl $0xa,(%eax)
/home/xaliver/WorkSpace/kOdin/kernel32/./test.hpp:14
return;
1020c: 90 nop
/home/xaliver/WorkSpace/kOdin/kernel32/./test.hpp:15
}
1020d: 5d pop %ebp
1020e: c3 ret
0001020f <main>:
main():
/home/xaliver/WorkSpace/kOdin/kernel32/./main.cpp:10
bool kPrintString(int iX, int iY, const char* pcString);
bool kInitializeKernel64Area(void);
bool kIsMemoryEnough(void);
void main(void)
{
1020f: 55 push %ebp
10210: 89 e5 mov %esp,%ebp
10212: 83 e4 f0 and $0xfffffff0,%esp
I use this linker script. 0x10200 is the first location
/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
"elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SEARCH_DIR("/home/xaliver/BuildTools/cross/x86_64-pc-linux/lib");
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;
/* DS Start */
/* Part moved to the front by section relocation */
.text 0x10200 :
{
main.o(.text)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em */
*(.gnu.warning)
} =0x90909090
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
/* Align start of data at the sector size */
. = ALIGN (512); /* Next .data will be located at aligned address by 512 byte */
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
. = .;
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = SEGMENT_START("ldata-segment", .);
. = ALIGN(32 / 8);
_end = .; PROVIDE (end = .);
/* DS End */
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
.rel.fini : { *(.rel.fini) }
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
.rel.data.rel.ro : { *(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) }
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
.rel.ctors : { *(.rel.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rel.got : { *(.rel.got) }
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
.rel.ifunc : { *(.rel.ifunc) }
.rel.plt :
{
*(.rel.plt)
PROVIDE_HIDDEN (__rel_iplt_start = .);
*(.rel.iplt)
PROVIDE_HIDDEN (__rel_iplt_end = .);
}
.init :
{
KEEP (*(SORT_NONE(.init)))
}
.plt : { *(.plt) *(.iplt) }
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
}
.fini :
{
KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array ))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array ))
PROVIDE_HIDDEN (__fini_array_end = .);
}
//_edata = .; PROVIDE (edata = .);
/* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
.got : { *(.got) *(.igot) }
//. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 12 ? 12 : 0, .);
.got.plt : { *(.got.plt) *(.igot.plt) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table
.gcc_except_table.*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges
.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF Extension. */
.debug_macro 0 : { *(.debug_macro) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
How can I set the main at the first location?
I would like to run my C++ code on a ChibiOS, I can compile and link the code if I'm replacing the new delete with the C functions malloc and free. But I still would like to fix the issue. When I'm using new delete I'm receiving the following error:
no memory region specified for loadable section `.ARM.extab'
This is the linking script
/*
* BCM2835 memory setup.
*/
__und_stack_size__ = 0x0004;
__abt_stack_size__ = 0x0004;
__fiq_stack_size__ = 0x0010;
__irq_stack_size__ = 0x0080;
__svc_stack_size__ = 0x0004;
__sys_stack_size__ = 0x0400;
__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__;
MEMORY
{
ram : org = 0x8000, len = 0x06000000 - 0x10021
extabram : org = 0x06008000 - 0x10020, len = 0x10000 - 0x20
}
__ram_start__ = ORIGIN(ram);
__ram_size__ = LENGTH(ram);
__ram_end__ = __ram_start__ + __ram_size__;
SECTIONS
{
. = 0;
.text : ALIGN(16) SUBALIGN(16)
{
_text = .;
KEEP(*(vectors))
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
*(.glue_7t)
*(.glue_7)
*(.gcc*)
*(.ctors)
*(.dtors)
} > ram
.ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > extabram
__exidx_start = .;
.ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > ram
__exidx_end = .;
.eh_frame_hdr : {*(.eh_frame_hdr)}
.eh_frame : ONLY_IF_RO {*(.eh_frame)}
. = ALIGN(4);
_etext = .;
_textdata = _etext;
.data :
{
_data = .;
*(.data)
. = ALIGN(4);
*(.data.*)
. = ALIGN(4);
*(.ramtext)
. = ALIGN(4);
_edata = .;
} > ram
.bss :
{
_bss_start = .;
*(.bss)
. = ALIGN(4);
*(.bss.*)
. = ALIGN(4);
*(COMMON)
. = ALIGN(4);
_bss_end = .;
} > ram
}
PROVIDE(end = .);
_end = .;
__heap_base__ = _end;
__heap_end__ = __ram_end__ - __stacks_total_size__;
__main_thread_stack_base__ = __ram_end__ - __stacks_total_size__;
what does it missing in the linker script?
EDITED
After I followed Chris Desjardins answer, I'm receiving the following errors:
Linking build/ch.elf
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-abort.o): In function `abort':
abort.c:(.text+0x10): undefined reference to `_exit'
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text+0x1c): undefined reference to `_fstat'
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text+0x18): undefined reference to `_sbrk'
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-signalr.o): In function `_kill_r':
signalr.c:(.text+0x1c): undefined reference to `_kill'
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-signalr.o): In function `_getpid_r':
signalr.c:(.text+0x44): undefined reference to `_getpid'
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text+0x20): undefined reference to `_write'
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text+0x18): undefined reference to `_close'
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text+0x18): undefined reference to `_isatty'
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text+0x20): undefined reference to `_lseek'
/home/robu/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/libc.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text+0x20): undefined reference to `_read'
collect2: error: ld returned 1 exit status
make: *** [build/ch.elf] Error 1
It seems that the ARM.extab section doesn't have a place in memory. In this example they put it in flash.
http://hertaville.com/2012/06/29/a-sample-linker-script/
But you should be ok just carving out some ram for it as follows:
MEMORY
{
ram : org = 0x8000, len = 0x06000000 - 0x10021
extabram : org = 0x06008000 - 0x10020, len = 0x10000 - 0x20
}
Then put the ARM.extab section in the new ram region:
.ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > extabram
You could also just try to put it into the normal ram section...
.ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > ram
.ARM.extab section is created when exception support is required.
One of the differences between malloc and new is that new cannot return NULL: it must throw an exception in the event of memory allocation failure.
Would compiling with --force_new_nothrow option help?