__dso_handle
Таинственная незнакомка неизменно появлялась в Начале. Тенью мелькала она среди невзрачных рабочих и прочих безликих ассистентов. Если специально не искать ее взглядом, то и не заметишь. Впрочем, никому и в голову не приходило искать ее специально. Серые мыши никого не интересуют.
Так думал и я, пока не столкнулся с ней в Конце. После этой встречи я не переставал думать о ней. Меня не обманула ее ложная скромность. Это была кротость омута, таящего в себе мрачную тайну. Кто она, какова ее роль во всем этом? Зачем она приходит в Начале и что делает в Конце? Никто не знал.
Я стал следить за ней, записывать, когда и где она появляется. Долгими бессонными ночами я строил планы, где и как подкараулить ее.
Сегодня наконец-то она попалась в мои силки. Теперь она расскажет нам все!
Я пристально смотрел на нее, а она - на меня. Таинственная глобальная переменная __dso_handle.
Если попробовать вывести ее значение в обычном исполняемом файле
Она покажется нам банальной пустышкой: (nil).
Нулевой указатель. Тогда зачем она вообще нужна? Совсем эти яйцеголовые разработчики накурились своих мануалов и айда сувать всякую гадость в свои __cxa_thread_atexit.
Однако я сам плюсовик, разрабатываю уже сто лет, внук председателя колхоза. Просто поверьте, тут не все так однозначно!..
Я специально __dso_handle не объявлял, вы, наверняка, тоже. Тогда кто же это сделал?
Компилятор, конечно! Он же обеспечивает вызов и управление глобальными конструкторами и деструкторами в файлах crtbegin (C Runtime Begin) и там же определяет эту магическую переменную. Для тривиальной сборки исполняемого файла компилятор будет применять файлы crtbegin, где
Для динамических библиотек будет применен особый файл crtbeginS.o, где уже
Обязательно нужно пометить символ как hidden, чтоб не засветить снаружи динамической библиотеки. В итоге, даже если мы загрузим 100500 so-объектов, у всех будет разная __dso_handle. Это наводит нас на очевидную мысль, что подобный символ можно использовать как некий маркер бинарного модуля.
Эта же мысль пришла в головы создателям требований Itanium C++ ABI.
В разделе 3.3.6.3
Runtime API в пункте C. Termination ангельским языком писано:
При компоновке любого разделяемого объекта (DSO), содержащего вызов __cxa_atexit, компоновщик должен определить скрытый символ __dso_handle, значением которого является адрес в одном из сегментов объекта. Конкретный адрес не важен, если для разных DSO они различаются.
Казалось бы, причем тут какая-то функция?
Таинственная незнакомка неизменно появлялась в Начале. Тенью мелькала она среди невзрачных рабочих и прочих безликих ассистентов. Если специально не искать ее взглядом, то и не заметишь. Впрочем, никому и в голову не приходило искать ее специально. Серые мыши никого не интересуют.
Так думал и я, пока не столкнулся с ней в Конце. После этой встречи я не переставал думать о ней. Меня не обманула ее ложная скромность. Это была кротость омута, таящего в себе мрачную тайну. Кто она, какова ее роль во всем этом? Зачем она приходит в Начале и что делает в Конце? Никто не знал.
Я стал следить за ней, записывать, когда и где она появляется. Долгими бессонными ночами я строил планы, где и как подкараулить ее.
Сегодня наконец-то она попалась в мои силки. Теперь она расскажет нам все!
Я пристально смотрел на нее, а она - на меня. Таинственная глобальная переменная __dso_handle.
Если попробовать вывести ее значение в обычном исполняемом файле
printf("%p", __dso_handle);
Она покажется нам банальной пустышкой: (nil).
Нулевой указатель. Тогда зачем она вообще нужна? Совсем эти яйцеголовые разработчики накурились своих мануалов и айда сувать всякую гадость в свои __cxa_thread_atexit.
Однако я сам плюсовик, разрабатываю уже сто лет, внук председателя колхоза. Просто поверьте, тут не все так однозначно!..
Я специально __dso_handle не объявлял, вы, наверняка, тоже. Тогда кто же это сделал?
Компилятор, конечно! Он же обеспечивает вызов и управление глобальными конструкторами и деструкторами в файлах crtbegin (C Runtime Begin) и там же определяет эту магическую переменную. Для тривиальной сборки исполняемого файла компилятор будет применять файлы crtbegin, где
void *__dso_handle = 0;
Для динамических библиотек будет применен особый файл crtbeginS.o, где уже
void *__dso_handle __attribute__ ((__visibility__ ("hidden"))) = &__dso_handle;
Обязательно нужно пометить символ как hidden, чтоб не засветить снаружи динамической библиотеки. В итоге, даже если мы загрузим 100500 so-объектов, у всех будет разная __dso_handle. Это наводит нас на очевидную мысль, что подобный символ можно использовать как некий маркер бинарного модуля.
Эта же мысль пришла в головы создателям требований Itanium C++ ABI.
В разделе 3.3.6.3
Runtime API в пункте C. Termination ангельским языком писано:
При компоновке любого разделяемого объекта (DSO), содержащего вызов __cxa_atexit, компоновщик должен определить скрытый символ __dso_handle, значением которого является адрес в одном из сегментов объекта. Конкретный адрес не важен, если для разных DSO они различаются.
Казалось бы, причем тут какая-то функция?