2016-02-28 2 views
0

Я разрабатываю встроенную систему с GCC и хотел бы использовать только несколько символов из libc. Например, я хотел бы использовать базовые memcpy, memmove, memset, strlen, strcpy и т. Д. Однако я хотел бы предоставить свою собственную (меньшую) функцию printf, поэтому я не хочу, чтобы libc лидировал printf. Я не хочу динамического выделения в этой платформе, поэтому я не хочу, чтобы malloc разрешал вообще.Связать только определенные символы из библиотеки

Есть ли способ рассказать GCC «только предоставить эти символы» из libc?

Редактировать: Чтобы быть ясным, я спрашиваю, есть ли способ предоставить только некоторые конкретные символы из библиотеки, а не просто переопределять библиотечную функцию с моей собственной реализацией. Если код использует символ, который находится в библиотеке, но не указан, компоновщик должен завершиться неудачей с «неразрешенным символом». Если еще один вопрос объясняет, как это сделать, я еще этого не видел.

+0

[родственный вопрос] (http://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker) и [другой связанный вопрос] (http://stackoverflow.com/questions/270984/g-partial-linking-in-archives) – Kenney

+1

Возможный дубликат [Как заменить функцию стандартной библиотеки C?] (Http://stackoverflow.com/questions/9107259/how-to-replace-c- стандартная библиотека-функция) –

+0

Я не рассматриваю это как дубликат, так как мой вопрос: «Могу я сказать компоновщику использовать только подмножество символов из библиотеки», а не «могу ли я заменить эту конкретную функцию.«Основное различие заключается в том, что в моем вопросе компоновщик должен исправить ошибку, если используется символ, который не был явно указан из библиотеки. – FazJaxton

ответ

-1

Самое простое решение, вероятно, использовать оболочку, которая определяет символы и устраняющее их во время выполнения с помощью dlfcn:

#include <dlfcn.h> 

void* (*memcpy)(void *dest, const void *src, size_t n); 
char* (*strncpy)(char *dest, const char *src, size_t n); 
... 

void init_symbols (void) { 
    void *handle = dlopen("/lib/libc.so.6", RTLD_LAZY); 

    memcpy = dlsym(handle, "memcpy"); 
    strncpy = dlsym(handle, "strncpy"); 
    ... 
} 

и связать двоичный файл с -nostdlib. Это дает вам лучший контроль над тем, какие символы использовать из какого источника.

+0

Вопрос помечен как встроенный. Вероятно, даже файловая система не доступна (OP очевидно, после сокращения кода, что является четким подсказкой). Как вы думаете, динамическая загрузка библиотеки будет работать? – Olaf

1

Это должно произойти «автоматически», пока поддерживаются настройки вашего libc и linker. Вы не сказали, что такое ваша платформа, так here is one where it does work.

Итак, давайте создадим глупый пример, используя snprintf.

/* 
* main.c 
*/ 
#include <stdio.h> 

int main(int argc, char **argv) { 
    char l[100]; 
    snprintf(l, 100, "%s %d\n", argv[0], argc); 
    return 0; 
} 

попытка собрать и связать его

$ CC=/opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-gcc 
$ CFLAGS="-mcpu=arm926ej-s -Wall -Wextra -O6" 
$ LDFLAGS="-nostartfiles -L. -Wl,--gc-sections,-emain" 
$ $CC $CFLAGS -c main.c -o main.o 
$ $CC $LDFLAGS main.o -o example 
/opt/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): In function `_sbrk_r': 
sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk' 
collect2: error: ld returned 1 exit status 

Необходимо _sbrk потому newlib *printf функции используют malloc, который необходим способ выделения системной памяти. Давайте дадим ему манекен.

/* 
* sbrk.c 
*/ 
#include <stdint.h> 
#include <unistd.h> 
void *_sbrk(intptr_t increment) { 
    return 0; 
} 

и скомпилировать его

$ $CC $CFLAGS -c sbrk.c -o sbrk.o 
$ $CC $LDFLAGS -Wl,-Map,"sbrk.map" main.o sbrk.o -o with-sbrk 
$ /opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-size with-sbrk 
    text data  bss  dec  hex filename 
    28956 2164  56 31176 79c8 with-sbrk 

Ну, вот почему вы хотите, чтобы избавиться от printf и друзей, не так ли? Теперь, замените snprintf с нашей функцией

/* 
* replace.c 
*/ 
#include <stdio.h> 
#include <string.h> 
int snprintf(char *str, size_t size, const char *format, ...) { 
    return strlen(format); 
} 

затем компилировать

$ $CC $CFLAGS -c replace.c -o replace.o 
$ $CC $LDFLAGS -Wl,-Map,"replace.map" main.o replace.o -o with-replace 
$ /opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-size with-sbrk 
    text data  bss  dec  hex filename 
    180  0  0  180  b4 with-replace 

Обратите внимание, что мы не использовали _sbrk заглушки на всех. Если вы не указали _sbrk, вы можете быть уверены, что malloc не является (не может быть) связан и используется.

+0

Спасибо за полный ответ. И хорошо догадаться, я использую arm-none-eabi с newlib. :) – FazJaxton

Смежные вопросы