Recent

Author Topic: [msdos] "unresolved external" when trying to link FPC *.a file  (Read 2062 times)

piola

  • Jr. Member
  • **
  • Posts: 61
Ok folks, I'm aware that there are probably not many users around here that are targeting the msdos-8086 platform. But it's the only place to ask this question, so I'll give it a try.

My problem in short: I have a QBasic program where I need  to include some objects created with FPC 3.2. Basically, this works fine. I have the following files:

- main.obj: This is the output of Microsoft BC, so it's an object created from the QBasic app
- system.lib: This is fpc\3.2.0\units\msdos\8086-compact\rtl\system.a converted to a static library with Microsoft Library Manager (LIB) 3.40
- math.lib: Same for math.a
- bcl71efr.lib: Static library from QBasic
- my.lib: This is the static library create from my FPC unit which I want to link to (same conversion with LIB from my.a to my.lib)

To link all together, I use Microsoft Linker 5.0 (all Microsoft tools are used in their DOS versions):

Quote
LINK main.obj,main.exe,,my.lib+bcl71efr.lib+math.lib+system.lib,nul.def

As I said, basically it works fine and I can call the procedures and functions contained in my.pas without any restriction or problem.

It gets complicated when I try to use some particular functions in my unit. One example is Randomize (which internally calls DOS-interrupt 21h) leading to this linker error:

Quote
SYSTEM.LIB(system0s1236.o) : error L2029: 'FPC_MSDOS' : unresolved external

Obviously, FPC_MSDOS is implemented in assembler as prt0c.asm and there is a compiled object named prt0c.o (I use "compact" memory model and assume the "c" version is the correct one). So I include prt0c.o as well:

Quote
LINK main.obj+prt0c.o,main.exe,,my.lib+bcl71efr.lib+math.lib+system.lib,nul.def

And this is the point where I'm stuck. This step leads to the following missing externals:

Quote
Microsoft (R) Segmented-Executable Linker  Version 5.10
Copyright (C) Microsoft Corp 1984-1990.  All rights reserved.

Temporary file .\lna02064 has been created.

prt0c.o(prt0c.asm) : error L2029: 'PASCALMAIN' : unresolved external
prt0c.o(prt0c.asm) : error L2029: '___heap' : unresolved external
prt0c.o(prt0c.asm) : error L2029: '___stack' : unresolved external
system.lib(system0s896.o) : error L2029: 'INITFINAL' : unresolved external

So first question is: in which object can I find "___heap" and "___stack"?

And second, as far as I understand, system.a seems to do calls to "pascalmain" and "initfinal" which seem to be sections of an FPC main program. However, I don't have (and don't want) one, as I only need a single unit.

Is there any possibility to resolve these externals?

I hope I have explained my situation well enough to understand what I want to do.

Thanks for any help!

PascalDragon

  • Hero Member
  • *****
  • Posts: 3170
  • Compiler Developer
Re: [msdos] "unresolved external" when trying to link FPC *.a file
« Reply #1 on: June 24, 2021, 09:34:03 am »
And this is the point where I'm stuck. This step leads to the following missing externals:

Quote
Microsoft (R) Segmented-Executable Linker  Version 5.10
Copyright (C) Microsoft Corp 1984-1990.  All rights reserved.

Temporary file .\lna02064 has been created.

prt0c.o(prt0c.asm) : error L2029: 'PASCALMAIN' : unresolved external
prt0c.o(prt0c.asm) : error L2029: '___heap' : unresolved external
prt0c.o(prt0c.asm) : error L2029: '___stack' : unresolved external
system.lib(system0s896.o) : error L2029: 'INITFINAL' : unresolved external

So first question is: in which object can I find "___heap" and "___stack"?

And second, as far as I understand, system.a seems to do calls to "pascalmain" and "initfinal" which seem to be sections of an FPC main program. However, I don't have (and don't want) one, as I only need a single unit.

Is there any possibility to resolve these externals?

The ___heap and ___stack symbols are created by the compiler when creating the main program source. It might be sufficient to create an assembly file with dummy symbols for these as well as PASCALMAIN and INITFINAL. Alternatively you could simply copy the code of FPC_MSDOS (which is the system call to DOS) into a separate assembly file.

Please note that without a proper INITFINAL initialization and finalization sections of units won't be run which is especially important for the System unit. You might be able to help that by manually calling the corresponding initialization symbol of that unit. Also you might need to provide your own memory manager without a proper ___heap if your code uses GetMem directly or indirectly.

In short: when doing such things you really, really need to know what you're doing and how the RTL works. If not you might get lucky once, but the next time things might im-/explode upon you.

piola

  • Jr. Member
  • **
  • Posts: 61
Re: [msdos] "unresolved external" when trying to link FPC *.a file
« Reply #2 on: June 30, 2021, 05:16:19 pm »
Thank you very much for this explanation. However, I do not fully understand this behavior. I'd expect the System unit's initialization and finalization to be the same for every program and to be called upon program startup. Your explanation makes me assume that the code of PASCALMAIN, INITFINAL, ___heap and ___stack were different for different programs. Am I correct so far?

But there has to be some source code for these 4 routines. I can't imagine the compiler magically creates same fancy content for those 4?

PascalDragon

  • Hero Member
  • *****
  • Posts: 3170
  • Compiler Developer
Re: [msdos] "unresolved external" when trying to link FPC *.a file
« Reply #3 on: July 01, 2021, 09:07:19 am »
Thank you very much for this explanation. However, I do not fully understand this behavior. I'd expect the System unit's initialization and finalization to be the same for every program and to be called upon program startup. Your explanation makes me assume that the code of PASCALMAIN, INITFINAL, ___heap and ___stack were different for different programs. Am I correct so far?

These symbols are provided by the main program file and used by the startup code. It's not the System unit that does the initialization, instead that is done inside PASCALMAIN directly before executing the code of the main beginend. block which in turn accesses the INITFINAL table. And PASCALMAIN is called by the startup code.

But there has to be some source code for these 4 routines. I can't imagine the compiler magically creates same fancy content for those 4?

Then you should widen your imagination, cause that is exactly what the compiler does ;)

 

TinyPortal © 2005-2018