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 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; }
int up_addrenv_destroy(FAR group_addrenv_t *addrenv) { bvdbg("addrenv=%p\n", addrenv); DEBUGASSERT(addrenv); /* Destroy the .text region */ arm_addrenv_destroy_region(addrenv->text, ARCH_TEXT_NSECTS, CONFIG_ARCH_TEXT_VBASE); /* Destroy the .bss/.data region */ arm_addrenv_destroy_region(addrenv->data, ARCH_DATA_NSECTS, CONFIG_ARCH_DATA_VBASE); #ifdef CONFIG_BUILD_KERNEL /* Destroy the heap region */ arm_addrenv_destroy_region(addrenv->heap, ARCH_HEAP_NSECTS, CONFIG_ARCH_HEAP_VBASE); #endif memset(addrenv, 0, sizeof(group_addrenv_t)); return OK; }
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; }
int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb) { bvdbg("group=%p tcb=%p\n", group, tcb); /* Nothing needs to be done in this implementation */ return OK; }
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 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 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 up_addrenv_vustack(FAR const struct tcb_s *tcb, FAR void **vstack) { bvdbg("Return=%p\n", (FAR void *)CONFIG_ARCH_STACK_VBASE); /* Not much to do in this case */ DEBUGASSERT(tcb); *vstack = (FAR void *)CONFIG_ARCH_STACK_VBASE; return OK; }
int up_addrenv_vtext(FAR group_addrenv_t *addrenv, FAR void **vtext) { bvdbg("return=%p\n", (FAR void *)CONFIG_ARCH_TEXT_VBASE); /* Not much to do in this case */ DEBUGASSERT(addrenv && vtext); *vtext = (FAR void *)CONFIG_ARCH_TEXT_VBASE; 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 up_addrenv_clone(FAR const group_addrenv_t *src, FAR group_addrenv_t *dest) { bvdbg("src=%p dest=%p\n", src, dest); DEBUGASSERT(src && dest); /* Just copy the address environment from the source to the destination */ memcpy(dest, src, sizeof(group_addrenv_t)); return OK; }
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 up_addrenv_vdata(FAR group_addrenv_t *addrenv, uintptr_t textsize, FAR void **vdata) { bvdbg("return=%p\n", (FAR void *)(CONFIG_ARCH_DATA_VBASE + ARCH_DATA_RESERVE_SIZE)); /* Not much to do in this case */ DEBUGASSERT(addrenv && vdata); *vdata = (FAR void *)(CONFIG_ARCH_DATA_VBASE + ARCH_DATA_RESERVE_SIZE); return OK; }
int up_addrenv_ustackfree(FAR struct tcb_s *tcb) { bvdbg("tcb=%p\n", tcb); DEBUGASSERT(tcb); /* Destroy the stack region */ arm_addrenv_destroy_region(tcb->xcp.ustack, ARCH_STACK_NSECTS, CONFIG_ARCH_STACK_VBASE); memset(tcb->xcp.ustack, 0, ARCH_STACK_NSECTS * sizeof(uintptr_t *)); return OK; }
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 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; }
static inline void exec_ctors(FAR const struct binary_s *binp) { binfmt_ctor_t *ctor = binp->ctors; int i; /* Execute each constructor */ for (i = 0; i < binp->nctors; i++) { bvdbg("Calling ctor %d at %p\n", i, (FAR void *)ctor); (*ctor)(); ctor++; } }
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; }
int up_addrenv_restore(FAR const save_addrenv_t *oldenv) { uintptr_t vaddr; int i; bvdbg("oldenv=%p\n", oldenv); DEBUGASSERT(oldenv); for (vaddr = CONFIG_ARCH_TEXT_VBASE, i = 0; i < ARCH_TEXT_NSECTS; vaddr += SECTION_SIZE, i++) { /* Restore the L1 page table entry */ mmu_l1_restore(vaddr, oldenv->text[i]); } for (vaddr = CONFIG_ARCH_DATA_VBASE, i = 0; i < ARCH_DATA_NSECTS; vaddr += SECTION_SIZE, i++) { /* Restore the L1 page table entry */ mmu_l1_restore(vaddr, oldenv->data[i]); } #ifdef CONFIG_BUILD_KERNEL for (vaddr = CONFIG_ARCH_HEAP_VBASE, i = 0; i < ARCH_HEAP_NSECTS; vaddr += SECTION_SIZE, i++) { /* Restore the L1 page table entry */ mmu_l1_restore(vaddr, oldenv->heap[i]); } #endif return OK; }
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 }
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 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 int elf_loadbinary(struct binary_s *binp) { struct elf_loadinfo_s loadinfo; /* Contains globals for libelf */ int ret; bvdbg("Loading file: %s\n", binp->filename); /* Initialize the xflat library to load the program binary. */ ret = elf_init(binp->filename, &loadinfo); elf_dumploadinfo(&loadinfo); if (ret != 0) { bdbg("Failed to initialize for load of ELF program: %d\n", ret); goto errout; } /* Load the program binary */ ret = elf_load(&loadinfo); elf_dumploadinfo(&loadinfo); if (ret != 0) { bdbg("Failed to load ELF program binary: %d\n", ret); goto errout_with_init; } /* Bind the program to the exported symbol table */ ret = elf_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.elfalloc + loadinfo.ehdr.e_entry); binp->alloc[0] = (FAR void *)loadinfo.elfalloc; binp->stacksize = CONFIG_ELF_STACKSIZE; #ifdef CONFIG_BINFMT_CONSTRUCTORS /* Save information about constructors. NOTE: desctructors are not * yet supported. */ binp->alloc[1] = loadinfo.ctoralloc; binp->ctors = loadinfo.ctors; binp->nctors = loadinfo.nctors; binp->alloc[2] = loadinfo.dtoralloc; binp->dtors = loadinfo.dtors; binp->ndtors = loadinfo.ndtors; #endif elf_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt, MIN(loadinfo.allocsize - loadinfo.ehdr.e_entry, 512)); elf_uninit(&loadinfo); return OK; errout_with_load: elf_unload(&loadinfo); errout_with_init: elf_uninit(&loadinfo); errout: return ret; }
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 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("ERROR: elf_loadshdrs failed: %d\n", ret); goto errout_with_buffers; } /* Determine total size to allocate */ elf_elfsize(loadinfo); /* Allocate (and zero) memory for the ELF file. */ ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize); if (ret < 0) { bdbg("ERROR: elf_addrenv_alloc() failed: %d\n", ret); goto errout_with_buffers; } #ifdef CONFIG_ARCH_ADDRENV /* 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); goto errout_with_buffers; } #endif /* Load ELF section data into memory */ ret = elf_loadfile(loadinfo); if (ret < 0) { bdbg("ERROR: elf_loadfile failed: %d\n", ret); goto errout_with_addrenv; } /* Load static constructors and destructors. */ #ifdef CONFIG_BINFMT_CONSTRUCTORS ret = elf_loadctors(loadinfo); if (ret < 0) { bdbg("ERROR: elf_loadctors failed: %d\n", ret); goto errout_with_addrenv; } ret = elf_loaddtors(loadinfo); if (ret < 0) { bdbg("ERROR: elf_loaddtors failed: %d\n", ret); goto errout_with_addrenv; } #endif #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); goto errout_with_buffers; } #endif return OK; /* Error exits */ errout_with_addrenv: #ifdef CONFIG_ARCH_ADDRENV (void)elf_addrenv_restore(loadinfo); #endif errout_with_buffers: elf_unload(loadinfo); return ret; }
int up_addrenv_create(size_t textsize, size_t datasize, size_t heapsize, FAR group_addrenv_t *addrenv) { int ret; bvdbg("addrenv=%p textsize=%lu datasize=%lu\n", addrenv, (unsigned long)textsize, (unsigned long)datasize); DEBUGASSERT(addrenv); /* Initialize the address environment structure to all zeroes */ memset(addrenv, 0, sizeof(group_addrenv_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(addrenv->text, ARCH_TEXT_NSECTS, CONFIG_ARCH_TEXT_VBASE, textsize, MMU_L2_UTEXTFLAGS); if (ret < 0) { bdbg("ERROR: Failed to create .text region: %d\n", ret); goto errout; } /* Allocate .bss/.data space pages. NOTE that a configurable offset is * added to the allocted size. This is matched by the offset that is * used when reporting the virtual data address in up_addrenv_vdata(). */ ret = arm_addrenv_create_region(addrenv->data, ARCH_DATA_NSECTS, CONFIG_ARCH_DATA_VBASE, datasize + ARCH_DATA_RESERVE_SIZE, MMU_L2_UDATAFLAGS); if (ret < 0) { bdbg("ERROR: Failed to create .bss/.data region: %d\n", ret); goto errout; } #ifdef CONFIG_BUILD_KERNEL /* Initialize the shared data are at the beginning of the .bss/.data * region. */ ret = up_addrenv_initdata((uintptr_t)addrenv->data[0] & PMD_PTE_PADDR_MASK); if (ret < 0) { bdbg("ERROR: Failed to initialize .bss/.data region: %d\n", ret); goto errout; } #endif #ifdef CONFIG_BUILD_KERNEL /* Allocate heap space pages */ ret = arm_addrenv_create_region(addrenv->heap, ARCH_HEAP_NSECTS, CONFIG_ARCH_HEAP_VBASE, heapsize, MMU_L2_UDATAFLAGS); if (ret < 0) { bdbg("ERROR: Failed to create heap region: %d\n", ret); goto errout; } /* Save the initial heap size allocated. This will be needed when * the heap data structures are initialized. */ addrenv->heapsize = (size_t)ret << MM_PGSHIFT; #endif return OK; errout: up_addrenv_destroy(addrenv); 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; }