Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/lib/libsa Clean up and split loadfile, reduces a patch I...



details:   https://anonhg.NetBSD.org/src/rev/51f011112080
branches:  trunk
changeset: 826733:51f011112080
user:      maxv <maxv%NetBSD.org@localhost>
date:      Mon Sep 25 20:39:21 2017 +0000

description:
Clean up and split loadfile, reduces a patch I have.

diffstat:

 sys/lib/libsa/loadfile_elf32.c |  459 ++++++++++++++++++++--------------------
 1 files changed, 224 insertions(+), 235 deletions(-)

diffs (truncated from 535 to 300 lines):

diff -r 054b2bdd5905 -r 51f011112080 sys/lib/libsa/loadfile_elf32.c
--- a/sys/lib/libsa/loadfile_elf32.c    Mon Sep 25 08:55:27 2017 +0000
+++ b/sys/lib/libsa/loadfile_elf32.c    Mon Sep 25 20:39:21 2017 +0000
@@ -1,12 +1,12 @@
-/* $NetBSD: loadfile_elf32.c,v 1.40 2017/04/18 07:44:20 uwe Exp $ */
+/* $NetBSD: loadfile_elf32.c,v 1.41 2017/09/25 20:39:21 maxv Exp $ */
 
 /*
- * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc.
+ * Copyright (c) 1997, 2008, 2017 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
- * NASA Ames Research Center and by Christos Zoulas.
+ * NASA Ames Research Center, by Christos Zoulas, and by Maxime Villard.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -259,8 +259,220 @@
 #define IS_DATA(p)     (p.p_flags & PF_W)
 #define IS_BSS(p)      (p.p_filesz < p.p_memsz)
 
+#ifndef MD_LOADSEG /* Allow processor ABI specific segment loads */
+#define MD_LOADSEG(a) /*CONSTCOND*/0
+#endif
+
+/* -------------------------------------------------------------------------- */
+
 /*
- * Load the ELF binary into memory. Layout of the memory:
+ * See comment below. This function is in charge of loading the SECTION HEADERS.
+ */
+static int
+ELFNAMEEND(loadsym)(int fd, Elf_Ehdr *elf, Elf_Addr maxp, Elf_Addr elfp,
+    u_long *marks, int flags, Elf_Addr *nmaxp)
+{
+       int boot_load_ctf = 1;
+       Elf_Shdr *shp;
+       Elf_Addr shpp;
+       char *shstr = NULL;
+       ssize_t nr, sz;
+       size_t i, j, shstrsz = 0;
+       u_long offset = marks[MARK_START];
+       struct __packed {
+               Elf_Nhdr nh;
+               uint8_t name[ELF_NOTE_NETBSD_NAMESZ + 1];
+               uint8_t desc[ELF_NOTE_NETBSD_DESCSZ];
+       } note;
+       int first;
+
+       /* some ports dont use the offset */
+       (void)&offset;
+
+       if (lseek(fd, elf->e_shoff, SEEK_SET) == -1)  {
+               WARN(("lseek section headers"));
+               return -1;
+       }
+       sz = elf->e_shnum * sizeof(Elf_Shdr);
+       shp = ALLOC(sz);
+
+       nr = read(fd, shp, sz);
+       if (nr == -1) {
+               WARN(("read section headers"));
+               goto out;
+       }
+       if (nr != sz) {
+               errno = EIO;
+               WARN(("read section headers"));
+               goto out;
+       }
+
+       shpp = maxp;
+       maxp += roundup(sz, ELFROUND);
+
+#ifndef _STANDALONE
+       for (i = 0; i < elf->e_shnum; i++)
+               internalize_shdr(elf->e_ident[EI_DATA], &shp[i]);
+#endif
+
+       /*
+        * First load the section names section. Only useful for CTF.
+        */
+       if (boot_load_ctf && (elf->e_shstrndx != SHN_UNDEF)) {
+               Elf_Off shstroff = shp[elf->e_shstrndx].sh_offset;
+               shstrsz = shp[elf->e_shstrndx].sh_size;
+               if (flags & LOAD_SYM) {
+                       if (lseek(fd, shstroff, SEEK_SET) == -1) {
+                               WARN(("lseek symbols"));
+                               goto out;
+                       }
+                       nr = READ(fd, maxp, shstrsz);
+                       if (nr == -1) {
+                               WARN(("read symbols"));
+                               goto out;
+                       }
+                       if (nr != (ssize_t)shstrsz) {
+                               errno = EIO;
+                               WARN(("read symbols"));
+                               goto out;
+                       }
+               }
+
+               /* Create a local copy */
+               shstr = ALLOC(shstrsz);
+               if (lseek(fd, shstroff, SEEK_SET) == -1) {
+                       WARN(("lseek symbols"));
+                       goto out;
+               }
+               nr = read(fd, shstr, shstrsz);
+               if (nr == -1) {
+                       WARN(("read symbols"));
+                       goto out;
+               }
+               shp[elf->e_shstrndx].sh_offset = maxp - elfp;
+               maxp += roundup(shstrsz, ELFROUND);
+       }
+
+       /*
+        * Now load the symbol sections themselves. Make sure the sections are
+        * ELFROUND-aligned. Update sh_offset to be relative to elfp. Set it to
+        * zero when we don't want the sections to be taken care of, the kernel
+        * will properly skip them.
+        */
+       first = 1;
+       for (i = 1; i < elf->e_shnum; i++) {
+               if (i == elf->e_shstrndx) {
+                       /* already loaded this section */
+                       continue;
+               }
+
+               switch (shp[i].sh_type) {
+               case SHT_PROGBITS:
+                       if (boot_load_ctf && shstr) {
+                               /* got a CTF section? */
+                               if (strncmp(&shstr[shp[i].sh_name],
+                                           ".SUNW_ctf", 10) == 0) {
+                                       goto havesym;
+                               }
+                       }
+
+                       shp[i].sh_offset = 0;
+                       break;
+               case SHT_STRTAB:
+                       for (j = 1; j < elf->e_shnum; j++)
+                               if (shp[j].sh_type == SHT_SYMTAB &&
+                                   shp[j].sh_link == (unsigned int)i)
+                                       goto havesym;
+                       /*
+                        * Don't bother with any string table that isn't
+                        * referenced by a symbol table.
+                        */
+                       shp[i].sh_offset = 0;
+                       break;
+havesym:
+               case SHT_SYMTAB:
+                       if (flags & LOAD_SYM) {
+                               PROGRESS(("%s%ld", first ? " [" : "+",
+                                   (u_long)shp[i].sh_size));
+                               if (lseek(fd, shp[i].sh_offset,
+                                   SEEK_SET) == -1) {
+                                       WARN(("lseek symbols"));
+                                       goto out;
+                               }
+                               nr = READ(fd, maxp, shp[i].sh_size);
+                               if (nr == -1) {
+                                       WARN(("read symbols"));
+                                       goto out;
+                               }
+                               if (nr != (ssize_t)shp[i].sh_size) {
+                                       errno = EIO;
+                                       WARN(("read symbols"));
+                                       goto out;
+                               }
+                       }
+                       shp[i].sh_offset = maxp - elfp;
+                       maxp += roundup(shp[i].sh_size, ELFROUND);
+                       first = 0;
+                       break;
+               case SHT_NOTE:
+                       if ((flags & LOAD_NOTE) == 0)
+                               break;
+                       if (shp[i].sh_size < sizeof(note)) {
+                               shp[i].sh_offset = 0;
+                               break;
+                       }
+                       if (lseek(fd, shp[i].sh_offset, SEEK_SET) == -1) {
+                               WARN(("lseek note"));
+                               goto out;
+                       }
+                       nr = read(fd, &note, sizeof(note));
+                       if (nr == -1) {
+                               WARN(("read note"));
+                               goto out;
+                       }
+                       if (note.nh.n_namesz == ELF_NOTE_NETBSD_NAMESZ &&
+                           note.nh.n_descsz == ELF_NOTE_NETBSD_DESCSZ &&
+                           note.nh.n_type == ELF_NOTE_TYPE_NETBSD_TAG &&
+                           memcmp(note.name, ELF_NOTE_NETBSD_NAME,
+                           sizeof(note.name)) == 0) {
+                               memcpy(&netbsd_version, &note.desc,
+                                   sizeof(netbsd_version));
+                       }
+                       shp[i].sh_offset = 0;
+                       break;
+               default:
+                       shp[i].sh_offset = 0;
+                       break;
+               }
+       }
+       if (flags & LOAD_SYM) {
+#ifndef _STANDALONE
+               for (i = 0; i < elf->e_shnum; i++)
+                       externalize_shdr(elf->e_ident[EI_DATA], &shp[i]);
+#endif
+               BCOPY(shp, shpp, sz);
+
+               if (first == 0)
+                       PROGRESS(("]"));
+       }
+
+       *nmaxp = maxp;
+       DEALLOC(shp, sz);
+       if (shstr != NULL)
+               DEALLOC(shstr, shstrsz);
+       return 0;
+
+out:
+       DEALLOC(shp, sz);
+       if (shstr != NULL)
+               DEALLOC(shstr, shstrsz);
+       return -1;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * Load a static ELF binary into memory. Layout of the memory:
  * +-----------------+------------+-----------------+-----------------+
  * | KERNEL SEGMENTS | ELF HEADER | SECTION HEADERS | SYMBOL SECTIONS |
  * +-----------------+------------+-----------------+-----------------+
@@ -273,27 +485,15 @@
  * We just give the kernel a pointer to the ELF HEADER, which is enough for it
  * to find the location and number of symbols by itself later.
  */
-
 int
 ELFNAMEEND(loadfile)(int fd, Elf_Ehdr *elf, u_long *marks, int flags)
 {
-       Elf_Shdr *shp;
        Elf_Phdr *phdr;
-       int i, j;
+       int i, first;
        ssize_t sz;
-       int first;
-       Elf_Addr shpp;
        Elf_Addr minp = ~0, maxp = 0, pos = 0, elfp = 0;
        u_long offset = marks[MARK_START];
        ssize_t nr;
-       struct __packed {
-               Elf_Nhdr nh;
-               uint8_t name[ELF_NOTE_NETBSD_NAMESZ + 1];
-               uint8_t desc[ELF_NOTE_NETBSD_DESCSZ];
-       } note;
-       char *shstr = NULL;
-       size_t shstrsz = 0;
-       int boot_load_ctf = 1;
 
        /* some ports dont use the offset */
        (void)&offset;
@@ -325,9 +525,6 @@
        for (i = 0; i < elf->e_phnum; i++) {
                internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]);
 
-#ifndef MD_LOADSEG /* Allow processor ABI specific segment loads */
-#define MD_LOADSEG(a) /*CONSTCOND*/0
-#endif
                if (MD_LOADSEG(&phdr[i]))
                        goto loadseg;
 
@@ -390,194 +587,25 @@
                }
        }
        DEALLOC(phdr, sz);
+       maxp = roundup(maxp, ELFROUND);
 
        /*
-        * Copy the ELF and section headers.
+        * Load the ELF HEADER, SECTION HEADERS and possibly the SYMBOL
+        * SECTIONS.
         */
-       maxp = roundup(maxp, ELFROUND);
        if (flags & (LOAD_HDR|COUNT_HDR)) {
                elfp = maxp;
                maxp += sizeof(Elf_Ehdr);
        }
-
        if (flags & (LOAD_SYM|COUNT_SYM)) {
-               if (lseek(fd, elf->e_shoff, SEEK_SET) == -1)  {
-                       WARN(("lseek section headers"));



Home | Main Index | Thread Index | Old Index