LINUX.ORG.RU

Сообщения igoro

 

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

Форум — Development

Добрый день!

  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? Можно написать свой?

Форум — Development

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

Форум — Development

Добрый день!

Есть необходимость сделать свою версию системного вызова __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 подписка на новые темы