static void elf_dumpentrypt(FAR struct binary_s *binp, FAR struct elf_loadinfo_s *loadinfo) { #ifdef CONFIG_ARCH_ADDRENV int ret; /* If CONFIG_ARCH_ADDRENV=y, then the loaded ELF lies in a virtual address * space that may not be in place now. elf_addrenv_select() will * temporarily instantiate that address space. */ ret = elf_addrenv_select(loadinfo); if (ret < 0) { bdbg("ERROR: elf_addrenv_select() failed: %d\n", ret); return; } #endif elf_dumpbuffer("Entry code", (FAR const uint8_t *)binp->entrypt, MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512)); #ifdef CONFIG_ARCH_ADDRENV /* Restore the original address environment */ ret = elf_addrenv_restore(loadinfo); if (ret < 0) { bdbg("ERROR: elf_addrenv_restore() failed: %d\n", ret); } #endif }
int exec(FAR const char *filename, FAR const char **argv, FAR const struct symtab_s *exports, int nexports) { struct binary_s bin; int ret; memset(&bin, 0, sizeof(struct binary_s)); bin.filename = filename; bin.exports = exports; bin.nexports = nexports; ret = load_module(&bin); if (ret < 0) { bdbg("ERROR: Failed to load program '%s'\n", filename); return ERROR; } ret = exec_module(&bin, 50); if (ret < 0) { bdbg("ERROR: Failed to execute program '%s'\n", filename); unload_module(&bin); return ERROR; } return ret; }
int unload_module(FAR struct binary_s *binp) { int ret; int i; if (binp) { /* Perform any format-specific unload operations */ if (binp->unload) { ret = binp->unload(binp); if (ret < 0) { bdbg("binp->unload() failed: %d\n", ret); set_errno(-ret); return ERROR; } } #ifdef CONFIG_BINFMT_CONSTRUCTORS /* Execute C++ destructors */ ret = exec_dtors(binp); if (ret < 0) { bdbg("exec_ctors() failed: %d\n", ret); set_errno(-ret); return ERROR; } #endif /* Unmap mapped address spaces */ if (binp->mapped) { bvdbg("Unmapping address space: %p\n", binp->mapped); munmap(binp->mapped, binp->mapsize); } /* Free allocated address spaces */ for (i = 0; i < BINFMT_NALLOC; i++) { if (binp->alloc[i]) { bvdbg("Freeing alloc[%d]: %p\n", i, binp->alloc[i]); kumm_free((FAR void *)binp->alloc[i]); } } /* Notice that the address environment is not destroyed. This should * happen automatically when the task exits. */ } return OK; }
static int nxflat_loadbinary(struct binary_s *binp) { struct nxflat_loadinfo_s loadinfo; /* Contains globals for libnxflat */ int ret; bvdbg("Loading file: %s\n", binp->filename); /* Initialize the xflat library to load the program binary. */ ret = nxflat_init(binp->filename, &loadinfo); nxflat_dumploadinfo(&loadinfo); if (ret != 0) { bdbg("Failed to initialize for load of NXFLT program: %d\n", ret); goto errout; } /* Load the program binary */ ret = nxflat_load(&loadinfo); nxflat_dumploadinfo(&loadinfo); if (ret != 0) { bdbg("Failed to load NXFLT program binary: %d\n", ret); goto errout_with_init; } /* Bind the program to the exported symbol table */ ret = nxflat_bind(&loadinfo, binp->exports, binp->nexports); if (ret != 0) { bdbg("Failed to bind symbols program binary: %d\n", ret); goto errout_with_load; } /* Return the load information */ binp->entrypt = (main_t)(loadinfo.ispace + loadinfo.entryoffs); binp->ispace = (void*)loadinfo.ispace; binp->dspace = (void*)loadinfo.dspace; binp->isize = loadinfo.isize; binp->stacksize = loadinfo.stacksize; nxflat_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt, MIN(binp->isize - loadinfo.entryoffs,512)); nxflat_uninit(&loadinfo); return OK; errout_with_load: nxflat_unload(&loadinfo); errout_with_init: nxflat_uninit(&loadinfo); errout: return ret; }
int nxflat_read(struct nxflat_loadinfo_s *loadinfo, char *buffer, int readsize, int offset) { ssize_t nbytes; /* Number of bytes read */ off_t rpos; /* Position returned by lseek */ char *bufptr; /* Next buffer location to read into */ int bytesleft; /* Number of bytes of .data left to read */ int bytesread; /* Total number of bytes read */ bvdbg("Read %d bytes from offset %d\n", readsize, offset); /* Seek to the position in the object file where the initialized * data is saved. */ bytesread = 0; bufptr = buffer; bytesleft = readsize; do { rpos = lseek(loadinfo->filfd, offset, SEEK_SET); if (rpos != offset) { int errval = errno; bdbg("Failed to seek to position %d: %d\n", offset, errval); return -errval; } /* Read the file data at offset into the user buffer */ nbytes = read(loadinfo->filfd, bufptr, bytesleft); if (nbytes < 0) { int errval = errno; if (errval != EINTR) { bdbg("Read from offset %d failed: %d\n", offset, errval); return -errval; } } else if (nbytes == 0) { bdbg("Unexpected end of file\n"); return -ENODATA; } else { bytesread += nbytes; bytesleft -= nbytes; bufptr += nbytes; offset += nbytes; } } while (bytesread < readsize); nxflat_dumpreaddata(buffer, readsize); return OK; }
static int builtin_loadbinary(struct binary_s *binp) { FAR const char *filename; FAR const struct builtin_s *b; int fd; int index; int ret; bvdbg("Loading file: %s\n", binp->filename); /* Open the binary file for reading (only) */ fd = open(binp->filename, O_RDONLY); if (fd < 0) { int errval = get_errno(); bdbg("ERROR: Failed to open binary %s: %d\n", binp->filename, errval); return -errval; } /* If this file is a BINFS file system, then we can recover the name of * the file using the FIOC_FILENAME ioctl() call. */ ret = ioctl(fd, FIOC_FILENAME, (unsigned long)((uintptr_t)&filename)); if (ret < 0) { int errval = get_errno(); bdbg("ERROR: FIOC_FILENAME ioctl failed: %d\n", errval); return -errval; } /* Other file systems may also support FIOC_FILENAME, so the real proof * is that we can look up the index to this name in g_builtins[]. */ index = builtin_isavail(filename); if (index < 0) { int errval = get_errno(); bdbg("ERROR: %s is not a builtin application\n", filename); return -errval; } /* Return the load information. NOTE: that there is no way to configure * the priority. That is a bug and needs to be fixed. */ b = builtin_for_index(index); binp->entrypt = b->main; binp->stacksize = b->stacksize; binp->priority = b->priority; return OK; }
int elf_load(FAR struct elf_loadinfo_s *loadinfo) { int ret; bvdbg("loadinfo: %p\n", loadinfo); DEBUGASSERT(loadinfo && loadinfo->filfd >= 0); /* Load section headers into memory */ ret = elf_loadshdrs(loadinfo); if (ret < 0) { bdbg("elf_loadshdrs failed: %d\n", ret); goto errout_with_buffers; } /* Determine total size to allocate */ elf_elfsize(loadinfo); /* Allocate memory and load sections into memory */ ret = elf_loadfile(loadinfo); if (ret < 0) { bdbg("elf_loadfile failed: %d\n", ret); goto errout_with_buffers; } /* Load static constructors and destructors. */ #ifdef CONFIG_BINFMT_CONSTRUCTORS ret = elf_loadctors(loadinfo); if (ret < 0) { bdbg("elf_loadctors failed: %d\n", ret); goto errout_with_buffers; } ret = elf_loaddtors(loadinfo); if (ret < 0) { bdbg("elf_loaddtors failed: %d\n", ret); goto errout_with_buffers; } #endif return OK; /* Error exits */ errout_with_buffers: elf_unload(loadinfo); return ret; }
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize, size_t datasize, size_t heapsize) { #ifdef CONFIG_ARCH_ADDRENV FAR void *vtext; FAR void *vdata; int ret; /* Create an address environment for the new ELF task */ ret = up_addrenv_create(textsize, datasize, heapsize, &loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_create failed: %d\n", ret); return ret; } /* Get the virtual address associated with the start of the address * environment. This is the base address that we will need to use to * access the ELF image (but only if the address environment has been * selected. */ ret = up_addrenv_vtext(&loadinfo->addrenv, &vtext); if (ret < 0) { bdbg("ERROR: up_addrenv_vtext failed: %d\n", ret); return ret; } ret = up_addrenv_vdata(&loadinfo->addrenv, textsize, &vdata); if (ret < 0) { bdbg("ERROR: up_adup_addrenv_vdatadrenv_vtext failed: %d\n", ret); return ret; } loadinfo->textalloc = (uintptr_t)vtext; loadinfo->dataalloc = (uintptr_t)vdata; return OK; #else /* Allocate memory to hold the ELF image */ loadinfo->textalloc = (uintptr_t)kumm_zalloc(textsize + datasize); if (!loadinfo->textalloc) { return -ENOMEM; } loadinfo->dataalloc = loadinfo->textalloc + textsize; return OK; #endif }
int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer, size_t readsize, off_t offset) { ssize_t nbytes; /* Number of bytes read */ off_t rpos; /* Position returned by lseek */ bvdbg("Read %ld bytes from offset %ld\n", (long)readsize, (long)offset); /* Loop until all of the requested data has been read. */ while (readsize > 0) { /* Seek to the next read position */ rpos = lseek(loadinfo->filfd, offset, SEEK_SET); if (rpos != offset) { int errval = errno; bdbg("Failed to seek to position %ld: %d\n", (long)offset, errval); return -errval; } /* Read the file data at offset into the user buffer */ nbytes = read(loadinfo->filfd, buffer, readsize); if (nbytes < 0) { int errval = errno; /* EINTR just means that we received a signal */ if (errval != EINTR) { bdbg("Read of .data failed: %d\n", errval); return -errval; } } else if (nbytes == 0) { bdbg("Unexpected end of file\n"); return -ENODATA; } else { readsize -= nbytes; buffer += nbytes; offset += nbytes; } } elf_dumpreaddata(buffer, readsize); return OK; }
int load_module(FAR struct binary_s *bin) { FAR struct binfmt_s *binfmt; int ret = -ENOENT; #ifdef CONFIG_DEBUG if (bin && bin->filename) #endif { bdbg("Loading %s\n", bin->filename); /* Disabling pre-emption should be sufficient protection while * accessing the list of registered binary format handlers. */ sched_lock(); /* Traverse the list of registered binary format handlers. Stop * when either (1) a handler recognized and loads the format, or * (2) no handler recognizes the format. */ for (binfmt = g_binfmts; binfmt; binfmt = binfmt->next) { /* Use this handler to try to load the format */ ret = binfmt->load(bin); if (ret == OK) { /* Successfully loaded -- break out with ret == 0 */ bvdbg("Successfully loaded module %s\n", bin->filename); dump_module(bin); break; } } sched_unlock(); } /* This is an end-user function. Return failures via errno */ if (ret < 0) { bdbg("Returning errno %d\n", -ret); errno = -ret; return ERROR; } return OK; }
void elf_addrenv_free(FAR struct elf_loadinfo_s *loadinfo) { #ifdef CONFIG_ARCH_ADDRENV int ret; /* Free the address environment */ ret = up_addrenv_destroy(&loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_destroy failed: %d\n", ret); } #else /* If there is an allocation for the ELF image, free it */ if (loadinfo->textalloc != 0) { kumm_free((FAR void *)loadinfo->textalloc); } #endif /* Clear out all indications of the allocated address environment */ loadinfo->textalloc = 0; loadinfo->dataalloc = 0; loadinfo->textsize = 0; loadinfo->datasize = 0; }
int up_addrenv_ustackalloc(FAR struct tcb_s *tcb, size_t stacksize) { int ret; bvdbg("tcb=%p stacksize=%lu\n", tcb, (unsigned long)stacksize); DEBUGASSERT(tcb); /* Initialize the address environment list to all zeroes */ memset(tcb->xcp.ustack, 0, ARCH_STACK_NSECTS * sizeof(uintptr_t *)); /* Back the allocation up with physical pages and set up the level 2 mapping * (which of course does nothing until the L2 page table is hooked into * the L1 page table). */ /* Allocate .text space pages */ ret = arm_addrenv_create_region(tcb->xcp.ustack, ARCH_STACK_NSECTS, CONFIG_ARCH_STACK_VBASE, stacksize, MMU_L2_UDATAFLAGS); if (ret < 0) { bdbg("ERROR: Failed to create stack region: %d\n", ret); up_addrenv_ustackfree(tcb); return ret; } return OK; }
static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo) { FAR uint8_t *dest; int ret; int i; /* Allocate (and zero) memory for the ELF file. */ loadinfo->elfalloc = (uintptr_t)kzalloc(loadinfo->elfsize); if (!loadinfo->elfalloc) { return -ENOMEM; } /* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */ bvdbg("Loaded sections:\n"); dest = (FAR uint8_t*)loadinfo->elfalloc; for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; /* SHF_ALLOC indicates that the section requires memory during * execution */ if ((shdr->sh_flags & SHF_ALLOC) == 0) { continue; } /* SHT_NOBITS indicates that there is no data in the file for the * section. */ if (shdr->sh_type != SHT_NOBITS) { /* Read the section data from sh_offset to dest */ ret = elf_read(loadinfo, dest, shdr->sh_size, shdr->sh_offset); if (ret < 0) { bdbg("Failed to read section %d: %d\n", i, ret); return ret; } } /* Update sh_addr to point to copy in memory */ bvdbg("%d. %08x->%08x\n", i, (long)shdr->sh_addr, (long)dest); shdr->sh_addr = (uintptr_t)dest; /* Setup the memory pointer for the next time through the loop */ dest += ELF_ALIGNUP(shdr->sh_size); } return OK; }
int prun(FAR char *exepath, size_t varsize, size_t strsize) { FAR struct pexec_s *st; int errcode; int ret = OK; /* Load the POFF file into memory */ st = pload(exepath, varsize, varsize); if (!st) { bdbg("ERROR: Could not load %s\n", exepath); return -ENOEXEC; } bvdbg("Loaded %s\n", exepath); /* Execute the P-Code program until a stopping condition occurs */ for (;;) { /* Execute the instruction; Check for exceptional conditions */ errcode = pexec(st); if (errcode != eNOERROR) { break; } } if (errcode != eEXIT) { /* REVISIT: Select a more appropriated return errocode */ bdbg("ERROR: Runtime error 0x%02x -- Execution Stopped\n", errcode); ret = -ENOEXEC; } /* Clean up resources used by the interpreter */ bvdbg("Execution terminated\n"); pexec_release(st); return ret; }
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t envsize) { #ifdef CONFIG_ADDRENV FAR void *vaddr; int ret; /* Create an address environment for the new ELF task */ ret = up_addrenv_create(envsize, &loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_create failed: %d\n", ret); return ret; } /* Get the virtual address associated with the start of the address * environment. This is the base address that we will need to use to * access the ELF image (but only if the address environment has been * selected. */ ret = up_addrenv_vaddr(loadinfo->addrenv, &vaddr); if (ret < 0) { bdbg("ERROR: up_addrenv_vaddr failed: %d\n", ret); return ret; } loadinfo->elfalloc = (uintptr_t)vaddr; return OK; #else /* Allocate memory to hold the ELF image */ loadinfo->elfalloc = (uintptr_t)kuzalloc(envsize); if (!loadinfo->elfalloc) { return -ENOMEM; } return OK; #endif }
int nxflat_initialize(void) { int ret; /* Register ourselves as a binfmt loader */ bvdbg("Registering NXFLAT\n"); ret = register_binfmt(&g_nxflatbinfmt); if (ret != 0) { bdbg("Failed to register binfmt: %d\n", ret); } return ret; }
int nxflat_verifyheader(const struct nxflat_hdr_s *header) { if (!header) { bdbg("NULL NXFLAT header!"); return -ENOEXEC; } /* Check the FLT header -- magic number and revision. * * If the magic number does not match. Just return * silently. This is not our binary. */ if (strncmp(header->h_magic, NXFLAT_MAGIC, 4) != 0) { bdbg("Unrecognized magic=\"%c%c%c%c\"\n", header->h_magic[0], header->h_magic[1], header->h_magic[2], header->h_magic[3]); return -ENOEXEC; } return OK; }
int elf_initialize(void) { int ret; /* Register ourselves as a binfmt loader */ bvdbg("Registering ELF\n"); ret = register_binfmt(&g_elfbinfmt); if (ret != 0) { bdbg("Failed to register binfmt: %d\n", ret); } return ret; }
int builtin_initialize(void) { int ret; /* Register ourselves as a binfmt loader */ bvdbg("Registering Builtin Loader\n"); ret = register_binfmt(&g_builtin_binfmt); if (ret != 0) { bdbg("Failed to register binfmt: %d\n", ret); } return ret; }
static int load_default_priority(FAR struct binary_s *bin) { struct sched_param param; int ret; /* Get the priority of this thread */ ret = sched_getparam(0, ¶m); if (ret < 0) { bdbg("ERROR: sched_getparam failed: %d\n", errno); return ERROR; } /* Save that as the priority of child thread */ bin->priority = param.sched_priority; return ret; }
int elf_allocbuffer(FAR struct elf_loadinfo_s *loadinfo) { /* Has a buffer been allocated> */ if (!loadinfo->iobuffer) { /* No.. allocate one now */ loadinfo->iobuffer = (FAR uint8_t *)kmm_malloc(CONFIG_ELF_BUFFERSIZE); if (!loadinfo->iobuffer) { bdbg("Failed to allocate an I/O buffer\n"); return -ENOMEM; } loadinfo->buflen = CONFIG_ELF_BUFFERSIZE; } return OK; }
static inline int exec_dtors(FAR struct binary_s *binp) { binfmt_dtor_t *dtor = binp->dtors; #ifdef CONFIG_ARCH_ADDRENV save_addrenv_t oldenv; int ret; #endif int i; /* Instantiate the address environment containing the destructors */ #ifdef CONFIG_ARCH_ADDRENV ret = up_addrenv_select(&binp->addrenv, &oldenv); if (ret < 0) { bdbg("ERROR: up_addrenv_select() failed: %d\n", ret); return ret; } #endif /* Execute each destructor */ for (i = 0; i < binp->ndtors; i++) { bvdbg("Calling dtor %d at %p\n", i, (FAR void *)dtor); (*dtor)(); dtor++; } /* Restore the address environment */ #ifdef CONFIG_ARCH_ADDRENV return up_addrenv_restore(&oldenv); #else return OK; #endif }
static inline int exec_ctors(FAR const struct binary_s *binp) { binfmt_ctor_t *ctor = binp->ctors; #ifdef CONFIG_ADDRENV hw_addrenv_t oldenv; int ret; #endif int i; /* Instantiate the address enviroment containing the constructors */ #ifdef CONFIG_ADDRENV ret = up_addrenv_select(binp->addrenv, &oldenv); if (ret < 0) { bdbg("up_addrenv_select() failed: %d\n", ret); return ret; } #endif /* Execute each constructor */ for (i = 0; i < binp->nctors; i++) { bvdbg("Calling ctor %d at %p\n", i, (FAR void *)ctor); (*ctor)(); ctor++; } /* Restore the address enviroment */ #ifdef CONFIG_ADDRENV return up_addrenv_restore(oldenv); #else return OK; #endif }
void nxflat_addrenv_free(FAR struct nxflat_loadinfo_s *loadinfo) { FAR struct dspace_s *dspace; #ifdef CONFIG_ADDRENV int ret; #endif DEBUGASSERT(loadinfo); dspace = loadinfo->dspace; if (dspace) { #ifdef CONFIG_ADDRENV /* Destroy the address environment */ ret = up_addrenv_destroy(loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_destroy failed: %d\n", ret); } loadinfo->addrenv = 0; #else /* Free the allocated D-Space region */ if (dspace->region) { kufree(dspace->region); } #endif /* Now destroy the D-Space container */ DEBUGASSERT(dspace->crefs == 1); kfree(dspace); loadinfo->dspace = NULL; } }
int elf_reallocbuffer(FAR struct elf_loadinfo_s *loadinfo, size_t increment) { FAR void *buffer; size_t newsize; /* Get the new size of the allocation */ newsize = loadinfo->buflen + increment; /* And perform the reallocation */ buffer = kmm_realloc((FAR void *)loadinfo->iobuffer, newsize); if (!buffer) { bdbg("Failed to reallocate the I/O buffer\n"); return -ENOMEM; } /* Save the new buffer info */ loadinfo->iobuffer = buffer; loadinfo->buflen = newsize; return OK; }
static int load_absmodule(FAR struct binary_s *bin) { FAR struct binfmt_s *binfmt; int ret = -ENOENT; bdbg("Loading %s\n", bin->filename); /* Disabling pre-emption should be sufficient protection while accessing * the list of registered binary format handlers. */ sched_lock(); /* Traverse the list of registered binary format handlers. Stop * when either (1) a handler recognized and loads the format, or * (2) no handler recognizes the format. */ for (binfmt = g_binfmts; binfmt; binfmt = binfmt->next) { /* Use this handler to try to load the format */ ret = binfmt->load(bin); if (ret == OK) { /* Successfully loaded -- break out with ret == 0 */ bvdbg("Successfully loaded module %s\n", bin->filename); dump_module(bin); break; } } sched_unlock(); return ret; }
static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo) { FAR uint8_t *dest; int ret; int i; /* Allocate (and zero) memory for the ELF file. */ ret = elf_addrenv_alloc(loadinfo, loadinfo->elfsize); if (ret < 0) { bdbg("ERROR: elf_addrenv_alloc() failed: %d\n", ret); return ret; } /* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */ bvdbg("Loaded sections:\n"); dest = (FAR uint8_t*)loadinfo->elfalloc; for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; /* SHF_ALLOC indicates that the section requires memory during * execution */ if ((shdr->sh_flags & SHF_ALLOC) == 0) { continue; } /* SHT_NOBITS indicates that there is no data in the file for the * section. */ if (shdr->sh_type != SHT_NOBITS) { /* If CONFIG_ADDRENV=y, then 'dest' lies in a virtual address space * that may not be in place now. elf_addrenv_select() will * temporarily instantiate that address space. */ #ifdef CONFIG_ADDRENV ret = elf_addrenv_select(loadinfo); if (ret < 0) { bdbg("ERROR: elf_addrenv_select() failed: %d\n", ret); return ret; } #endif /* Read the section data from sh_offset to dest */ ret = elf_read(loadinfo, dest, shdr->sh_size, shdr->sh_offset); if (ret < 0) { bdbg("Failed to read section %d: %d\n", i, ret); return ret; } /* Restore the original address environment */ #ifdef CONFIG_ADDRENV ret = elf_addrenv_restore(loadinfo); if (ret < 0) { bdbg("ERROR: elf_addrenv_restore() failed: %d\n", ret); return ret; } #endif } /* Update sh_addr to point to copy in memory */ bvdbg("%d. %08x->%08x\n", i, (long)shdr->sh_addr, (long)dest); shdr->sh_addr = (uintptr_t)dest; /* Setup the memory pointer for the next time through the loop */ dest += ELF_ALIGNUP(shdr->sh_size); } return OK; }
int nxflat_init(const char *filename, struct nxflat_loadinfo_s *loadinfo) { uint32_t datastart; uint32_t dataend; uint32_t bssstart; uint32_t bssend; int ret; bvdbg("filename: %s loadinfo: %p\n", filename, loadinfo); /* Clear the load info structure */ memset(loadinfo, 0, sizeof(struct nxflat_loadinfo_s)); /* Open the binary file */ loadinfo->filfd = open(filename, O_RDONLY); if (loadinfo->filfd < 0) { bdbg("Failed to open NXFLAT binary %s: %d\n", filename, ret); return -errno; } /* Read the NXFLAT header from offset 0 */ ret = nxflat_read(loadinfo, (char*)&loadinfo->header, sizeof(struct nxflat_hdr_s), 0); if (ret < 0) { bdbg("Failed to read NXFLAT header: %d\n", ret); return ret; } nxflat_dumpbuffer("NXFLAT header", (FAR const uint8_t*)&loadinfo->header, sizeof(struct nxflat_hdr_s)); /* Verify the NXFLAT header */ if (nxflat_verifyheader(&loadinfo->header) != 0) { /* This is not an error because we will be called to attempt loading * EVERY binary. Returning -ENOEXEC simply informs the system that * the file is not an NXFLAT file. Besides, if there is something worth * complaining about, nnxflat_verifyheader() has already * done so. */ bdbg("Bad NXFLAT header\n"); return -ENOEXEC; } /* Save all of the input values in the loadinfo structure * and extract some additional information from the xflat * header. Note that the information in the xflat header is in * network order. */ datastart = ntohl(loadinfo->header.h_datastart); dataend = ntohl(loadinfo->header.h_dataend); bssstart = dataend; bssend = ntohl(loadinfo->header.h_bssend); /* And put this information into the loadinfo structure as well. * * Note that: * * isize = the address range from 0 up to datastart. * datasize = the address range from datastart up to dataend * bsssize = the address range from dataend up to bssend. */ loadinfo->entryoffs = ntohl(loadinfo->header.h_entry); loadinfo->isize = datastart; loadinfo->datasize = dataend - datastart; loadinfo->bsssize = bssend - dataend; loadinfo->stacksize = ntohl(loadinfo->header.h_stacksize); /* This is the initial dspace size. We'll re-calculate this later * after the memory has been allocated. */ loadinfo->dsize = bssend - datastart; /* Get the offset to the start of the relocations (we'll relocate * this later). */ loadinfo->relocstart = ntohl(loadinfo->header.h_relocstart); loadinfo->reloccount = ntohs(loadinfo->header.h_reloccount); return 0; }
int group_addrenv(FAR struct tcb_s *tcb) { FAR struct task_group_s *group; FAR struct task_group_s *oldgroup; irqstate_t flags; gid_t gid; int ret; /* NULL for the tcb means to use the TCB of the task at the head of the * ready to run list. */ if (!tcb) { tcb = (FAR struct tcb_s *)g_readytorun.head; } DEBUGASSERT(tcb && tcb->group); group = tcb->group; /* Does the group have an address environment? */ if ((group->tg_flags & GROUP_FLAG_ADDRENV) == 0) { /* No... just return perhaps leaving a different address environment * intact. */ return OK; } /* Get the ID of the group that needs the address environment */ gid = group->tg_gid; DEBUGASSERT(gid != 0); /* Are we going to change address environments? */ flags = irqsave(); if (gid != g_gid_current) { /* Yes.. Is there a current address environment in place? */ if (g_gid_current != 0) { /* Find the old group with this ID. */ oldgroup = group_findbygid(g_gid_current); DEBUGASSERT(oldgroup && (oldgroup->tg_flags & GROUP_FLAG_ADDRENV) != 0); if (oldgroup) { /* We need to flush the D-Cache and Invalidate the I-Cache for * the group whose environment is disappearing. */ up_addrenv_coherent(&oldgroup->addrenv); } } /* Instantiate the new address environment (removing the old * environment in the process). For the case of kernel threads, * the old mappings will be removed and no new mappings will be * instantiated. */ ret = up_addrenv_select(&group->addrenv, NULL); if (ret < 0) { bdbg("ERROR: up_addrenv_select failed: %d\n", ret); } /* Save the new, current group */ g_gid_current = gid; } irqrestore(flags); return OK; }
int exec_module(FAR const struct binary_s *binp) { FAR _TCB *tcb; #ifndef CONFIG_CUSTOM_STACK FAR uint32_t *stack; #endif pid_t pid; int err; int ret; /* Sanity checking */ #ifdef CONFIG_DEBUG if (!binp || !binp->entrypt || binp->stacksize <= 0) { err = EINVAL; goto errout; } #endif bdbg("Executing %s\n", binp->filename); /* Allocate a TCB for the new task. */ tcb = (FAR _TCB*)kzalloc(sizeof(_TCB)); if (!tcb) { err = ENOMEM; goto errout; } /* Allocate the stack for the new task */ #ifndef CONFIG_CUSTOM_STACK stack = (FAR uint32_t*)kmalloc(binp->stacksize); if (!tcb) { err = ENOMEM; goto errout_with_tcb; } /* Initialize the task */ ret = task_init(tcb, binp->filename, binp->priority, stack, binp->stacksize, binp->entrypt, binp->argv); #else /* Initialize the task */ ret = task_init(tcb, binp->filename, binp->priority, stack, binp->entrypt, binp->argv); #endif if (ret < 0) { err = errno; bdbg("task_init() failed: %d\n", err); goto errout_with_stack; } /* Note that tcb->flags are not modified. 0=normal task */ /* tcb->flags |= TCB_FLAG_TTYPE_TASK; */ /* Add the D-Space address as the PIC base address. By convention, this * must be the first allocated address space. */ #ifdef CONFIG_PIC tcb->dspace = binp->alloc[0]; /* Re-initialize the task's initial state to account for the new PIC base */ up_initial_state(tcb); #endif /* Assign the address environment to the task */ #ifdef CONFIG_ADDRENV ret = up_addrenv_assign(binp->addrenv, tcb); if (ret < 0) { err = -ret; bdbg("up_addrenv_assign() failed: %d\n", ret); goto errout_with_stack; } #endif /* Get the assigned pid before we start the task */ pid = tcb->pid; /* Execute all of the C++ static constructors */ #ifdef CONFIG_BINFMT_CONSTRUCTORS ret = exec_ctors(binp); if (ret < 0) { err = -ret; bdbg("exec_ctors() failed: %d\n", ret); goto errout_with_stack; } #endif /* Then activate the task at the provided priority */ ret = task_activate(tcb); if (ret < 0) { err = errno; bdbg("task_activate() failed: %d\n", err); goto errout_with_stack; } return (int)pid; errout_with_stack: #ifndef CONFIG_CUSTOM_STACK tcb->stack_alloc_ptr = NULL; sched_releasetcb(tcb); kfree(stack); #else sched_releasetcb(tcb); #endif goto errout; errout_with_tcb: kfree(tcb); errout: errno = err; bdbg("returning errno: %d\n", err); return ERROR; }