Exemplo n.º 1
0
static const value_t *
elf_get_phdrs(const value_t *this_fn, parser_state_t *state,
              const char *filename, int binfd,
              Elf *e, GElf_Ehdr *ehdr, void *arg)
{
   const value_t *resval = NULL;
   size_t n;

   if (elf_getphdrnum(e, &n) != 0)
      parser_report(state, "ELF file has unknown number of segments - %s\n",
                    elf_errmsg(-1));
   else {
      size_t i;
      dir_t *partdir = dir_vec_new();

      for (i = 0; i < n; i++) {
         GElf_Phdr phdr;
         dir_t *pdir = dir_id_new();
         if (gelf_getphdr(e, i, &phdr) != &phdr)
            parser_report(state,
                          "ELF segment %d unretrievable - %s\n",
                          i, elf_errmsg(-1));
         else {
            dir_string_set(pdir,"type"   , value_int_new(phdr.p_type));
            dir_string_set(pdir,"offset" , value_int_new(phdr.p_offset));
            dir_string_set(pdir,"vaddr"  , value_int_new(phdr.p_vaddr));
            dir_string_set(pdir,"paddr"  , value_int_new(phdr.p_paddr));
            dir_string_set(pdir,"filesz" , value_int_new(phdr.p_filesz));
            dir_string_set(pdir,"memsz"  , value_int_new(phdr.p_memsz));
            dir_string_set(pdir,"flags"  , value_int_new(phdr.p_flags));
            dir_string_set(pdir,"align"  , value_int_new(phdr.p_align));

            dir_int_set(partdir, i, dir_value(pdir));
         }
      }
      resval = dir_value(partdir);
   }

   return resval;
}
Exemplo n.º 2
0
extern bool FTL_EXTENSION_MAIN(parser_state_t *state, dir_t *cmds)
{
    mod_add_val(cmds, "version", value_int_new(42));
}
Exemplo n.º 3
0
/* Invoke the argument FTL function with <addr> <buf> arguments for each of
   the ELF file's program segments */
static const value_t *
elf_load_with_fn(const value_t *this_fn, parser_state_t *state,
                 const char *filename, int binfd,
                 Elf *e, GElf_Ehdr *ehdr, void *arg)
{
   elf_loadfn_args_t *fnarg = (elf_loadfn_args_t *)arg;
   const value_t *hdrcheckfn = fnarg->hdrcheckfn;
   const value_t *memwrfn = fnarg->memwrfn;
   const value_t *resval = value_false;
   size_t n;

   if (elf_getphdrnum(e, &n) != 0)
      parser_report(state, "ELF file has unknown number of segments - %s\n",
                    elf_errmsg(-1));
   else {
      size_t i;
      bool ok = FALSE;

      if (hdrcheckfn != NULL) {
         const value_t *ehdrval = elf_get_ehdr(this_fn, state, filename, binfd,
                                               e, ehdr, /*arg*/NULL);
         if (ehdrval != NULL) {
            const value_t *code = value_closure_bind(hdrcheckfn, ehdrval);

            if (code == NULL) {
               parser_error(state, "couldn't apply "
                            "header argument to check function\n");
            } else {
               const value_t *fnres = invoke(code, state);
               /* we expect this to return a TRUE/FALSE value */
               ok = (fnres == value_true);
               /*if (!ok) printf("%s: check fn returns non-TRUE\n", codeid());*/
            }
         }
      } else
         ok = TRUE;

      resval = ok? value_true: value_false;

      if (ok && memwrfn != NULL) {
         for (i = 0; ok && i < n; i++) {
            GElf_Phdr phdr;

            if (gelf_getphdr(e, i, &phdr) != &phdr)
               parser_report(state, "ELF segment %d unretrievable - %s\n",
                             i, elf_errmsg(-1));
            else {
               long offset = (long)phdr.p_offset;
               if (phdr.p_offset != (Elf64_Off)offset)
                  parser_report(state, "ELF segment %d - "
                                 "offset does not fit in 32-bits\n", i);
               else
               if (-1 == fe_lseek(binfd, offset))
                  parser_report(state, "ELF segment %d - "
                                 "offset 0X%lX is outside file\n",
                                 i, offset);
               else
               if (phdr.p_memsz < phdr.p_filesz)
                  parser_report(state,
                                "ELF segment %d - smaller size in memory (%d)"
                                "than on file (%d) - corrupt header?\n",
                                i, phdr.p_memsz, phdr.p_filesz);
               else {
                  number_t addr = phdr.p_vaddr; /* where to load segment */
                  char *buf = NULL;
                  size_t buflen = (size_t)phdr.p_memsz;
                  value_t *addrval = value_int_new(addr);
                  value_t *dataval = value_string_alloc_new(buflen, &buf);

                  if (phdr.p_memsz != (Elf64_Xword)buflen)
                     parser_report(state, "ELF segment %d - "
                                    "size does not fit in 32-bits\n", i);
                  else
                  if (dataval == NULL)
                     parser_report(state,
                                   "ELF segment %d - no memory for "
                                   "next %d bytes\n",
                                   i, buflen);
                  else {
                     ssize_t readbytes = fe_read(binfd, buf, buflen);

                     if (readbytes < buflen)
                        parser_report(state,
                                      "ELF segment %d - "
                                      "only %d bytes of %d read\n",
                                      i, readbytes);
                     else {
                        const value_t *code;
                        ok = TRUE;

                        /* zero any uninitialized area */
                        if (phdr.p_memsz > phdr.p_filesz) {
                           size_t extra_bytes = (size_t)
                                                (phdr.p_memsz - phdr.p_filesz);
                           if ((Elf64_Xword)extra_bytes !=
                               phdr.p_memsz-phdr.p_filesz) {
                              ok = FALSE;
                              parser_report(state, "ELF segment %d - "
                                            "BSS area larger than 32-bits\n",
                                            i);
                           } else
                              memset(&buf[phdr.p_filesz], '\0', extra_bytes);
                        }

                        code = value_closure_bind_2(state, memwrfn,
                                                    "address", addrval,
                                                    "data", dataval);

                        if (NULL != code) {
                           const value_t *fnres = invoke(code, state);
                           /* we expect this to return a TRUE/FALSE value */
                           if (fnres != value_true) {
                              /*printf("%s: seg fn returns non-TRUE\n",
                                       codeid());*/
                              ok = FALSE;
                           }
                           /* we rely on garbage collection to collect the data
                            * buffer */
                        } else
                           value_delete(&dataval);
                     }
                  }
               }
            }
         }

         if (!ok)
            resval = value_false;
      }
   }
   return resval;
}
Exemplo n.º 4
0
static const value_t *
elf_get_ehdr(const value_t *this_fn, parser_state_t *state,
             const char *filename, int binfd,
             Elf *e, GElf_Ehdr *ehdr, void *arg)
{
   int eclass = gelf_getclass(e);
   char *id = elf_getident(e, NULL);
   dir_t *einfo = dir_id_new();
   dir_t *edir = dir_id_new();
   size_t n;

   if (eclass == ELFCLASS32)
      dir_string_set(einfo, "class", value_int_new(32));
   else if (eclass == ELFCLASS64)
      dir_string_set(einfo, "class", value_int_new(64));
   else {
      dir_string_set(einfo, "class", &value_null);
      if (eclass != ELFCLASSNONE)
         parser_report(state, "ELF file has unknown class %d - %s\n",
                       eclass, elf_errmsg(-1));
   }

   if (id == NULL)
      parser_report(state, "ELF file has unknown identity - %s\n",
                    elf_errmsg(-1));
   else
      dir_string_set(einfo, "id",
                     value_string_new(id, EI_NIDENT));

   dir_string_set(einfo, "ehdr", dir_value(edir));

   dir_string_set(edir,"type"   , value_int_new(ehdr->e_type));
   dir_string_set(edir,"machine", value_int_new(ehdr->e_machine));
   dir_string_set(edir,"version", value_int_new(ehdr->e_version));
   dir_string_set(edir,"entry"  , value_int_new(ehdr->e_entry));
   dir_string_set(edir,"phoff"  , value_int_new(ehdr->e_phoff));
   dir_string_set(edir,"shoff"  , value_int_new(ehdr->e_shoff));
   dir_string_set(edir,"flags"  , value_int_new(ehdr->e_flags));
   dir_string_set(edir,"ehsize" , value_int_new(ehdr->e_ehsize));
   dir_string_set(edir,"phentsize",
                  value_int_new(ehdr->e_phentsize));
   dir_string_set(edir,"shentsize",
                  value_int_new(ehdr->e_shentsize));

   if (elf_getphdrnum(e, &n) != 0)
      parser_report(state,"ELF file has unknown number of segments - %s\n",
                    elf_errmsg(-1));
   else
      dir_string_set(einfo, "progsects", value_int_new(n));

   if (elf_getshdrnum(e, &n) != 0)
      parser_report(state, "%s: ELF file has unknown number of sections - %s\n",
                    elf_errmsg(-1));
   else
      dir_string_set(einfo, "sections", value_int_new(n));

   if (elf_getshdrstrndx(e, &n) != 0)
      parser_report(state, "%s: ELF file has no section names - %s\n",
                    elf_errmsg(-1));
   else
      dir_string_set(einfo, "shdrstrndx", value_int_new(n));

   return dir_value(einfo);
}