2016-03-30 9 views
1

Вопрос для гуру-линкера. Я работаю с файлами mex в Matlab и получаю ужасные много необъяснимых сбоев, поэтому я хочу копать немного глубже.Как загрузчик распределяет/освобождает статические данные от динамического модуля

Можете ли вы объяснить мне, как статические данные распределяются (освобождаются) в пространстве виртуальной памяти процесса при загрузке (выгрузке) динамического модуля?

Я предполагаю, что это происходит в функциях _init() и _fini(). Однако сегменту BSS присваивается кусок памяти в куче пространства наряду с другими распределениями динамической памяти?

Что относительно глобальных данных в динамическом модуле? Будет ли возможность столкновения имен символов с основным исполняемым файлом?

Спасибо, что пролил свет на эти проблемы. Если мне нужно выбрать платформу, я бы хотел услышать от экспертов ELF, так как большую часть своей разработки я занимаюсь Linux.

ответ

2

Можете ли вы объяснить мне, как статические данные распределяются (освобождаются) в пространстве виртуальной памяти процесса при загрузке (выгрузке) динамического модуля?

Эта часть проста: каждый ELF файл имеет PT_LOAD сегменты, которые вы можете увидеть на выходе из readelf -Wl foo.so. При загрузке общего объекта каждый из этих сегментов составляет mmap ed в адресное пространство и служит как «распределение» для любых статических данных в этом общем объекте.

Когда выгружается foo.so, данные (и код) удаляются через системный вызов munmap.

Я предполагаю, что это происходит в _init() и _fini() функции

Это предположение не верно. _init и _fini - это динамическая инициализация (например, глобальные переменные типа класса в C++ с нетривиальным конструктором/деструктором). К моменту появления _init память для всех глобалов уже «зарезервирована» через mmap.

Однако делает сегмент BSS

.bss раздел включен в том же PT_LOAD сегменте, в котором другие инициализацию данные (запись) являются. Вот почему существует отдельный p_filesz и p_memsz в ElfXX_Phdr: p_filesz «охватывает» инициализированные данные, и (больше) p_memsz вызывает mmap, чтобы «выделить» пространство для обоих инициализирован и .bss данных.

Что относительно глобальных данных в динамическом модуле?

Что с этим делать? Я рассмотрел инициализированные данные выше.

Возможно ли возникновение конфликтов имен символов с основным исполняемым файлом?

Конечно. Вы можете определить int foo = 42; в a.out и int foo = 24; в foo.so. Обычным правилом является то, что , еслиfoo отображается в таблице динамических символов a.out, тогда foo будет использоваться независимо от того, на что он ссылается.

Осложнения возникают, когда a.out не экспортирует foo (если она не связана с -rdymamicи не связывает с foo.so), или когда foo.so связан с -Bsymbolic.

+0

Благодаря @EmployedRussian, я выкопал немного больше в таблице динамических символов, кажется, что глобальные символы экспортируются только в таблицу динамических символов, когда задано -rdynamic. Как правило, они не экспортируются, поэтому динамический модуль не может получить доступ к ним из исполняемого файла. Это верно? – DKWH

+0

@DKWH Существует 3 способа (которые я знаю) для символа, который будет экспортироваться из a.out: (1) вы ссылаетесь на '-rdynamic' (или' -E' или '--export-dynamic') или (2) вы напрямую связываетесь с 'foo.so', который использует символ, или (3) вы экспортируете символ в скрипт версии компоновщика. –