C stubs questions
Fred Graute (114) 627 posts |
In my ongoing efforts to improve StrongED’s Dump mode (ie bring it closer to Zap’s) I’ve added annotation of embedded function names, annotation of calls to such functions as well as annotation of calls to the SharedC library. This is working fine for Absolute files (either loaded or grabbed) and grabbed modules. Loaded modules however have an issue; it seems they use a base address <> &0. The modules I’ve tried all used &8000 as base address. Is that something that can be relied upon? If not, is the base address stored in the module somewhere? And can it be extracted (easily)? Also, what’s the highest defined chunk number? The highest I’ve seen so far is 4. With the exact number I can tighten up the sanity checks. |
Rick Murray (539) 13401 posts |
I think that’s just a bogus value – the correct base address would be put in place when the module is loaded. I’m guessing the base address is the second word passed via R3 to the LibInitModuleAPCS_32 SWI? I’ve looked at three random modules, and there’s &8000 there in each.
There is no base address. The base is where the OS loads the module. Somewhere in the init code, that value will be fixed up. Sadly the stuff CMHG generates is not available as source so it’s a bit black-boxy. However, I think the GCC version can output source which might help you see what’s going on as a C module starts up.
Define “chunk number”. SWI chunk? Error chunk? |
Fred Graute (114) 627 posts |
It can’t be completely bogus though as it’s applied to the addresses in each library chunk in the list of stub descriptions that is passed in r0 to SharedCLibrary_LibInitModule(APCS_32). As an example I’ve loaded RComp’s SafeStore module which runs from &0 – &384C. Its list of stub descriptions is at offset &2D00, and looks like this:
As you can see all the addresses are outside of the module (which ends at &384C). If I subtract &8000 then the addresses are correct, ie the first chunk starts at &2D64.
I only have the documentation for LibInitModule SWI to hand and it says that r3 points to the area to be zero-initialised. In the SafeStore module it’s pointing to &B650 so &3650 if you take off &8000 (which matches the offset if you grab the module from memory). It looks like the base address is passed to _kernel_moduleinit via the kernel init block in r0.
The library chunk ID as in the example above. The highest I’ve seen is 4 but Zap also mentions a chunk ID of 5. I use it as an additional sanity check to verify a valid list of stub descriptions has been found (currently I use a maximum of 9). The main sanity checks are to make sure the entry vector base & limit addresses are inside the file and that each chunk has only one type of instruction in it. |
Jeffrey Lee (213) 6046 posts |
Modules generally contain a relocation function which is generated by the linker ( |
Fred Graute (114) 627 posts |
Thanks. Does mean though that I’ll need to scan the file to find the base address.
Had a look at vncserv and it too passes the base address (at +0 in the block pointed to by r0) to _kernel_moduleinit. Is that something that can be relied upon? If so, that’d be great even though I had hoped to avoid further scanning of the code. |
Colin Ferris (399) 1748 posts |
Just a matter of interest – do the ‘C’ modules really need the 2x size jump table? Is the jump table out of range of Branch ‘B xxxx’? – since both are in the module area. Is there a 32bit memory map available? Has anyone had thoughts about making a swi ‘C’ jump table module – making it possible to use the same 26bit jmp space in a App program. (some 26bit progs are cramped for extra space) |
Jeffrey Lee (213) 6046 posts |
Interestingly _kernel_moduleinit seems to ignore the first word of the block – so you may find that the contents of that word differs depending on what flavour of stubs are in use (standard Acorn/ROOL, GCC, StubsG, etc.) https://www.riscosopen.org/viewer/view/castle/RiscOS/Sources/Lib/RISC_OSLib/kernel/s/k_body?rev=4.34#l199 (note use of LDMIB)
The RMA has a max size of 256MB on RISC OS 5. And if CLib is in ROM then it will be over 512MB away from the client module (RMA is currently based at address 512MB).
There’s no official one – we don’t want people hard-coding addresses into programs. Kernel.hdr.KernelWS defines the addresses of various locations that are fixed at build time, but they are liable to change between different OS versions (e.g. I rearranged things a bit when I introduced the PMP support). If a program needs to know the address of one of those areas then it’s generally exposed via OS_Memory 16 or OS_ReadSysInfo 6
That would be a bit tricky to get to work – some of the calls will need access to R10-R13 (and maybe R14?), e.g. printf needs to know R13 so it can read any values from the stack. And there are some functions which call back into the application (e.g. qsort and bsearch) |
Colin Ferris (399) 1748 posts |
Space is bit of a problem with 32 bitting ‘Eureka’ – overlays add to the fun. What is the bare minimum you can get away with the 32bit stubs – just the 2x jump tables? |
Fred Graute (114) 627 posts |
That indeed seems to be the case. Different tack needed so I’ve done as you suggested and added some code the identify the relocation function and obtain the base address from there. Had to make a few assumptions so it’s not as robust as I would have liked but it seems to work. |
Fred Graute (114) 627 posts |
If anyone wants to try this out, a new test release of StrongED (4.70a12) has been made available on the StrongED website (go to the download section and click on test release). |
Fred Graute (114) 627 posts |
Been doing some more work on annotating calls to the SharedCLibrary, this time for direct branches from ROM modules. This required me to dive a bit deeper into SharedCLib and it seems that currently there are 5 chunks defined. The names of the functions in chunk 1 & 2 (bar swi and swix) are described in the RO3 PRM. The function names for chunks 4 & 5 chunks can be (partially) found in Zap(!). For the remaining functions – chunk 3 (completely) and chunk 5 (partly) – no function names seem to be available publicly. I’d really appreciate it if someone could point me to, or provide me with, a complete list of CLib function names so that I can finish off this part of StrongED’s Dump mode. TIA |
Jeffrey Lee (213) 6046 posts |
The relevant source files are:
|
Rick Murray (539) 13401 posts |
This ought to be fixed in Zap too, but I don’t see what’s going wrong – but it provides some really odd results so…it ain’t right. :-( |
Fred Graute (114) 627 posts |
Thanks for the pointers, Jeffrey. I’ll go through these files to try and build up a complete list annotations for clib calls.
The output of the original Zap 1.47 seemed okay to me last I looked at it. Later versions, those adapted to modern hardware, get it wrong so it’s most likely that a bug was introduced somewhere. I haven’t fully looked into it but my impression at the time was that a divide by 4 had gone missing. The code first figures out the offset (in words) of the clib call relative to the start of a chunk. This is then divided by 4 to get the call’s index in the chunk. The chunk number + index are then used to find the annotation for that call (the full list can be found in ZapSource.data.clib_names). Using the FTPc (v1.51) RunImage as an example, the clib call at &80A8 is annotated in Zap as: |
Fred Graute (114) 627 posts |
Done that and tested against the Avalanche !RunImage (uses chunks 1,2,4,5) and the !Edit module from ROM (uses rlib and hence chunk 3) and it all looks good. :-)
Had a look at the Zap source and the bug is in this bit of code inside Mode4dis:
The commented out instruction at the top is original and may load from an unaligned address, the code below it is a fix to avoid an unaligned load. There is a typo in it though, the Arrgh, I’m fixing Zap bugs now… |
Rick Murray (539) 13401 posts |
Thanks! I’ll get that tweaked in the source I have.
Where would the fun be if you didn’t have any competition? :-) Thanks again. |
Steve Pampling (1551) 7931 posts |
So we actually need to have RO4.3x and RO5 to have different API’s then? :^) Good job Nemo’s not around at the moment… |
Rick Murray (539) 13401 posts |
Don’t they? ;-) |
Steve Pampling (1551) 7931 posts |
Edited: 4.3x of course |
Rick Murray (539) 13401 posts |
Zap updated to version 1.49 rick-06. I’ll do an update for !Store RealSoonNow™. For those impatient – http://heyrick.ddns.net/files/zapfix06.zip It’s just the Zap module. Stuff it into !Zap.Code and you’re good to go. Changelog: 2019/05/03 rick-06 Tiny tweak to the code that looks up CLib function names while doing a disassembly of C code. A shift was being applied the wrong way around so the function names returned were not the ones we actually wanted! Fix supplied by Fred Graute. Yes. The person responsible for The Competition. Fixed Zap. Because he's just that awesome. |