Сценарии компоновщика: стратегии для отладки?

Я пытаюсь отлаживать проблему компоновщика, которая у меня есть, при написании ядра.

Проблема в том, что у меня есть переменная SCAN_CODE_MAPPING, которую я не могу использовать - она ​​кажется пустой или что-то еще. Я могу исправить это, изменив способ связи моей программы, но я не знаю почему.

Когда я заглядываю в сгенерированный двоичный файл, используя objdump, данные для переменной определенно существуют, поэтому там что-то сломано со ссылкой на него.

Вот суть с обоими сценариями компоновщика и частью таблицы символов, которая отличается от двух файлов.

Что меня смущает, так это то, что обе таблицы символов имеют одинаковые символы, они имеют одинаковую длину и, как представляется, содержат правильные данные. Единственное отличие, которое я вижу, это то, что они не в одном порядке.

До сих пор я пробовал

  • проверка местоположения памяти SCAN_CODE_MAPPING, чтобы убедиться, что он имеет данные, которые я ожидаю, и не был обнулен.
  • проверка того, что все символы одинаковы
  • проверка того, что все содержимое символа имеет одинаковую длину
  • глядя на .data.rel.ro.local, чтобы убедиться, что он имеет адрес данных

Один из возможных подсказок - это предупреждение:

warning: uninitialized space declared in non-BSS section `.text': zeroing

который я получаю как в сломанном, так и в правильном случае.

Что мне делать дальше?

Ответы

Ответ 1

Вы можете получить тонну дополнительной информации, используя "readelf".

В частности, посмотрите заголовки программы:

readelf -l program

Ваш раздел BSS отличается от стандартного, что, вероятно, вызывает предупреждение. Вот что выглядит по умолчанию в моей системе:

  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   /* Align here to ensure that the .bss section occupies space up to
      _end.  Align after .bss to ensure correct alignment even if the
      .bss section disappears because there are no input sections.
      FIXME: Why do we need it? When there is no .bss section, we don't
      pad the .data section.  */
   . = ALIGN(. != 0 ? 64 / 8 : 1);
  }

Если раздел ввода ничего не соответствует вашему компоновщику script, компоновщик все равно должен его где-то разместить. Убедитесь, что вы покрываете все секции ввода.

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

Секция родата обычно идет после текстового раздела. Они доступны только для чтения во время выполнения и будут отображаться один раз в заголовках вашей программы как запись LOAD с разрешениями на чтение и выполнение. Эта запись LOAD является текстовым сегментом.

Раздел bss обычно проходит после раздела данных. Они записываются во время выполнения и будут отображаться один раз в заголовках вашей программы как запись LOAD с разрешениями на чтение и запись. Эта запись LOAD является сегментом данных.

Если вы меняете порядок, это влияет на то, как компоновщик генерирует заголовки программ. Заголовки программ, а не заголовки разделов, используются при загрузке вашей программы перед ее выполнением. Обязательно проверьте заголовки программ при использовании пользовательского компоновщика script.

Если вы можете дать более подробную информацию о своих действительных симптомах, тогда вам будет легче помочь.

Ответ 2

Проблема здесь заключалась в том, что я писал ОС, и вместо всего этого загружалось всего 12 тыс. Поэтому компоновщик script действительно работал нормально.

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

  • нм
  • objdump
  • readelf