:: commit b7bca1b000b5d2593429bea85096183639390bd4

Bryce Lanham <blanham@gmail.com> — 2023-05-03 01:09

parents: 4960086ec6

multiboot2: fix 32 bit elf section loading

Existing code was using 64 bit elf section header unconditionally. This
commit fixes that :)
diff --git a/common/lib/elf.c b/common/lib/elf.c
index ed0b63eb..b5f7e8f5 100644
--- a/common/lib/elf.c
+++ b/common/lib/elf.c
@@ -76,19 +76,6 @@ struct elf32_phdr {
     uint32_t p_align;
 };
 
-struct elf32_shdr {
-    uint32_t sh_name;
-    uint32_t sh_type;
-    uint32_t sh_flags;
-    uint32_t sh_addr;
-    uint32_t sh_offset;
-    uint32_t sh_size;
-    uint32_t sh_link;
-    uint32_t sh_info;
-    uint32_t sh_addralign;
-    uint32_t sh_entsize;
-};
-
 struct elf64_rela {
     uint64_t r_addr;
     uint32_t r_info;
diff --git a/common/lib/elf.h b/common/lib/elf.h
index 98a7c9d1..e7df68c0 100644
--- a/common/lib/elf.h
+++ b/common/lib/elf.h
@@ -69,6 +69,19 @@ struct elf64_shdr {
     uint64_t sh_entsize;
 };
 
+struct elf32_shdr {
+    uint32_t sh_name;
+    uint32_t sh_type;
+    uint32_t sh_flags;
+    uint32_t sh_addr;
+    uint32_t sh_offset;
+    uint32_t sh_size;
+    uint32_t sh_link;
+    uint32_t sh_info;
+    uint32_t sh_addralign;
+    uint32_t sh_entsize;
+};
+
 struct elf64_sym {
     uint32_t st_name;
     uint8_t  st_info;
diff --git a/common/protos/multiboot2.c b/common/protos/multiboot2.c
index 65f678c0..c3fc8c3d 100644
--- a/common/protos/multiboot2.c
+++ b/common/protos/multiboot2.c
@@ -376,22 +376,42 @@ noreturn void multiboot2_load(char *config, char* cmdline) {
 
         memcpy(tag->sections, kernel + section_hdr_info.section_offset, section_hdr_info.section_entry_size * section_hdr_info.num);
 
+        int bits = elf_bits(kernel);
+
         for (size_t i = 0; i < section_hdr_info.num; i++) {
-            struct elf64_shdr *shdr = (void *)tag->sections + i * section_hdr_info.section_entry_size;
+            if (bits == 64)  {
+                struct elf64_shdr *shdr = (void *)tag->sections + i * section_hdr_info.section_entry_size;
 
-            if (shdr->sh_addr != 0 || shdr->sh_size == 0) {
-                continue;
-            }
+                if (shdr->sh_addr != 0 || shdr->sh_size == 0) {
+                    continue;
+                }
 
-            uint64_t section = (uint64_t)-1; /* no target preference, use top */
+                uint64_t section = (uint64_t)-1; /* no target preference, use top */
 
-            if (!elsewhere_append(true /* flexible target */,
-                    ranges, &ranges_count,
-                    kernel + shdr->sh_offset, &section, shdr->sh_size)) {
-                panic(true, "multiboot2: Cannot allocate elf sections");
-            }
+                if (!elsewhere_append(true /* flexible target */,
+                        ranges, &ranges_count,
+                        kernel + shdr->sh_offset, &section, shdr->sh_size)) {
+                    panic(true, "multiboot2: Cannot allocate elf sections");
+                }
+
+                shdr->sh_addr = section;
+            } else {
+                struct elf32_shdr *shdr = (void *)tag->sections + i * section_hdr_info.section_entry_size;
+
+                if (shdr->sh_addr != 0 || shdr->sh_size == 0) {
+                    continue;
+                }
+
+                uint64_t section = (uint64_t)-1; /* no target preference, use top */
 
-            shdr->sh_addr = section;
+                if (!elsewhere_append(true /* flexible target */,
+                        ranges, &ranges_count,
+                        kernel + shdr->sh_offset, &section, shdr->sh_size)) {
+                    panic(true, "multiboot2: Cannot allocate elf sections");
+                }
+
+                shdr->sh_addr = section;
+            }
         }
 
         append_tag(info_idx, tag);
tab: 248 wrap: offon