Linker
Options
--export=<file>
-
Not supported.
--error-numbers
-
Not supported.
--mem-holes
-
Not supported.
--extmap=a
-
Not supported.
--orphan-handling={warn|error|place}
-
The LLVM toolchain supports
--orphan-handling=<value>
. This controls how orphan sections are handled when a linker script is used. The default value is place.
Library
- stdlib
-
standard library does not define the target or environment symbols. Those symbols should be defined by the user.
__attribute__ ((weak)) int close (int desc); __attribute__ ((weak)) char*__my_environ[2]; __attribute__ ((weak)) char**environ; __attribute__ ((weak)) void _exit(int status); __attribute__ ((weak)) int remove(const char *path); __attribute__ ((weak)) void *sbrk(size_t incr); __attribute__ ((weak)) void write(int fd, char* s, int len);
Example of stub definition of such symbols:
- close
-
__attribute__ ((weak)) int close (int desc) { (void)desc; // Return error return -1; }
- environ
-
__attribute__ ((weak)) char*__my_environ[2] = {"", 0}; __attribute__ ((weak)) char**environ = __my_environ;
- exit
-
__attribute__ ((weak)) void _exit(int status) { (void)status; // TODO: do whatever you need to to at exit, e.g. execute debug instruction while (1) ; }
- remove
-
__attribute__ ((weak)) int remove(const char *path) { (void)path; // Return error return -1; }
- sbrk
-
#include "stdlib.h" extern char __heap_base__; extern char __heap_end__; __attribute__ ((weak)) void *sbrk(size_t incr) { void *ret; static char *heap_top = & __heap_base__; char *new_heap_top = heap_top + incr; if (new_heap_top > & __heap_end__) { return (void*)(-1); } if (new_heap_top < & __heap_base__) abort(); ret = (void *) heap_top; heap_top = new_heap_top; return ret; }
- write
-
#include "stdlib.h" __attribute__ ((weak)) void write(int fd, char* s, int len) { (void)fd; (void)s; (void)len; }
- undefined references in libraries
-
- GNU
-
If you pass a list of libraries to the linker, the linker will parse the libraries in the given order and try to resolve the references. If the linker fails to resolve all the references, e.g. due to the existence of cyclic references, then the following message will be issued:
undefined reference to symbol name
The linker can also automatically resolve cyclic references so that the order of libraries becomes irrelevant. The corresponding linker option is
-Wl,--start-group <list> -Wl,--end-group
. <list> is used here as a placeholder for your list of libraries, e.g.tricore-gcc -Wl,--start-group foo.o bar.o -Wl,--end-group
- LLVM
-
Linker link order does not matter, (
--start-group <libraries> --end-group
) is enabled by default.
TriCore™ Sections
- .ctors/.init_array
-
Different symbols for C++ .ctors/.init_array
GNU’s .ctors/.init_array choice is a configure option--enable-initfini-array
.
clang
provides an internal option-fno-use-init-array
. It can be used as-Xclang -fno-use-init-array
.
Advanced Multi-Core Support
- core extensions
-
The following linker script core extensions are not supported:
-
CORE_SEC(section)
-
CORE_SYM(symbol)
-
CORE_ID=<label>
-
CORE_ALIAS ("NAME" = <label>)
-
- core flags
-
Not supported. Where the linker adds core flags to the sections and symbols that are assigned to a core. So the following Advanced Multi-Core Support features are not supported:
-
"Memory mode"
-
"Prelinking with core assignment"
-
"Core assignment in the source code"
-
"Locating" and "Performance optimization by decomposing pragma sections"
-
Small data
Small data symbol name
The LLVM compiler requires two underscore symbols:
__SMALL_DATA__
__SMALL_DATA1__
Compared to the GCC compiler:
_SMALL_DATA_
_SMALL_DATA1_
Small data symbol creation
With LLVM, the small data symbols are not created automatically. They must always be explicitly defined in the linker script.
Small data eabi compliance
In GCC, the handling of small data is not eabi compliant. The compiler always emits %a0
as the base register, and the instructions are patched by the linker, replacing not only the offset but also the register.
The symbols in the linker script are assigned to the middle of the section relative to the section beginning. Small data sections can have max 64K, so the middle is the shift by 32K:
.sbss (NOLOAD) : ALIGN(8) {
_SMALL_DATA_ = 0x8000;
...
}
In LLVM, the handling of small data is eabi compliant. The symbols are assigned with an absolute address in the middle of the small data section. A Small data section can have max 64K, so the middle is the start shifted by 32K:
.sbss (NOLOAD) : ALIGN(8) {
PROVIDE(__SMALL_DATA__ = . + 0x8000);
...
}