[PATCH 15/17] risu: Allow use of ELF test files

Richard Henderson posted 17 patches 6 months, 2 weeks ago
[PATCH 15/17] risu: Allow use of ELF test files
Posted by Richard Henderson 6 months, 2 weeks ago
By using elf files, we make it easier to disassemble
the test file, to match comparison failures to code.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 risu.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/risu.c b/risu.c
index c28b4a5..e3845f6 100644
--- a/risu.c
+++ b/risu.c
@@ -24,6 +24,8 @@
 #include <sys/mman.h>
 #include <fcntl.h>
 #include <string.h>
+#include <elf.h>
+#include <endian.h>
 
 #include "config.h"
 #include "risu.h"
@@ -371,6 +373,57 @@ static void load_image(const char *imgfile)
     close(fd);
     image_start = addr;
     image_start_address = (uintptr_t) addr;
+
+    /*
+     * TODO: More complete parsing of ELF file, verify assumtion, namely:
+     * Single PT_LOAD covering the ELF header, code and data.
+     * For now, simply update image_start from the elf header.
+     */
+    if (memcmp(addr, ELFMAG, SELFMAG) == 0) {
+        const unsigned char *e_ident = addr;
+        bool swap, is_64;
+
+        switch (e_ident[EI_DATA]) {
+        case ELFDATA2LSB:
+            swap = __BYTE_ORDER != __LITTLE_ENDIAN;
+            break;
+        case ELFDATA2MSB:
+            swap = __BYTE_ORDER == __LITTLE_ENDIAN;
+            break;
+        default:
+            fprintf(stderr, "%s: Bad elf header: EI_DATA = %x\n",
+                    imgfile, e_ident[EI_DATA]);
+            exit(1);
+        }
+        switch (e_ident[EI_CLASS]) {
+        case ELFCLASS32:
+            is_64 = false;
+            break;
+        case ELFCLASS64:
+            is_64 = true;
+            break;
+        default:
+            fprintf(stderr, "%s: Bad elf header: EI_CLASS = %x\n",
+                    imgfile, e_ident[EI_CLASS]);
+            exit(1);
+        }
+
+        if (is_64) {
+            const Elf64_Ehdr *h64 = addr;
+            Elf64_Addr e64 = h64->e_entry;
+            if (swap) {
+                e64 = __builtin_bswap64(e64);
+            }
+            image_start = addr + e64;
+        } else {
+            const Elf32_Ehdr *h32 = addr;
+            Elf32_Addr e32 = h32->e_entry;
+            if (swap) {
+                e32 = __builtin_bswap32(e32);
+            }
+            image_start = addr + e32;
+        }
+    }
 }
 
 static int master(void)
-- 
2.34.1
Re: [PATCH 15/17] risu: Allow use of ELF test files
Posted by Philippe Mathieu-Daudé 6 months, 1 week ago
On 11/5/24 13:53, Richard Henderson wrote:
> By using elf files, we make it easier to disassemble
> the test file, to match comparison failures to code.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   risu.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 53 insertions(+)
> 
> diff --git a/risu.c b/risu.c
> index c28b4a5..e3845f6 100644
> --- a/risu.c
> +++ b/risu.c
> @@ -24,6 +24,8 @@
>   #include <sys/mman.h>
>   #include <fcntl.h>
>   #include <string.h>
> +#include <elf.h>
> +#include <endian.h>
>   
>   #include "config.h"
>   #include "risu.h"
> @@ -371,6 +373,57 @@ static void load_image(const char *imgfile)
>       close(fd);

Maybe move the code here, doing 'addr = e32 | e64;', ...

>       image_start = addr;
>       image_start_address = (uintptr_t) addr;
> +
> +    /*
> +     * TODO: More complete parsing of ELF file, verify assumtion, namely:
> +     * Single PT_LOAD covering the ELF header, code and data.
> +     * For now, simply update image_start from the elf header.
> +     */
> +    if (memcmp(addr, ELFMAG, SELFMAG) == 0) {
> +        const unsigned char *e_ident = addr;
> +        bool swap, is_64;
> +
> +        switch (e_ident[EI_DATA]) {
> +        case ELFDATA2LSB:
> +            swap = __BYTE_ORDER != __LITTLE_ENDIAN;
> +            break;
> +        case ELFDATA2MSB:
> +            swap = __BYTE_ORDER == __LITTLE_ENDIAN;
> +            break;
> +        default:
> +            fprintf(stderr, "%s: Bad elf header: EI_DATA = %x\n",
> +                    imgfile, e_ident[EI_DATA]);
> +            exit(1);
> +        }
> +        switch (e_ident[EI_CLASS]) {
> +        case ELFCLASS32:
> +            is_64 = false;
> +            break;
> +        case ELFCLASS64:
> +            is_64 = true;
> +            break;
> +        default:
> +            fprintf(stderr, "%s: Bad elf header: EI_CLASS = %x\n",
> +                    imgfile, e_ident[EI_CLASS]);
> +            exit(1);
> +        }
> +
> +        if (is_64) {
> +            const Elf64_Ehdr *h64 = addr;
> +            Elf64_Addr e64 = h64->e_entry;
> +            if (swap) {
> +                e64 = __builtin_bswap64(e64);
> +            }
> +            image_start = addr + e64;
> +        } else {
> +            const Elf32_Ehdr *h32 = addr;
> +            Elf32_Addr e32 = h32->e_entry;
> +            if (swap) {
> +                e32 = __builtin_bswap32(e32);
> +            }
> +            image_start = addr + e32;
> +        }
> +    }

... otherwise image_start_address == &e_ident.

>   }
>   
>   static int master(void)