LINUX.ORG.RU

Сообщения igoro

 

Вопрос новичка: Как заменить xstat64/lxstat64/fxstat64 из GLIBC-2.17 64-битной машины на свои версии? (длинное)

Добрый день!

  1. Ранее была тема про компиляцию своих вызовов stat, lstat, xstat для замены стандартных из GLIBC. Оказалось, что эти вызовы на самом деле статические врапперы и заменить их LD_PRELOAD нельзя. Фактически работают скрытые вызовы __xstat, __lxstat, __fxstat, которые линкуются динамически, поэтому их заменить уже можно своими версиями. GLIBC использует такую последовательность вызовов для stat-подобных функций
функция     скрытая      системный
GRLIB       функция      вызов INLINE_SYSCALL
--------    ----------   --------------------					
stat()  ->  __xstat()   -> stat
lstat() ->  __lxstat()  -> lstat
fstat() ->  __fxstat()  -> fstat
  1. Были написаны свои версии вызовов __xstat, __lxstat, __fxstat. Они подключаются c LD_PRELOAD, заменяют стандартные вызовы GLIBC и работают как нужно.

  2. Приложение, с которыми я отлаживал вызовы, использует также вызовы __xstat64, __lxstat64 и __fxstat64 и свои врапперы stat(), lstat(). Которые пока остаются оригинальными. Хочется и их заменить своими версиями.

$ nm application | grep stat

  U __fxstat64@@GLIBC_2.2.5	из GLIBC!!!!!!!   требует замены
  U __fxstat@@GLIBC_2.2.5	из GLIBC!!!!!!!	  есть своя версия!!!
  U stat			внешняя!!!!!!!    требует замены
  U fstat			внешняя!!!!!!!    требует замены
  U __lxstat			внешняя!!!!!!!	  есть своя версия!!!
  U __lxstat64			внешняя!!!!!!!    требует замены
  U __xstat			внешняя!!!!!!!	  есть своя версия!!!
  U __xstat64			внешняя!!!!!!!    требует замены
  1. Врапперы stat, fstat тут динамические, поэтому их можно заменить своей версией. Пример врапперов есть в GLIBC и их можно просто повторить как переходник между stat и __xstat.
#include <sys/stat.h>
int
stat (const char *file, struct stat *buf)
{
  return __xstat (_STAT_VER, file, buf);
}
  1. Возникает вопрос - что делать с вызовами __xstat64, __lxstat64 и __fxstat64? Вызовы stat64, lstat64, fstat64 существуют на 32-битных платформах и на моей 64-бит платформе они заменяются едиными вызовами stat, lstat, fstat. Исходники вызовов stat64, lstat64, fstat64 пустые.

Разрешение имен вызовов осуществляется алиасами GRLIB

weak_hidden_alias (__stat, stat)
weak_hidden_alias (__lstat, lstat)
weak_hidden_alias (__fstat, fstat)
hidden_def (__xstat)
weak_alias (__xstat, _xstat)
hidden_def (__lxstat)
weak_alias (__lxstat, _lxstat)
hidden_def (__fxstat)
weak_alias (__fxstat, _fxstat)
strong_alias (__xstat, __xstat64);
strong_alias (__lxstat, __lxstat64);
weak_alias (__fxstat, _fxstat);
strong_alias (__fxstat, __fxstat64);
  1. Я сдублировал три своих вызова __xstat, __lxstat, __fxstat под новыми именами __xstat64, __lxstat64, __fxstat64 и собрал их всех в новую shared библиотеку mylib.so в надежде, что приложение их подхватит c LD_PRELOAD.
int __xstat64 (int vers, const char *name, struct stat *buf)
{
......
    // call system task
    res = INLINE_SYSCALL (stat, 2, name, CHECK_1 (buf));
......
    return res;
}

int __lxstat64 (int vers, const char *name, struct stat *buf)
{
......
    // call system task
    res = INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), CHECK_1 (buf));
......
    return res;
}

int __fxstat64 (int vers, int fd, struct stat *buf)
{
......
    // call system task
    res = INLINE_SYSCALL (fstat, 2, fd, CHECK_1 (buf));
......
    return res;
}
  1. Для проверки работоспособности новых вызовов я использовал специальный тест, где делал вызовы stat(), lstat(), fstat(), stat64(), lstat64(), fstat64() для специально созданных файлов и линка и печатал информацию о них сначала изнутри моих вызовов а потом повторно из тела тестовой программы. Изначально тестовая программа ссылалась на вызовы из GRLIB
$ nm test_stat64 | grep stat

                 U __fxstat64@@GLIBC_2.2.5
                 U __fxstat@@GLIBC_2.2.5
                 U __lxstat64@@GLIBC_2.2.5
                 U __lxstat@@GLIBC_2.2.5
                 U __xstat64@@GLIBC_2.2.5
                 U __xstat@@GLIBC_2.2.5
  1. Затем тестовая программа запускалась с подключением библиотеки с новыми вызовами
LD_PRELOAD=./mylib.so test_stat64

Сначала запрашивается информация о файле testfile1 с помощью stat() Сначала запрашивается информация о файле testfile2 с помощью open(),fstat() Сначала запрашивается информация о линке testlink1 с помощью lstat()

stat -> __xstat

Сначала информация печатается изнутри вызова, затем из теста. Вызов заменен на новый __xstat(), что видно по печати.

Info: __xstat(1) call for /var/tmp/testfile1
__xstat: file name: /var/tmp/testfile1
__xstat: __xstat() result: 0
__xstat: stat.st_dev : 2050
__xstat: stat.st_ino : 5505095
__xstat: stat.st_mode : 33204
__xstat: stat.st_nlink : 1
__xstat: stat.st_uid : 1001
__xstat: stat.st_gid : 1001
__xstat: stat.st_rdev : 0
__xstat: stat.st_size : 0
__xstat: stat.st_blksize : 4096
__xstat: stat.st_blocks  : 0
__xstat: stat.st_atim : {1677590502, 0}
__xstat: stat.st_mtim : {1677590502, 0}
__xstat: stat.st_ctim : {1688124431, 879050715}

FILE /var/tmp/testfile1 stat(): 0
st_dev = 2050
st_ino = 5505095
st_mode = 100664
st_nlink = 1
st_uid = 1751
st_gid = 1751
st_rdev = 0
st_size = 0
st_blksize = 4096
st_blocks = 0
st_atim = 1677590502  Tue Feb 28 16:21:42 2023
st_mtim = 1677590502  Tue Feb 28 16:21:42 2023
st_ctim = 1688124431  Fri Jun 30 14:27:11 2023

fstat -> __fxstat

Сначала информация печатается изнутри вызова, затем из теста. Вызов заменен на новый __fxstat(), что видно по печати.

FILE /var/tmp/testfile2 open(): 3

Info: _fxstat(1) call for 3
_fxstat: file descr: 3
_fxstat: fstat() result: 0
_fxstat: stat.st_dev : 2050
_fxstat: stat.st_ino : 5516674
_fxstat: stat.st_mode : 33204
_fxstat: stat.st_nlink : 1
_fxstat: stat.st_uid : 1001
_fxstat: stat.st_gid : 1001
_fxstat: stat.st_rdev : 0
_fxstat: stat.st_size : 0
_fxstat: stat.st_blksize : 4096
_fxstat: stat.st_blocks  : 0
_fxstat: stat.st_atim : {1655144133, 0}
_fxstat: stat.st_mtim : {1655144133, 0}
_fxstat: stat.st_ctim : {1688124431, 942049389}

FILE /var/tmp/testfile2 fstat(): 0
st_dev = 2050
st_ino = 5516674
st_mode = 100664
st_nlink = 1
st_uid = 1751
st_gid = 1751
st_rdev = 0
st_size = 0
st_blksize = 4096
st_blocks = 0
st_atim = 1655144133  Mon Jun 13 21:15:33 2022
st_mtim = 1655144133  Mon Jun 13 21:15:33 2022
st_ctim = 1688124431  Fri Jun 30 14:27:11 2023

lstat -> __lxstat

Сначала информация печатается изнутри вызова, затем из теста. Вызов заменен на новый __lxstat(), что видно по печати.

Info: _lxstat(1) call for testlink1
_lxstat: file name: testlink1
_lxstat: lstat() result: 0
_lxstat: stat.st_dev : 2050
_lxstat: stat.st_ino : 3683704
_lxstat: stat.st_mode : 41471
_lxstat: stat.st_nlink : 1
_lxstat: stat.st_uid : 1001
_lxstat: stat.st_gid : 1001
_lxstat: stat.st_rdev : 0
_lxstat: stat.st_size : 9
_lxstat: stat.st_blksize : 4096
_lxstat: stat.st_blocks  : 0
_lxstat: stat.st_atim : {1688647746, 698036866}
_lxstat: stat.st_mtim : {1679927030, 675625380}
_lxstat: stat.st_ctim : {1679927030, 675625380}

LINK testlink1 stat(): 0
st_dev = 2050
st_ino = 3683704
st_mode = 120777
st_nlink = 1
st_uid = 1751
st_gid = 1751
st_rdev = 0
st_size = 9
st_blksize = 4096
st_blocks = 0
st_atim = 1688647746  Thu Jul  6 15:49:06 2023
st_mtim = 1679927030  Mon Mar 27 17:23:50 2023
st_ctim = 1679927030  Mon Mar 27 17:23:50 2023

С тремя первыми вызовами все нормально - они заменяются и работают

Далее те же действия повторяются с вызовами stat64, lstat64, fstat64.

stat64 -> __xstat64

Печати изнутри вызова __xstat64 нет, то есть он не заменился.

FILE /var/tmp/testfile1 stat64(): 0
st_dev = 2050
st_ino = 5505095
st_mode = 100664
st_nlink = 1
st_uid = 1751
st_gid = 1751
st_rdev = 0
st_size = 0
st_blksize = 4096
st_blocks = 0
st_atim = 1677590502  Tue Feb 28 16:21:42 2023
st_mtim = 1677590502  Tue Feb 28 16:21:42 2023
st_ctim = 1688124431  Fri Jun 30 14:27:11 2023

Печати изнутри вызова __fxstat64 нет, то есть он не заменился.

FILE /var/tmp/testfile2 open(): 3
FILE /var/tmp/testfile2 fstat64(): 0
st_dev = 2050
st_ino = 5516674
st_mode = 100664
st_nlink = 1
st_uid = 1751
st_gid = 1751
st_rdev = 0
st_size = 0
st_blksize = 4096
st_blocks = 0
st_atim = 1655144133  Mon Jun 13 21:15:33 2022
st_mtim = 1655144133  Mon Jun 13 21:15:33 2022
st_ctim = 1688124431  Fri Jun 30 14:27:11 2023

Печати изнутри вызова __lxstat64 нет, то есть он не заменился.

LINK testlink1 lstat64(): 0
st_dev = 2050
st_ino = 3683704
st_mode = 120777
st_nlink = 1
st_uid = 1751
st_gid = 1751
st_rdev = 0
st_size = 9
st_blksize = 4096
st_blocks = 0
st_atim = 1688647746  Thu Jul  6 15:49:06 2023
st_mtim = 1679927030  Mon Mar 27 17:23:50 2023
st_ctim = 1679927030  Mon Mar 27 17:23:50 2023

Таким образом, если вызовы __xstat, __lxstat, __fxstat были заменены на новые из моей shared библиотеки, то вызовы __xstat64, __lxstat64, __fxstat64 остались стандартными и не были заменены.

Судя по обсуждениям на форумах, проверить какие библиотеки были использованы приложением можно только в /proc/номерпроцесса/maps но тест выполняется очень быстро и зафиксировать номер процесса не получается.

Почему замена вызовов __xstat64, __lxstat64, __fxstat64 не произошла?

Что у меня идет не так?

Сам подход для замены __xstat64, __lxstat64, __fxstat64 работоспособный?

Спасибо за любые советы!

 ,

igoro
()

Вопрос новичка: где найти исходный код вызова __libc_errno? Можно написать свой?

Возвращаясь к проблеме отсутствия __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? Извините за сумбурное описание проблемы. Спасибо!

 ,

igoro
()

Вопрос новичка: как скомпилировать xstat.c из GLIBC-2.17 в свою shared библиотеку?

Добрый день!

Есть необходимость сделать свою версию системного вызова __xstat() в отдельной shared библиотеке, чтобы посмотреть как она работает внутри. Добавить туда печать внутренних данных и использовать с помощью LD_PRELOAD. На машине стоит CentOS 7 с GLIBC-2.17, поэтому взял за основу исходники GLIBC-2.17. Архив отлично собрался и установился в отдельное место.

Сначала сделал свою версию вызова stat() но оказалось что ее не заменить в GLIBC динамически и надо подменять вызов __xstat(), только он динамически линкуется. Стал смотреть как собирался xstat.c при сборке библиотеки GLIBC. Вижу последовательность команд которыми make собирает всю GLIBC и исходник вызова xstat.c. У него много вариантов но собирается один

gcc ../sysdeps/unix/sysv/linux/wordsize-64/xstat.c .....

Сам исходник очень короткий, в десяток строк, но использует переменные и внутренние вызовы библиотеки, которые задаются где-то в конфигурации и h-файлах. Подтягивается целая лавина h-файлов, define, переменных, внутренних вызовов. Для начала хотел просто распечатать все переменные и параметры при вызове. Добавил печать параметров и переменных прямо в тело xstat.c и пытался пересобрать GLIBC. Исходник и вся библиотека перестала собираться совсем. Тогда решил скомпилировать только xstat.c в свою библиотеку xstat.so и использовать динамически. В версии 2.37 появляется несколько веток внутри вызова - не понятно какая ветка работает. В 2.17 ветка одна к счастью.

Хочу собрать из этого xstat.c свою xstat.so библиотеку с отладочной печатью которую использовать следующим образом

$ LD_PRELOAD=xstat.so <программа cо stat()>

Вот исходник __xstat

/* xstat using old-style Unix stat system call.
   Copyright (C) 1991, 1995, 1996, 1997, 1998, 2000, 2002, 2003, 2004
   Free Software Foundation, Inc.
   This file is part of the GNU C Library.
......
/* Ho hum, since xstat == xstat64 we must get rid of the prototype or gcc
   will complain since they don't strictly match.  */
#define __xstat64 __xstat64_disable

#include <errno.h>
#include <stddef.h>
#include <sys/stat.h>

#include <sysdep.h>
#include <sys/syscall.h>
#include <bp-checks.h>

/////////////////////////////////////////////////////////////////////////
// added for printf
#include <stdio.h>
#include <stdlib.h>
/////////////////////////////////////////////////////////////////////////

/* Get information about the file NAME in BUF.  */
int
__xstat (int vers, const char *name, struct stat *buf)
{
/////////////////////////////////////////////////////////////////////////
// added printf
printf("\n__xstat:  vers: %d  name: %s  _STAT_VER_KERNEL: %d  _STAT_VER_LINUX: %d\n",
vers,name,_STAT_VER_KERNEL,_STAT_VER_LINUX);
/////////////////////////////////////////////////////////////////////////
  if (vers == _STAT_VER_KERNEL || vers == _STAT_VER_LINUX)
    return INLINE_SYSCALL (stat, 2, name, CHECK_1 (buf));

  __set_errno (EINVAL);
  return -1;
}

В локальном sys/stat.h закомментарил объявление __xstat внешней функцией.

//extern int __xstat (int __ver, const char *__filename, struct stat *__stat_buf) __THROW __nonnull ((2, 3));

И читаю свою версию

#include "./sys_stat.h"

Пытаюсь cкомпилировать свою версию xstat.c у себя с этими же опциями gcc как при сборке чтобы все необходимое было найдено в области сборки GLIBC.

При сборке библиотеки

$ cd glibc-2.17; cd build; make configure; make

видно что нужный мне исходник компилируется ТРИ раза, последний раз для librtld.so

make[4]: Entering directory `libc/glibc-2.17/io'
gcc ../sysdeps/unix/sysv/linux/wordsize-64/xstat.c -c -std=gnu99 -fgnu89-inline  -O2 -Wall -Winline \
-Wwrite-strings -fmerge-all-constants -frounding-math -g -Wstrict-prototypes \
-I../include -I/home/xxx/libc/glibc-2.17/buildnew/io -I/home/xxx/libc/glibc-2.17/buildnew \
-I../sysdeps/unix/sysv/linux/x86_64/64/nptl -I../sysdeps/unix/sysv/linux/x86_64/64 \
-I../nptl/sysdeps/unix/sysv/linux/x86_64 -I../nptl/sysdeps/unix/sysv/linux/x86 \
-I../sysdeps/unix/sysv/linux/x86 -I../sysdeps/unix/sysv/linux/x86_64 -I../sysdeps/unix/sysv/linux/wordsize-64 \
-I../nptl/sysdeps/unix/sysv/linux -I../nptl/sysdeps/pthread -I../sysdeps/pthread -I../ports/sysdeps/unix/sysv/linux \
-I../sysdeps/unix/sysv/linux -I../sysdeps/gnu -I../sysdeps/unix/inet -I../nptl/sysdeps/unix/sysv \
-I../ports/sysdeps/unix/sysv -I../sysdeps/unix/sysv -I../sysdeps/unix/x86_64 -I../nptl/sysdeps/unix \
-I../ports/sysdeps/unix -I../sysdeps/unix -I../sysdeps/posix -I../nptl/sysdeps/x86_64/64 \
-I../sysdeps/x86_64/64 -I../sysdeps/x86_64/fpu/multiarch -I../sysdeps/x86_64/fpu -I../sysdeps/x86/fpu \
-I../sysdeps/x86_64/multiarch -I../nptl/sysdeps/x86_64 -I../sysdeps/x86_64 -I../sysdeps/x86 \
-I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64/wordsize-64 -I../sysdeps/ieee754/dbl-64 \
-I../sysdeps/ieee754/flt-32 -I../sysdeps/wordsize-64 -I../sysdeps/ieee754 -I../sysdeps/generic \
-I../nptl -I../ports  -I.. -I../libio -I.   -D_LIBC_REENTRANT -include ../include/libc-symbols.h \
-o /home/xxx/libc/glibc-2.17/buildnew/io/xstat.o -MD -MP \
-MF /home/xxx/libc/glibc-2.17/buildnew/io/xstat.o.dt \
-MT /home/xxx/libc/glibc-2.17/buildnew/io/xstat.o 

make[4]: Entering directory `libc/glibc-2.17/io'
gcc ../sysdeps/unix/sysv/linux/wordsize-64/xstat.c -c -std=gnu99 -fgnu89-inline  -O2 -Wall -Winline \
-Wwrite-strings -fmerge-all-constants -frounding-math -g -Wstrict-prototypes   -fPIC \
-I../include -I/home/xxx/libc/glibc-2.17/buildnew/io -I/home/xxx/libc/glibc-2.17/buildnew \
-I../sysdeps/unix/sysv/linux/x86_64/64/nptl -I../sysdeps/unix/sysv/linux/x86_64/64 \
-I../nptl/sysdeps/unix/sysv/linux/x86_64 -I../nptl/sysdeps/unix/sysv/linux/x86 \
-I../sysdeps/unix/sysv/linux/x86 -I../sysdeps/unix/sysv/linux/x86_64 -I../sysdeps/unix/sysv/linux/wordsize-64 \
-I../nptl/sysdeps/unix/sysv/linux -I../nptl/sysdeps/pthread -I../sysdeps/pthread \
-I../ports/sysdeps/unix/sysv/linux -I../sysdeps/unix/sysv/linux -I../sysdeps/gnu -I../sysdeps/unix/inet \
-I../nptl/sysdeps/unix/sysv -I../ports/sysdeps/unix/sysv -I../sysdeps/unix/sysv -I../sysdeps/unix/x86_64 \
-I../nptl/sysdeps/unix -I../ports/sysdeps/unix -I../sysdeps/unix -I../sysdeps/posix \
-I../nptl/sysdeps/x86_64/64 -I../sysdeps/x86_64/64 -I../sysdeps/x86_64/fpu/multiarch -I../sysdeps/x86_64/fpu \
-I../sysdeps/x86/fpu -I../sysdeps/x86_64/multiarch -I../nptl/sysdeps/x86_64 -I../sysdeps/x86_64 \
-I../sysdeps/x86 -I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64/wordsize-64 \
-I../sysdeps/ieee754/dbl-64 -I../sysdeps/ieee754/flt-32 -I../sysdeps/wordsize-64 -I../sysdeps/ieee754 \
-I../sysdeps/generic -I../nptl -I../ports  -I.. -I../libio -I.   -D_LIBC_REENTRANT \
-include ../include/libc-symbols.h  -DPIC -DSHARED \
-o /home/xxx/libc/glibc-2.17/buildnew/io/xstat.os -MD -MP \
-MF /home/xxx/libc/glibc-2.17/buildnew/io/xstat.os.dt \
-MT /home/xxx/libc/glibc-2.17/buildnew/io/xstat.os 

make[4]: Entering directory `libc/glibc-2.17/io'
gcc ../sysdeps/unix/sysv/linux/wordsize-64/xstat.c -c -std=gnu99 -fgnu89-inline  -O2 -Wall -Winline \
-Wwrite-strings -fmerge-all-constants -frounding-math -g -Wstrict-prototypes   -fPIC \
-I../include -I/home/xxx/libc/glibc-2.17/buildnew/io -I/home/xxx/libc/glibc-2.17/buildnew \
-I../sysdeps/unix/sysv/linux/x86_64/64/nptl -I../sysdeps/unix/sysv/linux/x86_64/64 \
-I../nptl/sysdeps/unix/sysv/linux/x86_64 -I../nptl/sysdeps/unix/sysv/linux/x86 \
-I../sysdeps/unix/sysv/linux/x86 -I../sysdeps/unix/sysv/linux/x86_64 -I../sysdeps/unix/sysv/linux/wordsize-64 \
-I../nptl/sysdeps/unix/sysv/linux -I../nptl/sysdeps/pthread -I../sysdeps/pthread \
-I../ports/sysdeps/unix/sysv/linux -I../sysdeps/unix/sysv/linux -I../sysdeps/gnu -I../sysdeps/unix/inet \
-I../nptl/sysdeps/unix/sysv -I../ports/sysdeps/unix/sysv -I../sysdeps/unix/sysv -I../sysdeps/unix/x86_64 \
-I../nptl/sysdeps/unix -I../ports/sysdeps/unix -I../sysdeps/unix -I../sysdeps/posix \
-I../nptl/sysdeps/x86_64/64 -I../sysdeps/x86_64/64 -I../sysdeps/x86_64/fpu/multiarch -I../sysdeps/x86_64/fpu \
-I../sysdeps/x86/fpu -I../sysdeps/x86_64/multiarch -I../nptl/sysdeps/x86_64 -I../sysdeps/x86_64 \
-I../sysdeps/x86 -I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64/wordsize-64 \
-I../sysdeps/ieee754/dbl-64 -I../sysdeps/ieee754/flt-32 -I../sysdeps/wordsize-64 -I../sysdeps/ieee754 \
-I../sysdeps/generic -I../nptl -I../ports  -I.. -I../libio -I.   -D_LIBC_REENTRANT \
-include ../include/libc-symbols.h  -DPIC -DSHARED \
-o /home/xxx/libc/glibc-2.17/buildnew/io/rtld-xstat.os -MD -MP \
-MF /home/xxx/libc/glibc-2.17/buildnew/io/rtld-xstat.os.dt \
-MT /home/xxx/libc/glibc-2.17/buildnew/io/rtld-xstat.os \
-DNOT_IN_libc=1 -DIS_IN_rtld=1 -DIN_LIB=rtld

Трудно сказать какой сеанс компиляции более мне подходит, взял первый, где создается xstat.o Не уверен, стоило ли оставлять параметры -D_LIBC_REENTRANT -include ${GLIBC_PATH}/include/libc-symbols.h может они нужны только при сборке полной GLIBC а здесь нет.

Моя команда компиляции выглядит следующим образом.

#!/bin/sh

export GLIBC_PATH=/home/xxx/libc/glibc-2.17

gcc -fPIC -shared ./xstat.c -std=gnu99 -fgnu89-inline -O2 -Winline -Wwrite-strings -fmerge-all-constants \
-frounding-math -Wstrict-prototypes -I${GLIBC_PATH}/include -I${GLIBC_PATH}/build/io -I${GLIBC_PATH}/build \
-I${GLIBC_PATH}/sysdeps/unix/sysv/linux/x86_64/64/nptl -I${GLIBC_PATH}/sysdeps/unix/sysv/linux/x86_64/64 \
-I${GLIBC_PATH}/nptl/sysdeps/unix/sysv/linux/x86_64 -I${GLIBC_PATH}/nptl/sysdeps/unix/sysv/linux/x86 \
-I${GLIBC_PATH}/sysdeps/unix/sysv/linux/x86 -I${GLIBC_PATH}/sysdeps/unix/sysv/linux/x86_64 \
-I${GLIBC_PATH}/sysdeps/unix/sysv/linux/wordsize-64 -I${GLIBC_PATH}/nptl/sysdeps/unix/sysv/linux \
-I${GLIBC_PATH}/nptl/sysdeps/pthread -I${GLIBC_PATH}/sysdeps/pthread \
-I${GLIBC_PATH}/ports/sysdeps/unix/sysv/linux -I${GLIBC_PATH}/sysdeps/unix/sysv/linux \
-I${GLIBC_PATH}/sysdeps/gnu -I${GLIBC_PATH}/sysdeps/unix/inet -I${GLIBC_PATH}/nptl/sysdeps/unix/sysv \
-I${GLIBC_PATH}/ports/sysdeps/unix/sysv -I${GLIBC_PATH}/sysdeps/unix/sysv -I${GLIBC_PATH}/sysdeps/unix/x86_64 \
-I${GLIBC_PATH}/nptl/sysdeps/unix -I${GLIBC_PATH}/ports/sysdeps/unix -I${GLIBC_PATH}/sysdeps/unix \
-I${GLIBC_PATH}/sysdeps/posix -I${GLIBC_PATH}/nptl/sysdeps/x86_64/64 -I${GLIBC_PATH}/sysdeps/x86_64/64 \
-I${GLIBC_PATH}/sysdeps/x86_64/fpu/multiarch -I${GLIBC_PATH}/sysdeps/x86_64/fpu \
-I${GLIBC_PATH}/sysdeps/x86/fpu -I${GLIBC_PATH}/sysdeps/x86_64/multiarch -I${GLIBC_PATH}/nptl/sysdeps/x86_64 \
-I${GLIBC_PATH}/sysdeps/x86_64 -I${GLIBC_PATH}/sysdeps/x86 -I${GLIBC_PATH}/sysdeps/ieee754/ldbl-96 \
-I${GLIBC_PATH}/sysdeps/ieee754/dbl-64/wordsize-64 -I${GLIBC_PATH}/sysdeps/ieee754/dbl-64 \
-I${GLIBC_PATH}/sysdeps/ieee754/flt-32 -I${GLIBC_PATH}/sysdeps/wordsize-64 -I${GLIBC_PATH}/sysdeps/ieee754 \
-I${GLIBC_PATH}/sysdeps/generic -I${GLIBC_PATH}/nptl -I${GLIBC_PATH}/ports  -I${GLIBC_PATH} \
-I${GLIBC_PATH}/libio -I${GLIBC_PATH}/build -D_LIBC_REENTRANT -include ${GLIBC_PATH}/include/libc-symbols.h \
-L/lib64 -lc -o xstat.so 
$ file xstat.so

xstat.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=b5f3154c730e812b14426f4eeb943c973d8ef363, not stripped

$ ldd  xstat.so

	linux-vdso.so.1 =>  (0x00007fff420ec000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f564f6bb000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f564fc8d000)

Компиляция завершается без ошибок. Однако при использовании новой библиотеки есть сообщение об отсутствии системного вызова __libc_errno, который должен быть в GLIBC

$ LD_PRELOAD=./xstat.so date
date: symbol lookup error: ./xstat.so: undefined symbol: __libc_errno

его действительно нет в моей библиотеке, но он есть в системной библиотеке libc-2.17.so

$ nm -D ./xstat.so | grep ' U '
                 U ctime
                 U ftime
                 U getenv
                 U gmtime
                 U __libc_errno
                 U printf
                 U puts
                 U sscanf
                 U strcpy
                 U timegm

$ nm /lib64/libc-2.17.so | grep __libc_errno
0000000000000010 b __libc_errno

Как подцепить недостающие вызовы к xstat.so и проверить что там еще не хватает? Как правильно скомпилировать отдельный исходник из GLIBC в отдельную shared библиотеку?

Буду благодарен за любой совет!

 ,

igoro
()

RSS подписка на новые темы