1
votes

My goal is to run a compiled C code in my RISCV simlator. I have compiled a C code with RISCV32I (32bit) compiler and it output my code in ELF format (then i have selected .text section and used it in my RISC-V simulator). Perfect. Then, i tried to run that compiled code in my simulator, but i found that in in <__libc_init_array> function there is "some" code that will always jump to the adress 0 of my program, which i dont want, obviously.

Disassembly of my output file:

 000102ec <__libc_init_array>:
   102ec:   ff010113            addi    sp,sp,-16
   102f0:   00812423            sw  s0,8(sp)
   102f4:   01212023            sw  s2,0(sp)
   102f8:   00001417            auipc   s0,0x1
   102fc:   3c840413            addi    s0,s0,968 # 116c0 <__init_array_start>
   10300:   00001917            auipc   s2,0x1
   10304:   3c090913            addi    s2,s2,960 # 116c0 <__init_array_start>
   10308:   40890933            sub s2,s2,s0
   1030c:   00112623            sw  ra,12(sp)
   10310:   00912223            sw  s1,4(sp)
   10314:   40295913            srai    s2,s2,0x2
   10318:   00090e63            beqz    s2,10334 <__libc_init_array+0x48>
   1031c:   00000493            li  s1,0
   10320:   00042783            lw  a5,0(s0)
   10324:   00148493            addi    s1,s1,1
   10328:   00440413            addi    s0,s0,4
   1032c:   000780e7            jalr    a5
   10330:   fe9918e3            bne s2,s1,10320 <__libc_init_array+0x34>
   10334:   00001417            auipc   s0,0x1
   10338:   38c40413            addi    s0,s0,908 # 116c0 <__init_array_start>
   1033c:   00001917            auipc   s2,0x1
   10340:   38c90913            addi    s2,s2,908 # 116c8 <__init_array_end>
   10344:   40890933            sub s2,s2,s0
   10348:   40295913            srai    s2,s2,0x2
   1034c:   dbdff0ef            jal ra,10108 <_fini>
   10350:   00090e63            beqz    s2,1036c <__libc_init_array+0x80>
   10354:   00000493            li  s1,0
   10358:   00042783            lw  a5,0(s0)
   1035c:   00148493            addi    s1,s1,1
   10360:   00440413            addi    s0,s0,4
   10364:   000780e7            jalr    a5
   10368:   fe9918e3            bne s2,s1,10358 <__libc_init_array+0x6c>
   1036c:   00c12083            lw  ra,12(sp)
   10370:   00812403            lw  s0,8(sp)
   10374:   00412483            lw  s1,4(sp)
   10378:   00012903            lw  s2,0(sp)
   1037c:   01010113            addi    sp,sp,16
   10380:   00008067            ret

On the line 10350 we can find an comparison that if true, will jump over a few lines. But for some reason it is not true, so we must continue. And here it becomes interesting. The next instruction loads a 0 into register s1, fine, but the next one tries to load some value into reg a5 from address 0(s0). But the output of the read will be 0, because in the memory there is nothing. I could not find any reference to this specific address form start of this code (from _start). In fact, there is no attempt to write or read to that address at all apart from this function.

   10350:   00090e63            beqz    s2,1036c <__libc_init_array+0x80>
   10354:   00000493            li  s1,0
   10358:   00042783            lw  a5,0(s0)
   1035c:   00148493            addi    s1,s1,1
   10360:   00440413            addi    s0,s0,4
   10364:   000780e7            jalr    a5

Am i missing something? This is the last step before the program jumps to the main section so i do not want to go back to address 0.

Thanks for any help

EDIT

There is a dump of .init_array and .data, but I don't see how they can effect the value on the problematic address (there is even compressed instruction and some unknown FLD, both of these are unsupported by my simulator).

Disassembly of section .init_array:

000116c0 <__init_array_start>:
   116c0:   00ac                    addi    a1,sp,72
   116c2:   0001                    nop

000116c4 <__frame_dummy_init_array_entry>:
   116c4:   01a8                    addi    a0,sp,200
   116c6:   0001                    nop

Disassembly of section .fini_array:

000116c8 <__do_global_dtors_aux_fini_array_entry>:
   116c8:   0160                    addi    s0,sp,140
   116ca:   0001                    nop

Disassembly of section .data:

000116d0 <__DATA_BEGIN__>:
   116d0:   0000                    unimp
   116d2:   0000                    unimp
   116d4:   19bc                    addi    a5,sp,248
   116d6:   0001                    nop
   116d8:   1a24                    addi    s1,sp,312
   116da:   0001                    nop
   116dc:   1a8c                    addi    a1,sp,368
   116de:   0001                    nop
    ...
   11778:   0001                    nop
   1177a:   0000                    unimp
   1177c:   0000                    unimp
   1177e:   0000                    unimp
   11780:   330e                    fld ft6,224(sp)
   11782:   abcd                    j   11d74 <__BSS_END__+0x230>
   11784:   1234                    addi    a3,sp,296
   11786:   e66d                    bnez    a2,11870 <__DATA_BEGIN__+0x1a0>
   11788:   deec                    sw  a1,124(a3)
   1178a:   0005                    c.nop   1
   1178c:   0000000b            0xb
    ...
1
10338 sets up s0 to point to __init_array_start. s2 is set up to be the size of that array. If the size is not zero, there should most certainly be something in the array which is not NULL or else you have some problem. Note it's data so you won't see any code writing to it.Jester
@Jester That makes sense, Thank you. But this runs on startup of my program, before the main setction, so how am i supposed to modify the data on that adress? The code is auto-generated form the compiler so i do not know why is not 0.Kralik_011
__init_array_start array holds addresses of global constructors. For some reason linker resolves one of these addresses to NULL but it's not possible to say why without full reprocase.yugr
@yugr Thanks. My program starts on _start section, then it jumps into some functions like _memset and so on. Please note that i only run my program from _start, with clear memory. It never writes anything to this adress. So i am not sure what and why is it trying to do.Kralik_011
"with clear memory" - do you mean that all memory is set to zero at start? You'll need to initialize .data segment from ELF file.yugr

1 Answers

1
votes

Code which you pointed out scans contents of .init_array section from __init_array_start to __init_array_end. This section contains addresses of global constructors which need to be run before executing main (BTW as you mentioned it does not make sense to disassemble this section as it contains data, not code, so you need to use objdump -s instead of objdump -d). You can see that addresses are initialized here:

10338:   38c40413            addi    s0,s0,908 # 116c0 <__init_array_start>
...
10340:   38c90913            addi    s2,s2,908 # 116c8 <__init_array_end>

and then used to compute size of section (in 4-byte words):

10344:   40890933            sub s2,s2,s0
10348:   40295913            srai    s2,s2,0x2

Then startup code proceeds with looping over pointers in .init_array and executing them:

10350:   00090e63            beqz    s2,1036c <__libc_init_array+0x80>  ; Skip if .init_array is empty
10354:   00000493            li  s1,0         ; Initialize loop counter
10358:   00042783            lw  a5,0(s0)     ; Load address of global ctor
1035c:   00148493            addi    s1,s1,1  ; Increment loop counter
10360:   00440413            addi    s0,s0,4  ; Compute address which holds address of next global pointer
10364:   000780e7            jalr    a5       ; Execute global ctor
10368:   fe9918e3            bne s2,s1,10358 <__libc_init_array+0x6c>  ; Loop if within .init_array

According to data in your question there are no NULL entries in your .init_array section so my only guess is that for some reason data segment (.data, .rodata, .init_array, etc.) is not loaded properly from ELF file at start of simulation (you also mention that you provide only .text section to simulator).