Возвращаясь к проблеме отсутствия __libc_errno вызова при сборке своей shared библиотеки с несколькими системными вызовами типа xstat() возникла идея написать самому некую замену этому вызову взамен отсутствующего. Может это конечно и глупая идея но других идей нет. Пока собрать свою shared library полноценно не получается.
Подробнее. Собираю код __xstat() и еще __lxstat(), __fxstat() в отдельном исходнике c глобальными переменными для обмена и своими доработками, компилирую их той же командой что и при сборке GLIBC и ошибок компиляции нет. Однако при использовании библиотеки не находится __libc_errno. Хотя она явно есть внутри libc.so и пути к ней указаны.
$ LD_PRELOAD=./xstat.so date
date: symbol lookup error: ./xstat.so: undefined symbol: __libc_errno
Вызова этой процедуры нет явно в коде xstat(), есть только __set_errno().
int
__xstat (int vers, const char *name, struct stat *buf)
{
if (vers == _STAT_VER_KERNEL || vers == _STAT_VER_LINUX)
return INLINE_SYSCALL (stat, 2, name, CHECK_1 (buf));
__set_errno (EINVAL); // <<<<<<<<<<<<<<<<<
return -1;
}
когда я закомментарил этот вызов, это не помогло.
//__set_errno (EINVAL); // <<<<<<<<<<<<<<<<<
По прежнему он кем-то используется и его так и нет в моей shared библиотеке.
date: symbol lookup error: ./xstat.so: undefined symbol: __libc_errno
Корректная отработка ошибок при системных вызовах мне не требуется, так как shared библиотека работает с отлаженными программами и там весь код уже написан правильно. Отсюда и идея написать свою процедуры-пустышку для сборки библиотеки. При это она уже не будет extern.
Просмотрел всю инсталляцию GLIBC-2.17 и не обнаружил нигде каких-либо исходников этого вызова. Хотя его название в внутри libc.so есть, может только название а не код.
0000000000000010 b __libc_errno
0000000000000054 b __libc_h_errno
Сам вызов упоминается всего в нескольких местах
../include/errno.h:# define errno __libc_errno
../ports/sysdeps/unix/sysv/linux/ia64/nptl/sysdep-cancel.h:# define SYSDEP_CANCEL_ERRNO __libc_errno
../ports/sysdeps/unix/sysv/linux/m68k/sysdep.h:# define SYSCALL_ERROR_ERRNO __libc_errno
../sysdeps/unix/sysv/linux/sparc/sparc64/sysdep.h:# define SYSCALL_ERROR_ERRNO __libc_errno
../sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h:# define SYSCALL_ERROR_ERRNO __libc_errno
../sysdeps/unix/sysv/linux/i386/sysdep.h:# define SYSCALL_ERROR_ERRNO __libc_errno
../sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h:# define SYSCALL_ERROR_ERRNO __libc_errno
../sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h:# define SYSCALL_ERROR_ERRNO __libc_errno
../sysdeps/unix/sysv/linux/x86_64/sysdep.h:# define SYSCALL_ERROR_ERRNO __libc_errno
../sysdeps/unix/sysv/linux/sh/sysdep.h:# define SYSCALL_ERROR_ERRNO __libc_errno
Есть даже некий код связанный с обработкой ошибок в ../sysdeps/unix/sysv/linux/x86_64/sysdep.h где используется определение SYSCALL_ERROR_ERRNO
# if defined PIC && defined RTLD_PRIVATE_ERRNO
# define SYSCALL_SET_ERRNO \
lea rtld_errno(%rip), %RCX_LP; \
neg %eax; \
movl %eax, (%rcx)
# else
# ifndef NOT_IN_libc
# define SYSCALL_ERROR_ERRNO __libc_errno
# else
# define SYSCALL_ERROR_ERRNO errno
# endif
# define SYSCALL_SET_ERRNO \
movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\
neg %eax; \
movl %eax, %fs:(%rcx);
# endif
Там же для обработки ошибок используется опять другая процедура __set_errno
# define INLINE_SYSCALL(name, nr, args...) \
({ \
unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args); \
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0)) \
{ \
__set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \
resultvar = (unsigned long int) -1; \
} \
(long int) resultvar; })
Она в одном месте описана как присвоение кода ошибки
./include/errno.h
# define __set_errno(val) (errno = (val))
Но мне попадался и такой код процедуры
#include <errno.h>
int __set_errno(int n)
{
errno = n;
return -1;
}
Возвращаясь к __libc_errno. Хотелось бы написать подобный аналог для __libc_errno. Единственное объявление __libc_errno находится в ../csu/errno.c
__thread int errno;
extern __thread int __libc_errno __attribute__ ((alias ("errno")))
attribute_hidden;
Вопрос как правильно написать оболочку этого вызова?
Результат - int Имя вызова - __libc_errno Параметр - что такое (alias («errno»))? Что туда передается? По идее тоже код ошибки как и в __set_errno.
К сожалению никаких примеров прямого вызова процедуры _libc_errno нигде не нашел. Только куски ассемблера. Хотелось бы написать что-то вроде этого чтобы вызывать из С.
#include <errno.h>
int __libc_errno (int n)
{
errno = n;
return -1;
}
Это вообще возможно написать такую замену __libc_errno не сломав GLIBC? Извините за сумбурное описание проблемы. Спасибо!