how to fix a local symbol' can not be used when making a shared object error?

10,746

Solution 1

You should compile with -fPIC. See how to recompile with -fPIC

Non-PIC code needs to be modified when it's relocated to another address. These modifications of the binary code and data are called relocations. There are many different types of relocations. They might involve putting the absolute address of a symbol into a data word, or modifying some of the bits of a MOVW or MOVT instruction to place part of a constant into the instruction itself. That latter one is your problem.

The static linker will do all of these relocations when you link your executable. If you use a shared library, then the dynamic linker must do them when the executable is run and dynamically linked to shared library.

Some types of relocations, called text relocations or TEXTRELS, might not be supported by the dynamic linker. These involve modifying the text segment, with the actual code, and putting values inside instructions. Since it modifies the code, that part of the shared library won't be shared anymore between processes. You're supposed to make the library position independent via -fPIC, so the dynamic linker doesn't need to do text relocations.

It's possible that your previous code didn't cause the compiler to emit anything that needed an unsupported relocation. And then the file you added had something in it that did. For instance, accessing a global variable can trigger this on ARM.

int x = 1;
void foo(void) { x=42; }

Compiles to:

    movw    r3, #:lower16:x
    mov     r2, #42
    movt    r3, #:upper16:x
    str     r2, [r3]
    bx      lr

The lower and upper half of the address of x need to be placed into the movw and movt instructions. The dynamic linker doesn't support this. If the code had been compiled with -fPIC (or -mword-relocations), the compiler would produce different output that would not need these relocations.

"protocol.o" has unsupported relocations and before your change it wasn't there, or wasn't used, or didn't have them. If libservice.a was already there, keep in mind that code from a static library is only included if it's used. Maybe "protocol.o" wasn't used by anything, but whatever you added did use it.

Solution 2

It depends on which kind of files are added by you into the source folder. For example, if you add a new library file and that new library file is built against -fPIC build option, you may meet similar case.

Actually, the error message gives the enough information to you how to fix it. It will be OK to recompile it via "-fPIC" build option.

  • If you are building via command line, appendix "-fPIC" in the command line.
  • If you are building via Makefiles, modify the makefiles as below:

    CFLAGS += -fPIC

  • For ARM Compiler, please refer to

http://infocenter.arm.com/help/topic/com.arm.doc.dui0804b/CHDECFHF.html?resultof=%22%2d%66%70%69%63%22%20

  • For GCC Compiler, please refer to

https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html

Share:
10,746
achoora
Author by

achoora

An Embedded Systems Engineer. Exposed to Linux VxWorks, BSP and ARM

Updated on July 19, 2022

Comments

  • achoora
    achoora almost 2 years

    My compilation of c source files failed with the following error:

    libservices.a(protocol.o): relocation R_ARM_MOVW_ABS_NC against `a local symbol' can not be used when making a shared object; recompile with -fPIC
    libservices.a: error adding symbols: Bad value collect2.exe:
    error: ld returned 1 exit status

    I didn't do any changes other than adding an extra file to the source directory and things went for a toss. It was working fine without these warnings even though I have not used -fPIC option. Since I didn't make any make file changes I am curious to know why this error and what's the meaning of this, and how to get out of this issue. Help is appreciated.