From 74e3ac2b7e62f70440622db5c9a377a04f22697c Mon Sep 17 00:00:00 2001 From: William Marlow Date: Tue, 12 Jul 2022 07:41:25 +0100 Subject: AIX: Export symbols from IBMClang IPA objects When interprocedural analysis is enabled on the IBMClang family of compilers (via the `-flto` option) then the resulting object files contain LLVM IR rather than XCOFF objects[1]. ExportImportList needs to detect LLVM IR objects and use the `ibm-llvm-nm` tool that ships with the compiler to create the extract the defined symbols. Without this change, such objects result in an error message from `dump` and no symbols being exported from the object file. [1]: https://www.ibm.com/docs/en/openxl-c-and-cpp-aix/17.1.0?topic=compatibility-link-time-optimization-lto --- Modules/Platform/AIX-GNU.cmake | 4 +-- Modules/Platform/AIX-XL.cmake | 4 +-- Modules/Platform/AIX/ExportImportList | 46 ++++++++++++++++++++++++++--------- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake index 5a532c7..a9aa8e0 100644 --- a/Modules/Platform/AIX-GNU.cmake +++ b/Modules/Platform/AIX-GNU.cmake @@ -23,11 +23,11 @@ macro(__aix_compiler_gnu lang) # Construct the export list ourselves to pass only the object files so # that we export only the symbols actually provided by the sources. set(CMAKE_${lang}_CREATE_SHARED_LIBRARY - "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o /exports.exp " + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o /exports.exp -c " " -Wl,-bE:/exports.exp -o " ) set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS - "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o -l . " + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o -c -l . " " -Wl,-bE: -o ") endmacro() diff --git a/Modules/Platform/AIX-XL.cmake b/Modules/Platform/AIX-XL.cmake index 2a8c159..902cbb3 100644 --- a/Modules/Platform/AIX-XL.cmake +++ b/Modules/Platform/AIX-XL.cmake @@ -29,12 +29,12 @@ macro(__aix_compiler_xl lang) # Construct the export list ourselves to pass only the object files so # that we export only the symbols actually provided by the sources. set(CMAKE_${lang}_CREATE_SHARED_LIBRARY - "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o /exports.exp ${_OBJECTS}" + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o /exports.exp -c ${_OBJECTS}" " -Wl,-bE:/exports.exp -o " ) set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS - "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o -l . " + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o -c -l . " " -Wl,-bE: -o ") unset(_OBJECTS) diff --git a/Modules/Platform/AIX/ExportImportList b/Modules/Platform/AIX/ExportImportList index 891bce7..5e16fcb 100755 --- a/Modules/Platform/AIX/ExportImportList +++ b/Modules/Platform/AIX/ExportImportList @@ -5,7 +5,7 @@ # This script is internal to CMake and meant only to be # invoked by CMake-generated build systems on AIX. -usage='usage: ExportImportList -o [-l ] [-n] [--] ...' +usage='usage: ExportImportList -o -c [-l ] [-n] [--] ...' die() { echo "$@" 1>&2; exit 1 @@ -15,11 +15,13 @@ die() { out='' lib='' no_objects='' +compiler='' while test "$#" != 0; do case "$1" in -l) shift; lib="$1" ;; -o) shift; out="$1" ;; -n) no_objects='1' ;; + -c) shift; compiler="$1" ;; --) shift; break ;; -*) die "$usage" ;; *) break ;; @@ -27,27 +29,47 @@ while test "$#" != 0; do shift done test -n "$out" || die "$usage" +# We need the compiler executable to resolve where the ibm-llvm-nm executable is +test -n "$compiler" || die "$usage" # Build a temporary file that atomically replaces the output later. out_tmp="$out.tmp$$" trap 'rm -f "$out_tmp"' EXIT INT TERM > "$out_tmp" +# If IPA was enabled and a compiler from the IBMClang family is used, then +# the object files contain LLVM bitcode[0] rather than XCOFF objects and so +# need to be handled differently. +# +# [0]: https://www.ibm.com/docs/en/openxl-c-and-cpp-aix/17.1.0?topic=compatibility-link-time-optimization-lto +NM="$(dirname "$compiler")/../libexec/ibm-llvm-nm" + +function IsBitcode { + # N4 = first 4 bytes, -tx = output in hexadecimal, -An = don't display offset + # cut: trim off the preceding whitespace where the offset would be + # 4243code is the hexadecimal magic number for LLVM bitcode + [ "$(od -N4 -tx -An $1 | cut -d ' ' -f 2)" == "4243c0de" ]; +} + # Collect symbols exported from all object files. if test -z "$no_objects"; then for f in "$@"; do - dump -tov -X 32_64 "$f" | - awk ' - BEGIN { - V["EXPORTED"]=" export" - V["PROTECTED"]=" protected" - } - /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / { - if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) { - print $NF V[$(NF-1)] + if IsBitcode "$f"; then + "$NM" "$f" --defined-only --extern-only --just-symbol-name 2>/dev/null + else + dump -tov -X 32_64 "$f" | + awk ' + BEGIN { + V["EXPORTED"]=" export" + V["PROTECTED"]=" protected" + } + /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / { + if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) { + print $NF V[$(NF-1)] + } } - } - ' + ' + fi done >> "$out_tmp" fi -- cgit v0.12