Recent

Author Topic: Peculiarities in the EXE header of generated binaries for DOS/GO32V2 target  (Read 430 times)

Laaca

  • Newbie
  • Posts: 4
As you maybe know, since Freepascal 3.0.0 is not longer possible to compress the  DOS/GO32V2 generated binaries with famous UPX executable packer.
I raised an issue on the GitHub page of  the UPX project.: https://github.com/upx/upx/issues/18892

The UPX author found some peculiarities in the EXE header and he has some question which I am not able to answer.
Can somebody of you say something to this?


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

Here are two peculiarities I have noticed in BBOXFPC3.EXE from FreePascal 3.x:

The Section header for the bss Section has 0xfffff800 for a .scnptr.
The Section header for the text Section has 0x200 for a .scnptr.
Looking at file BBOXFPC3.EXE using a tool which maps the whole file into its address space beginning at 0x200000000:

(gdb) x/5xw 0x800+0x200000000   ## the COFF header
0x200000800:    0x0005014c  0x00000000  0x0000c200  0x000001b1   ## 5 Sections
0x200000810:    0x0107001c

(gdb) x/7xw   ## the a.out header
0x200000814:    0x0000010b  0x0000a5a0  0x00000cdc  0x00006e58
0x200000824:    0x00001084  0x00001000  0x0000c000

(gdb) x/10xw   ## the 5 Section headers
0x200000830:    0x7865742e  0x00000074  0x00001000  0x00001000   ## ".text" beginning at RVA 0x1000
0x200000840:    0x0000a5a0  0x00000200  0x00000000  0x00000000   ## .scnptr == 0x200
0x200000850:    0x00000000  0x00000020
(gdb)
0x200000858:    0x7461642e  0x00000061  0x0000c000  0x0000c000   ## ".data"
0x200000868:    0x00000cdc  0x0000a800  0x00000000  0x00000000
0x200000878:    0x00000000  0x00000000
(gdb)
0x200000880:    0x7373622e  0x00000000  0x0000d000  0x0000d000   ## ".bss"
0x200000890:    0x00006e58  0xfffff800  0x00000000  0x00000000   ## .scnptr == 0xfffff800
0x2000008a0:    0x00000000  0x00000080
(gdb)
0x2000008a8:    0x6174732e  0x00000062  0x00000000  0x00000000   ## ."stab"
0x2000008b8:    0x000007e0  0x0000b600  0x00000000  0x00000000
0x2000008c8:    0x00000000  0x00000200
(gdb)
0x2000008d0:    0x6174732e  0x72747362  0x00000000  0x00000000   ## ."stabstr"
0x2000008e0:    0x00000339  0x0000be00  0x00000000  0x00000000
0x2000008f0:    0x00000000  0x00000200
In previous compiled versions BBOXFPC1.EXE and BBOXFPC2.EXE, and most other .EXE, then .bss.scnptr is zero because there is no association of the .bss Section with any offset in the file. Why is BBOXPC3 different, and what is the meaning of 0xfffff800?

Understanding a .text.scnptr of 0x200 is tricky and requires several steps. During compression, then UPX copies the go32stub in file offsets [0x200, 0x800) from input file to output file. This means that execution of the compressed output will start exactly the same as the execution of the not-compressed input.

However, the first 80 bytes or so of go32stub are a data area, not instructions. At least a couple fields are stored into during startup, including the memory_handle and values of several segments: ds, cs, and psp. But if .text.scnptr is less than 0x800 (the end of the region that is reserved for go32stub), then UPX run-time de-compression will overwrite the active go32stub with the de-compressed values that were re-generated from .text of the input file. So if values from the overwritten region ever are used again in the same process, then almost certainly that will be an error. Thus, a .text.scnptr of less than 0x800 has a very high probability of causing an error.

Why does FreePascal 3.x want to copy go32stub beginning at 0x200 into its .text process address space beginning at 0x1000?

Thaddy

  • Hero Member
  • *****
  • Posts: 19625
  • Glad to be alive.
Why does FreePascal 3.x want to copy go32stub beginning at 0x200 into its .text process address space beginning at 0x1000?
It should not. File a bug report. This is a bug in FPC. (Even if it only manifests itself with upx compression: you need to mention that, possibly add the comments from the UPX developers too, they are clear)

Note, although UPX is no longer distributed with Freepascal, it should still work when you use it.
The reasons for removal from the distribution is simply that it can conflict with many antivirus and has no benefits with modern storage.
« Last Edit: July 15, 2026, 11:59:32 am by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
It seems the go32v2 linker is a variant of the win32 linker, mostly in ogcoff, with some overrides for a map file in systems\t_go32v2.pas

It might be something with the tool the pattern was copied from or to exploit similarities with the win32/64 linker. 

A bug report would indeed be best.


Thaddy

  • Hero Member
  • *****
  • Posts: 19625
  • Glad to be alive.
@laaca
About  https://gitlab.com/freepascal.org/fpc/source/-/work_items/41818

Well phrased bug report. Note the remark: an external linker (use -Xe) solves the issue at the moment.
But it confirms it is definitely a Freepascal bug.
« Last Edit: July 18, 2026, 07:54:56 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

Laaca

  • Newbie
  • Posts: 4
Well, the bug report is created and somebody hopefuly works on it and in the next FPC version it will be fixed. But what do you think - would be difficult to write also some "fixer" for already compiled EXEs? Because not always I have the source and even if I have not always is trivial to perform the recompilation.

Laaca

  • Newbie
  • Posts: 4
Well, with the AI assistance I managed to create the corrector for FPC 3.x generated EXEfiles. After correction they can be packed with UPX.

https://www.laaca.borec.cz/soubory/fixfpc3.zip

 

TinyPortal © 2005-2018