4.10. Directives that Encode Metadata

The following directives provide a means of communicating information to downstream object file consumer tools like the linker by encoding information into the assembler generated object file.

.no_dead_strip [section]
.sym_meta_info symbol, “[kind]”, value

4.10.1. .eabi_attribute

.eabi_attribute tag, value

The .eabi_attribute directive sets an EABI object file build attribute specified by tag to value. Build attributes are used to check for compatibility between object files and to select suitable versions of the runtime libraries.

The tag argument is a numeric attribute ID. For example, 6 is the ID for Tag_CPU_arch. For information regarding these attribute IDs, see the “Build Attributes” section of the ARM ABI addendum.

The value is the value assigned to the attribute in the compiler-generated object file. This is typically an integer, but may be a string, depending on the tag.

For example, suppose a simple hello.c source file is compiled with the following command line:

tiarmclang -mcpu=cortex-m0 -S hello.c

The resulting assembly file contains the following examples of the .eabi_attribute directive:

.text
.syntax unified
.eabi_attribute 67, "2.09"      @ Tag_conformance
.cpu    cortex-m0
.eabi_attribute 6, 12   @ Tag_CPU_arch
.eabi_attribute 7, 77   @ Tag_CPU_arch_profile
.eabi_attribute 8, 0    @ Tag_ARM_ISA_use
.eabi_attribute 9, 1    @ Tag_THUMB_ISA_use
.eabi_attribute 34, 0   @ Tag_CPU_unaligned_access
.eabi_attribute 17, 1   @ Tag_ABI_PCS_GOT_use
.eabi_attribute 20, 1   @ Tag_ABI_FP_denormal
.eabi_attribute 21, 0   @ Tag_ABI_FP_exceptions
.eabi_attribute 23, 3   @ Tag_ABI_FP_number_model
.eabi_attribute 24, 1   @ Tag_ABI_align_needed
.eabi_attribute 25, 1   @ Tag_ABI_align_preserved
.eabi_attribute 38, 1   @ Tag_ABI_FP_16bit_format
.eabi_attribute 18, 4   @ Tag_ABI_PCS_wchar_t
.eabi_attribute 26, 1   @ Tag_ABI_enum_size
.eabi_attribute 14, 0   @ Tag_ABI_PCS_R9_use

The .eabi_attribute directive does not affect that set of instructions the assembler accepts. Arm recommends that the .arch, .cpu, and .fpu directives be used instead where possible. These other directives are recommended because they also make sure that instructions for the selected architecture are valid while also setting the relevant build attributes. Therefore, the .eabi_attribute directive is only needed for build attributes not covered by these other directives.

Note: The following legacy values are also accepted for the tag: Tag_VFP_arch, Tag_ABI_align8_needed, Tag_ABI_align8_preserved, and Tag_VFP_HP_extension.

4.10.2. .no_dead_strip

.no_dead_strip [section]

The .no_dead_strip directive instructs the linker to include the current or specified section in the linked output file, regardless of whether or not the section is referenced. That is, the section is not eligible for removal via conditional linking. The section name must be enclosed in double quotes. A section name can contain a subsection name in the form section_name:subsection_name.

You can also override conditional linking for a given section with the --retain linker option. You can disable conditional linking entirely with the --unused_section_elimination=off linker option.

By default, the linker assumes that all sections are eligible for removal via conditional linking. (However, the linker automatically retains the .reset section.) The .no_dead_strip directive is useful for overriding this default behavior for sections you want to retain in the link, even if the section is not referenced by any other section in the link. For example, you could apply a .no_dead_strip directive to an interrupt function that is written in assembly language, but is not referenced from any normal entry point in the application.

This directive is a TI extension that is not portable to other GNU assemblers.

4.10.3. .sym_meta_info

.sym_meta_info symbol, “[kind]”, value

The .sym_meta_info directive provides ways to annotate the symbol table entry information about a symbol. This information can then be used by the linker to influence the linker’s processing of the symbol or the section in which the symbol is defined.

This directive is a TI extension; it is not portable to other GNU assemblers.

The symbol argument specifies a symbol to representing a function or data object definition.

The kind argument is a quoted string that defines the type of information that the directive is providing for use by the linker. Available kinds include “location”, “noinit”, “persistent”, “printf_formatstrinfo”, and “prinf_forward”.

  • “location” indicates that the linker should place the symbol definition at the address in target memory specified by value.

  • “noinit” with a value of 1 indicates that the symbol is an uninitialized symbol that should not be set to 0 during a reset.

  • “persistent” with a value of 1 indicates that the symbol is an initialized symbol that should not be re-initialized during a reset.

  • “printf_formatstrinfo” indicates that the value is a string representation of the collection of format specifiers that appear in the const char string argument to a printf-like function call. For example, printf("hello: %d\n", my_int); will generate a .sym_meta_info printf,"printf_formatstrinfo", "d" directive when compiled.

  • “prinf_forward” indicates that the value is the name of a function whose definition calls a printf-like function with a const char * to a string that it received as an argument.

The value can be an integer, a string constant, or a symbol name depending on the specified kind.

Example 1: The following example uses a kind of “location” to specify the location for the mysym symbol:

.sym_meta_info mysym, "location", 0x00ff

Example 2: The following example shows several .sym_meta_info directives. Suppose the following C code is compiled:

#include <stdio.h>

__attribute__((persistent)) int my_init_var = 10;

__attribute__((location(0x2000)))
int main() {
    printf("my_init_var is %d\n", my_init_var);
    return 0;
}

The resulting assembly code would contain the following (this has been somewhat simplified for readability):

     .section        .text.main,"ax",%progbits
     .hidden main                            @ -- Begin function main
     .globl  main
     .p2align        4
     .type   main,%function
     .sym_meta_info  main, "location", 8192

     ...

     .section        .TI.persistent,"aw",%progbits
     .globl  my_init_var
     .p2align        2
my_init_var:
     .long   10                              @ 0xa
     .size   my_init_var, 4
     .sym_meta_info  my_init_var, "noinit", 1

     ...

     .sym_meta_info  printf, "printf_formatstrinfo", "d"

The location attribute in the C code indicates that the section where main() is defined should be placed at target address (0x2000). This information is communicated to the linker via a .sym_meta_info directive that encodes a type of “location” and a value of 0x2000 in a special .symtab_meta section. It associates this information with the main function symbol.

The persistent attribute in the C code indicates that the initial value for my_init_var when the program is loaded is 10, but the value will not be re-initialized if the processor is reset. In this case, the .sym_meta_info directive inserts symbol information into the .symtab_meta section telling the linker that the my_init_var variable can be directly initialized at load time, but that no .cinit record should be generated for it, since it is not to be re-initialized when the processor is reset and execution starts from the _c_int00() boot routine.

The printf() call in the C code results in a .sym_meta_info directive that passes information to the linker about how a call to the printf() function can be specialized. Each format specifier used in the format string passed to printf() is recorded in the .symtab_meta section. In this case, only the %d format specifier is used, so only one .sym_meta_info directive is generated. In this case, the linker will determine based on the directive that it can use a call to __TI_printf_nofloat instead of the larger __TI_printf function to implement printf() functionality at run-time. This can result in a significant code size savings for a function that does a lot of simple printf() calls.