int mod_loadshdrs(FAR struct mod_loadinfo_s *loadinfo) { size_t shdrsize; int ret; DEBUGASSERT(loadinfo->shdr == NULL); /* Verify that there are sections */ if (loadinfo->ehdr.e_shnum < 1) { serr("ERROR: No sections(?)\n"); return -EINVAL; } /* Get the total size of the section header table */ shdrsize = (size_t)loadinfo->ehdr.e_shentsize * (size_t)loadinfo->ehdr.e_shnum; if (loadinfo->ehdr.e_shoff + shdrsize > loadinfo->filelen) { serr("ERROR: Insufficent space in file for section header table\n"); return -ESPIPE; } /* Allocate memory to hold a working copy of the sector header table */ loadinfo->shdr = (FAR FAR Elf32_Shdr *)kmm_malloc(shdrsize); if (!loadinfo->shdr) { serr("ERROR: Failed to allocate the section header table. Size: %ld\n", (long)shdrsize); return -ENOMEM; } /* Read the section header table into memory */ ret = mod_read(loadinfo, (FAR uint8_t *)loadinfo->shdr, shdrsize, loadinfo->ehdr.e_shoff); if (ret < 0) { serr("ERROR: Failed to read section header table: %d\n", ret); } return ret; }
static inline int mod_loadfile(FAR struct mod_loadinfo_s *loadinfo) { FAR uint8_t *text; FAR uint8_t *data; FAR uint8_t **pptr; int ret; int i; /* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */ svdbg("Loaded sections:\n"); text = (FAR uint8_t *)loadinfo->textalloc; data = (FAR uint8_t *)loadinfo->datastart; 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; } /* SHF_WRITE indicates that the section address space is write- * able */ if ((shdr->sh_flags & SHF_WRITE) != 0) { pptr = &data; } else { pptr = &text; } /* 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 the memory region */ ret = mod_read(loadinfo, *pptr, shdr->sh_size, shdr->sh_offset); if (ret < 0) { sdbg("ERROR: Failed to read section %d: %d\n", i, ret); return ret; } } /* If there is no data in an allocated section, then the allocated * section must be cleared. */ else { memset(*pptr, 0, shdr->sh_size); } /* Update sh_addr to point to copy in memory */ svdbg("%d. %08lx->%08lx\n", i, (unsigned long)shdr->sh_addr, (unsigned long)*pptr); shdr->sh_addr = (uintptr_t)*pptr; /* Setup the memory pointer for the next time through the loop */ *pptr += ELF_ALIGNUP(shdr->sh_size); } return OK; }
static inline int mod_sectname(FAR struct mod_loadinfo_s *loadinfo, FAR const Elf32_Shdr *shdr) { FAR Elf32_Shdr *shstr; FAR uint8_t *buffer; off_t offset; size_t readlen; size_t bytesread; int shstrndx; int ret; /* Get the section header table index of the entry associated with the * section name string table. If the file has no section name string table, * this member holds the value SH_UNDEF. */ shstrndx = loadinfo->ehdr.e_shstrndx; if (shstrndx == SHN_UNDEF) { serr("ERROR: No section header string table\n"); return -EINVAL; } /* Get the section name string table section header */ shstr = &loadinfo->shdr[shstrndx]; /* Get the file offset to the string that is the name of the section. This * is the sum of: * * shstr->sh_offset: The file offset to the first byte of the section * header string table data. * shdr->sh_name: The offset to the name of the section in the section * name table */ offset = shstr->sh_offset + shdr->sh_name; /* Loop until we get the entire section name into memory */ buffer = loadinfo->iobuffer; bytesread = 0; for (; ; ) { /* Get the number of bytes to read */ readlen = loadinfo->buflen - bytesread; if (offset + readlen > loadinfo->filelen) { if (loadinfo->filelen <= offset) { serr("ERROR: At end of file\n"); return -EINVAL; } readlen = loadinfo->filelen - offset; } /* Read that number of bytes into the array */ buffer = &loadinfo->iobuffer[bytesread]; ret = mod_read(loadinfo, buffer, readlen, offset); if (ret < 0) { serr("ERROR: Failed to read section name: %d\n", ret); return ret; } bytesread += readlen; /* Did we read the NUL terminator? */ if (memchr(buffer, '\0', readlen) != NULL) { /* Yes, the buffer contains a NUL terminator. */ return OK; } /* No.. then we have to read more */ ret = mod_reallocbuffer(loadinfo, CONFIG_MODULE_BUFFERINCR); if (ret < 0) { serr("ERROR: mod_reallocbuffer failed: %d\n", ret); return ret; } } /* We will not get here */ return OK; }
int mod_initialize(FAR const char *filename, FAR struct mod_loadinfo_s *loadinfo) { int ret; svdbg("filename: %s loadinfo: %p\n", filename, loadinfo); /* Clear the load info structure */ memset(loadinfo, 0, sizeof(struct mod_loadinfo_s)); /* Get the length of the file. */ ret = mod_filelen(loadinfo, filename); if (ret < 0) { sdbg("mod_filelen failed: %d\n", ret); return ret; } /* Open the binary file for reading (only) */ loadinfo->filfd = open(filename, O_RDONLY); if (loadinfo->filfd < 0) { int errval = errno; sdbg("Failed to open ELF binary %s: %d\n", filename, errval); return -errval; } /* Read the ELF ehdr from offset 0 */ ret = mod_read(loadinfo, (FAR uint8_t *)&loadinfo->ehdr, sizeof(Elf32_Ehdr), 0); if (ret < 0) { sdbg("Failed to read ELF header: %d\n", ret); return ret; } mod_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr, sizeof(Elf32_Ehdr)); /* Verify the ELF header */ ret = mod_verifyheader(&loadinfo->ehdr); if (ret < 0) { /* This may not be an error because we will be called to attempt loading * EVERY binary. If mod_verifyheader() does not recognize the ELF header, * it will -ENOEXEC whcih simply informs the system that the file is not an * ELF file. mod_verifyheader() will return other errors if the ELF header * is not correctly formed. */ sdbg("Bad ELF header: %d\n", ret); return ret; } return OK; }