29 Jun 2015

Linking OMF files with Delphi

Continuing the discussion about Delphi compiler and the object files.

Here is the OMF file template I made for 010 Editor: https://www.mediafire.com/?bkpbkjvgen7ubz1

Please note, it is not a full-featured implementation of OMF specification. I only implemented all OMF file records that are processed by Delphi 2007 compiler. So, next time you have a cryptic compiler error while trying to link OMF file in Delphi, you can take a look into your OBJ file and make an educated guess what's causing the problem.

TL;DR version

In 95+% of cases you will encounter OBJ file that has unsupported segment name in SEGDEF record. And it's a simple fix, too - you just need to use objconv.exe by Agner Fog and use -nr option to rename the offending segment. Something like this:

Next possible issue is exceeding the number of EXTDEF or LNAMES records - this can happen if you're trying to convert a really large DLL file into OBJ file.

Finally, your OBJ file might contain some record type which is not supported by Delphi compiler at all. I'm not aware of a simple way to fix it, I would try using 010Editor and OMF template to remove the entire record.

If your problem is not caused from any of the above issues, please feel free to drop me a note - I'll be happy to look into it.

Known limitations of Delphi compiler

This is a list of limitations I was able to compile and/or confirm. Some of them come from Embarcadero official notes and the rest I obtained by analyzing dcc32.exe.

SEGDEF (98H, 99H)

  • Not more than 10 segments - if number of segments exceeds 10, buffer overrun will probably happen.
  • Segments must be 32bits. Will cause "E2215 16-Bit segment encountered in object file '%s'"
  • Segment name must be one of (case insensitive):
    • Code segments: "CODE", "CSEG", "_TEXT"
    • Constant data segments: "CONST", "_DATA"
    • Read-write data segments: "DATA", "DSEG", "_BSS"

    Segment with any other name will be ignored.


Not more than 50 local names in LNAMES records - will cause "E2045 Bad object file format: '%s'" error.


Not more than 255 external symbols - will cause "E2045 Bad object file format: '%s'"
Certain EXTDEF records can also cause "E2068 Illegal reference to symbol '%s' in object file '%s'" and "E2045 Bad object file format: '%s'"

PUBDEF (90H, 91H)

Can cause "E2045 Bad object file format: '%s'" and "F2084 Internal Error: %s%d"


Embarcadero says that "LEDATA and LIDATA records must be in offset order" - I am not really sure what that means. Can cause "E2045 Bad object file format: '%s'"


Embarcadero says that "LEDATA and LIDATA records must be in offset order" - I am not really sure what that means. Can cause "E2045 Bad object file format: '%s'"


This type of record is unsupported, will cause immediate error "E2103 16-Bit fixup encountered in object file '%s'"


Embarcadero documentation says:

  • No THREAD subrecords are supported in FIXU32 records
  • Only segment and self relative fixups
  • Target of a fixup must be a segment, a group or an EXTDEF

Again I'm not sure what they mean. But there are lots of checks that can cause "E2045 Bad object file format: '%s'"


Accepted by compiler, but no real checks are performed.

LINNUM (94H, 95H)

Accepted by compiler, but no real checks are performed.


Accepted by compiler, but no real checks are performed.


Ignored by compiler.

That's the end of the list. Any other entry type will cause immediate error "E2045 Bad object file format: '%s'" smile

Useful links

My OMF file template for 010Editor: https://www.mediafire.com/?bkpbkjvgen7ubz1
OMF file format specification.
The Borland Developer's Technical Guide
Objconv.exe by Agner Fog
Manual for objconv.exe

3 thoughts on “Linking OMF files with Delphi

  1. Sorry about this comment being on an old article :-)

    I'm having some issues with an .obj file I have extracted from the Citrix Virtual Channel SDK:

    {hidden link}

    The original extracted file is called vdapi.original.obj, located here:

    {hidden link}

    As I understand it, there's 8 symbols that need to be "implemented" in Delphi, namely:


    Because of 7 of the exported names having an "@" in them, I've used objconv to rename them, and remove the underscore. The resulting .obj file is vdapi.obj in the same folder as vdapi.original.obj

    These files are in COFF format, which Delphi XE2 or greater is supposed to be able to handle, and I can link to vdapi.obj without any errors.

    This code is used to build a DLL that is loaded via Citrix. The DLL is supposed to (according to the docs) export a single function called Load, which mine does, which calls the Load function exported from the .obj (as _Load). According to the docs, _Load "forwards the driver entry points defined in the .DLL to the client engine", the driver entry points being the "implemented" functions. The DLL has the Load function called by Citrix, however for some reason none of the "forwarded" functions are ever called.

    My question is whether the renaming might have affected the end result, or there is some other issue. I have also tried to convert the .obj to OMF as per your articles, however I ended up with a "Bad object file format" error.

    Any ideas about how I might be able to make this work?

    • No problem, I'm happy that someone actually reads these posts. :)

      Renaming that you described shouldn't affect the result.

      If you could send me your example Delphi source+your compiled DLL+MAP/symbols for the DLL (optional but would greatly help), I will be happy to look at it and try to locate the issue. My email is at the bottom of the page.

Leave a Reply

  • Be nice to me and everyone else.
  • If you are reporting a problem in my tool, please upload the file which causes the problem.
    I can`t help you without seeing the file.
  • Links in comments are visible only to me. Other visitors cannot see them.

Your email address will not be published.

4  +   =  eleven