Reference bsp_section_data_start from C yields "R_PPC_EMB_SDA21 relocation is in the wrong output section"

Till Straumann strauman at
Mon May 17 16:24:29 UTC 2010

No. The section a symbol is residing in doesn't necessarily
mean that the compiler uses any type of special relocation
- *but* on a select platform it *may*.

E.g., on the 68k or x86 (iirc) all addresses (for data access)
are computed the same way and the subject of this
thread is not applicable.

However, the PPC/sysv ABI defines a 'small data area' (SDA), i.e.,
a 64k block of memory  where the compiler is encouraged
to put small objects. One register (r13) is reserved to
point into the middle of the SDA so that any address in the
SDA can be computed as

   address = R13 + 16-bit-offset

which means that such an object can be accessed with
a single ppc instruction (as opposed to 3 for a 'normal' 32-bit pointer
access). This is one of the rare cases where time *and* space
are saved.

According the the ABI, the sections '.sdata' and '.sbss' are used
to group small objects together so that the linker can put them
into the SDA.

Since a 32-bit address and a SDA address are computed
differently, the compiler emits different types of relocations
-- hence it must 'know' what kind of address it is dealing with
and this depends on the section where a symbol resides.

.sdata/.sbss -> use r13 + 16-bit offset
everything else: 32-bit relocation

The PPC sysv eabi extension defines a second 64k
block (SDA2) which is accessed via R2 + 16-bit-offset
and therefore requires yet a different relocation type.

The sections .sdata2/.sbss2 group such objects together
and there are some semantics which I don't recall exactly ATM
but which define whether something goes into .sdata or .sdata2,
I believe that 'const' stuff goes into SDA2.

-- Till

On 05/17/2010 10:53 AM, Eric Norum wrote:
> On May 16, 2010, at 8:52 PM, Till Straumann wrote:
>> I did that, too, but you have to know what you are doing.
>> This trick *only* works if you know that your symbol is
>> in the 'data' area and you want to avoid the compiler to
>> assume it to be in the short data area.
>> E.g., if you know our symbol is .text then you would declare
>> it as a function, of course.
>> Using a section __attribute__ is IMO preferable.
> I must be missing something.   Here's a section of the uc5282 BSP linkcmds:
> {
>      _header_offset = 0;
>      /*
>       * Text, data and bss segments
>       */
>      .text _DownloadLocation : {
>          *(.text*)
>          *(.ram_code)
>          /*
>           * C++ constructors/destructors
>           */
>          *(.gnu.linkonce.t.*)
>          /*
>           * Initialization and finalization code.
>           *
>           * Various files can provide initialization and finalization
>           * functions.  crtbegin.o and crtend.o are two instances. The
>           * body of these functions are in .init and .fini sections. We
>           * accumulate the bodies here, and prepend function prologues
>           * from crti.o and function epilogues from crtn.o. crti.o must
>           * be linked first; crtn.o must be linked last.  Because these
>           * are wildcards, it doesn't matter if the user does not
>           * actually link against crti.o and crtn.o; the linker won't
>           * look for a file to match a wildcard.  The wildcard also
>           * means that it doesn't matter which directory crti.o and
>           * crtn.o are in.
>           */
>          PROVIDE (_init = .);
>          *crti.o(.init)
>          *(.init)
>          *crtn.o(.init)
>          PROVIDE (_fini = .);
>          *crti.o(.fini)
>          *(.fini)
>          *crtn.o(.fini)
>          /*
>           * Special FreeBSD sysctl sections.
>           */
>          . = ALIGN (16);
>          __start_set_sysctl_set = .;
>          *(set_sysctl_*);
>          __stop_set_sysctl_set = ABSOLUTE(.);
>          *(set_domain_*);
>          *(set_pseudo_*);
> =================================
> In a C program I tried:
> extern char __start_set_sysctl_set[];
> printf("%ld\n", (unsigned long)__start_set_sysctl_set);
> This compiled and linked with no complaints even though the symbol is in the text segment:
>   m68k-rtems4.10-nm example | grep __start_set_sysctl_set
> 00143360 T __start_set_sysctl_set
> Am I venturing into 'undefined behaviour' territory?

More information about the users mailing list