Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28434 Discussions

Replacing for_main.o (dangerous)

ereisch
New Contributor II
716 Views

First, I will preface: yes, I know replacing compiler intrinsics is risky and not necessarily portable between compiler versions.  I want to set up my programs (many of them built in this project) so they will optionally call raise(SIGSTOP) immediately after starting if a certain command-line parameter is set.  This is so they may wait for a debugger to attach.  There are many, many instances of PROGRAM <whatever> in the code as many dozens (or even hundreds) of executables are built, though they do all share a central library and build system.  So a pre-MAIN__ solution here would be ideal.

I was curious if it was possible to replace the for_main.o with an alternative that does the same thing, only I can inject some more code prior to calling MAIN__.  Doing an "nm" on for_main.o (this is on Linux), I'm seeing this routine only calls 3 symbols outside of MAIN__ (the target provided by a Fortran PROGRAM statement), and its assembler looks pretty simple.  Would it be feasible for me to override this routine with one of my own where I check a couple command-line arguments, and then call for_rtl_init_ followed by MAIN__, followed by for_rtl_finish_?  There also appears to be call to another routine (__intel_new_feature_proc_init), though I don't know where in the sequencing that should go, and whether or not any of these routines accept arguments.

Any advice would be appreciated.  Thanks in advance.

0 Kudos
1 Solution
ereisch
New Contributor II
489 Views

UPDATE: I was able to get around this by using a C/C++ trick to inject a routine between _start() and main():

__attribute__((constructor(101))) __attribute__((force_align_arg_pointer)) __attribute__((no_instrument_function)) void launch_debug() {
   /* Code that checks arguments and conditionally calls SIGSTOP here */
}

Note there is a complication in that constructors aren't passed argc/argv, so if you need access to these you need to wander through /proc/self/cmdline. 

 

I put in the force_align_arg_pointer because it looks like for_main.o is also doing this; I'm not sure why, but figured there was a good reason it was being done, and didn't want to break anything the Fortran RTL was somehow relying on.

View solution in original post

0 Kudos
5 Replies
Steve_Lionel
Honored Contributor III
716 Views

I do not recommend trying this - there are assumptions that Intel's for_main.o is used. You don't know all of what it is doing.

When I have wanted to do the sort of thing you describe, I simply add a call at the start of the main program to my chosen routine.

0 Kudos
jimdempseyatthecove
Honored Contributor III
716 Views

>>I want to set up my programs (many of them built in this project) so they will optionally call raise(SIGSTOP) immediately after starting if a certain command-line parameter is set.  This is so they may wait for a debugger to attach.

VolatileLogicalOptionPresent = functionFindsDesiredCommandLineOption()
do while(VolatileLogicalOptionPresent)
  call SleepQQ(1) ! Attatch to process, issue Stop, set VolatileLogicalOptionPresent=.false.
end do

The "volatile" use is to assure the compiler optimization does not do something funny with your loop.

Jim Dempsey

0 Kudos
ereisch
New Contributor II
716 Views

Thanks Jim, but my goal was to have a solution that involved a pre-MAIN__ implementation so as to not have to change the dozens/hundreds of files that have PROGRAM statements.  I have a code solution that issues the SIGSTOP signal (and therefore doesn't require the user to do anything special after they've attached the debugger), but it's just a matter of finding a common place to inject it.  I was hoping we could do it through the for_main.o entry point, but Steve's suggestion to avoid that means we're going to have to modify all those files anyhow.

 

Thanks

0 Kudos
jimdempseyatthecove
Honored Contributor III
716 Views

>>my goal was to have a solution that involved a pre-MAIN__ implementation

Then make a C++ main with a type containing a ctor like in my suggestion in #3, and instantiate one static object of this type (place either first or last in the link phase as required to have its ctor be first in line).

Then change your Fortran PROGRAM into a SUBROUTINE with no args. You may need to add a call to for_rtl_init from your ctor.

See: https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/language-reference/a-to-z-reference/e-to-f/for-rtl-init.html

Jim Dempsey

0 Kudos
ereisch
New Contributor II
490 Views

UPDATE: I was able to get around this by using a C/C++ trick to inject a routine between _start() and main():

__attribute__((constructor(101))) __attribute__((force_align_arg_pointer)) __attribute__((no_instrument_function)) void launch_debug() {
   /* Code that checks arguments and conditionally calls SIGSTOP here */
}

Note there is a complication in that constructors aren't passed argc/argv, so if you need access to these you need to wander through /proc/self/cmdline. 

 

I put in the force_align_arg_pointer because it looks like for_main.o is also doing this; I'm not sure why, but figured there was a good reason it was being done, and didn't want to break anything the Fortran RTL was somehow relying on.

0 Kudos
Reply