1
votes

I'm trying to compile Beebdroid for my Android phone (to fix a Bluetooth keyboard weirdness). I'm hitting a problem with the linker complaining about the text segment being unsharable:

arm-linux-androideabi/bin/ld: warning: shared library text segment is not shareable

I'm only familiar with segments in principle, and haven't encountered this before. I see -fPIC is already on the x86 branches in the makefile, and it seems unlikely ARM would need it with its easy PC-relative addressing, but I added it to the ARM flags anyway to no avail, so I'm presuming it's not the C code.

This leads me to assume it's the assembly code that's triggering the error.

https://github.com/littlefluffytoys/Beebdroid/blob/master/app/src/main/jni/6502asm_arm.S

It does say .text early in the assembly file, but I looked at the clang assembler guide at infocentre.arm.com and the only executable segments I could substitute are 'init' and 'fini', neither of which look like a good idea.

Is the assembler spotting some dodgy code in the assembly, and marking the text segment as unshareable, to make the linker explode? There's no warning to that effect.

There is a look-up table indexed by 6502 op-codes to find implementing routines:

@ Get the ASM function. If this doesnt exist, fall back to C version.
adr   r1, fns_asm    // previously ldr r1, =fns_asm
ldr   r2, [ r1,  r0, lsl #2]
cmp   r2, #0
beq  use_c_fn

@ Call assembly function
blx  r2
b done_call

I already changed the ldr to an adr, and moved the function closer to the table so it was within range, and I'm expecting to have to get the assembler to make the table relative, and add the PC before I do the jump, but I was kinda hoping to get a successful compile before I start trying to puzzle the details of that out.

There are plenty of macros, but the only directives I can see are .text, .global exec6502, and an .ltorg, none of which look like they should be causing a problem.

Is it choking on the table itself? Do I have to subtract another label from each of the routine labels, so the assembler understands they're relative? Seems... a bit sophisticated.

Is there even an assembler version of -fPIC I need to supply?

Thanks for any pointers.


Edit: I've just noticed there are some more ldr Rx,= instructions - two related to labels defined elsewhere, and one (I think) to absolute address 40000. Looks like I need to ask how to get C labels from assembler in a PIC-compatible way!

Edit 2: I think I can just add function pointer fields to the CPU register structure, which I'll pass to the code in r0 (instead of using acpu) and keep in r4 as the current code is.

1
There are some alternate ways here. As well, it might want stack annotations in the assembler. See: GAS Arm Unwinding. Why exactly do you need an 6502 emulator to fix a blue tooth problem? Maybe you can just stub out the assembler?artless noise
@artlessnoise thanks for this. I can't just re-use the library from the APK because the Android toolset made a breaking change and no longer supports non-PIC libraries, so I can't patch the Java to fix the keyboard without either a new library or retrieving the legacy toolset and remembering how to use it. Stubbing the assembler would be quite a lot of detailed work, and comments in the code make it look like it would cause huge slow-down. (I suppose in the worst case I could check back in time through the repo to see whether the C code for it is still there.)android.weasel
I assembled with a listing and I think that ldr %r4, =acpu and ldr %r1, =fns are problematic. I believe you need a GOT to access these. You can remove the lines to see if it builds. Then you need to figure a way to put them back to make the code work. I also think you are correct about the table. You need fns_asm: .word fns_asm - opasm_ora_indzx ... Then you will sub the table lookup to the fns_asm address loaded at run time. Like, @ Call assembly function\n sub %r2, %r1, %r2\n blx %r2.artless noise
The whole table fns_asm needs to be converted from an address to an offset. Ie, subtract a common address from the table entries. Then reverse that at run time. This table can be used for jump threading by changing 'RETURN' to look up the next instruction.artless noise
@artlessnoise thanks for going to that trouble for me! I'm turning the acpu into a parameter to exec6502 and adding the fns_c to the acpu structure. (I don't need to worry about the bl sbc_bcd and similar, do I - the linker will magic that? I'm used to the BBC Basic assembler which had no linker at all.) The table is already sort-of offset: I have its base address and can compute it on the fly for a first stab. But yes, I'll replace its entries with macros that do maths, and look for more efficiencies as the need arises.android.weasel

1 Answers

0
votes

The problem was a combination of the ldr r1, =c_symbol instructions and the table of .word assembler_label entries.

It was enough to move some code nearer to the table, to allow me to replace ldr r1, =fns_asm with adr r1, fns_asm and (as @Artlessnoise said) search/replace the table into computed offsets:

fns_asm:
    .word 0                 // 0x00 BRK
    .word 0 - fns_asm + opasm_ora_indzx     // 0x01 ORA (,x)
    .word 0 - fns_asm + opasm_undef
...and so on

because it turns out that it was the raw symbols making the linker unhappy. I had thought just to use it as if it were .word 0 + opasm_ora_indzx and do the subtraction at run-time, but this worked:

@ Get the ASM function. If this doesnt exist, fall back to C version.
adr   r1, fns_asm
ldr   r2, [ r1,  r0, lsl #2] // = fns_asm[ op * 4 ]
cmp   r2, #0
beq  use_c_fn

@ Call assembly function
add  r2, r2, r1  // 0 - fns_asm + asy_func + fns_asm
blx  r2 // Call assembly function
b done_call

I should tidy up the table, but the 0 - x + y nonsense was the easiest search-replace for all 256 entries.

Now it's compiling and running for ARM, I can try to fix the parts of the main application I was actually concerned about.