raspberrypi / pico-sdk

BSD 3-Clause "New" or "Revised" License
3.24k stars 837 forks source link

elf2uf2 on s390x: ERROR: Not an ELF file #1722

Open josch opened 3 weeks ago

josch commented 3 weeks ago

Hi,

I have this CMakeLists.txt:

cmake_minimum_required(VERSION 3.13)
include(pico_sdk_import.cmake)
project(hello_world)
pico_sdk_init()

add_executable(hello_world hello.c)
target_link_libraries(hello_world pico_stdlib)
pico_add_extra_outputs(hello_world)

and this hello-world program (yes this program is not even making use of the pico sdk but the problem is also there if we add that):

#include <stdio.h>

int main() {
    printf("Hello, world!\n");
    return 0;
}

On s390x the build will fail like this:

$ make VERBOSE=1
[...]
/usr/bin/arm-none-eabi-objcopy -Oihex /home/josch/hello_world.elf hello_world.hex
/usr/bin/arm-none-eabi-objcopy -Obinary /home/josch/hello_world.elf hello_world.bin
/usr/bin/arm-none-eabi-objdump -h /home/josch/hello_world.elf > hello_world.dis
/usr/bin/arm-none-eabi-objdump -d /home/josch/hello_world.elf >> hello_world.dis
elf2uf2/elf2uf2 /home/josch/hello_world.elf hello_world.uf2
ERROR: Not an ELF file
make[2]: *** [CMakeFiles/hello_world.dir/build.make:812: hello_world.elf] Error 254
make[2]: *** Deleting file 'hello_world.elf'
make[2]: Leaving directory '/home/josch'
make[1]: *** [CMakeFiles/Makefile2:1491: CMakeFiles/hello_world.dir/all] Error 2
make[1]: Leaving directory '/home/josch'
make: *** [Makefile:91: all] Error 2

I added some printfs into tools/elf2uf2/main.cpp to investigate the values of ELF_MAGIC and eh_out.common.magic in read_and_check_elf32_header and got this:

ELF_MAGIC = 464c457f
eh_out.common.magic = 7f454c46

There seems to be an endian problem somewhere? The file utility seems to think that my hello_world.elf has the correct magic:

$ file hello_world.elf
hello_world.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped

Any ideas?

lurch commented 3 weeks ago

I guess this would be fixed by #329 ?

josch commented 3 weeks ago

Thank you! In the mean-time I had this patch cooked up:

--- a/tools/elf2uf2/main.cpp    2023-06-13 22:27:33.000000000 +0000
+++ b/tools/elf2uf2/main.cpp    2024-06-05 08:20:56.156138030 +0000
@@ -11,6 +11,7 @@
 #include <cstring>
 #include <cstdarg>
 #include <algorithm>
+#include <endian.h>
 #include "boot/uf2.h"
 #include "elf.h"

@@ -101,6 +103,20 @@
     if (1 != fread(&eh_out, sizeof(eh_out), 1, in)) {
         return fail(ERROR_READ_FAILED, "Unable to read ELF header");
     }
+    eh_out.common.magic    = le32toh(eh_out.common.magic);
+    eh_out.common.type     = le16toh(eh_out.common.type);
+    eh_out.common.machine  = le16toh(eh_out.common.machine);
+    eh_out.common.version2 = le32toh(eh_out.common.version2);
+    eh_out.entry           = le32toh(eh_out.entry);
+    eh_out.ph_offset       = le32toh(eh_out.ph_offset);
+    eh_out.sh_offset       = le32toh(eh_out.sh_offset);
+    eh_out.flags           = le32toh(eh_out.flags);
+    eh_out.eh_size         = le16toh(eh_out.eh_size);
+    eh_out.ph_entry_size   = le16toh(eh_out.ph_entry_size);
+    eh_out.ph_num          = le16toh(eh_out.ph_num);
+    eh_out.sh_entry_size   = le16toh(eh_out.sh_entry_size);
+    eh_out.sh_num          = le16toh(eh_out.sh_num);
+    eh_out.sh_str_index    = le16toh(eh_out.sh_str_index);
     if (eh_out.common.magic != ELF_MAGIC) {
         return fail(ERROR_FORMAT, "Not an ELF file");
     }
@@ -154,6 +175,16 @@
         if (eh.ph_num != fread(&entries[0], sizeof(struct elf32_ph_entry), eh.ph_num, in)) {
             return fail_read_error();
         }
+   for (int i = 0; i < eh.ph_num; i++) {
+       entries[i].type = le32toh(entries[i].type);
+       entries[i].offset = le32toh(entries[i].offset);
+       entries[i].vaddr = le32toh(entries[i].vaddr);
+       entries[i].paddr = le32toh(entries[i].paddr);
+       entries[i].filez = le32toh(entries[i].filez);
+       entries[i].memsz = le32toh(entries[i].memsz);
+       entries[i].flags = le32toh(entries[i].flags);
+       entries[i].align = le32toh(entries[i].align);
+   }
     }
     return 0;
 }

I also rebased the patch from #329 onto my local pico-sdk version and:

[100%] Linking CXX executable hello_world.elf
[100%] Built target hello_world

It works fine, thank you!