biggestsonicfan / i960-CTOOLS-with-NINDY

A repo in which i960 CTOOLS and NINDY are mirrored and a work in progress for binaries will be.
4 stars 2 forks source link

Fault when trying to run compiled `hello.c` program #6

Open biggestsonicfan opened 4 years ago

biggestsonicfan commented 4 years ago

After connecting the board via serial and uploading hello over xmodem, attempting to run the program gives the following error

␍ Operation fault at: 00000000␊
␍ Fault record is on stack at 0801c9d0: ␊
␍ fdata : 00000000 00000000 00000201␊
␍ fsubtype 01:     fflags : 00␊

It 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.

biggestsonicfan commented 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...

biggestsonicfan commented 4 years ago

Stepping through program execution by setting a breakpoint and stepping through it seems to work? Perhaps there's something wrong with the "go" command?

biggestsonicfan commented 4 years ago

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.

biggestsonicfan commented 4 years ago

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.

biggestsonicfan commented 4 years ago

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.

biggestsonicfan commented 4 years ago

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?

DrItanium commented 4 years ago

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.

biggestsonicfan commented 4 years ago

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
DrItanium commented 4 years ago

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:

https://github.com/cglmrfreeman/i960-CTOOLS-with-NINDY/blob/d24012627f70f65eb2b3e3fa53bce2ff63e4d3eb/nindy-src/kx/kx_init.s#L121

biggestsonicfan commented 4 years ago

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.

DrItanium commented 4 years ago

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

biggestsonicfan commented 4 years ago

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...

biggestsonicfan commented 4 years ago

Well, I removed all unreferenced errors by removing their references and AT LEAST I get hello.c to output something on serial:

https://github.com/cglmrfreeman/i960-CTOOLS-with-NINDY/blob/d24012627f70f65eb2b3e3fa53bce2ff63e4d3eb/nindy-src/hello.c#L8

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.

biggestsonicfan commented 4 years ago
.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.