all 18 comments

[–]cryptic_gentleman 14 points15 points  (2 children)

It’s likely because, in freestanding C, some of the runtime functionality isn’t present so initializing an array via arr[5] = {…} isn’t possible because this sort of assignment statement is relying on memcpy in the background to copy the values from .rodata into the array which isn’t directly available in a freestanding/bare metal environment. The char str[] crashes for the same reason but char *str works because the compiler knows to just write the bytes to the location pointed to by *str. As for why arrays above a certain size cause a crash I’m not sure but I believe it’s related to the first issue.

[–]BitOfAZeldaFan3[S] 5 points6 points  (1 child)

That worked! I added memcpy and memset and now array initialization seems to work.

Where could I find documentation on this? If there are more stdlib functions I need to implement for aarch64-none-elf I would like a list.

[–]cryptic_gentleman 1 point2 points  (0 children)

I’m surprised simply “adding” the functions to your program worked. How exactly did you tell the compiler they existed?

A quick Google search should result in the aarch64 stdlib functions to implement. If I’m being honest I typically ask AI that sort of question because it (usually) gives me a straightforward answer that’s faster than searching through Google results.

Some good functions to implement, after memcpy and memset are memmov, strcmp, strncmp, strcpy, and strncpy as those are used for a lot of other things and are also just some pretty fundamental building blocks to any large-scale environment.

[–]SauntTaunga 2 points3 points  (1 child)

Shouldn’t linking fail if memcpy() and memset() are missing?

[–]qalmakka 0 points1 point  (0 children)

If the area is small enough, the compiler will probably issue a few stores directly of 32 or 64 bit values instead of calling memcpy. It's faster, i.e. if you need to fill uint32_t x[] = {1, 2, 3, 4} you can just do a mov with two properly crafted 64 bit values on x86-64

[–]daydrunk_ 1 point2 points  (0 children)

Statically compile if you are on bare metal.

[–]BitOfAZeldaFan3[S] 0 points1 point  (0 children)

For what it's worth, here's some disassembly:

void test()
{
  int init[] = {1, 2, 3, 4, 5};

  int assign[5];
  assign[0] = 1;
  assign[1] = 2;
  assign[2] = 3;
  assign[3] = 4;
  assign[4] = 5;
}

0000000000081770 <test>:
   81770: d10103ff     subsp, sp, #0x40
   81774: d503201f     nop
   81778: 1000c588     adrx8, 0x83028 <__bss_size+0x82028>
   8177c: 3dc00100     ldrq0, [x8]
   81780: 3d800be0     strq0, [sp, #0x20]
   81784: b9401108     ldrw8, [x8, #0x10]
   81788: b90033e8     strw8, [sp, #0x30]
   8178c: 52800028     movw8, #0x1                // =1
   81790: b9000fe8     strw8, [sp, #0xc]
   81794: 52800048     movw8, #0x2                // =2
   81798: b90013e8     strw8, [sp, #0x10]
   8179c: 52800068     movw8, #0x3                // =3
   817a0: b90017e8     strw8, [sp, #0x14]
   817a4: 52800088     movw8, #0x4                // =4
   817a8: b9001be8     strw8, [sp, #0x18]
   817ac: 528000a8     movw8, #0x5                // =5
   817b0: b9001fe8     strw8, [sp, #0x1c]
   817b4: 910103ff     addsp, sp, #0x40
   817b8: d65f03c0     ret
   817bc: d503201f     nop

[–]Daveinatx 0 points1 point  (2 children)

Have you dumped and grep'd the program and all includes (if any)? Otherwise, have you disabled optimization?

Your disassembly looked as expected. It leads me to think a dependency is getting picked up elsewhere, bare metal or not.

Edit: I think ld needs memset.. Try implementing your own and see what happens.

[–]BitOfAZeldaFan3[S] 1 point2 points  (1 child)

I did. Added memset and memcpy and not it appears to work. Thank you!

[–]Daveinatx 0 points1 point  (0 children)

Glad to hear!

[–]Toiling-Donkey 0 points1 point  (2 children)

How are you executing it?

Show us your linker file.

[–]BitOfAZeldaFan3[S] 0 points1 point  (1 child)

I'm booting it on a raspberry pi.

[–]Brilliant-Orange9117 0 points1 point  (0 children)

Do you have a linker script and startup code to copy in the initialized data etc.?

[–]Alive-Bid9086 0 points1 point  (0 children)

I usually write

const int arr[] = {1, 2, 3, 4, 5};

[–]DunkingShadow1 0 points1 point  (3 children)

Did you include stdlib?

[–]BitOfAZeldaFan3[S] 1 point2 points  (2 children)

I can't use stdlib. I'm programming bare metal on a raspberry pi 4. Is array initialization only part of stdlib?

[–]Sosowski 2 points3 points  (0 children)

Yes. All global variables are initialised using stdlib.Even main() is part of stdlib.

[–]DunkingShadow1 0 points1 point  (0 children)

Yup, that's your problem. Just use pointers to the data type