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);
    ...
}

Miscelanious

  • Memory region option "p", for example, MYRAM1 (w!xp): org is not supported.

  • Prefixes determining type is not supported:

From:

*(.data.mydata*)

To:

*(.mydata*)