Как проверить, что символ определен в скрипте компоновщика - PullRequest
1 голос
/ 07 февраля 2012

Я использую другой скрипт компоновщика.В некоторых это значение определено, в других оно не определено:

DIRECTORY_ADDRESS = 0x80100000;
DIRECTORY_SIZE = 32M;

При выполнении я хочу поведение по умолчанию, когда это значение не определено, и специальное поведение, когда оно определено.

Классически я получаю такие значения:

extern void * DIRECTORY_ADDRESS;
extern void * DIRECTORY_SIZE;

void f() { 
  void *dir_addr = &DIRECTORY_ADDRESS;
  int dir_size   = (int)&DIRECTORY_SIZE;
}

Мой первый пример условного выполнения кода в соответствии с существованием этого значения в скрипте компоновщика - слабый атрибут:

extern void * DIRECTORY_ADDRESS  __attribute__ ((weak)) = 0x0;
extern void * DIRECTORY_SIZE __attribute__ ((weak)) = 0x0;

void f() {
  if ( DIRECTORY_ADDRESS )
    // special code
  else
    // default code
}

Но это не может работать, так как я инициализирую значение указателя, а не его адрес: даже неопределенный слабый символ имеет адрес.Так что адрес каталога всегда! = NULL.

Я почти уверен, что эта проблема уже решена, но я не могу найти ни одной связанной проблемы в Интернете.

Ответы [ 2 ]

1 голос
/ 22 февраля 2012

Неинициализированные глобалы слабы по умолчанию, поэтому вы можете просто использовать

void * DIRECTORY_ADDRESS;
void * DIRECTORY_SIZE;

Если для этих имен не определен внешний символ, значением по умолчанию будет NULL. Чтобы принудительно установить значение по умолчанию, отличное от NULL, вы можете использовать

void * DIRECTORY_ADDRESS __attribute__ ((weak)) = OTHER_VALUE;
void * DIRECTORY_SIZE __attribute__ ((weak)) = OTHER_VALUE;

Обратите внимание, что инициализация extern на самом деле не имеет смысла: extern означает, что определение является внешним по отношению к файлу, но инициализация предоставляет определение. Мой компилятор (gcc 4.4) предупреждает пользователя об этом, а затем игнорирует модификатор extern. Это означает, что ваш пример работал для меня как ожидалось (даже при инициализации 0x0), но, возможно, ваш компилятор по-разному справляется с этой неоднозначной ситуацией.

1 голос
/ 07 февраля 2012

Моя ошибка!

Я пробовал много комбинаций, и эта на самом деле неверна:

Поскольку я инициализирую слабые символы, есть "полуслабые"

extern void * DIRECTORY_ADDRESS  __attribute__ ((weak)) = 0x0;
extern void * DIRECTORY_SIZE __attribute__ ((weak)) = 0x0;

Чтобы решить мою проблему, я просто должен позволить слабым символам неинициализироваться, тогда адрес символа будет НЕДЕЙСТВИТЕЛЕН, если они не определены сильным символом:

extern void * DIRECTORY_ADDRESS  __attribute__ ((weak));
extern void * DIRECTORY_SIZE __attribute__ ((weak));
...