OMF2D 1.02  32- OMF  Delphi,  OMF
Copyright (C) 2003 Radim Picha, www.anticracking.sk/EliCZ
: OMF2D <InputOMF> [OutputOMF] []
:
/ C +   
/ CL [#] name = name  [# - ] LNAME
/ CE [#] name = name  [# - ] EXT / COM / EXPDEF 
/ CP [#] name = name  [#th ]  PUBDEF
/ U-    EXT / COM / EXP / PUBDEF
/ UUdll dll,   UndecorateName
/ U_ *     EXT / COM / EXP / PUBDEF
/ U * _    EXT / COM / EXP / PUBDEF
/ D-   __declspec (dllimport)
/ SEname =   EXTDEF  ABS
/ F +  -Offset32 () 
/ Ofile    


================================================== ============================================

-------
Freeware,  .  ,   ,   .


================================================== ============================================

-------
http://www.anticracking.sk/EliCZ/Export/OMF2D.zip

1.01 - mov eax, [dllimport] -> mov eax, dllimport  ,  LEDATA   .
1.02 - dllimport ,   LEDATA   .

================================================== ============================================

-------
OMF2D           ()  ()
      -   :
 + .obj = 
(  .obj       Main)

  ?
OMF   .         OMF
.       ,   .
  -    /    . 
    .
OMF2D       32-    
(32bit =   Offset32    ).
 Delphi    -      
   (  {$ L OMF.obj}).      
    ,  OMF.

   :
*)     ,   Functions.obj.
(Main00 ..MainXX   Delphi; Functions.obj   VC).
*)      (   )  
   .
:     MASM  Visual C        Delphi
.

 ,      (    ),
    (    ).


================================================== ============================================
   Delphi
--------------------------

1)      .

LIBMAN -LIST Library.lib> Objects.txt

2)   ,    (),     , 
   ,      .
(        , 
   -          ).

LIBMAN -EXTRACT: Object.obj Library.lib

3)  Object.obj   COFF,    OMF.

COFF2OMF Object.obj

(COFF2OMF -  ,    COFF   OMF.
  Digital Mars C / C ++ (www.digitalmars.com).      
   ,     Borland C ++    
 .)

4)  OMF    OMF.

OMF2D Object.obj /OLNames.opt /OENames.opt> Object.dh

(  DFix.bat.      .)

5)     Delphi:
{$ I Object.dh}
{$ L Object.obj}


.       COFF2OMF.exe  DFix.bat.

================================================== ============================================
 
------------
InputOMF - () name.ext; ;    .
:   .obj

OutputOMF - () name.ext; ;      InputOMF;
   ,  InputOMF.
:   .obj

   .

C + -   .     ,     .
 : / CL, / CE, / CP, / U-, / UU, / U_ *, / U * _, / O.

[#] - # = 0..65535; ;
0 -     (  ,   );
1,2, .. 65535 -  , , 65535- .
(#      (  0)
    ( 




OMF2D 1.02 converts 32bit OMF to Delphi linkable OMF
Copyright (C) 2003 Radim Picha, www.anticracking.sk/EliCZ
Usage: OMF2D <InputOMF> [OutputOMF] [Options]
Options:
/C+   Change names only
/CL[#]name=name   Change [#th occurrence of] LNAME
/CE[#]name=name   Change [#th occurrence of] EXT/COM/EXPDEF name
/CP[#]name=name   Change [#th occurrence of] PUBDEF name
/U-   Do not undecorate EXT/COM/EXP/PUBDEF names
/UUdll   dll exporting user's UndecorateName
/U_*   Keep leading underscore of EXT/COM/EXP/PUBDEF names
/U*_   Keep end     underscore of EXT/COM/EXP/PUBDEF names
/D-   Do not handle __declspec(dllimport)
/SEname=value   Take EXTDEF as ABS
/F+   Keep non Offset32 (debug) fixups
/Ofile   Read options from file


==============================================================================================
License
-------
  Freeware, everything allowed. No support, not carefully tested, no responsibility.


==============================================================================================
Updates
-------
  http://www.anticracking.sk/EliCZ/Export/OMF2D.zip

  1.01 - mov eax, [dllimport] -> mov eax, dllimport is also done when LEDATA starts with it.
  1.02 - dllimport fixed even if LEDATA starts with it.

==============================================================================================
Purpose
-------
  OMF2D can help in static linking given object file with main (object) file(s)
by converting given object file to main-linker-compatible object file:
  Main + Functions.obj = Module
(here Functions.obj must be converted to be linkable with Main)

  Why is the conversion neccessary?
  OMF should be standard. However some linkers are too simple to support all OMF
features. They are not able to work with object files created by "other" compilers.
Second problem are the names of used / exported functions and variables. Different
name decoration tactics exist.
  OMF2D tries to convert given object file in 32bit relocatable object module format
(32bit = containing Offset32 fixups for relevant segments only).
  Delphi linker was evaluated as the simplest - converted object file should be linkable
by this linker (via {$L OMF.obj} directive). Then the converted file should be theoretically
linkable by any more complex linker that supports OMF.

  Where it may help:
*) Programmer's code needs to call functions contained within Functions.obj.
   (Main00 ..MainXX written in Delphi; Functions.obj written in VC).
*) Developer wants to provide his code (in form of object files) for static
   linking with any code.
Example: Developer wrote code in MASM or Visual C and now wants to use this code in Delphi
project.

  Again this is about static linking (using code from current module),
not about dynamic linking (using code from another modules).


==============================================================================================
Example of use with Delphi
--------------------------

1) Get list of object files in library.

   LIBMAN -LIST Library.lib > Objects.txt

2) Extract object file that contains wanted function(s) and extract also object files that
   contain variables and functions referenced from the first object file.
   (Sometimes are some of variables and functions present in initialization codes, then
   the task becomes difficult - you must run this init code before calling wanted function).

   LIBMAN -EXTRACT:Object.obj Library.lib

3) If Object.obj is in COFF, convert it to OMF.

   COFF2OMF Object.obj

   (COFF2OMF is a utility that converts COFF file to OMF file. This utility is shipped
   with the Digital Mars C/C++ package (www.digitalmars.com). Do not confuse it with tool
   with the same name that is present in Borland C++ package and that serves for converting
   import libraries.)

4) Convert OMF to widely acceptable OMF.

   OMF2D Object.obj /OLNames.opt /OENames.opt >Object.dh

   (It is recommended to use DFix.bat. Set the right paths in this file.)

5) Add files to Delphi project:
   {$I Object.dh}
   {$L Object.obj}


Note: Do not forget to specify path for the right COFF2OMF.exe in DFix.bat.

==============================================================================================
Command line
------------
InputOMF  - (path)name.ext; required; name of file to convert.
            Example: "This Input File.obj"

OutputOMF - (path)name.ext; optional; name of file with converted contents of InputOMF;
            if omitted, InputOMF is used.
            Example: "This Output File.obj"

Options are case sensitive.

C+        - change names only. Serve as name editor, do not make any other changes.
            Relevant options: /CL, /CE, /CP, /U-, /UU, /U_*, /U*_, /O.

[#]       - # = 0..65535; optional;
            0 - replace any occurrence of name (the same effect as if omitted);
            1,2,..65535 - replace 1st, 2nd, 65535th occurrence of name.
            (# can be in octal notation (starting with 0)
             or in hexadecimal format (preceded by 0x))
            Example:
            /CLA_CODE=A_TEXT
              - replace any LNAME "A_CODE" with "A_TEXT"
            /CE[2]_wsprintfA=wsprintfA
              - replace 2nd occurence of EXT/COM/EXPDEF name "_wsprintfA" with "wsprintfA"
            /CP[0]__@@QQ$ll$[]$:()=ReadableName
              - replace any PUBDEF name "__@@QQ$ll$[]$:()" with "ReadableName"
            Windows 9x: It is better to specify names containing <,>,| in /Ofile
            then on command line.

U         - name undecration options - see "Undecorating names" section.

D-        - see "Handling dllimport" section.

SEname=value - Take EXTDEF variable as ABS (EQU) variable.

F+        - do not remove non Offset32 fixups. Non Offset32 (usually Pointer32) fixups are
            usually present due to symbolic debug information and have meaning only for
            debugging.
            You can use this option when you do not plan to link with Delphi, e.g. you are
            changing some name in object file only and you want to keep full debug info.

Ofile     - file = (path)name.ext that contains any of options (including next /O) per line.


==============================================================================================
Undecorating names
------------------
  Many compilers tend to decorate names of public symbols, e.g. GetVersion -> _GetVersion@0.
Delphi linker understands simple (or names decorated by BC++) names only.
U- option disables names undecoration.
  User can supply his own UndecorateName function residing in dll in command line switch /UU.
Example: /UUc:\MyUN.dll
Format of UndecorateName function is:
  BYTE __stdcall UndecorateName(PBYTE OrgName, PBYTE NewName, BOOL Keep_X, BOOL KeepX_);
OrgName - input pascal string (OrgName[0] = length);
NewName - specifies where to write output (undecorated) pascal string;
Keep_X  - TRUE when user specified /U_* option (wants to keep first _)
KeepX_  - TRUE when user specified /U*_ option (wants to keep last _)
UndecorateName function must return 1 if it found that OrgName is dllimport name
otherwise it must return 0.
  Name is undecorated only when it was not changed by /C? options.
  Local XXDEFs names are left intact (you can change them by next application of OMF2D to
object file).
  Default UndecorateName is designed for Delphi.
  Default UndecorateName tries to determine if input name is ++ decorated - then it exchanges
"bad" characters (@,$,:,[,],(,)) with letters. If name has simple ++ decoration or standard
decoration it is undecorated.
  U_* option tells UndecorateName to keep first _.
Example: Many compilers (when not in ++ mode) produce EXTDEF name _wsprintfA.
TASM, BC need _wpsrintfA; Delphi needs wsprintfA -> specify this option when you do not want
to link with Delphi.
  U*_ option tells UndecorateName to keep last _. Removing last _ helps to undecorate Watcom
__fastcall names. If you see in OMF dump that OMF was not created by Watcom and that there
are some EXT/COM/EXP/PUBDEF names with _ at the end, specify this option.


==============================================================================================
Handling __declspec(dllimport)
------------------------------
  Borland compilers / linkers do not support dllimport, imported function is still called via
thunk: call dllimport0thunk .. dllimport0thunk: jmp dword ptr [dllimport0].
When OMF2D detects dllimport, changes it into "Borland form". You can watch the change on
stderror output so you can always return the original byte values back.
Changed instructions:
  mov  eax,      [dllimport] ->     mov eax, dllimport;
  mov  r32,      [dllimport] -> ss: mov r32, dllimport;
  push dword ptr [dllimport] -> ss: push     dllimport;
  call dword ptr [dllimport] -> ss: call     dllimport;
  jmp  dword ptr [dllimport] -> ss: jmp      dllimport;

Rare case:
  typedef int (__stdcall *TFunctionX)(void);
  __declspec(dllimport) TFunctionX FunctionX;
Right psudocode for 
  FunctionX();
is:
  AddressOfPointerToFunctionX = [FunctionX];
  call [AddressOfPointerToFunctionX];
but some compilers translate it to:
  call [FunctionX];
In the case of wrong translation will be code changed as it would be regular dllimport.

  Option D- disables __declspec(dllimport) handling -> use it when you want to link your
code, created by compilers that do support __dllimport, with non Borland linkers.


==============================================================================================
Problems
--------
*) Fixups for LIDATA. Many linkers refuse them.
   If you have ASM source, replace
     Here  DD 12345678
     There DD Count DUP (Here)
   with
     There LABEL DWORD
     REPT Count
       DD Here
     ENDM
   Maybe next versions of OMF2D will solve this problem.

*) MASM bug: NameA ?? Count DUP (??)
   MASM treats Count as (Count mod 65536):
     ArrayA ?? 65536   DUP (??) -> ArrayA ?? 0 DUP (??)
       Count 0  causes Delphi to emit an error.
     ArrayA ?? 65536+1 DUP (??) -> ArrayA ?? 1 DUP (??)
       Formally correct but not intended.
   OMF2D can fix this bug (for the main repeat count only, not for internal counts)
   only when there exist next LXDAXX record for given segment.

*) MASM bug: Bad fixup generated for pointer in .CONST or relevant segment to variable in
   relevant segment.
   OMF2D fixes this bug.

Delphi linker problems
----------------------
*) Always initialize data; instead of
     MYSTRUCT ms;
   specify
     MYSTRUCT ms = {?};
   where ? is of the same type as first MYSTRUCT member.

*) Segments
   Base segments are segments with name _TEXT, CSEG, CONST, _DATA, _BSS.
   When they contain references to variables in another segments, the referenced
   segments must have names that end with (relevant segments) _TEXT, CSEG, CONST, _DATA, _BSS.
   Offset32 fixups are allowed for base and relevant segments only.
   Plus, all SEGDEFs for base and relevant segments must precede SEGDEFs for other segments.
   That's why there is LNames.opt file, that solves the SEGDEF precedence by replacing
   known irrelevant segment names by relevant names and that's why are non Offset32 fixups
   removed by default.

*) TLS will not work
   TLS is not base segment - TLS variables in object file will become part of _DATA
   (prescribed in LNames.opt: _TLS is renamed to _TLS_DATA). So offsets of TLS variables
   will be related to the beginning of _DATA segment (0) not to the beginning of _TLS
   segment. This is potential source of unexpected exceptions.
   Example: good - [TLS_DATAPTR +8], wrong - [TLS_DATAPTR +0x40C098].

*) Delphi "datapointer shift"
   Data variable for which exist both EXTDEF and PUBDEF but is not referenced in Offset32
   fixups may confuse Delphi linker's "datapointer". Data segments will be merged in the
   right way, but some fixups will be shifted. Object file linkage will be successful
   but thread running inside created module may cause unexpected exception. Solution is
   to replace EXTDEF name of given variable with another EXTDEF name.
   This rare case was observed only in the case of object files created by
   LCC, ICL when source contained const variables and compilation forced debug info presence.
   Example: Dump of object file revealed that there is EXTDEF with name "ConstVar" and
   PUBDEF with name "ConstVar" and variable sits in _DATA segment. Moreover inspection of dump
   showed that there is no reference to this EXTDEF variable in Offset32 fixups.
   Then it is good to replace EXTDEF name "ConstVar" with another PUBDEF or EXTDEF name
   present in object file (e.g "ExitProcess"). See DataShift directory.

*) Functions in non *_TEXT segments
   Delphi can call functions that are present in *_TEXT segments only. If the dump tells you
   that wanted functions are in other segments, rename these segments to _TEXT:
   e.g. /CL_DATA=_TEXT, /CLFuncSEG=_TEXT. After Delphi produces new module, add WRITEABLE bit
   in TEXT section attributes. See Delphi_uses_ASM\NonStd directory.

*) $L object file can import public variables from main program and units, not
   from other $L files.

*) Absolute external variables (EQUs, e.g. __tls_array) can be referenced if they
   are given values using /SE option (only 32bit fixups). Then it is good to rename
   such ext. variable to some of other PUBDEF or EXTDEFs. See Delphi_uses_ASM directory.

*) Objects, classes
   All you can do is to call original static methods. See Delphi_uses_Class directory.


==============================================================================================
Miscelaneous information
------------------------
*) Borland C++ __fastcall == Delphi register != standard (MS) __fastcall.

*) COFF2OMF generates bad sizes of communal variables when real size was in interval
   (0xFFFF .. 0xFFFFF).
