diff --git a/projects/rocm-core/CHANGELOG.md b/projects/rocm-core/CHANGELOG.md index 294b597e90..7be9b06418 100644 --- a/projects/rocm-core/CHANGELOG.md +++ b/projects/rocm-core/CHANGELOG.md @@ -1,5 +1,14 @@ Change Logs for rocm-core -Unreleased for ROCm5.5.0 + +Unreleased ROCm6.0.0 release + - Added script to convert RUNPATH in libraries and binaries to RPATH. + - Disabled ROCm file reorg backward compatibility + +ROCm5.6.0 release + - Added initial support for Adress Sanitizer(ASAN) enabled builds. + - Full support of ASAN will be coming in later release + +ROCm5.5.0 release - Added module file support for ROCm. - From ROCm5.5.0 release ROCm module files can be loaded as rocm/5.5.0 diff --git a/projects/rocm-core/CMakeLists.txt b/projects/rocm-core/CMakeLists.txt index 7a2763a10b..3597012ca9 100644 --- a/projects/rocm-core/CMakeLists.txt +++ b/projects/rocm-core/CMakeLists.txt @@ -122,6 +122,7 @@ install ( TARGETS ${CORE_TARGET} DESTINATION ${CMAKE_INSTALL_LIBDIR} PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE COMPONENT ${COMP_TYPE} ) install ( FILES ${BUILD_DIR}/rocm_version.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocm-core COMPONENT runtime ) +install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/runpath_to_rpath.py DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/rocm-core COMPONENT runtime ) install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/rocmmod DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime ) # License file @@ -173,12 +174,14 @@ set ( CPACK_RPM_FILE_NAME "RPM-DEFAULT" ) set ( CPACK_DEBIAN_PACKAGE_DEPENDS ${DEB_DEPENDS_STRING} ) set ( CPACK_DEBIAN_ASAN_PACKAGE_DEPENDS ${CORE_TARGET} ) set ( CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/RadeonOpenCompute/ROCm" ) +set ( CPACK_DEBIAN_PACKAGE_DEPENDS "patchelf" ) set ( CPACK_DEBIAN_RUNTIME_PACKAGE_CONTROL_EXTRA "${BUILD_DIR}/postinst;${BUILD_DIR}/prerm" ) ## RPM package specific variables set ( CPACK_RPM_PACKAGE_REQUIRES ${RPM_DEPENDS_STRING} ) set ( CPACK_RPM_ASAN_PACKAGE_REQUIRES ${CORE_TARGET} ) set ( CPACK_RPM_PACKAGE_LICENSE "MIT" ) +set ( CPACK_RPM_PACKAGE_REQUIRES "patchelf" ) set ( CPACK_RPM_RUNTIME_POST_INSTALL_SCRIPT_FILE "${CMAKE_CURRENT_BINARY_DIR}/postinst" ) set ( CPACK_RPM_RUNTIME_POST_UNINSTALL_SCRIPT_FILE "${CMAKE_CURRENT_BINARY_DIR}/prerm" ) diff --git a/projects/rocm-core/runpath_to_rpath.py b/projects/rocm-core/runpath_to_rpath.py new file mode 100644 index 0000000000..0b93b51694 --- /dev/null +++ b/projects/rocm-core/runpath_to_rpath.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +################################################################################ +## +## MIT License +## +## Copyright (c) 2017 - 2023 Advanced Micro Devices, Inc. All rights Reserved. +## +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to deal +## in the Software without restriction, including without limitation the rights +## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +## copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all +## copies or substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +## SOFTWARE. +## +################################################################################ + +import os +import sys +import subprocess +import argparse +import pathlib + +try: + from elftools.elf.elffile import ELFFile + from elftools.elf.dynamic import DynamicSection + from elftools.common.exceptions import ELFError +except ImportError: + print("Error : pyelftools failed to import.\n" + "Run \'pip3 install pyelftools\' to install the prerequisite\n") + +# Function remove the runpath from the binary +def remove_runpath(filename) : + ''' Remove the DT_RUNPATH tag from filename''' + REMOVE_RPATH_COMMAND = ['patchelf', '--remove-rpath', filename] + print("Executing the command : ", REMOVE_RPATH_COMMAND) + subprocess.run(REMOVE_RPATH_COMMAND, check=True) + +def add_rpath(filename, runpath) : + ''' Use runpath and add it as DT_PATH tag in filename''' + ADD_RPATH_COMMAND = ['patchelf', '--force-rpath', '--set-rpath', runpath, filename] + print("Executing the command : ", ADD_RPATH_COMMAND) + subprocess.run(ADD_RPATH_COMMAND, check=True) + +def update_rpath(search_path, excludes) : + ''' Function helps to change DT_RUNPATH in libraries and binaries in search_path to DT_RPATH. + Its done with the following steps : + 1. Check all if the file is an ELF except in excludes folder + 2. Read and store the DT_RUNPATH from the binaries/libraries. + 3. Delete DT_RUNPATH and readd it as DT_RPATH ''' + for path, dirs, files in os.walk(search_path, topdown=True, followlinks=True): + dirs[:] = [d for d in dirs if d not in excludes] + print( dirs ) + for filename in files: + filename = os.path.join(path, filename) + print("Opening file ", filename) + # Open the file and check if its ELF file + try : + with open(filename, 'rb') as file: + elffile = ELFFile(file) + for section in elffile.iter_sections(): + if not isinstance(section, DynamicSection): + continue + for tag in section.iter_tags(): + if tag.entry.d_tag == 'DT_RUNPATH': + runpath = tag.runpath + print(runpath) + remove_runpath(filename) + add_rpath(filename, runpath) + break + break + except ELFError: + print("Discarding file as its not an ELF file", filename) + continue + except FileNotFoundError: + print("Discarding file with bad links", filename) + continue + except OSError: + print("Discarding file with OS error", filename) + continue + except Exception as ex: + print("Discarding file ", filename, ex) + continue + +def main(): + # The script expect a search folder as parameter. It finds all ELF files and updates RPATH + argparser = argparse.ArgumentParser( + usage='usage: %(prog)s ', + description='Find the ELF files in the specified folder and convert the RUNPATH to RPATH. \n', + add_help=False, + prog='runpath_to_rpath.py') + + argparser.add_argument('searchdir', + nargs='?', type=pathlib.Path, default=None, + help='Folder to search for ELF file. \nPlease note: Any folder with name llvm in that path will be discarded') + argparser.add_argument('-h', '--help', + action='store_true', dest='help', + help='Display this information') + + args = argparser.parse_args() + if args.help or not args.searchdir: + argparser.print_help() + sys.exit(0) + + # pyelftools is a mandatory requirement for this script. Exit if requirement is not met + if 'ELFFile' not in globals(): + print('Please install pyelftools using \'pip3 install pyelftools\' ' + + 'before using the script : runpath_to_rpath.py') + sys.exit(0) + + # Find the elf files in the serach path and update RPATH + excludes = ['llvm', 'rocm-llvm', 'llvm-alt'] + update_rpath(args.searchdir, excludes) + print("Done with rpath update") + +if __name__ == "__main__": + main()