1

I've put asm INT 3 end; in the very first line of my main procedure.

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  asm INT 3 end;

  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Yet, the SysInit._InitExe call is placed before it. Refer to the below image. Removing VCL units from uses clause is not an option.

enter image description here

forsajt
  • 857
  • 1
  • 7
  • 13
  • Simple answer is that short of hacking the compiled executable, you can't get your code to run before the unit initialization. What are you trying to achieve? – David Heffernan Feb 28 '18 at 09:00
  • 1
    Have you tried putting the `Int 3` into the `Initialization` section of a new unit and then adding the unit as the first unit in the .Dpr file? That works ... – MartynA Feb 28 '18 at 09:11
  • 1
    @DavidHeffernan Say, my program is run by a hypervisor, and the thread it is started in, is kind of "corrupted". I need to fix some things in TEB, before VCL code gets executed. – forsajt Feb 28 '18 at 09:43
  • Is it a distinct procedure that needs to be called after your code? Or do you mean the initialization section of any VCL unit? – nil Feb 28 '18 at 10:50
  • @nil Preferably, all the VCL initialization. I tried MartynA's suggestion, and there are still few calls executed before. – forsajt Feb 28 '18 at 12:13
  • Ah, ok. Unit initialization as MartynA suggested would have gotten your code executed earlier, but if that is not enough ... – nil Feb 28 '18 at 12:19
  • @nil the disassembled code in the questions makes it very clear that unit initialization code is too late – David Heffernan Feb 28 '18 at 12:45
  • @DavidHeffernan Well it wasn't for me, sorry. In XE2, XE7 and Tokyo information in the 'Disassembly' looked so different, to be sure I read that correctly: _InitExe is what is this all about? Then 'VCL init' is misleading, that happens for none VCL projects too. – nil Feb 28 '18 at 13:43
  • 1
    What about putting the interrupt into a DLL, and then have the EXE statically link to the DLL? That way, the DLL gets initialized before the EXE is initialized. – Remy Lebeau Feb 28 '18 at 20:18
  • @RemyLebeau That's right. Another option be would using a TLS callback. In the end, MartynA's solution passed the exam - it turned out to be early enough to successfully apply the fix. But I will accept David's answer as I indicated the exact place in disassembly - that can't be achieved unfortunately. Thanks to everyone. – forsajt Mar 02 '18 at 10:08
  • 1
    The picture is wrong. What you marked as VCL init is the call to `SysInit._InitExe` which then calls `System._StartExe` which calls `System.InitUnits` which eventually calls all initialization parts of units being used in the module by their order of appearance in the uses (see http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Programs_and_Units_(Delphi)#The_Initialization_Section). A unit being put first into the dpr uses will have its initialization part being executed first (if it does not have any other units in its uses itself though) – Stefan Glienke Mar 02 '18 at 10:24
  • @Stefan Glienke thanks for correction. I was too lazy to import the symbols. I realized that's "some VCL initialization code" after quick stepping though it. – forsajt Mar 02 '18 at 10:32
  • Well the entire argumentation that the "new unit into uses clause" does not work is based on this false premise, so it should be corrected and you should add what you really are trying to achieve into the question. – Stefan Glienke Mar 02 '18 at 10:39

2 Answers2

1

There's no way to do what you need using the built-in tooling. You'll need to do some post compilation modification of the executable file.

  1. Include the code that you need to execute first in your source file so that it is compiled into the executable, but don't call it.
  2. Modify the entry point in the PE header to point to your new entry point code.
  3. Arrange that your new entry point code jumps to the original entry point when it is done.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Probably easier to just use your debugger to set a breakpoint at whatever asm instruction you want it to stop at, instead of going to all this trouble to permanently insert one. – Peter Cordes Feb 28 '18 at 09:58
  • @PeterCordes As I read the comments to the question, that's not a practical solution – David Heffernan Feb 28 '18 at 10:04
  • If I say no again, will you ask the question for the third time? In order to modify the executable, you'll want to read the detailed map file to find your function's location. – David Heffernan Feb 28 '18 at 10:41
1

You could place the asm code into the initialization section of a new unit and put this unit first into the uses clause of your project. That way the code should be executed after the initialization section of the System unit. (Be sure to test this, I have not tried it at all.)

dummzeuch
  • 10,975
  • 4
  • 51
  • 158
  • The graphic in the question indicates that the code should run before then, as the very first thing executed in the executable – David Heffernan Feb 28 '18 at 13:56
  • 2
    Yes, this is what I suggested in a comment and an answer earlier, and it does execute before any other unit's initialization section. I deleted my answer when @DavidHeffernan objected that it didn't answer the question, because it doesn't execute before the VCL's initialization code, though tbh I am not sure which code he had in mind. – MartynA Feb 28 '18 at 15:24
  • 2
    Uhm? Of course the initialization of any unit placed *before* `Forms` in the dpr will execute *before* any VCL initialization code which is executed somewhere inside any of the initialization blocks of either `Forms` or some other unit. The call marked in question which was executed before his int 3 is the `InitExe` call which then calls all the initialization parts in order of uses appearance. – Stefan Glienke Mar 02 '18 at 10:17