Skip to content

Commit

Permalink
Merge pull request #3357 from NK-Nikunj/static_hpx_main_impl
Browse files Browse the repository at this point in the history
Static/dynamic executable implementation
  • Loading branch information
hkaiser committed Jul 7, 2018
2 parents 3739d0c + c657d71 commit ad566a3
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 8 deletions.
6 changes: 5 additions & 1 deletion cmake/HPX_GeneratePackage.cmake
Expand Up @@ -74,6 +74,11 @@ else()
endif()
endif()

set(HPX_LINKER_FLAGS "")
if(CMAKE_SYSTEM_NAME STREQUAL Linux)
set(HPX_LINKER_FLAGS "-Wl,-wrap=__libc_start_main")
endif()

# Get the include directories we need ...
get_directory_property(_INCLUDE_DIRS INCLUDE_DIRECTORIES)

Expand Down Expand Up @@ -230,4 +235,3 @@ install(
DESTINATION ${LIB}/bazel
COMPONENT bazel
)

5 changes: 4 additions & 1 deletion cmake/HPX_SetupTarget.cmake
Expand Up @@ -187,7 +187,6 @@ function(hpx_setup_target target)
set(_USE_CONFIG 0)
endif()

# linker instructions
if(NOT target_NOLIBS)
set(hpx_libs hpx)
if(NOT target_STATIC_LINKING)
Expand All @@ -204,6 +203,10 @@ function(hpx_setup_target target)
if(DEFINED HPX_LIBRARIES)
set(hpx_libs ${hpx_libs} ${HPX_LIBRARIES})
endif()
get_target_property(target_type ${target} TYPE)
if(CMAKE_SYSTEM_NAME STREQUAL Linux AND target_type STREQUAL EXECUTABLE)
set_target_properties(${target} PROPERTIES LINK_FLAGS "-Wl,-wrap=__libc_start_main")
endif()
else()
target_compile_options(${target} PUBLIC ${CXX_FLAG})
endif()
Expand Down
3 changes: 1 addition & 2 deletions cmake/templates/hpx_application.pc.in
Expand Up @@ -12,6 +12,5 @@ includedir=${exec_prefix}/include
Name: hpx_application
Description: High Performance ParalleX (application configuration)
Version: @HPX_VERSION@
Libs: @CXX_FLAG@ -L${libdir} @HPX_PKG_LIBRARY_DIR@ @HPX_PKG_LIBRARIES@
Libs: @CXX_FLAG@ -L${libdir} @HPX_PKG_LIBRARY_DIR@ @HPX_PKG_LIBRARIES@ @HPX_LINKER_FLAGS@
Cflags: @CXX_FLAG@ @HPX_CONF_INCLUDE_DIRS@ -DHPX_APPLICATION_EXPORTS -DHPX_ENABLE_ASSERT_HANDLER

3 changes: 1 addition & 2 deletions cmake/templates/hpx_application_debug.pc.in
Expand Up @@ -12,6 +12,5 @@ includedir=${exec_prefix}/include
Name: hpx_application
Description: High Performance ParalleX (application configuration) - debug build
Version: @HPX_VERSION@
Libs: @CXX_FLAG@ -L${libdir} @HPX_PKG_LIBRARY_DIR@ @HPX_PKG_DEBUG_LIBRARIES@
Libs: @CXX_FLAG@ -L${libdir} @HPX_PKG_LIBRARY_DIR@ @HPX_PKG_DEBUG_LIBRARIES@ @HPX_LINKER_FLAGS@
Cflags: @CXX_FLAG@ -DHPX_DEBUG @HPX_CONF_INCLUDE_DIRS@ -DHPX_APPLICATION_EXPORTS -DHPX_ENABLE_ASSERT_HANDLER

16 changes: 16 additions & 0 deletions hpx/hpx_main.hpp
@@ -1,4 +1,5 @@
// Copyright (c) 2007-2014 Hartmut Kaiser
// Copyright (c) 2018 Nikunj Gupta
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -9,6 +10,20 @@
#include <hpx/config.hpp>
#include <hpx/hpx_init.hpp>

// We support different implementation depending upon the Operating
// System in use.
#if defined(__linux) || defined(__linux__) || defined(linux)

namespace hpx_start {
// include_libhpx_wrap here is an override for the one present in
// src/hpx_wrap.cpp. The value of this variable defines if we need
// to change the program's entry point or not.
extern bool include_libhpx_wrap;
bool include_libhpx_wrap = true;
}

#else

#if defined(HPX_HAVE_STATIC_LINKING)
#include <hpx/hpx_main_impl.hpp>
#endif
Expand All @@ -17,5 +32,6 @@
// as the first HPX-thread (equivalent to hpx_main()). This is implemented by
// a macro redefining main, so we disable it by default.
#define main hpx_startup::user_main
#endif

#endif /*HPX_HPX_MAIN_HPP*/
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
@@ -1,5 +1,6 @@
# Copyright (c) 2007-2017 Hartmut Kaiser
# Copyright (c) 2011 Bryce Lelbach
# Copyright (c) 2018 Nikunj Gupta
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -20,7 +21,7 @@ endforeach()
# libhpx sources
add_hpx_library_sources(hpx
GLOB GLOBS "${PROJECT_SOURCE_DIR}/src/*.cpp"
EXCLUDE "(.*(hpx_main|hpx_user).*[.]cpp)|main.cpp")
EXCLUDE "(.*(hpx_main|hpx_user).*[.]cpp)|main.cpp|hpx_wrap.cpp")
add_hpx_library_sources(hpx
GLOB GLOBS "${PROJECT_SOURCE_DIR}/src/pre_main.cpp"
APPEND)
Expand All @@ -44,7 +45,6 @@ add_hpx_library_sources(hpx
GLOB_RECURSE GLOBS "${PROJECT_SOURCE_DIR}/src/compat/*.cpp"
APPEND)


# libhpx_init sources
add_hpx_library_sources(hpx_init
GLOB GLOBS "${PROJECT_SOURCE_DIR}/src/hpx_*.cpp"
Expand Down
131 changes: 131 additions & 0 deletions src/hpx_wrap.cpp
@@ -0,0 +1,131 @@
// Copyright (c) 20018 Nikunj Gupta
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

// The following implementation is only possible for Linux systems.
#if defined(__linux) || defined(__linux__) || defined(linux)

namespace hpx_start {
// include_libhpx_wrap is a weak symbol which helps to determine the course
// of function calls at runtime. It has a deafult value of `false` which
// corresponds to the program's entry point being main().
// It is overriden in hpx/hpx_main.hpp. Thus, inclusion of the header file
// will change the program's entry point to HPX's own custom entry point
// initialize_main. Subsequent calls before entering main() are handled
// by this code.
extern bool include_libhpx_wrap;
bool include_libhpx_wrap __attribute__((weak)) = false;
}

#include <hpx/hpx_init.hpp>
#include <hpx/hpx.hpp>

#include<vector>
#include <iostream>

////////////////////////////////////////////////////////////////////////////////
// Function declarations
//

namespace hpx_start{
// Main entry point of HPX runtime system
extern int hpx_entry(int argc, char* argv[]);
}

// HPX's implented program's entry point
extern int initialize_main(int argc, char** argv, char** envp);

// Real libc function __libc_start_main. Function definition can be
// found in the glibc source in `glibc/csu/libc-start.c`
extern "C" int __real___libc_start_main (
int (*main)(int, char**, char**), int argc, char * * ubp_av,
void (*init) (void), void (*fini) (void),
void (*rtld_fini) (void), void (* stack_end));

// Wrapper function for __libc_start_main
extern "C" int __wrap___libc_start_main (
int (*main)(int, char**, char**), int argc, char * * ubp_av,
void (*init) (void), void (*fini) (void),
void (*rtld_fini) (void), void (* stack_end));


////////////////////////////////////////////////////////////////////////////////
// Global pointers

namespace hpx_start {
// actual_main is responsible to store the pointer to the main()
// function. POSIX implementation of main requires pointer to envp
// so it is stored as well.
int (*actual_main)(int, char**, char**) = nullptr;
char** __envp = nullptr;


// main entry point of the HPX runtime system
int hpx_entry(int argc, char* argv[])
{
// Call to the main() function
int return_value = hpx_start::actual_main(argc, argv, __envp);

//Finalizing the HPX runtime
return hpx::finalize(return_value);
}
}

// This is the main entry point of C runtime system.
// The HPX runtime system is initialized here, which
// is similar to initializing HPX from main() and utilising
// the hpx_main() as the entry point.
int initialize_main(int argc, char** argv, char** envp)
{
// initializing envp pointer to utilize when
// calling the actual main.
hpx_start::__envp = envp;

// Configuring HPX system before runtime
std::vector<std::string> const cfg = {
"hpx.commandline.allow_unknown!=1",
"hpx.commandline.aliasing=0",
};

using hpx::util::placeholders::_1;
using hpx::util::placeholders::_2;
hpx::util::function_nonser<int(int, char**)> start_function =
hpx::util::bind(&hpx_start::hpx_entry, _1, _2);

// Initialize the HPX runtime system
return hpx::init(start_function, argc, argv,
cfg, hpx::runtime_mode_console);
}


////////////////////////////////////////////////////////////////////////////////
// Wrapper for the libc function __libc_start_main
//

// We are hooking into __libc_start_main to change the entry
// point of the C runtime system to our custom implemented
// function initialize_main
extern "C" int __wrap___libc_start_main (
int (*main)(int, char**, char**), int argc, char * * ubp_av,
void (*init) (void), void (*fini) (void),
void (*rtld_fini) (void), void (* stack_end))
{

// We determine the function call stack at runtime from the
// value of include_libhpx_wrap.
if(hpx_start::include_libhpx_wrap) {
// Assigning pointer to C main to actual_main
hpx_start::actual_main = main;

// Calling original __libc_start_main with our custom entry point.
return __real___libc_start_main(&initialize_main, argc, ubp_av, init,
fini, rtld_fini, stack_end);
}
return __real___libc_start_main(main, argc, ubp_av, init,
fini, rtld_fini, stack_end);

}
////////////////////////////////////////////////////////////////////////////////

#endif

0 comments on commit ad566a3

Please sign in to comment.