mirror of
https://github.com/DynamoRIO/dynamorio.git
synced 2026-10-12 02:02:04 +00:00
These are the oldest Linux releases we'd like to support with our binary packages: + Debian Bullseye, which is on glibc 2.31 + RHEL 8, which is on glibc 2.28 + Ubuntu 22.04, which is on glibc 2.35 Therefore, we want to support at least glibc 2.28. Unfortunately, there is a compatibility break where glibc 2.34 contains `__libc_start_main@GLIBC_2.34` and non-trivial changes such that any binary built with 2.34+ will not run on a system with 2.33 or older. Since the oldest glibc Github Actions provides is Ubuntu 22.04's 2.35, we cannot easily build a pre-2.34 version. For now we make 2.34 the minimum so our Github Actions docs and package builds succeed. We leave open under #5860 the task of setting up a pre-2.34 build somewhere such as Travis so our binary releases will work on RHEL8 and Debian Bullseye. This is the final piece toward migrating all our Github Actions jobs to Ubuntu 22.04 which we complete here by updating ci-package.yml to use 22.04. Issue: #5860, #7270 Fixes #7270
188 lines
7.5 KiB
CMake
188 lines
7.5 KiB
CMake
# **********************************************************
|
|
# Copyright (c) 2015-2025 Google, Inc. All rights reserved.
|
|
# Copyright (c) 2009 VMware, Inc. All rights reserved.
|
|
# **********************************************************
|
|
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
#
|
|
# * Redistributions of source code must retain the above copyright notice,
|
|
# this list of conditions and the following disclaimer.
|
|
#
|
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
# this list of conditions and the following disclaimer in the documentation
|
|
# and/or other materials provided with the distribution.
|
|
#
|
|
# * Neither the name of VMware, Inc. nor the names of its contributors may be
|
|
# used to endorse or promote products derived from this software without
|
|
# specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
|
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
# DAMAGE.
|
|
|
|
# Caller must set:
|
|
# + "lib_fileloc" to /absolute/path/<name> that represents a file <name>.cmake that
|
|
# contains a set(<name> <path>) where path is the target binary location.
|
|
# + "READELF_EXECUTABLE" so it can be a cache variable
|
|
# + "check_textrel" to ON or OFF to check to text relocations
|
|
# + "check_deps" to ON or OFF to check for zero deps
|
|
# + "check_libc" to ON or OFF to check for too-recent libc imports
|
|
# + "check_interp" to ON or OFF to check for a PT_INTERP section
|
|
|
|
# PR 212290: ensure no text relocations (they violate selinux execmod policies)
|
|
# looking for dynamic section tag:
|
|
# 0x00000016 (TEXTREL) 0x0
|
|
|
|
include(${lib_fileloc}.cmake)
|
|
|
|
get_filename_component(lib_file ${lib_fileloc} NAME)
|
|
|
|
if (check_textrel)
|
|
execute_process(COMMAND
|
|
${READELF_EXECUTABLE} -d ${${lib_file}}
|
|
RESULT_VARIABLE readelf_result
|
|
ERROR_VARIABLE readelf_error
|
|
OUTPUT_VARIABLE string
|
|
)
|
|
if (readelf_result OR readelf_error)
|
|
message(FATAL_ERROR "*** ${READELF_EXECUTABLE} failed: ***\n${readelf_error}")
|
|
endif (readelf_result OR readelf_error)
|
|
string(REGEX MATCH
|
|
"TEXTREL"
|
|
has_textrel "${string}")
|
|
if (has_textrel)
|
|
message(FATAL_ERROR "*** Error: ${${lib_file}} has text relocations")
|
|
endif (has_textrel)
|
|
endif ()
|
|
|
|
# also check for execstack
|
|
# looking for stack properties:
|
|
# GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
|
|
execute_process(COMMAND
|
|
${READELF_EXECUTABLE} -l ${${lib_file}}
|
|
RESULT_VARIABLE readelf_result
|
|
ERROR_VARIABLE readelf_error
|
|
OUTPUT_VARIABLE string
|
|
)
|
|
if (readelf_result OR readelf_error)
|
|
message(FATAL_ERROR "*** ${READELF_EXECUTABLE} failed: ***\n${readelf_error}")
|
|
endif (readelf_result OR readelf_error)
|
|
string(REGEX MATCH
|
|
"STACK.*RWE"
|
|
has_execstack "${string}")
|
|
if (has_execstack)
|
|
message(FATAL_ERROR "*** Error: ${${lib_file}} has executable stack")
|
|
endif (has_execstack)
|
|
|
|
if (check_deps)
|
|
# First, look for global undefined symbols:
|
|
execute_process(COMMAND
|
|
${READELF_EXECUTABLE} -s ${${lib_file}}
|
|
RESULT_VARIABLE readelf_result
|
|
ERROR_VARIABLE readelf_error
|
|
OUTPUT_VARIABLE string
|
|
)
|
|
if (readelf_result OR readelf_error)
|
|
message(FATAL_ERROR "*** ${READELF_EXECUTABLE} failed: ***\n${readelf_error}")
|
|
endif (readelf_result OR readelf_error)
|
|
string(REGEX MATCH " GLOBAL [ A-Z]* UND " has_undefined "${string}")
|
|
if (has_undefined)
|
|
string(REGEX MATCH " GLOBAL [ A-Z]* UND *[^\n]*\n" symname "${string}")
|
|
message(FATAL_ERROR "*** Error: ${${lib_file}} has undefined symbol: ${symname}")
|
|
endif ()
|
|
|
|
# Second, look for DT_NEEDED entries:
|
|
execute_process(COMMAND
|
|
${READELF_EXECUTABLE} -d ${${lib_file}}
|
|
RESULT_VARIABLE readelf_result
|
|
ERROR_VARIABLE readelf_error
|
|
OUTPUT_VARIABLE string
|
|
)
|
|
if (readelf_result OR readelf_error)
|
|
message(FATAL_ERROR "*** ${READELF_EXECUTABLE} failed: ***\n${readelf_error}")
|
|
endif (readelf_result OR readelf_error)
|
|
string(REGEX MATCH "NEEDED" has_needed "${string}")
|
|
if (has_needed)
|
|
string(REGEX MATCH "NEEDED[^\n]*\n" libname "${string}")
|
|
message(FATAL_ERROR "*** Error: ${${lib_file}} depends on: ${libname}")
|
|
endif ()
|
|
endif ()
|
|
|
|
if (check_libc)
|
|
execute_process(COMMAND
|
|
${READELF_EXECUTABLE} -s --wide ${${lib_file}}
|
|
RESULT_VARIABLE readelf_result
|
|
ERROR_VARIABLE readelf_error
|
|
OUTPUT_VARIABLE string
|
|
)
|
|
if (readelf_result OR readelf_error)
|
|
message(FATAL_ERROR "*** ${READELF_EXECUTABLE} failed: ***\n${readelf_error}")
|
|
endif (readelf_result OR readelf_error)
|
|
|
|
# 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
|
|
)
|
|
|
|
# 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 June 2025, these are:
|
|
# * Debian Bullseye, which is on glibc 2.31
|
|
# * RHEL 8, which is on glibc 2.28
|
|
# * Ubuntu 22.04, which is on glibc 2.35
|
|
#
|
|
# Therefore, we want to support at least glibc 2.28.
|
|
# Unfortunately, there is a compatibility break where glibc 2.34 contains
|
|
# `__libc_start_main@GLIBC_2.34` and non-trivial changes such that any binary
|
|
# built with 2.34+ will not run on a system with 2.33 or older.
|
|
# Since the oldest glibc Github Actions provides is Ubuntu 22.04's 2.35,
|
|
# we cannot easily build a pre-2.34 version. For now we make 2.34 the minimum
|
|
# so our Github Actions docs and package builds succeed.
|
|
# XXX i#5860: Set up a pre-2.34 build somewhere such as Travis so our binary
|
|
# releases will work on RHEL8 and Debian Bullseye.
|
|
set (glibc_version "2.34")
|
|
|
|
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 ()
|
|
|
|
if (check_interp)
|
|
execute_process(COMMAND
|
|
${READELF_EXECUTABLE} -l ${${lib_file}}
|
|
RESULT_VARIABLE readelf_result
|
|
ERROR_VARIABLE readelf_error
|
|
OUTPUT_VARIABLE output
|
|
)
|
|
if (readelf_result OR readelf_error)
|
|
message(FATAL_ERROR "*** ${READELF_EXECUTABLE} failed: ***\n${readelf_error}")
|
|
endif (readelf_result OR readelf_error)
|
|
if (output MATCHES " INTERP")
|
|
message(FATAL_ERROR "*** Error: ${${lib_file}} contains an INTERP header (for Android, be sure you're using ld.bfd and not ld.gold)")
|
|
endif ()
|
|
endif ()
|