Skip to content

Commit

Permalink
Restore -static-executable on Linux.
Browse files Browse the repository at this point in the history
- Add back StaticBinaryELF.cpp which provides swift::lookupSymbol()
  for statically linked ELF binaries.

- Build libswiftImageInspectionStatic.a from StaticBinaryELF.cpp

- Update static-executable-args.lnk and replace
  libswiftImageInspectionShared with libswiftImageInspectionStatic.

- Fix linkage to pthreads to avoid weak linkage issues in a static
  executable.

- Add driver test for '-static-executable' on Linux to validate
  that output binary is statically linked.
  • Loading branch information
spevans committed Jan 11, 2020
1 parent b3f5d61 commit 3b25795
Show file tree
Hide file tree
Showing 6 changed files with 401 additions and 51 deletions.
10 changes: 5 additions & 5 deletions lib/Driver/UnixToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,6 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job,
Arguments.push_back(context.Args.MakeArgString(A->getValue()));
}

if (getTriple().getOS() == llvm::Triple::Linux &&
job.getKind() == LinkKind::Executable) {
Arguments.push_back("-pie");
}

bool staticExecutable = false;
bool staticStdlib = false;

Expand All @@ -205,6 +200,11 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job,
staticStdlib = true;
}

if (getTriple().getOS() == llvm::Triple::Linux &&
job.getKind() == LinkKind::Executable && !staticExecutable) {
Arguments.push_back("-pie");
}

SmallVector<std::string, 4> RuntimeLibPaths;
getRuntimeLibraryPaths(RuntimeLibPaths, context.Args, context.OI.SDKPath,
/*Shared=*/!(staticExecutable || staticStdlib));
Expand Down
73 changes: 42 additions & 31 deletions stdlib/public/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ endif(LLVM_ENABLE_ASSERTIONS)

# Acknowledge that the following sources are known.
set(LLVM_OPTIONAL_SOURCES
StaticBinaryELF.cpp
SwiftRT-COFF.cpp
SwiftRT-ELF.cpp
${swift_runtime_sources}
Expand All @@ -102,35 +103,43 @@ if(SWIFT_BUILD_STATIC_STDLIB AND "${sdk}" STREQUAL "LINUX")
SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
INSTALL_IN_COMPONENT stdlib)

foreach(arch IN LISTS SWIFT_SDK_${sdk}_ARCHITECTURES)
set(FragileSupportLibrary swiftImageInspectionShared-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch})
set(LibraryLocation ${SWIFTSTATICLIB_DIR}/${lowercase_sdk}/${arch})
add_custom_command_target(swift_image_inspection_${arch}_static
COMMAND
"${CMAKE_COMMAND}" -E copy $<TARGET_FILE:${FragileSupportLibrary}> ${LibraryLocation}
OUTPUT
"${LibraryLocation}/${CMAKE_STATIC_LIBRARY_PREFIX}swiftImageInspectionShared${CMAKE_STATIC_LIBRARY_SUFFIX}"
DEPENDS
${FragileSupportLibrary})
add_dependencies(stdlib ${FragileSupportLibrary})
swift_install_in_component(FILES $<TARGET_FILE:${FragileSupportLibrary}>
DESTINATION "lib/swift_static/${lowercase_sdk}/${arch}"
COMPONENT stdlib)
endforeach()
add_swift_target_library(swiftImageInspectionStatic TARGET_LIBRARY STATIC
StaticBinaryELF.cpp ImageInspectionELF.cpp
C_COMPILE_FLAGS ${swift_runtime_library_compile_flags} -DELF_STATIC_LIB
LINK_FLAGS ${swift_runtime_linker_flags}
INSTALL_IN_COMPONENT stdlib)

set(FragileSupportLibraryPrimary swiftImageInspectionShared-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${SWIFT_PRIMARY_VARIANT_ARCH})
set(LibraryLocationPrimary ${SWIFTSTATICLIB_DIR}/${lowercase_sdk})
add_custom_command_target(swift_image_inspection_static_primary_arch
COMMAND
"${CMAKE_COMMAND}" -E copy $<TARGET_FILE:${FragileSupportLibraryPrimary}> ${LibraryLocationPrimary}
OUTPUT
"${LibraryLocationPrimary}/${CMAKE_STATIC_LIBRARY_PREFIX}swiftImageInspectionShared${CMAKE_STATIC_LIBRARY_SUFFIX}"
DEPENDS
${FragileSupportLibraryPrimary})
add_dependencies(stdlib ${FragileSupportLibraryPrimary})
swift_install_in_component(FILES $<TARGET_FILE:${FragileSupportLibraryPrimary}>
DESTINATION "lib/swift_static/${lowercase_sdk}"
COMPONENT stdlib)
foreach(linktype Shared Static)
foreach(arch IN LISTS SWIFT_SDK_${sdk}_ARCHITECTURES)
set(FragileSupportLibrary swiftImageInspection${linktype}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch})
set(LibraryLocation ${SWIFTSTATICLIB_DIR}/${lowercase_sdk}/${arch})
add_custom_command_target(swift_image_inspection_${linktype}_${arch}_static
COMMAND
"${CMAKE_COMMAND}" -E copy $<TARGET_FILE:${FragileSupportLibrary}> ${LibraryLocation}
OUTPUT
"${LibraryLocation}/${CMAKE_STATIC_LIBRARY_PREFIX}swiftImageInspection${linktype}${CMAKE_STATIC_LIBRARY_SUFFIX}"
DEPENDS
${FragileSupportLibrary})
add_dependencies(stdlib ${FragileSupportLibrary})
swift_install_in_component(FILES $<TARGET_FILE:${FragileSupportLibrary}>
DESTINATION "lib/swift_static/${lowercase_sdk}/${arch}"
COMPONENT stdlib)
endforeach()

set(FragileSupportLibraryPrimary swiftImageInspection${linktype}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${SWIFT_PRIMARY_VARIANT_ARCH})
set(LibraryLocationPrimary ${SWIFTSTATICLIB_DIR}/${lowercase_sdk})
add_custom_command_target(swift_image_inspection_${linktype}_primary_arch
COMMAND
"${CMAKE_COMMAND}" -E copy $<TARGET_FILE:${FragileSupportLibraryPrimary}> ${LibraryLocationPrimary}
OUTPUT
"${LibraryLocationPrimary}/${CMAKE_STATIC_LIBRARY_PREFIX}swiftImageInspection${linktype}${CMAKE_STATIC_LIBRARY_SUFFIX}"
DEPENDS
${FragileSupportLibraryPrimary})
add_dependencies(stdlib ${FragileSupportLibraryPrimary})
swift_install_in_component(FILES $<TARGET_FILE:${FragileSupportLibraryPrimary}>
DESTINATION "lib/swift_static/${lowercase_sdk}"
COMPONENT stdlib)
endforeach()

# Generate the static-executable-args.lnk file used for ELF systems (eg linux)
set(linkfile "${lowercase_sdk}/static-executable-args.lnk")
Expand All @@ -149,10 +158,12 @@ if(SWIFT_BUILD_STATIC_STDLIB AND "${sdk}" STREQUAL "LINUX")
DESTINATION "lib/swift_static/${lowercase_sdk}"
COMPONENT stdlib)
add_custom_target(static_binary_magic ALL DEPENDS ${static_binary_lnk_file_list})
foreach(arch IN LISTS SWIFT_SDK_LINUX_ARCHITECTURES)
add_dependencies(static_binary_magic ${swift_image_inspection_${arch}_static})
foreach(linktype Shared Static)
foreach(arch IN LISTS SWIFT_SDK_LINUX_ARCHITECTURES)
add_dependencies(static_binary_magic ${swift_image_inspection_${linktype}_${arch}_static})
endforeach()
add_dependencies(static_binary_magic ${swift_image_inspection_${linktype}_primary_arch})
endforeach()
add_dependencies(static_binary_magic ${swift_image_inspection_static_primary_arch})
add_dependencies(stdlib static_binary_magic)

add_swift_target_library(swiftImageInspectionSharedObject OBJECT_LIBRARY
Expand Down
18 changes: 14 additions & 4 deletions stdlib/public/runtime/ImageInspectionELF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@

#include "ImageInspection.h"
#include "ImageInspectionELF.h"

#ifndef ELF_STATIC_LIB
#include <dlfcn.h>
#endif

using namespace swift;

Expand Down Expand Up @@ -56,6 +59,7 @@ void swift::initializeProtocolLookup() {
sections = sections->next;
}
}

void swift::initializeProtocolConformanceLookup() {
const swift::MetadataSections *sections = registered;
while (true) {
Expand Down Expand Up @@ -89,10 +93,8 @@ void swift::initializeTypeMetadataRecordLookup() {
void swift::initializeDynamicReplacementLookup() {
}

// As ELF images are loaded, ImageInspectionInit:sectionDataInit() will call
// addNewDSOImage() with an address in the image that can later be used via
// dladdr() to dlopen() the image after the appropriate initialize*Lookup()
// function has been called.
// As ELF images are loaded, SwiftRT-ELF:swift_image_constructor() will call
// addNewDSOImage() with a pointer to the MetadataSections in the image.
SWIFT_RUNTIME_EXPORT
void swift_addNewDSOImage(const void *addr) {
const swift::MetadataSections *sections =
Expand Down Expand Up @@ -131,6 +133,12 @@ void swift_addNewDSOImage(const void *addr) {
}
}

#ifndef ELF_STATIC_LIB

// For shared executables only, static executables use the version defined in
// StaticBinaryELF.cpp.
// libswiftImageInspectionShared.a contains the below function and
// libswiftImageInspectionStatic.a contains the version in StaticBinaryELF.cpp
int swift::lookupSymbol(const void *address, SymbolInfo *info) {
Dl_info dlinfo;
if (dladdr(address, &dlinfo) == 0) {
Expand All @@ -144,6 +152,8 @@ int swift::lookupSymbol(const void *address, SymbolInfo *info) {
return 1;
}

#endif

// This is only used for backward deployment hooks, which we currently only support for
// MachO. Add a stub here to make sure it still compiles.
void *swift::lookupSection(const char *segment, const char *section, size_t *outSize) {
Expand Down
Loading

0 comments on commit 3b25795

Please sign in to comment.