Pascal + AxRuntime

deadwood · 5035

magorium

  • Legendary Member
  • *****
    • Posts: 632
    • Karma: +62/-0
  • Convicted non contributor
Reply #30 on: March 16, 2022, 01:15:07 PM
As promised, a more elaborated example, based on ALB42's version for AxRT 40.2.

Code: (pascal) [Select]
program axrt_window;

{$MODE OBJFPC}{$H+}

uses
  ctypes, dynlibs;

//
//  AxRT functionality
//
const
  n_axrt      = './libaxrt-4.0.so';

  RT_STARTUP  = 3;
  RT_ABI      = 4;
  RT_VERSION  = 41;
  RT_REVISION = 1;
  RT_VER      = ( (RT_STARTUP shl 28) or (RT_ABI shl 24) or (RT_VERSION shl 8) or (RT_REVISION shl 0) );

var
  h_axrt      : TLibHandle = 0;
  memlocation : pointer;
  funname     : string;

  __set_runtime_env : procedure(x: cint); cdecl;
  __kick_start      : procedure(p: pointer; x: cint); cdecl;

//
//  exec.library functionality
//
var
  AOS_ExecBase  : Pointer = nil;

type
  IPTR      = NativeUInt;
  ULONG     = LongWord;
  STRPTR    = PChar;

  PLibrary  = Pointer;

  function  AvailMem(Requirements: ULONG): ULONG;                           syscall AOS_ExecBase   36*8;
  function  OpenLibrary(const LibName: STRPTR; Version: ULONG): pLibrary;   syscall AOS_ExecBase   92*8;
  procedure CloseLibrary(LibBase: pLibrary);                                syscall AOS_ExecBase   69*8;

//
//  utility.library functionality
//
type
  Tag       = ULONG;
  PTag      = ^Tag;

  PTagItem  = ^TTagItem;
  TTagItem  =
  record
    ti_Tag  : Tag;
    ti_Data : IPTR;
  end;
  PPTagItem = ^PTagItem;

const
  TAG_DONE  = 0;
  TAG_END   = TAG_DONE;

  TAG_USER  = DWord(1 shl 31);  // differentiates user tags from system tags

//
//  intuition.library functionality
//
var
  IntuitionBase   : pLibrary;

const
  // some window flags to play with
  WA_Dummy        = TAG_USER + 99; { $80000063   }
  WA_Left         = WA_Dummy + 1;
  WA_Top          = WA_Dummy + 2;
  WA_Width        = WA_Dummy + 3;
  WA_Height       = WA_Dummy + 4;
  WA_DetailPen    = WA_Dummy + 5;
  WA_BlockPen     = WA_Dummy + 6;
  WA_IDCMP        = WA_Dummy + 7;
  WA_Flags        = WA_Dummy + 8;
  WA_Gadgets      = WA_Dummy + 9;
  WA_Checkmark    = WA_Dummy + 10;
  WA_Title        = WA_Dummy + 11;
  WA_ScreenTitle  = WA_Dummy + 12;
  WA_CustomScreen = WA_Dummy + 13;
  WA_SuperBitMap  = WA_Dummy + 14;
  WA_MinWidth     = WA_Dummy + 15;
  WA_MinHeight    = WA_Dummy + 16;
  WA_MaxWidth     = WA_Dummy + 17;
  WA_MaxHeight    = WA_Dummy + 18;
  WA_InnerWidth   = WA_Dummy + 19;
  WA_InnerHeight  = WA_Dummy + 20;

type
  PNewWindow = Pointer;
  PWindow    = Pointer;

  function  OpenWindowTagList(NewWindow: pNewWindow; TagList: pTagItem): pWindow; syscall IntuitionBase 101*8;
  procedure CloseWindow(Window: pWindow);                                         syscall IntuitionBase  12*8;

  function OpenWindowTags(NewWindow: pNewWindow; const Tags: array of PtrUInt): pWindow;
  begin
    OpenWindowTags := OpenWindowTagList(NewWindow, @Tags);
  end;

//
//  AxRT Startup Entry
//
function __startup_entry(argstr: pchar; argsize: longint; SysBase: pointer): cint; cdecl;
var
  AxRT_Window: pWindow;
begin
  Result := 0;
  AOS_ExecBase := SysBase;

  writeln('Available memory : ', AvailMem(0));

  // open intuition library
  writeln('Opening intuition.library');
  IntuitionBase := OpenLibrary('intuition.library', 0);
  if assigned(IntuitionBase) then
  begin
    writeln('Intuition.library located at $', HexStr(IntuitionBase));

    // open intuition window
    writeln('Opening intuition window');
    AxRT_Window := OpenWindowTags(nil,
    [
      WA_Width , 640,
      WA_Height, 500,
      WA_Title , PtrUInt(PChar('FPC says hello to AxRT thanks to ALB42 and deadw00d')),
      TAG_DONE
    ]);
    if assigned(AxRT_Window)
    then writeln('Intuition window located at $', HexStr(AxRT_Window))
    else writeln('Unable to open intuition window');

    // wait for enter
    writeln('Press enter to continue');
    Readln;

    // close intuition window when required
    if assigned(AxRT_Window) then CloseWindow(AxRT_Window);

    // close intuition library
    writeln('Closing intuition.library');
    CloseLibrary(IntuitionBase);

  end
  else writeln('Unable to open intuition.library');
end;


//
// main pascal startup entry:
//
begin
  writeln('begin');

  // load dynlib libaxrt
  h_axrt := LoadLibrary(n_axrt);

  // if libaxrt loaded successfully
  if h_axrt <> NilHandle then
  begin
    writeln('loaded ax runtime library');

    // #######################

    writeln('retrieving libaxrt function pointers');

    funname := '__set_runtime_env';
    memlocation := GetProcedureAddress(h_axrt, funname);
    if assigned(memlocation) then  pointer(__set_runtime_env) := memlocation else writeln('unable to locate function ' + funname);

    funname := '__kick_start';
    memlocation := GetProcedureAddress(h_axrt, funname);
    if assigned(memlocation) then  pointer(__kick_start) := memlocation else writeln('unable to locate function ' + funname);

    // -> wrongfully assume previous code executed without problems <-

    writeln('set runtime environment');
    __set_runtime_env(RT_VER);

    writeln('kick start startup entry');
    __kick_start(@__startup_entry, RT_VER);

    // #######################

    if unloadlibrary(h_axrt)
      then writeln('unloaded ax runtime library')
    else writeln('failed unloading ax runtime library');
  end
  else writeln('failed to load ax runtime library');

  writeln('end');
end.

Picture of the above code running on AxRT 41.1 is attached.

That means that currently there remains two issues for me now:
1) What about the libaxrt:cannot open shared.... message ?
2) How to return to Pascal calll function after kickstart is executed so that FPC can free up it's used resources (managed types etc) and run it's shutdown code properly.

Actually for my development there are two other items as well:
1) fix the offset multiplier
2) can the FPC RTL 'switch' to support AxRT (instead of (only) Linux). e.g. native pascal calls would not (only) be made in the linux context but (also) the AxRT context.


magorium

  • Legendary Member
  • *****
    • Posts: 632
    • Karma: +62/-0
  • Convicted non contributor
Reply #31 on: March 16, 2022, 01:40:58 PM
I have a general question about FCP on x86_64 (Linux I guess). Which code model (small, medium, large) is the default for the FPC compiler?
afaik there is no provision for selecting different code models (for 64 bit targets) so i am therefor (very ignorantly) inclined to say that there is no default  :-[

I have no idea about the underlying reason why you asked, so is there need for you for a more precise/exact answer ?

Sorry for not sharing this. It is more related to AROS than to AxRuntime. AROS x86_64 assumes that large code model is used. Is small model is used, binaries will still work if user has less than 2GB of RAM. If user has more, then binaries will randomly crash depending on whether they were loaded below or above 2GB and there is no AROS-side control of where this happens.
Please don't apologise for my shortcomings  :)

It is that i didn't had the knowledge of the code-model concept that made me uncertain on how it impact things for AxRT/FPC. So thank you for the elaborating on  that topic. I seem to recall there is actually a memory limit within FPC but am currently not sure if that is only related to the memory model or also the code model.

Would that mean that whenever i would go overboard and try to play around and use more than 2Gb of memory that this can lead to issues ? Right now we can allocate memory twofold: either by using the linux api, or the AxRT api. I assume that AxRT would properly take care of itself in that regards ?


deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #32 on: March 16, 2022, 01:50:38 PM
That's a great window to see ^^

It really went much much easier that I expected :O

About issues you mentioned:

1) I still don't know where this is coming from :/
2) That's something I have to fix. Nothing you can do for now on Pascal side



deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #33 on: March 16, 2022, 01:54:50 PM
Would that mean that whenever i would go overboard and try to play around and use more than 2Gb of memory that this can lead to issues ? Right now we can allocate memory twofold: either by using the linux api, or the AxRT api. I assume that AxRT would properly take care of itself in that regards ?

Well, I just pushed changes that should make small code model executable behave in a predictable way when you have more than 2GB RAM on AROS.

About your question: the code models are related to code itself. It would indeed be a problem if your compiled binary be bigger that 2 GB, but having such big binaries is rather unlikely. As for dynamic allocation of memory (AllocMem & Co), I think you should be able to allocated memory blocks bigger than 2GBs on Ax though I never tried it.



magorium

  • Legendary Member
  • *****
    • Posts: 632
    • Karma: +62/-0
  • Convicted non contributor
Reply #34 on: March 16, 2022, 10:30:31 PM
That's a great window to see ^^
It is most definitely a start ;)

Quote
It really went much much easier that I expected :O
I was surprised about that myself as well  :o

I expected a bit more hurdles, especially with regards to my inexperience of messing with the FPC internals. However, (i am worried) there might be some skeletons hidden somewhere. Time will tell :ducks:

Fwiw: i could not have done it without the exceptional help, positive feedback and groundwork from you, ALB42 and Chain-Q.

Quote
About issues you mentioned:

1) I still don't know where this is coming from :/
I do not know your priorities so, please let me know when/if you wish to persue (if at all).

Although i have switched to Linux, i am not very proficient with the linux counterparts of some of the debugging utilities that i used to use on Windows.

I can f.e. provide a ltrace log but, i was unable to make heads nor tails out of it myself (showing off my inexperience here :) ). Perhaps there are better tools for debugging such things ?

Quote
2) That's something I have to fix. Nothing you can do for now on Pascal side
Understood. I'll work around things for the moment. I am just not sure how it affects the host (if at all).

Note to self:
- show dependencies: https://www.simplified.guide/linux/show-shared-library-dependency
- dynamically loaded libraries from exe: https://unix.stackexchange.com/questions/120015/how-to-find-out-the-dynamic-libraries-executables-loads-when-run


deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #35 on: March 17, 2022, 12:09:51 AM
@magorium

1) is not a high priority for me. If you can send me an executable that triggers this, I will eventually try to trace it.



deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #36 on: March 17, 2022, 01:35:10 AM
@magorium

I have a question related to FCP on AROS this time. As mentioned in another thread I added support for small code model, but FCP programs still crash when memory is allocated from > 2GB. I tested MCAmiga and Leu and they both crash in the same place during initialization.

Here is stack trace:

Code: [Select]
#0  0x0000000060132003 in Dos_16_DupLock (lock=0xffffffffefd28af0) at /ssd/deadwood/repo-github-dd-core/AROS/rom/dos/./duplock.c:54
#1  0x000000006013cee0 in __inline_Dos_DupLock (__arg1=0xffffffffefd28af0, __DOSBase=0x7fffef71e3b0)
    at /ssd/deadwood/repo-github-dd-core/core-linux-x86_64-d/bin/linux-x86_64/gen/rom/dos/dos/include/inline/dos.h:196
#2  0x000000006013cfce in Dos_67_NameFromLock (lock=0xffffffffefd28af0, buffer=0x7fffeff90a20 "", length=255)
    at /ssd/deadwood/repo-github-dd-core/AROS/rom/dos/./namefromlock.c:78
#3  0x00000000413db6a5 in SYSTEM_$$_GETWBARG$SMALLINT$$SHORTSTRING ()
#4  0x00000000413dbfd4 in SYSTEM_$$_PARAMSTR$LONGINT$$SHORTSTRING ()
#5  0x00000000413db85a in SYSTEM_$$_GENERATEARGS ()
#6  0x00000000413dc607 in SYSTEM_$$_init$ ()
#7  0x00000000413d5083 in fpc_initializeunits ()
#8  0x00000000413c64a9 in main ()
#9  0x00000000413c1ca1 in SI_PRC_$$_PASCALMAINENTRY ()
#10 0x000000006000cffe in Exec_134_NewStackSwap (sss=0x7fffefd52ea8, entry=0x6000d460 <Exec_20_Disable>, args=0x41002830)

Look at the address of lock argument. It is completely out of memory range. It looks like it was sign-extended from 32-bit value. Is it possible that FCP uses 32-bit BPTRs (and maps them to signed int) under 64-bit AROS? How to report this issue?

EDIT: you cannot easily trigger this issues in current public release of AROS x86_64 ABIv11. If needed I will prepare a version of AROS for testing.
« Last Edit: March 17, 2022, 01:42:15 AM by deadwood »



magorium

  • Legendary Member
  • *****
    • Posts: 632
    • Karma: +62/-0
  • Convicted non contributor
Reply #37 on: March 17, 2022, 07:42:55 AM
@magorium
Thank you for reporting your issue.

Quote
How to report this issue?

OK, i do believe there is need to elaborate there a little.

Usually, the very official way, would be to report such issues to the official Free Pascal Compiler repo here https://gitlab.com/freepascal.org/fpc/source/-/issues?sort=created_date&state=opened.

However, (and that is not blaming anyone) it isn't a priority there as AROS is a niche (they simply have larger fish to fry). Going that route usually means ALB42 and/or Chain-Q are the people actually spending time on fixing the issue.

Besides that you seem to have an issue with a particular program. It would need to be dissected and reproduced in a generic manner before able to report at the official channel there.

Whenever i run into issues i normally contact ALB42 directly (usually by IRC in the weekends or whenever he is around), or very rarely (depends on the issue) directly to Chain-Q. I am able to reach them by other means as well, in case necessary.

The above might be tiresome to do so for you, that i understand.

So, mentioning it here on AE forums at the Free Pascal Compiler forum (or as you did right now but, i might miss it in generic forums) at least has my attention (i am still not 100% sure if ALB42 keeps an eye on it) and i will forward the issue for you (or i'll try to fix the issue myself and/or try to get it fixed upstream).

Luckily, you mention specific programs from ALB42. To get his direct attention (usually the quickest):
- MCAmiga: https://github.com/alb42/MCAmiga
- MUIMapparium: https://github.com/alb42/MUIMapparium
- Leu: https://github.com/alb42/Leu

ALB42 also has a blog, mentioning all his programs here https://blog.alb42.de/

You can always leave a message there at the corresponding sub-page for a specific program or just make a remark in general there. It gets noted there as well.

fwiw: ALB42 is one of the official maintainers of FPC together with Chain-Q, that have a genuine interest for supporting AROS/Amiga/MorphOS.

I'm currently occupied with other things but i'll have a look at your issue this evening and see if i am able to figure out what is going wrong there. Your own suggested cause most probably being the culprit.

Feel free to report it somewhere else as mentioned in this post though. Whatever the case I'll get back to you.

PS: the AxRT support for FPC is currently completely my thing and is definitely not officially supported (if ever). I'll have to think about how i want to continue with that. For now i have to prepare patches against the official repo so the AxRT syscall support can be added if someone wishes to do so.
« Last Edit: March 17, 2022, 08:01:55 AM by magorium »



magorium

  • Legendary Member
  • *****
    • Posts: 632
    • Karma: +62/-0
  • Convicted non contributor
Reply #38 on: March 17, 2022, 08:41:27 AM
Look at the address of lock argument. It is completely out of memory range. It looks like it was sign-extended from 32-bit value. Is it possible that FCP uses 32-bit BPTRs (and maps them to signed int) under 64-bit AROS? How to report this issue?
TeaTime   ;D

Looking at the backtrace, it seems to crash immediately on startup when trying to retrieve the wb startup message.

This is done in the system unit for AROS. I see no special case for 64 bit, so the WBArg structure would then look like::
Code: [Select]
    PWBArg = ^TWBArg;
    TWBArg = record
        wa_Lock         : LongInt;      { a lock descriptor }
        wa_Name         : PChar;       { a string relative to that lock }
    end;
So, indeed wa_lock is defined as Longint which, looking at it with a quick glance over the code, seems to be the culprit there.

Note that i do not have experience with 64 bit AROS whatsoever, so my immediate question would be, has a BPTR for 64 bit platforms become a 64 bit sized entry ?

If indeed the culprit then it is located at the aros system unit though so it would require upstream fixing.

Quote
EDIT: you cannot easily trigger this issues in current public release of AROS x86_64 ABIv11. If needed I will prepare a version of AROS for testing.
If you are able to tell me the requirements that triggers this issue then i can check that (preferably in a small isolated example) for you as well.

My cookie went all soft and mushy now. Bye.


deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #39 on: March 17, 2022, 11:33:09 AM
@magorium

Thanks for taking this up. Yes, BPTR is essentially an pointer size type on any AROS platform than m68k. On m68k its a 32 bit integer, so for 64-bit AROS it should be 64-bit unsigned.

I'll prepare a development version of ABIv11 later today for you to test these things.



deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #40 on: March 17, 2022, 11:57:52 AM
@magorium

Here is a test package:

https://axrt.org/development/AROS-20220317-1-linux-x86_64-system.tar.bz2

Scenario OK:
1. $ ./boot/linux/AROSBootstrap -m 480
2. Start Leu

Scenario FAIL:
1. $ ./boot/linux/AROSBootstrap -m 640
2. Start Leu

Explanation: AROS will allocate first 512 MB RAM from 32-bit memory and the rest from 64-bit memory. 64-bit memory has priority.
In both scenarios, the code will be loaded into 32-bit memory assuming small code model. In first scenario heap will be in 32-bit range, in second it will be in 64-bit range.



magorium

  • Legendary Member
  • *****
    • Posts: 632
    • Karma: +62/-0
  • Convicted non contributor
Reply #41 on: March 17, 2022, 12:28:05 PM
@deadw00d:
Thank you.

It is confirmed. Even the smallest of example crashes for me now as well.

I can also answer the question if ALB42 is watching or not... see https://gitlab.com/freepascal.org/fpc/source/-/commit/729d920ed3f96c09ef015303d656455efdb078a6

So, it should be fixed now. I'll try to confirm later this evening. It might take a while for ALB42 to update his programs though.

Thank you for reporting !


deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #42 on: March 17, 2022, 12:39:03 PM
Wow, that was fast. Looking forward to refreshed programs :)



magorium

  • Legendary Member
  • *****
    • Posts: 632
    • Karma: +62/-0
  • Convicted non contributor
Reply #43 on: March 17, 2022, 01:08:48 PM
There are some coders around in amiga land (i do not name names) :p that say they are the fastest in programming business but i highly doubt they are faster than ALB42 :ducks:

ALB42 already updated his online compiler, here http://home.alb42.de/fpamiga/

You can use the helloworld example (that crashed before the fix as well), select AROS x64 ABIv1 and compile. It will produce an executable for you that you can download and test.



deadwood

  • AROS Developer
  • Legendary Member
  • *****
    • Posts: 1524
    • Karma: +118/-0
Reply #44 on: March 17, 2022, 02:39:57 PM
That's a handy website :) Indeed programs now work correctly  ;D