Skip to content

Commit

Permalink
i#5130: improve glibc import checks and make them optional (#5280)
Browse files Browse the repository at this point in the history
This addresses issue #5130 in the following ways:

 - Improve the glibc import checking code by using a regex to match all imports, and then for each import extract the version and use CMake's version comparison functionality to match the version. This allows us to write the desired glibc version as a string such as "2.4", instead of having to write a regular expression that matches everything greater than 2.4 or in general the desired version.
 - Introduce a BUILD_PACKAGE option that is OFF by default, but can be turned on when invoking cmake as follows: `cmake -DBUILD_PACKAGE=ON ..`. This is important for rolling release distributions where glibc 2.32 is currently stable and these checks prevent drrun from building. By defaulting to OFF, building from source will provide a nice out-of-the-box experience on such distributions.
 - When packaging up DynamoRIO, BUILD_PACKAGE is set to ON in make/package.cmake. This way we ensure that the glibc checks are performed against the distributable version, such that it works on all supported Linux distributions, i.e. those that have not yet reached EOL.
 - Bump the glibc version to 2.17. After checking multiple distributions with long support times (typically Debian and CentOS, and Ubuntu LTS being a close one), The oldest versions that are still supported as of writing are Debian Stretch, CentOS 7, RHEL 7, and Ubuntu 16.04 LTS (Xenial). These ship glibc 2.24, glibc 2.17 glibc 2.17 and glibc 2.23 respectively. According to the release page of glibc the release date of glibc 2.17 is 2012-12-25.
 - The AArch64 version was 2.17, while non-AArch64 was 2.4. We no longer make a distinction between architectures when selecting the minimum supported glibc version, as all non-rolling release distributions use the same glibc for a given version regardless of the architecture.
 - This change is also described in the changelog for the upcoming DynamoRIO release.

Co-authored-by: Derek Bruening <bruening@google.com>
  • Loading branch information
StephanvanSchaik and derekbruening committed Jan 15, 2022
1 parent 247e98c commit 1dec190
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Expand Up @@ -143,6 +143,12 @@ endif (UNIX)

# many are core-specific

# whether this build of DynamoRIO is meant for distribution, in which case
# glibc should not have any too-recent imports. See core/CMake_readelf.cmake
# for more information. This is off by default, but gets set by
# make/package.cmake.
option(BUILD_PACKAGE "build DynamoRIO for packaging purposes by performing glibc checks" OFF)

# configurations that also have defines
option(DRSTATS_DEMO "build DRstats without the no-longer-supported Run, etc. controls" ON)

Expand Down
6 changes: 5 additions & 1 deletion api/docs/release.dox
Expand Up @@ -126,7 +126,11 @@ clients.

The changes between version \DR_VERSION and 9.0.0 include the following compatibility
changes:
- (Nothing so far: this is a placeholder.)
- Introduced a new CMake option called BUILD_PACKAGE to skip glibc
compatibility checks. This is off by default such that building DynamoRIO
from source is straight-forward to do on rolling release Linux
distributions, and enabled by make/package.cmake when building a
distributable version of DynamoRIO.

Further non-compatibility-affecting changes include:
- Added alias support to droption.
Expand Down
4 changes: 2 additions & 2 deletions core/CMakeLists.txt
Expand Up @@ -661,7 +661,7 @@ if (UNIX)
ARGS -D lib_fileloc=${CMAKE_CURRENT_BINARY_DIR}/${locvar_name}
-D check_textrel=${check_textrel}
-D check_deps=${check_deps}
-D check_libc=OFF
-D check_libc=${BUILD_PACKAGE}
-D check_interp=ON
-D READELF_EXECUTABLE=${READELF_EXECUTABLE}
-P ${CMAKE_CURRENT_SOURCE_DIR}/CMake_readelf.cmake
Expand Down Expand Up @@ -931,7 +931,7 @@ if (UNIX)
ARGS -D lib_fileloc=${CMAKE_CURRENT_BINARY_DIR}/${locvar_name}
-D check_textrel=ON
-D check_deps=OFF
-D check_libc=ON
-D check_libc=${BUILD_PACKAGE}
-D check_interp=ON
-D READELF_EXECUTABLE=${READELF_EXECUTABLE}
-P ${CMAKE_CURRENT_SOURCE_DIR}/CMake_readelf.cmake
Expand Down
43 changes: 31 additions & 12 deletions core/CMake_readelf.cmake
Expand Up @@ -127,23 +127,42 @@ if (check_libc)
if (readelf_result OR readelf_error)
message(FATAL_ERROR "*** ${READELF_EXECUTABLE} failed: ***\n${readelf_error}")
endif (readelf_result OR readelf_error)
# Avoid dependences beyond glibc 2.4 (2.17 on AArch64) for maximum backward

# Avoid dependences beyond the oldest well-supported version of glibc for maximum backward
# portability without going to extremes with a fixed toolchain (xref i#1504):
execute_process(COMMAND
${READELF_EXECUTABLE} -h ${${lib_file}}
OUTPUT_VARIABLE file_header_result
)
if (file_header_result MATCHES "AArch64")
set (glibc_version_regexp "2\\.(1[8-9]|[2-9][0-9])")
else ()
set (glibc_version_regexp "2\\.([5-9]|[1-9][0-9])")
endif ()
string(REGEX MATCH " GLOBAL [ A-Z]* UND [^\n]*@GLIBC_${glibc_version_regexp}"
has_recent "${string}")
if (has_recent)
string(REGEX MATCH " GLOBAL DEFAULT UND [^\n]*@GLIBC_${glibc_version_regexp}[^\n]*\n"
symname "${string}")
message(FATAL_ERROR "*** Error: ${${lib_file}} has too-recent import: ${symname}")

# To determine the minimum version of glibc that we should support for packaging, we should
# check the Linux distributions that are known not to be rolling releases and offer long
# support, and then check the oldest option available that is not yet EOL. As of writing,
# these are:
# * Debian Stretch, which is on glibc 2.24
# * CentOS 7/RHEL 7, which is on glibc 2.17
# * Ubuntu 16.04 LTS (Xenial), which is on glibc 2.23
#
# Therefore, we want to support at least glibc 2.17.
#
# The glibc version is independent of the architecture. For instance, RHEL 7 for AArch64 also
# ships glibc 2.17 as of writing.
set (glibc_version "2.17")

set (glibc_version_regexp " GLOBAL [ A-Z]* UND [^\n]*@GLIBC_([0-9]+\\.[0-9]+)")
string(REGEX MATCHALL "${glibc_version_regexp}" imports "${string}")

foreach (import ${imports})
string(REGEX MATCH "${glibc_version_regexp}" match "${import}")
set(version ${CMAKE_MATCH_1})

if (${version} VERSION_GREATER ${glibc_version})
set(too_recent "${too_recent}\n ${import}")
endif ()
endforeach ()

if (too_recent)
message(FATAL_ERROR "*** Error: ${${lib_file}} has too-recent import(s):${too_recent}")
endif ()
endif ()

Expand Down
1 change: 1 addition & 0 deletions make/package.cmake
Expand Up @@ -163,6 +163,7 @@ set(base_cache "
${base_cache}
BUILD_NUMBER:STRING=${arg_build}
UNIQUE_BUILD_NUMBER:STRING=${arg_ubuild}
BUILD_PACKAGE:BOOL=ON
${arg_cacheappend}
")

Expand Down
2 changes: 1 addition & 1 deletion tools/CMakeLists.txt
Expand Up @@ -198,7 +198,7 @@ foreach (deploytgt drconfig drrun drinject)
ARGS -D lib_fileloc=${CMAKE_CURRENT_BINARY_DIR}/${locvar_name}
-D check_textrel=ON
-D check_deps=OFF
-D check_libc=ON
-D check_libc=${BUILD_PACKAGE}
-D READELF_EXECUTABLE=${READELF_EXECUTABLE}
-P ${PROJECT_SOURCE_DIR}/core/CMake_readelf.cmake
VERBATIM # recommended: p260
Expand Down

0 comments on commit 1dec190

Please sign in to comment.