8.6.1. Using Linker Symbols in C/C++ Applications

Linker symbols have a name and a value. The value is a 32-bit unsigned integer, even if it represents a pointer value on a target that has pointers smaller than 32 bits.

The most common kind of symbol is generated by the compiler for each function and variable. The value represents the target address where that function or variable is located. When you refer to the symbol by name in the linker command file, you get that 32-bit integer value.

However, in C and C++ names mean something different. If you have a variable named x that contains the value Y, and you use the name “x” in your C program, you are actually referring to the contents of variable x. If “x” is used on the right-hand side of an expression, the compiler fetches the value Y. To realize this variable, the compiler generates a linker symbol named x with the value &x. Even though the C/C++ variable and the linker symbol have the same name, they don’t represent the same thing. In C, x is a variable name with the address &x and content Y. For linker symbols, x is an address, and that address contains the value Y.

Because of this difference, there are some tricks to referring to linker symbols in C code. The basic technique is to cause the compiler to create a “fake” C variable or function and take its address. The details differ depending on the type of linker symbol.

Linker symbols that represent a function address: In C code, declare the function as an extern function. Then, refer to the value of the linker symbol using the same name. This works because function pointers “decay” to their address value when used without adornment. For example:

extern void _c_int00(void);

printf("_c_int00 %lx\n", (unsigned long)&_c_int00);

Suppose your linker command file defines the following linker symbol:

func_sym=printf+100;

Your C application can refer to this symbol as follows:

extern void func_sym(void);

printf("func_sym %lx\n", (unsigned long)&func_sym);

Linker symbols that represent a data address: In C code, declare the variable as an extern variable. Then, refer to the value of the linker symbol using the & operator. Because the variable is at a valid data address, we know that a data pointer can represent the value.

Suppose your linker command file defines the following linker symbols:

data_sym=.data+100; xyz=12345

Your C application can refer to these symbols as follows:

extern char data_sym;
extern int xyz;

printf("data_sym %p\n", &data_sym);  myvar = &xyz;

Linker symbols for an arbitrary address: In C code, declare the linker symbol as an extern symbol. The type does not matter. If you are using GCC extensions, declare it as “extern void”. If you are not using GCC extensions, declare it as “extern char”. Then, refer to the value of the linker symbol mySymbol as &mySymbol.

Suppose your linker command file defines the following linker symbol:

abs_sym=0x12345678;

Your C application can refer to this symbol as follows:

extern char abs_sym;

printf("abs_sym %lx\n", &abs_sym);

Note

This technique assumes that the pointer to the symbol is 32 bits, which matches the 32-bit value of the linker symbol.