Open biggestsonicfan opened 4 years ago
Apparently, the NINDY gives the same error regardless of what (or even IF a) COFF executable is loaded. This could indicate something is wrong with the xmodem transfer, hmm...
Stepping through program execution by setting a breakpoint and stepping through it seems to work? Perhaps there's something wrong with the "go" command?
Copying and pasting information from the manual here for easier reference:
Make sure you have run the INIT.bat file to copy all of the LIB and CRT files to their respective places in the I960BASE directory. Provided with the NINDY source is a file “hello.c” which is a basic “hello world” program with the benchmark timer turned on. The benchmark timing is included as an example of how to time programs (normally you would not be timing the I/O for accurate results). It is also included to illustrate how to compile using all of the NINDY libraries. If you can get a program which prints a message to compile and run, you have 90% of the pieces working together. If you get timing working also, you have about 99% of everything working together.
To compile “hello.c” for RAM using KB architecture on the QT960 board:
ic960 -Tqtnindy -AKB -02 -o hello hello.c -lqt
This command line tells the compiler to use the “qtnindy.ld” file found in the I960BASE\LIB directory for linker directives (-Tqtnindy), to compile it for the KB architecture (-AKB -this is the default if omitted), to use optimizations where possible (-O2), to rename the output “hello” (-o hello), and to link in the library “libqt.a” found in the I960BASE\LIB directory (-Iqt). If the benchmark timing is not desired, the -Iqt switch may be omitted and the timing related code commented out. The “qtnindy.Id” file automatically links in “crtnin.0” and “libnin.a" from the I960BASE\LIB directory.
The manual states go [<address>]
is how to execute code in NINDY, however within the code itself, it looks like go
takes multiple arguments go( step_flag, nargs, addr )
. I am unsure what this means, however.
The 'st' command works fine. It looks like I'm going to have to literally debug this issue at the disassembly level by stepping through the hello
program to see where the Operation Fault occurs. Not fun times.
Actually, debugging turned out to be fairly simple after tracing the main routine back a little ways in IDA Pro:
.text:08000024 loop: # CODE XREF: start+30↓j
.text:08000024 mov g0, g0
.text:08000028 st r6, (r5)
.text:0800002C addo 4, r5, r5
.text:08000030 cmpobl r5, r4, loop
.text:08000034 lda 0x8005AD4, sp
.text:0800003C lda 0x2000(sp), sp
.text:08000044 lda 0x40(sp), sp
.text:08000048 lda 0xFFFFFFC0, r12
.text:08000050 and r12, sp, sp # <- CRASHES HERE
.text:08000054 st sp, _stack_start
.text:0800005C call init_frames
.text:08000060 ret
So something's not right here. I'm not sure where that value comes from. Though the lda 0x2000(sp), sp
looks suspiciously like it's loading the heap_size
into the stack pointer.
EDIT: The code is literally right here in crtnin.s
.
Is ldconst
being interpreted as lda
at compile time? That'd be super strange...
EDIT2: From the i960 Processor Assembler User's Guide Chapter 8:
Pseudo-instructions appear in the assembly file like valid machine instructions. In actuality, the assembler substitutes one or more machine-level instructions for them. For example, when you enter the optimized load constant or
ldconst
, the assembler selects the fastest instruction available to place the specified value in the designated register.This instruction can be a move, add, subtract, shift, or load-address,depending on the given value.
EDIT3: Register dump prior to crash:
g0 : 08000000 g1 : 0000000d g2 : 08000048 g3 : 2800000c
g4 : ffffffff g5 : 000088b0 g6 : 00006f00 g7 : 000088b0
g8 : 00000000 g9 : 00000000 g10: 00000000 g11: 00000000
g12: 0801c300 g13: 00000020 g14: 00000000 fp : 0801c9c0
pfp: 0801c980 sp : 08007b14 rip: 08000050 r3 : 0000000d
r4 : 08005ad4 r5 : 08005ad4 r6 : 00000000 r7 : 00000001
r8 : 0000000c r9 : 08005420 r10: 00000000 r11: 00000000
r12: ffffffc0 r13: 0000000c r14: fffffffc r15: 0000000d
pc : 001f0003 ac : 3b101002 tc : 00800080 ip : 08000050
fp0:0.000000e 0
fp1:0.000000e 0
fp2:0.101730e0
fp3:1.000000e1
Perhaps it's crashing because of the definition of _end
?
It's interesting that the crash is at an and operation. The faults able to be generated by 'and' are the normal set. The ldconst is attempting to align sp.
Decoding the operation fault record it looks like the jump to address zero with the error subtype being "INVALID_OPCODE". Even if sp gets corrupted, it won't affect the pfp so the return call should cause the previous frame to be restored.
Something is jumping to zero. The stack is setup properly since the fault record is stored there. While the size and alignment are implementation dependent the codes are consistent.
The heap may be messing with things but the jump to address zero is the culprit. Makes me wonder if there is a routine which is defaulting to address zero when it shouldn't. These are guesses on the cause though.
Let's say, for testing purposes, I replace and r12, sp, sp
with lda 0x8007B00, sp
. I choose 0x8007B00
because if you logical AND
0xFFFFFFC0
and 0x08007b14
, that is the result. The program will progress all the way to the following:
.text:08003660 # int isatty(int)
.text:08003660 .global _isatty
.text:08003660 _isatty: # CODE XREF: __stdio_init+A0↑p
.text:08003660 # __stdio_init+108↑p
.text:08003660 addo 0x10, sp, sp # ___gnu_compiled_c_21
.text:08003664 lda 0x40(fp), g1
.text:08003668 lda 0xEB, g13
.text:0800366C calls g13 # <- CRASHES AFTER THIS
.text:08003670 cmpi g0, 0
.text:08003674 mov g0, r4
.text:08003678 be loc_800368C
.text:0800367C bal _errno_ptr_lf
.text:08003680 st r4, (g0)
.text:08003684 subo 1, 0, g0
.text:08003688 ret
The resultant error:
Operation fault at: 00000000
Fault record is on stack at 0801c9d0:
fdata : 00000000 00000000 00000203
fsubtype 01: fflags : 00
And register dump:
g0 : 00000001 g1 : 08007c80 g2 : 08003668 g3 : 2800000c
g4 : 08005a40 g5 : ffffffff g6 : 08005f0f g7 : 08007aff
g8 : 00000000 g9 : 00000000 g10: 00000000 g11: 00000000
g12: 0801c300 g13: 000000eb g14: 00000000 fp : 08007c40
pfp: 08007bc0 sp : 08007c90 rip: 0800366c r3 : 0000000d
r4 : 00000000 r5 : 00000400 r6 : ffffffff r7 : 00000001
r8 : acdbadcb r9 : ffffffff r10: 00001910 r11: 00000400
r12: 00000000 r13: 00000000 r14: 00007bd4 r15: 00000020
pc : 001f0003 ac : 3b101001 tc : 00800080 ip : 0800366c
fp0:0.000000e 0
fp1:0.000000e 0
fp2:0.101730e0
fp3:1.000000e1
that's a supervisor call to procedure number 0xEB. Interestingly enough, the SPT where the cpu jumps to doesn't seem to have that many entries. I'm looking at the KB programmers guide but I found the SPT here:
What's interesting is that I can't find why it's doing that based on the source code within isatty.c
. Unless I'm not interpreting it properly.
isatty.c targets mon960 and that's why you see the calls:
https://github.com/DrItanium/i960/blob/master/src/gnu960/src/mon960/common/sdm.h#L90.
It seems that libll is mon960 specific. You'll have to see if you can't build using libnin instead. It would also explain the random crashes
Ah, that brings us full circle now to issue #4
Alright, back to the drawing board.
EDIT: What source files would I need to compile and include in libnin to satisfy the __LL_init
, __errno_pt
, and _isatty
unidentified reference errors, hmmm...
Well, I removed all unreferenced errors by removing their references and AT LEAST I get hello.c
to output something on serial:
This line executes! Hurrah! Now obviously removing all of these would not be production ideal, but I am simply testing here, and yes, we do get output now. Now to figure out why we are getting nope on malloc.
EDIT: IDA Pro really doesn't like the COFF executable I've produced and crashes each time I load it. Hmm.
.text:08000560 _malloc: # CODE XREF: _main+18↑p
.text:08000560 # _realloc+10↓j ...
.text:08000560 cmpibne 0, g0, loc_800056C # ___gnu_compiled_c_4
.text:08000564
.text:08000564 loc_8000564: # CODE XREF: _malloc+FC↓j
.text:08000564 # _malloc:loc_80006F8↓j
.text:08000564 mov 0, g0
.text:08000568 ret
.text:0800056C # ---------------------------------------------------------------------------
.text:0800056C
.text:0800056C loc_800056C: # CODE XREF: _malloc↑j
.text:0800056C ld __free_list, r4
.text:08000574 addo g0, 0xF, g0
.text:08000578 mov 0, g5
.text:0800057C cmpi r4, 0
.text:08000580 notand g0, 0xF, r5
.text:08000584 be loc_800059C
.text:08000588
.text:08000588 loc_8000588: # CODE XREF: _malloc+38↓j
.text:08000588 ld 0xC(r4), g4
.text:0800058C cmpobge g4, r5, loc_800059C
.text:08000590 mov r4, g5
.text:08000594 ld 4(r4), r4
.text:08000598 cmpibne 0, r4, loc_8000588
.text:0800059C
.text:0800059C loc_800059C: # CODE XREF: _malloc+24↑j
.text:0800059C # _malloc+2C↑j
.text:0800059C cmpibe 0, r4, loc_80005F0
.text:080005A0 cmpi g5, 0
.text:080005A4 ld 4(r4), g4
.text:080005A8 mov g0, g0
.text:080005AC bne loc_80005BC
.text:080005B0 st g4, __free_list
.text:080005B8 b loc_80005C0
.text:080005BC # ---------------------------------------------------------------------------
.text:080005BC
.text:080005BC loc_80005BC: # CODE XREF: _malloc+4C↑j
.text:080005BC st g4, 4(g5)
.text:080005C0
.text:080005C0 loc_80005C0: # CODE XREF: _malloc+58↑j
.text:080005C0 ld 0xC(r4), g4
.text:080005C4 lda 0xFFFFFFFF, g6
.text:080005CC lda 0x20(r5), g5
.text:080005D0 cmpo g4, g5
.text:080005D4 st g6, 4(r4)
.text:080005D8 mov g0, g0
.text:080005DC bl loc_80005E8
.text:080005E0 movl r4, g0
.text:080005E4 call __Lsplit_block
.text:080005E8
.text:080005E8 loc_80005E8: # CODE XREF: _malloc+7C↑j
.text:080005E8 addo r4, 0x10, g0
.text:080005EC ret
.text:080005F0 # ---------------------------------------------------------------------------
.text:080005F0
.text:080005F0 loc_80005F0: # CODE XREF: _malloc:loc_800059C↑j
.text:080005F0 ld __heap_end, g5
.text:080005F8 cmpibe 0, g5, loc_80006A8
.text:080005FC ld 4(g5), g4
.text:08000600 lda 0xFFFFFFFF, r4
.text:08000608 cmpibe g4, r4, loc_80006A8
.text:0800060C ld 0xC(g5), g4
.text:08000610 subo g4, r5, r5
.text:08000614 mov r5, g0
.text:08000618 call _sbrk
.text:0800061C cmpibe 0, g0, loc_80006F8
.text:08000620 cmpibe g0, r4, loc_80006F8
.text:08000624 ld __free_list, r4
.text:0800062C cmpi 0, r4
.text:08000630 mov 0, g5
.text:08000634 ld __heap_end, g4
.text:0800063C be loc_8000650
.text:08000640
.text:08000640 loc_8000640: # CODE XREF: _malloc+EC↓j
.text:08000640 cmpibe r4, g4, loc_8000650
.text:08000644 mov r4, g5
.text:08000648 ld 4(r4), r4
.text:0800064C cmpibne 0, r4, loc_8000640
.text:08000650
.text:08000650 loc_8000650: # CODE XREF: _malloc+DC↑j
.text:08000650 # _malloc:loc_8000640↑j
.text:08000650 cmpibne 0, r4, loc_8000660
.text:08000654 mov 4, g0
.text:08000658 call _raise
.text:0800065C b loc_8000564
.text:08000660 # ---------------------------------------------------------------------------
.text:08000660
.text:08000660 loc_8000660: # CODE XREF: _malloc:loc_8000650↑j
.text:08000660 cmpi g5, 0
.text:08000664 ld 4(r4), g4
.text:08000668 mov g0, g0
.text:0800066C bne loc_800067C
.text:08000670 st g4, __free_list
.text:08000678 b loc_8000680
.text:0800067C # ---------------------------------------------------------------------------
.text:0800067C
.text:0800067C loc_800067C: # CODE XREF: _malloc+10C↑j
.text:0800067C st g4, 4(g5)
.text:08000680
.text:08000680 loc_8000680: # CODE XREF: _malloc+118↑j
.text:08000680 ldq (r4), g4
.text:08000684 lda 0xFFFFFFFF, g5
.text:0800068C addo r5, g7, g1
.text:08000690 mov g1, g7
.text:08000694 addo r4, 0x10, g0
.text:08000698 stl g4, (r4)
.text:0800069C st g6, 8(r4)
.text:080006A0 st g1, 0xC(r4)
.text:080006A4 ret
.text:080006A8 # ---------------------------------------------------------------------------
.text:080006A8
.text:080006A8 loc_80006A8: # CODE XREF: _malloc+98↑j
.text:080006A8 # _malloc+A8↑j
.text:080006A8 addo r5, 0x10, g0
.text:080006AC call _sbrk
.text:080006B0 cmpibe 0, g0, loc_80006F8
.text:080006B4 lda 0xFFFFFFFF, g5
.text:080006BC cmpibe g0, g5, loc_80006F8
.text:080006C0 lda 0xACDBADCB, r8
.text:080006C8 st r5, 0xC(g0)
.text:080006CC mov g5, r9
.text:080006D0 mov r5, r11
.text:080006D4 st r8, (g0)
.text:080006D8 ld __heap_end, g4
.text:080006E0 st g5, 4(g0)
.text:080006E4 st g0, __heap_end
.text:080006EC st g4, 8(g0)
.text:080006F0 addo g0, 0x10, g0
.text:080006F4 ret
.text:080006F8 # ---------------------------------------------------------------------------
.text:080006F8
.text:080006F8 loc_80006F8: # CODE XREF: _malloc+BC↑j
.text:080006F8 # _malloc+C0↑j ...
.text:080006F8 b loc_8000564
.text:080006F8 # End of function _malloc
.text:080006F8
For some reason, my code is always falling through to 08000564
, returning 0 to malloc in main
.
EDIT1: Here is the registers with a breakpoint at 0800063C
. It looks like __free_list
is 0...
g0 : 08005980 g1 : 000000be g2 : 0800063c g3 : 2800000c
g4 : 08005570 g5 : 00000000 g6 : 00001388 g7 : 00001388
g8 : 00000000 g9 : 00000000 g10: 00000000 g11: 00000000
g12: 0801c300 g13: 0000c000 g14: 00000000 fp : 08007600
pfp: 080075c0 sp : 08007640 rip: 08000650 r3 : 000013b7
r4 : 00000000 r5 : 0000000f r6 : 0000139c r7 : 00000001
r8 : a92a3055 r9 : 4047e813 r10: 000013b7 r11: 00001388
r12: 2f05a709 r13: 3fba0afa r14: 000000be r15: 0000002a
pc : 001f0003 ac : 3b101002 tc : 00800080 ip : 08000650
fp0:0.000000e 0
fp1:0.000000e 0
fp2:0.101730e0
fp3:4.781310e1
The next instruction at 08000650
checks if r4 is not equal to 0, and of course that fails.
After connecting the board via serial and uploading
hello
over xmodem, attempting to run the program gives the following errorIt may be difficult to figure out what's going on but I believe it's important to understand how a successfully running compile would work using the NetBSD copy of CTOOLS.
It must be assumed because this
hello
program does not work, the compiled NINDY from source will not work either. It may have something to do with issue #5.