mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 23:00:07 +00:00
Revert "Detect ld.so and libc.so version inconsistency during startup"
This reverts commit 6f85dbf102
.
Once this change hits the release branches, it will require relinking
of all statically linked applications before static dlopen works
again, for the majority of updates on release branches: The NEWS file
is regularly updated with bug references, so the __libc_early_init
suffix changes, and static dlopen cannot find the function anymore.
While this ABI check is still technically correct (we do require
rebuilding & relinking after glibc updates to keep static dlopen
working), it is too drastic for stable release branches.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
parent
025a8cce63
commit
89baed0b93
10
INSTALL
10
INSTALL
@ -120,16 +120,6 @@ if 'CFLAGS' is specified it must enable optimization. For example:
|
|||||||
compiler flags which target a later instruction set architecture
|
compiler flags which target a later instruction set architecture
|
||||||
(ISA).
|
(ISA).
|
||||||
|
|
||||||
'--with-extra-version-id=STRING'
|
|
||||||
Use STRING as part of the fingerprint that is used by the dynamic
|
|
||||||
linker to detect an incompatible version of 'libc.so'. For
|
|
||||||
example, STRING could be the full package version and release
|
|
||||||
string used by a distribution build of the GNU C Library. This
|
|
||||||
way, concurrent process creation during a package update will fail
|
|
||||||
with an error message, _error while loading shared libraries:
|
|
||||||
/lib64/libc.so.6: ld.so/libc.so mismatch detected (upgrade in
|
|
||||||
progress?)_, rather than crashing mysteriously.
|
|
||||||
|
|
||||||
'--with-timeoutfactor=NUM'
|
'--with-timeoutfactor=NUM'
|
||||||
Specify an integer NUM to scale the timeout of test programs. This
|
Specify an integer NUM to scale the timeout of test programs. This
|
||||||
factor can be changed at run time using 'TIMEOUTFACTOR' environment
|
factor can be changed at run time using 'TIMEOUTFACTOR' environment
|
||||||
|
14
Makerules
14
Makerules
@ -112,20 +112,6 @@ before-compile := $(common-objpfx)first-versions.h \
|
|||||||
$(common-objpfx)ldbl-compat-choose.h $(before-compile)
|
$(common-objpfx)ldbl-compat-choose.h $(before-compile)
|
||||||
$(common-objpfx)first-versions.h: $(common-objpfx)versions.stmp
|
$(common-objpfx)first-versions.h: $(common-objpfx)versions.stmp
|
||||||
$(common-objpfx)ldbl-compat-choose.h: $(common-objpfx)versions.stmp
|
$(common-objpfx)ldbl-compat-choose.h: $(common-objpfx)versions.stmp
|
||||||
|
|
||||||
# libc_early_init_name.h provides the actual name of the
|
|
||||||
# __libc_early_init function. It is used as a protocol version marker
|
|
||||||
# between ld.so and libc.so
|
|
||||||
before-compile := $(common-objpfx)libc_early_init_name.h $(before-compile)
|
|
||||||
libc_early_init_name-deps = \
|
|
||||||
$(..)NEWS $(..)sysdeps/generic/ldsodefs.h $(..)include/link.h
|
|
||||||
$(common-objpfx)libc_early_init_name.h: $(..)scripts/libc_early_init_name.py \
|
|
||||||
$(common-objpfx)config.make $(libc_early_init_name-deps)
|
|
||||||
$(PYTHON) $(..)scripts/libc_early_init_name.py \
|
|
||||||
--output=$@T \
|
|
||||||
--extra-version-id="$(extra-version-id)" \
|
|
||||||
$(libc_early_init_name-deps)
|
|
||||||
$(move-if-change) $@T $@
|
|
||||||
endif # avoid-generated
|
endif # avoid-generated
|
||||||
endif # $(build-shared) = yes
|
endif # $(build-shared) = yes
|
||||||
|
|
||||||
|
7
NEWS
7
NEWS
@ -9,12 +9,7 @@ Version 2.37
|
|||||||
|
|
||||||
Major new features:
|
Major new features:
|
||||||
|
|
||||||
* The dynamic loader now prints an error message, "ld.so/libc.so
|
[Add new features here]
|
||||||
mismatch detected (upgrade in progress?)" if it detects that the
|
|
||||||
version of libc.so it loaded comes from a different build of glibc.
|
|
||||||
The new configure option --with-extra-version-id can be used to
|
|
||||||
specify an arbitrary string that affects the computation of the
|
|
||||||
version fingerprint.
|
|
||||||
|
|
||||||
Deprecated and removed features, and other changes affecting compatibility:
|
Deprecated and removed features, and other changes affecting compatibility:
|
||||||
|
|
||||||
|
@ -98,7 +98,6 @@ build-hardcoded-path-in-tests= @hardcoded_path_in_tests@
|
|||||||
build-pt-chown = @build_pt_chown@
|
build-pt-chown = @build_pt_chown@
|
||||||
have-tunables = @have_tunables@
|
have-tunables = @have_tunables@
|
||||||
pthread-in-libc = @pthread_in_libc@
|
pthread-in-libc = @pthread_in_libc@
|
||||||
extra-version-id = @extra_version_id@
|
|
||||||
|
|
||||||
# Build tools.
|
# Build tools.
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
|
11
configure
vendored
11
configure
vendored
@ -760,7 +760,6 @@ with_headers
|
|||||||
with_default_link
|
with_default_link
|
||||||
with_nonshared_cflags
|
with_nonshared_cflags
|
||||||
with_rtld_early_cflags
|
with_rtld_early_cflags
|
||||||
with_extra_version_id
|
|
||||||
with_timeoutfactor
|
with_timeoutfactor
|
||||||
enable_sanity_checks
|
enable_sanity_checks
|
||||||
enable_shared
|
enable_shared
|
||||||
@ -1482,9 +1481,6 @@ Optional Packages:
|
|||||||
build nonshared libraries with additional CFLAGS
|
build nonshared libraries with additional CFLAGS
|
||||||
--with-rtld-early-cflags=CFLAGS
|
--with-rtld-early-cflags=CFLAGS
|
||||||
build early initialization with additional CFLAGS
|
build early initialization with additional CFLAGS
|
||||||
--extra-version-id=STRING
|
|
||||||
specify an extra version string to use in internal
|
|
||||||
ABI checks
|
|
||||||
--with-timeoutfactor=NUM
|
--with-timeoutfactor=NUM
|
||||||
specify an integer to scale the timeout
|
specify an integer to scale the timeout
|
||||||
--with-cpu=CPU select code for CPU variant
|
--with-cpu=CPU select code for CPU variant
|
||||||
@ -3401,13 +3397,6 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check whether --with-extra-version-id was given.
|
|
||||||
if test "${with_extra_version_id+set}" = set; then :
|
|
||||||
withval=$with_extra_version_id; extra_version_id="$withval"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check whether --with-timeoutfactor was given.
|
# Check whether --with-timeoutfactor was given.
|
||||||
if test "${with_timeoutfactor+set}" = set; then :
|
if test "${with_timeoutfactor+set}" = set; then :
|
||||||
withval=$with_timeoutfactor; timeoutfactor=$withval
|
withval=$with_timeoutfactor; timeoutfactor=$withval
|
||||||
|
@ -169,11 +169,6 @@ AC_ARG_WITH([rtld-early-cflags],
|
|||||||
[rtld_early_cflags=])
|
[rtld_early_cflags=])
|
||||||
AC_SUBST(rtld_early_cflags)
|
AC_SUBST(rtld_early_cflags)
|
||||||
|
|
||||||
AC_ARG_WITH([extra-version-id],
|
|
||||||
AS_HELP_STRING([--extra-version-id=STRING],
|
|
||||||
[specify an extra version string to use in internal ABI checks]),
|
|
||||||
[extra_version_id="$withval"])
|
|
||||||
|
|
||||||
AC_ARG_WITH([timeoutfactor],
|
AC_ARG_WITH([timeoutfactor],
|
||||||
AS_HELP_STRING([--with-timeoutfactor=NUM],
|
AS_HELP_STRING([--with-timeoutfactor=NUM],
|
||||||
[specify an integer to scale the timeout]),
|
[specify an integer to scale the timeout]),
|
||||||
|
@ -52,6 +52,7 @@ routines = \
|
|||||||
# The core dynamic linking functions are in libc for the static and
|
# The core dynamic linking functions are in libc for the static and
|
||||||
# profiled libraries.
|
# profiled libraries.
|
||||||
dl-routines = \
|
dl-routines = \
|
||||||
|
dl-call-libc-early-init \
|
||||||
dl-close \
|
dl-close \
|
||||||
dl-debug \
|
dl-debug \
|
||||||
dl-debug-symbols \
|
dl-debug-symbols \
|
||||||
@ -64,7 +65,6 @@ dl-routines = \
|
|||||||
dl-load \
|
dl-load \
|
||||||
dl-lookup \
|
dl-lookup \
|
||||||
dl-lookup-direct \
|
dl-lookup-direct \
|
||||||
dl-lookup_libc_early_init \
|
|
||||||
dl-minimal-malloc \
|
dl-minimal-malloc \
|
||||||
dl-misc \
|
dl-misc \
|
||||||
dl-object \
|
dl-object \
|
||||||
|
@ -29,8 +29,8 @@ libc {
|
|||||||
__placeholder_only_for_empty_version_map;
|
__placeholder_only_for_empty_version_map;
|
||||||
}
|
}
|
||||||
GLIBC_PRIVATE {
|
GLIBC_PRIVATE {
|
||||||
# A pattern is needed here because the suffix is dynamically generated.
|
# functions used in other libraries
|
||||||
__libc_early_init_*;
|
__libc_early_init;
|
||||||
|
|
||||||
# Internal error handling support. Interposes the functions in ld.so.
|
# Internal error handling support. Interposes the functions in ld.so.
|
||||||
_dl_signal_exception; _dl_catch_exception;
|
_dl_signal_exception; _dl_catch_exception;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Find the address of the __libc_early_init function.
|
/* Invoke the early initialization function in libc.so.
|
||||||
Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
@ -16,21 +16,26 @@
|
|||||||
License along with the GNU C Library; if not, see
|
License along with the GNU C Library; if not, see
|
||||||
<https://www.gnu.org/licenses/>. */
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
#include <libc-early-init.h>
|
#include <libc-early-init.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
__typeof (__libc_early_init) *
|
void
|
||||||
_dl_lookup_libc_early_init (struct link_map *libc_map)
|
_dl_call_libc_early_init (struct link_map *libc_map, _Bool initial)
|
||||||
{
|
{
|
||||||
|
/* There is nothing to do if we did not actually load libc.so. */
|
||||||
|
if (libc_map == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
const ElfW(Sym) *sym
|
const ElfW(Sym) *sym
|
||||||
= _dl_lookup_direct (libc_map, LIBC_EARLY_INIT_NAME_STRING,
|
= _dl_lookup_direct (libc_map, "__libc_early_init",
|
||||||
LIBC_EARLY_INIT_GNU_HASH,
|
0x069682ac, /* dl_new_hash output. */
|
||||||
"GLIBC_PRIVATE",
|
"GLIBC_PRIVATE",
|
||||||
0x0963cf85); /* _dl_elf_hash output. */
|
0x0963cf85); /* _dl_elf_hash output. */
|
||||||
if (sym == NULL)
|
assert (sym != NULL);
|
||||||
_dl_signal_error (0, libc_map->l_name, NULL, "\
|
__typeof (__libc_early_init) *early_init
|
||||||
ld.so/libc.so mismatch detected (upgrade in progress?)");
|
= DL_SYMBOL_ADDRESS (libc_map, sym);
|
||||||
return DL_SYMBOL_ADDRESS (libc_map, sym);
|
early_init (initial);
|
||||||
}
|
}
|
@ -31,6 +31,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <gnu/lib-names.h>
|
||||||
|
|
||||||
/* Type for the buffer we put the ELF header and hopefully the program
|
/* Type for the buffer we put the ELF header and hopefully the program
|
||||||
header. This buffer does not really have to be too large. In most
|
header. This buffer does not really have to be too large. In most
|
||||||
@ -1465,6 +1466,14 @@ cannot enable executable stack as shared object requires");
|
|||||||
add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
|
add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
|
||||||
+ l->l_info[DT_SONAME]->d_un.d_val));
|
+ l->l_info[DT_SONAME]->d_un.d_val));
|
||||||
|
|
||||||
|
/* If we have newly loaded libc.so, update the namespace
|
||||||
|
description. */
|
||||||
|
if (GL(dl_ns)[nsid].libc_map == NULL
|
||||||
|
&& l->l_info[DT_SONAME] != NULL
|
||||||
|
&& strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
|
||||||
|
+ l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
|
||||||
|
GL(dl_ns)[nsid].libc_map = l;
|
||||||
|
|
||||||
/* _dl_close can only eventually undo the module ID assignment (via
|
/* _dl_close can only eventually undo the module ID assignment (via
|
||||||
remove_slotinfo) if this function returns a pointer to a link
|
remove_slotinfo) if this function returns a pointer to a link
|
||||||
map. Therefore, delay this step until all possibilities for
|
map. Therefore, delay this step until all possibilities for
|
||||||
|
@ -760,8 +760,8 @@ dl_open_worker_begin (void *a)
|
|||||||
if (!args->libc_already_loaded)
|
if (!args->libc_already_loaded)
|
||||||
{
|
{
|
||||||
/* dlopen cannot be used to load an initial libc by design. */
|
/* dlopen cannot be used to load an initial libc by design. */
|
||||||
if (GL(dl_ns)[args->nsid].libc_map != NULL)
|
struct link_map *libc_map = GL(dl_ns)[args->nsid].libc_map;
|
||||||
GL(dl_ns)[args->nsid].libc_map_early_init (false);
|
_dl_call_libc_early_init (libc_map, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
args->worker_continue = true;
|
args->worker_continue = true;
|
||||||
|
@ -23,8 +23,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
#include <_itoa.h>
|
#include <_itoa.h>
|
||||||
#include <gnu/lib-names.h>
|
|
||||||
#include <libc-early-init.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@ -361,22 +359,6 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detect a libc.so loaded into this namespace. The
|
|
||||||
__libc_early_init lookup below means that we have to do this
|
|
||||||
after parsing the version data. */
|
|
||||||
if (GL(dl_ns)[map->l_ns].libc_map == NULL
|
|
||||||
&& map->l_info[DT_SONAME] != NULL
|
|
||||||
&& strcmp (((const char *) D_PTR (map, l_info[DT_STRTAB])
|
|
||||||
+ map->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
|
|
||||||
{
|
|
||||||
/* Look up this symbol early to trigger a mismatch error before
|
|
||||||
relocation (which may call IFUNC resolvers, and those can
|
|
||||||
have an internal ABI dependency). */
|
|
||||||
GL(dl_ns)[map->l_ns].libc_map_early_init
|
|
||||||
= _dl_lookup_libc_early_init (map);
|
|
||||||
GL(dl_ns)[map->l_ns].libc_map = map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue
|
/* When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue
|
||||||
an error if there is a DT_RELR entry without GLIBC_ABI_DT_RELR
|
an error if there is a DT_RELR entry without GLIBC_ABI_DT_RELR
|
||||||
dependency. */
|
dependency. */
|
||||||
|
@ -19,10 +19,13 @@
|
|||||||
#ifndef _LIBC_EARLY_INIT_H
|
#ifndef _LIBC_EARLY_INIT_H
|
||||||
#define _LIBC_EARLY_INIT_H
|
#define _LIBC_EARLY_INIT_H
|
||||||
|
|
||||||
#include <libc_early_init_name.h>
|
|
||||||
|
|
||||||
struct link_map;
|
struct link_map;
|
||||||
|
|
||||||
|
/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
|
||||||
|
and call this function, with INITIAL as the argument. */
|
||||||
|
void _dl_call_libc_early_init (struct link_map *libc_map, _Bool initial)
|
||||||
|
attribute_hidden;
|
||||||
|
|
||||||
/* In the shared case, this function is defined in libc.so and invoked
|
/* In the shared case, this function is defined in libc.so and invoked
|
||||||
from ld.so (or on the fist static dlopen) after complete relocation
|
from ld.so (or on the fist static dlopen) after complete relocation
|
||||||
of a new loaded libc.so, but before user-defined ELF constructors
|
of a new loaded libc.so, but before user-defined ELF constructors
|
||||||
@ -30,18 +33,6 @@ struct link_map;
|
|||||||
startup code. If INITIAL is true, the libc being initialized is
|
startup code. If INITIAL is true, the libc being initialized is
|
||||||
the libc for the main program. INITIAL is false for libcs loaded
|
the libc for the main program. INITIAL is false for libcs loaded
|
||||||
for audit modules, dlmopen, and static dlopen. */
|
for audit modules, dlmopen, and static dlopen. */
|
||||||
void __libc_early_init (_Bool initial)
|
void __libc_early_init (_Bool initial);
|
||||||
#ifdef SHARED
|
|
||||||
/* Redirect to the actual implementation name. */
|
|
||||||
__asm__ (LIBC_EARLY_INIT_NAME_STRING)
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
|
|
||||||
/* Attempts to find the appropriately named __libc_early_init function
|
|
||||||
in LIBC_MAP. On lookup failure, an exception is signaled,
|
|
||||||
indicating an ld.so/libc.so mismatch. */
|
|
||||||
__typeof (__libc_early_init) *_dl_lookup_libc_early_init (struct link_map *
|
|
||||||
libc_map)
|
|
||||||
attribute_hidden;
|
|
||||||
|
|
||||||
#endif /* _LIBC_EARLY_INIT_H */
|
#endif /* _LIBC_EARLY_INIT_H */
|
||||||
|
12
elf/rtld.c
12
elf/rtld.c
@ -1707,6 +1707,15 @@ dl_main (const ElfW(Phdr) *phdr,
|
|||||||
/* Extract the contents of the dynamic section for easy access. */
|
/* Extract the contents of the dynamic section for easy access. */
|
||||||
elf_get_dynamic_info (main_map, false, false);
|
elf_get_dynamic_info (main_map, false, false);
|
||||||
|
|
||||||
|
/* If the main map is libc.so, update the base namespace to
|
||||||
|
refer to this map. If libc.so is loaded later, this happens
|
||||||
|
in _dl_map_object_from_fd. */
|
||||||
|
if (main_map->l_info[DT_SONAME] != NULL
|
||||||
|
&& (strcmp (((const char *) D_PTR (main_map, l_info[DT_STRTAB])
|
||||||
|
+ main_map->l_info[DT_SONAME]->d_un.d_val), LIBC_SO)
|
||||||
|
== 0))
|
||||||
|
GL(dl_ns)[LM_ID_BASE].libc_map = main_map;
|
||||||
|
|
||||||
/* Set up our cache of pointers into the hash table. */
|
/* Set up our cache of pointers into the hash table. */
|
||||||
_dl_setup_hash (main_map);
|
_dl_setup_hash (main_map);
|
||||||
}
|
}
|
||||||
@ -2377,8 +2386,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
|||||||
/* Relocation is complete. Perform early libc initialization. This
|
/* Relocation is complete. Perform early libc initialization. This
|
||||||
is the initial libc, even if audit modules have been loaded with
|
is the initial libc, even if audit modules have been loaded with
|
||||||
other libcs. */
|
other libcs. */
|
||||||
if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL)
|
_dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map, true);
|
||||||
GL(dl_ns)[LM_ID_BASE].libc_map_early_init (true);
|
|
||||||
|
|
||||||
/* Do any necessary cleanups for the startup OS interface code.
|
/* Do any necessary cleanups for the startup OS interface code.
|
||||||
We do these now so that no calls are made after rtld re-relocation
|
We do these now so that no calls are made after rtld re-relocation
|
||||||
|
@ -144,15 +144,6 @@ dynamic linker diagnostics to run on CPUs which are not compatible with
|
|||||||
the rest of @theglibc{}, for example, due to compiler flags which target
|
the rest of @theglibc{}, for example, due to compiler flags which target
|
||||||
a later instruction set architecture (ISA).
|
a later instruction set architecture (ISA).
|
||||||
|
|
||||||
@item --with-extra-version-id=@var{string}
|
|
||||||
Use @var{string} as part of the fingerprint that is used by the dynamic
|
|
||||||
linker to detect an incompatible version of @file{libc.so}. For
|
|
||||||
example, @var{string} could be the full package version and release
|
|
||||||
string used by a distribution build of @theglibc{}. This way,
|
|
||||||
concurrent process creation during a package update will fail with an
|
|
||||||
error message, @emph{ld.so/libc.so mismatch detected (upgrade in
|
|
||||||
progress?)}, rather than crashing mysteriously.
|
|
||||||
|
|
||||||
@item --with-timeoutfactor=@var{NUM}
|
@item --with-timeoutfactor=@var{NUM}
|
||||||
Specify an integer @var{NUM} to scale the timeout of test programs.
|
Specify an integer @var{NUM} to scale the timeout of test programs.
|
||||||
This factor can be changed at run time using @env{TIMEOUTFACTOR}
|
This factor can be changed at run time using @env{TIMEOUTFACTOR}
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
# Compute the hash-based name of the __libc_early_init function.
|
|
||||||
# Copyright (C) 2022 Free Software Foundation, Inc.
|
|
||||||
# This file is part of the GNU C Library.
|
|
||||||
#
|
|
||||||
# The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
|
||||||
# License as published by the Free Software Foundation; either
|
|
||||||
# version 2.1 of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
# Lesser General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Lesser General Public
|
|
||||||
# License along with the GNU C Library; if not, see
|
|
||||||
# <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
"""Compute the name of the __libc_early_init function, which is used
|
|
||||||
as a protocol version marker between ld.so and libc.so.
|
|
||||||
|
|
||||||
The name contains a hash suffix, and the hash changes if certain key
|
|
||||||
files in the source tree change. Distributions can also configure
|
|
||||||
with --with-extra-version-id, to make the computed hash dependent on
|
|
||||||
the package version.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import hashlib
|
|
||||||
import os
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def gnu_hash(s):
|
|
||||||
"""Computes the GNU hash of the string."""
|
|
||||||
h = 5381
|
|
||||||
for ch in s:
|
|
||||||
if type(ch) is not int:
|
|
||||||
ch = ord(ch)
|
|
||||||
h = (h * 33 + ch) & 0xffffffff
|
|
||||||
return h
|
|
||||||
|
|
||||||
# Parse the command line.
|
|
||||||
parser = argparse.ArgumentParser(description=__doc__)
|
|
||||||
parser.add_argument('--output', metavar='PATH',
|
|
||||||
help='path to header file this tool generates')
|
|
||||||
parser.add_argument('--extra-version-id', metavar='ID',
|
|
||||||
help='extra string to influence hash computation')
|
|
||||||
parser.add_argument('inputs', metavar='PATH', nargs='*',
|
|
||||||
help='files whose contents influences the generated hash')
|
|
||||||
opts = parser.parse_args()
|
|
||||||
|
|
||||||
# Obtain the blobs that affect the generated hash.
|
|
||||||
blobs = [(opts.extra_version_id or '').encode('UTF-8')]
|
|
||||||
for path in opts.inputs:
|
|
||||||
with open(path, 'rb') as inp:
|
|
||||||
blobs.append(inp.read())
|
|
||||||
|
|
||||||
# Hash the file boundaries.
|
|
||||||
md = hashlib.sha256()
|
|
||||||
md.update(repr([len(blob) for blob in blobs]).encode('UTF-8'))
|
|
||||||
|
|
||||||
# And then hash the file contents. Do not hash the paths, to avoid
|
|
||||||
# impacting reproducibility.
|
|
||||||
for blob in blobs:
|
|
||||||
md.update(blob)
|
|
||||||
|
|
||||||
# These are the bits used to compute the suffix.
|
|
||||||
derived_bits = int.from_bytes(md.digest(), byteorder='big', signed=False)
|
|
||||||
|
|
||||||
# These digits are used in the suffix (should result in base-62 encoding).
|
|
||||||
# They must be valid in C identifiers.
|
|
||||||
digits = string.digits + string.ascii_letters
|
|
||||||
|
|
||||||
# Generate eight digits as a suffix. They should provide enough
|
|
||||||
# uniqueness (47.6 bits).
|
|
||||||
name = '__libc_early_init_'
|
|
||||||
for n in range(8):
|
|
||||||
name += digits[derived_bits % len(digits)]
|
|
||||||
derived_bits //= len(digits)
|
|
||||||
|
|
||||||
# Write the output file.
|
|
||||||
with open(opts.output, 'w') if opts.output else sys.stdout as out:
|
|
||||||
out.write('#define LIBC_EARLY_INIT_NAME {}\n'.format(name))
|
|
||||||
out.write('#define LIBC_EARLY_INIT_NAME_STRING "{}"\n'.format(name))
|
|
||||||
out.write('#define LIBC_EARLY_INIT_GNU_HASH {}\n'.format(
|
|
||||||
gnu_hash(name)))
|
|
@ -333,10 +333,6 @@ struct rtld_global
|
|||||||
its link map. */
|
its link map. */
|
||||||
struct link_map *libc_map;
|
struct link_map *libc_map;
|
||||||
|
|
||||||
/* __libc_early_init function in libc_map. Initialized at the
|
|
||||||
same time as libc_map. */
|
|
||||||
void (*libc_map_early_init) (_Bool);
|
|
||||||
|
|
||||||
/* Search table for unique objects. */
|
/* Search table for unique objects. */
|
||||||
struct unique_sym_table
|
struct unique_sym_table
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user