Author: adrian
Date: Tue Aug 10 09:24:19 2010
New Revision: 211137
URL: http://svn.freebsd.org/changeset/base/211137

Log:
  Port over changes to the crunch symbol hiding method from NetBSD.
  
  The older symbol hiding method breaks for MIPS. This implements
  symbol hiding through renaming to a symbol name which is highly
  unlikely to clash.
  
  The NetBSD code didn't use byte-swapping macros for endian-awareness;
  so it didn't work when cross-compiling a MIPS world on i386/amd64.
  This patch includes those (as best as I could figure what they
  should be) and has been tested to generate valid MIPS crunch
  binaries both cross- and native- compiled.

Modified:
  head/usr.sbin/crunch/crunchide/exec_elf32.c

Modified: head/usr.sbin/crunch/crunchide/exec_elf32.c
==============================================================================
--- head/usr.sbin/crunch/crunchide/exec_elf32.c Tue Aug 10 07:56:56 2010        
(r211136)
+++ head/usr.sbin/crunch/crunchide/exec_elf32.c Tue Aug 10 09:24:19 2010        
(r211137)
@@ -130,6 +130,20 @@ xmalloc(size_t size, const char *fn, con
        return (rv);
 }
 
+static void *
+xrealloc(void *ptr, size_t size, const char *fn, const char *use)
+{
+       void *rv;
+               
+       rv = realloc(ptr, size);
+       if (rv == NULL) {
+               free(ptr);
+               fprintf(stderr, "%s: out of memory (reallocating for %s)\n",
+                   fn, use);
+       }
+       return (rv);
+} 
+
 int
 ELFNAMEEND(check)(int fd, const char *fn)
 {
@@ -197,6 +211,21 @@ ELFNAMEEND(check)(int fd, const char *fn
        return 1;
 }
 
+/*
+ * This function 'hides' (some of) ELF executable file's symbols.
+ * It hides them by renaming them to "_$$hide$$ <filename> <symbolname>".
+ * Symbols in the global keep list, or which are marked as being undefined,
+ * are left alone.
+ *
+ * An old version of this code shuffled various tables around, turning
+ * global symbols to be hidden into local symbols.  That lost on the
+ * mips, because CALL16 relocs must reference global symbols, and, if
+ * those symbols were being hidden, they were no longer global.
+ *
+ * The new renaming behaviour doesn't take global symbols out of the
+ * namespace.  However, it's ... unlikely that there will ever be
+ * any collisions in practice because of the new method.
+ */
 int
 ELFNAMEEND(hide)(int fd, const char *fn)
 {
@@ -204,11 +233,14 @@ ELFNAMEEND(hide)(int fd, const char *fn)
        Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr;
        Elf_Sym *symtabp = NULL;
        char *strtabp = NULL;
-       Elf_Size *symfwmap = NULL, *symrvmap = NULL, nsyms, nlocalsyms, ewi;
-       struct listelem *relalist = NULL, *rellist = NULL, *tmpl;
+       Elf_Size  nsyms, nlocalsyms, ewi;
        ssize_t shdrsize;
        int rv, i, weird;
+       size_t nstrtab_size, nstrtab_nextoff, fn_size;
+       char *nstrtabp = NULL;
        unsigned char data;
+       Elf_Off maxoff, stroff;
+       const char *weirdreason = NULL;
 
        rv = 0;
        if (xreadatoff(fd, &ehdr, 0, sizeof ehdr, fn) != sizeof ehdr)
@@ -225,42 +257,38 @@ ELFNAMEEND(hide)(int fd, const char *fn)
 
        symtabshdr = strtabshdr = NULL;
        weird = 0;
+       maxoff = stroff = 0;
        for (i = 0; i < xe16toh(ehdr.e_shnum); i++) {
+               if (xewtoh(shdrp[i].sh_offset) > maxoff)
+                       maxoff = xewtoh(shdrp[i].sh_offset);
                switch (xe32toh(shdrp[i].sh_type)) {
                case SHT_SYMTAB:
                        if (symtabshdr != NULL)
                                weird = 1;
                        symtabshdr = &shdrp[i];
                        strtabshdr = &shdrp[xe32toh(shdrp[i].sh_link)];
-                       break;
-               case SHT_RELA:
-                       tmpl = xmalloc(sizeof *tmpl, fn, "rela list element");
-                       if (tmpl == NULL)
-                               goto bad;
-                       tmpl->mem = NULL;
-                       tmpl->file = xewtoh(shdrp[i].sh_offset);
-                       tmpl->size = xewtoh(shdrp[i].sh_size);
-                       tmpl->next = relalist;
-                       relalist = tmpl;
-                       break;
-               case SHT_REL:
-                       tmpl = xmalloc(sizeof *tmpl, fn, "rel list element");
-                       if (tmpl == NULL)
-                               goto bad;
-                       tmpl->mem = NULL;
-                       tmpl->file = xewtoh(shdrp[i].sh_offset);
-                       tmpl->size = xewtoh(shdrp[i].sh_size);
-                       tmpl->next = rellist;
-                       rellist = tmpl;
+
+                       /* Check whether the string table is the last section */
+                       stroff = 
xewtoh(shdrp[xe32toh(shdrp[i].sh_link)].sh_offset);
+                       if (!weird && xe32toh(shdrp[i].sh_link) != 
(xe16toh(ehdr.e_shnum) - 1)) {
+                               weird = 1;
+                               weirdreason = "string table not last section";
+                       }
                        break;
                }
        }
+       if (! weirdreason)
+               weirdreason = "unsupported";
        if (symtabshdr == NULL)
                goto out;
        if (strtabshdr == NULL)
                weird = 1;
+       if (!weird && stroff != maxoff) {
+               weird = 1;
+               weirdreason = "string table section not last in file";
+       }   
        if (weird) {
-               fprintf(stderr, "%s: weird executable (unsupported)\n", fn);
+               fprintf(stderr, "%s: weird executable (%s)\n", fn, weirdreason);
                goto bad;
        }
 
@@ -284,105 +312,53 @@ ELFNAMEEND(hide)(int fd, const char *fn)
            xewtoh(strtabshdr->sh_size), fn) != xewtoh(strtabshdr->sh_size))
                goto bad;
 
-       /* any rela tables */
-       for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
-               if ((tmpl->mem = xmalloc(tmpl->size, fn, "rela table"))
-                   == NULL)
-                       goto bad;
-               if (xreadatoff(fd, tmpl->mem, tmpl->file,
-                   tmpl->size, fn) != tmpl->size)
-                       goto bad;
-       }
+       nstrtab_size = 256;
+       nstrtabp = xmalloc(nstrtab_size, fn, "new string table");
+       if (nstrtabp == NULL)
+               goto bad;
+       nstrtab_nextoff = 0;
 
-       /* any rel tables */
-       for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
-               if ((tmpl->mem = xmalloc(tmpl->size, fn, "rel table"))
-                   == NULL)
-                       goto bad;
-               if (xreadatoff(fd, tmpl->mem, tmpl->file,
-                   tmpl->size, fn) != tmpl->size)
-                       goto bad;
-       }
+       fn_size = strlen(fn);
 
        /* Prepare data structures for symbol movement. */
        nsyms = xewtoh(symtabshdr->sh_size) / xewtoh(symtabshdr->sh_entsize);
        nlocalsyms = xe32toh(symtabshdr->sh_info);
-       if ((symfwmap = xmalloc(nsyms * sizeof (Elf_Size), fn,
-           "symbol forward mapping table")) == NULL)
-               goto bad;
-       if ((symrvmap = xmalloc(nsyms * sizeof (Elf_Size), fn,
-           "symbol reverse mapping table")) == NULL)
-               goto bad;
-
-       /* init location -> symbol # table */
-       for (ewi = 0; ewi < nsyms; ewi++)
-               symrvmap[ewi] = ewi;
 
        /* move symbols, making them local */
-       for (ewi = nlocalsyms; ewi < nsyms; ewi++) {
-               Elf_Sym *sp, symswap;
-               Elf_Size mapswap;
-
-               sp = &symtabp[ewi];
-
-               /* if it's on our keep list, don't move it */
-               if (in_keep_list(strtabp + xe32toh(sp->st_name)))
-                       continue;
-
-               /* if it's an undefined symbol, keep it */
-               if (xe16toh(sp->st_shndx) == SHN_UNDEF)
-                       continue;
-
-               /* adjust the symbol so that it's local */
-               sp->st_info =
-                   ELF_ST_INFO(STB_LOCAL, sp->st_info);
-/*                 (STB_LOCAL << 4) | ELF_SYM_TYPE(sp->st_info); *//* XXX */
-
+       for (ewi = 0; ewi < nsyms; ewi++) {
+               Elf_Sym *sp = &symtabp[ewi];
+               const char *symname = strtabp + xe32toh(sp->st_name);
+               size_t newent_len;
                /*
-                * move the symbol to its new location
+                * make sure there's size for the next entry, even if it's
+                * as large as it can be.
+                *
+                * "_$$hide$$ <filename> <symname><NUL>" ->
+                *    9 + 3 + sizes of fn and sym name
                 */
-
-               /* note that symbols in those locations have been swapped */
-               mapswap = symrvmap[ewi];
-               symrvmap[ewi] = symrvmap[nlocalsyms];
-               symrvmap[nlocalsyms] = mapswap;
-
-               /* and swap the symbols */
-               symswap = *sp;
-               *sp = symtabp[nlocalsyms];
-               symtabp[nlocalsyms] = symswap;
-
-               nlocalsyms++;                   /* note new local sym */
-       }
-       symtabshdr->sh_info = htoxe32(nlocalsyms);
-
-       /* set up symbol # -> location mapping table */
-       for (ewi = 0; ewi < nsyms; ewi++)
-               symfwmap[symrvmap[ewi]] = ewi;
-
-       /* any rela tables */
-       for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
-               Elf_Rela *relap = tmpl->mem;
-
-               for (ewi = 0; ewi < tmpl->size / sizeof(*relap); ewi++) {
-                       relap[ewi].r_info = htoxew(ELF_R_INFO(
-                           symfwmap[ELF_R_SYM(xewtoh(relap[ewi].r_info))],
-                           ELF_R_TYPE(xewtoh(relap[ewi].r_info))
-                       ));
+               while ((nstrtab_size - nstrtab_nextoff) <
+                   strlen(symname) + fn_size + 12) {
+                       nstrtab_size *= 2;
+                       nstrtabp = xrealloc(nstrtabp, nstrtab_size, fn,
+                           "new string table");
+                       if (nstrtabp == NULL)
+                               goto bad;
                }
-       }
 
-       /* any rel tables */
-       for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
-               Elf_Rel *relp = tmpl->mem;
-
-               for (ewi = 0; ewi < tmpl->size / sizeof *relp; ewi++) {
-                       relp[ewi].r_info = htoxew(ELF_R_INFO(
-                           symfwmap[ELF_R_SYM(xewtoh(relp[ewi].r_info))],
-                           ELF_R_TYPE(xewtoh(relp[ewi].r_info))
-                       ));
+               sp->st_name = htoxew(nstrtab_nextoff);
+
+               /* if it's a keeper or is undefined, don't rename it. */
+               if (in_keep_list(symname) ||
+                   (xe16toh(sp->st_shndx) == SHN_UNDEF)) {
+                       newent_len = sprintf(nstrtabp + nstrtab_nextoff,
+                           "%s", symname) + 1;
+               } else {
+                       newent_len = sprintf(nstrtabp + nstrtab_nextoff,
+                           "_$$hide$$ %s %s", fn, symname) + 1;
                }
+               nstrtab_nextoff += newent_len;
        }
+       strtabshdr->sh_size = htoxew(nstrtab_nextoff);
 
        /*
         * write new tables to the file
@@ -393,16 +369,10 @@ ELFNAMEEND(hide)(int fd, const char *fn)
        if (xwriteatoff(fd, symtabp, xewtoh(symtabshdr->sh_offset),
            xewtoh(symtabshdr->sh_size), fn) != xewtoh(symtabshdr->sh_size))
                goto bad;
-       for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
-               if (xwriteatoff(fd, tmpl->mem, tmpl->file,
-                   tmpl->size, fn) != tmpl->size)
-                       goto bad;
-       }
-       for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
-               if (xwriteatoff(fd, tmpl->mem, tmpl->file,
-                   tmpl->size, fn) != tmpl->size)
-                       goto bad;
-       }
+       /* write new symbol table strings */
+       if ((size_t)xwriteatoff(fd, nstrtabp, xewtoh(strtabshdr->sh_offset),
+           xewtoh(strtabshdr->sh_size), fn) != xewtoh(strtabshdr->sh_size))
+               goto bad;
 
 out:
        if (shdrp != NULL)
@@ -411,22 +381,6 @@ out:
                free(symtabp);
        if (strtabp != NULL)
                free(strtabp);
-       if (symfwmap != NULL)
-               free(symfwmap);
-       if (symrvmap != NULL)
-               free(symrvmap);
-       while ((tmpl = relalist) != NULL) {
-               relalist = tmpl->next;
-               if (tmpl->mem != NULL)
-                       free(tmpl->mem);
-               free(tmpl);
-       }
-       while ((tmpl = rellist) != NULL) {
-               rellist = tmpl->next;
-               if (tmpl->mem != NULL)
-                       free(tmpl->mem);
-               free(tmpl);
-       }
        return (rv);
 
 bad:
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to