Как использовать внешние символы в общей библиотеке в C - PullRequest
0 голосов
/ 29 апреля 2018

Я пытаюсь скомпилировать следующие тестовые файлы для создания общей библиотеки:

answer.c

#include <stdio.h>    
#include "add.h"    
extern int myvar();

int answer()
{    
    printf("\r\n myvar:%d \r\n", myvar());    
    setSummand(20);    
    return add(22);  // Will return 42 (=20+22)   
}

add.c

#include <stdio.h>

int gSummand;    

void setSummand(int summand)
{    
    printf("1Library is initialized\n");    
    gSummand = summand;
}

int add(int summand)
{    
  return gSummand + summand;    
}

Я хочу создать общую библиотеку из 2-х файлов «answer.c» «add.c», я использую следующие команды:

gcc -c answer.c  -o answer.o
gcc -c add.c  -o add.o
gcc -shared add.o answer.o -o libtest.so

Однако третья команда выдает следующую ошибку:

answer.o:answer.c:(.text+0x9): undefined reference to `myvar'
answer.o:answer.c:(.text+0x9): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `myvar'
collect2: error: ld returned 1 exit status

Те же настройки успешно установятся, если я использую следующую команду для создания статической библиотеки вместо динамической. Поэтому я не вижу никакой ошибки, если я пытаюсь выполнить следующую команду:

ar rcs libtest.a add.o answer.o

Хотите знать, если я что-то здесь упускаю. Также хочу знать, как использовать внешние символы в общей библиотеке.

1 Ответ

0 голосов
/ 29 апреля 2018

ELF разделяемые библиотеки должны быть независимыми от позиции. Они будут отображены в адресное пространство исполняемого файла по адресу, который неизвестен до времени выполнения. Это означает, что никакие абсолютные адресные инструкции вызова, такие как, могут использоваться, чтобы вызвать myvar().

Вам необходимо указать -fpic при компиляции источника в объектные файлы, когда эти объектные файлы будут помещены в общую библиотеку. Это говорит компилятору генерировать код, который не использует абсолютные адреса и т. Д., Поэтому он может быть независимым от позиции.

Пример файла main.c для использования этой библиотеки:

extern int answer(void);
int myvar() { return 1; }
int main(void) { return answer(); }

Пример без -fpic:

[test]$ gcc -c add.c
[test]$ gcc -c answer.c 
[test]$ gcc -shared add.o answer.o -o libtest.so
/usr/bin/ld: add.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: answer.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status

Пример с -fpic:

[test]$ gcc -fpic -c add.c
[test]$ gcc -fpic -c answer.c
[test]$ gcc -shared add.o answer.o -o libtest.so
[test]$ gcc main.c libtest.so
[test]$ LD_LIBRARY_PATH=. ./a.out

 myvar:1 
1Library is initialized
...