int ELFManager::elf_read_ehdr(Elf_Ehdr &ehdr) { int ret; if(_is_32_bit) { Elf32_Ehdr ehdr32; ret = elf_read(0, &ehdr32, sizeof(ehdr32)); if (ret < 0) { fprintf(stderr, "read ehdr32 error!\n"); return -1; } ehdr.e_shoff = ehdr32.e_shoff; ehdr.e_shentsize = ehdr32.e_shentsize; ehdr.e_shnum = ehdr32.e_shnum; } else { Elf64_Ehdr ehdr64; ret = elf_read(0, &ehdr64, sizeof(ehdr64)); if (ret < 0) { fprintf(stderr, "read ehdr error!\n"); return -1; } ehdr.e_shoff = ehdr64.e_shoff; ehdr.e_shentsize = ehdr64.e_shentsize; ehdr.e_shnum = ehdr64.e_shnum; } return 0; }
char* elf_strptr(Elf *elf, size_t shstrndx, size_t str_idx) { int ofs,sofs,i; if (elf->strtab == NULL) { elf->strtab = elf64_getshdr_by_ndx(elf,shstrndx); DPRINTF((stderr,"StrTab(%d) at ofs=%d\n",shstrndx, E_OFF(elf->strtab->sh_offset))); } DPRINTF((stderr,"elf_strptr with shstrndx = %d, str_idx = %d\n", shstrndx, str_idx)); ofs = E_OFF(elf->strtab->sh_offset) + str_idx; sofs = 0; elf->strtab = NULL; do { elf_read(elf,ofs,&string_table[sofs],ELF_INTERN_STR); for ( i=0;i<ELF_INTERN_STR;i++ ) { if ( string_table[sofs+i] == '\0') return (string_table); } ofs += ELF_INTERN_STR; sofs += ELF_INTERN_STR; } while (sofs < ELF_STR_READS*ELF_INTERN_STR); return (NULL); }
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; }
Elf_Data* elf_getdata(Elf_Scn *scn, Elf_Data *data) { static Elf_Data theData; if (scn == NULL) return NULL; if (data == NULL) { elf_read(scn->elf,scn->shdr.sh_offset,&theData,sizeof(Elf_Data)); } return &theData; }
void* elf_alloc_read(Elf *elf, unsigned int ofs, size_t size) { void *buf = malloc(size); if (buf == NULL) { elf_error("No room for elf_alloc_read"); return (NULL); } elf_read(elf,ofs,buf,size); return (buf); }
int sys_execve(const char *filename, char *const argv[], char *const envp[]) { elf_t bin; if (!elf_read(filename, &bin)) { return -1; } elf_load(&bin); elf_start(&bin, argv, envp); /* never reached */ return -1; }
int ELFManager::elf_read_shdrs(Elf_Shdr *shdrs, unsigned int shnum) { int ret; if(_is_32_bit) { Elf32_Shdr shdrs32[shnum]; int shsize = shnum * _ehdr.e_shentsize; ret = elf_read(_ehdr.e_shoff , shdrs32, shsize); if (ret < 0) { return -1; } for (unsigned int i=0; i<shnum; i++) { shdrs[i].sh_type = shdrs32[i].sh_type; shdrs[i].sh_offset = shdrs32[i].sh_offset; shdrs[i].sh_size = shdrs32[i].sh_size; shdrs[i].sh_link = shdrs32[i].sh_link; shdrs[i].sh_entsize = shdrs32[i].sh_entsize; } } else { Elf64_Shdr shdrs64[shnum]; int shsize = shnum * _ehdr.e_shentsize; ret = elf_read(_ehdr.e_shoff , shdrs64, shsize); if (ret < 0) { return -1; } for (unsigned int i=0; i<shnum; i++) { shdrs[i].sh_type = shdrs64[i].sh_type; shdrs[i].sh_offset = shdrs64[i].sh_offset; shdrs[i].sh_size = shdrs64[i].sh_size; shdrs[i].sh_link = shdrs64[i].sh_link; shdrs[i].sh_entsize = shdrs64[i].sh_entsize; } } return 0; }
int elf_read_library(struct task *task, struct libref *libref, const char *filename, GElf_Addr bias) { struct mt_elf mte = { }; int ret; libref_set_filename(libref, filename); if (elf_read(&mte, task, filename) == -1) return -1; mte.bias = bias; mte.entry_addr = mte.ehdr.e_entry - mte.vstart + bias; ret = elf_lib_init(&mte, task, libref); close_elf(&mte); return ret; }
int ELFManager::elf_open(const char *filename) { //只读模式打开 _fd = open(filename, O_RDONLY); if (_fd < 0) { perror("open fail!"); return -1; } _filename = filename; int ret = elf_read(0, _ident, sizeof(_ident)); if (ret < 0) { fprintf(stderr, "read e_ident error!\n"); return -1; } _is_32_bit = (_ident[EI_CLASS] != ELFCLASS64); ret = elf_read_ehdr(_ehdr); if(ret != 0) { return -1; } return _fd; }
int main(int argc, char** argv) { if (argc < 2) { fprintf(stderr, "no input elf specified\n"); return EXIT_FAILURE; } elf_t elf; int ret = elf_read(argv[1], &elf); if (ret != 0) { fprintf(stderr, "unable to parse elf: %d\n", ret); return EXIT_FAILURE; } elf_print_sections(&elf); elf_print_symbols(&elf); int symbol; uint64_t faddr; uint32_t* val; ret = elf_get_symbol_by_name(&elf, "SOME_GLOBAL", &symbol); if (ret != 0) { fprintf(stderr, "no such symbol 'SOME_GLOBAL'\n"); return EXIT_FAILURE; } ret = elf_get_symbol_faddr(&elf, symbol, &faddr); if (ret != 0) { fprintf(stderr, "unable to map symbol: %d\n", ret); return EXIT_FAILURE; } val = (uint32_t*)(elf.elf_data + faddr); printf("Value of SOME_GLOBAL: 0x%x\n", *val); elf_free(&elf); return EXIT_SUCCESS; }
int elf_object_map(struct process *proc, struct elf_module *m) { int i; int r; dprintf("to load (%d)\n", m->num_to_load); dprintf("%-8s %-8s %-8s %-8s\n", "vaddr", "memsz", "offset", "filesz"); for (i = 0; i < m->num_to_load; i++) { m->min_vaddr = MIN(round_down_to_page(m->to_load[i].p_vaddr), m->min_vaddr); m->max_vaddr = MAX(round_up_to_page(m->to_load[i].p_vaddr + m->to_load[i].p_memsz), m->max_vaddr); dprintf("%08x %08x %08x %08x\n", m->to_load[i].p_vaddr, m->to_load[i].p_memsz, m->to_load[i].p_offset, m->to_load[i].p_filesz); } dprintf("vaddr -> %08x-%08x\n", m->min_vaddr, m->max_vaddr); /* reserve memory for image */ m->base = vm_process_map(proc, m->min_vaddr, m->max_vaddr - m->min_vaddr, _l_PROT_NONE, _l_MAP_ANONYMOUS|_l_MAP_PRIVATE, NULL, 0); if (m->base == _l_MAP_FAILED) { dprintf("mmap failed\n"); goto error; } dprintf("base = %08x\n", m->base); for (i = 0; i < m->num_to_load; i++) { int mapflags = elf_mmap_flags_get(m->to_load[i].p_flags); user_ptr_t p; unsigned int vaddr = round_down_to_page(m->to_load[i].p_vaddr); unsigned int vaddr_offset = (m->to_load[i].p_vaddr & pagemask); unsigned int memsz = round_up_to_page(vaddr_offset + m->to_load[i].p_memsz); unsigned int max_addr; void *ptr; size_t max_sz = 0; elf_map_flags_print(mapflags); p = m->base - m->min_vaddr + vaddr; dprintf("map at %08x, offset %08x sz %08x\n", p, vaddr, memsz); /* * Map anonymous memory then read the data in * rather than mapping the file directly. * * The windows page granularity is different to that on Linux. * The pages may need to be modified to apply relocations. * * nb. need MAP_FIXED to blow away our old mapping */ p = vm_process_map(proc, p, memsz, _l_PROT_READ | _l_PROT_WRITE | _l_PROT_EXEC, _l_MAP_FIXED|_l_MAP_PRIVATE|_l_MAP_ANONYMOUS, NULL, 0); if (p == _l_MAP_FAILED) { fprintf(stderr, "mmap failed (%d)\n", -(int)p); goto error; } p = m->base - m->min_vaddr + m->to_load[i].p_vaddr; dprintf("pread %08x bytes from %08x to %08x\n", m->to_load[i].p_filesz, m->to_load[i].p_offset, p); r = vm_get_pointer(proc, p, &ptr, &max_sz); if (r < 0) goto error; if (max_sz < m->to_load[i].p_filesz) { r = -_L(EPERM); goto error; } r = elf_read(m->fp, ptr, m->to_load[i].p_filesz, m->to_load[i].p_offset); if (r != m->to_load[i].p_filesz) { fprintf(stderr, "read failed (%08x != %08x)\n", m->to_load[i].p_filesz, r); goto error; } /* remember highest address we mapped, use it for brk */ max_addr = m->to_load[i].p_vaddr + m->to_load[i].p_memsz; max_addr = round_up(max_addr, pagesize); if (proc->brk < max_addr) proc->brk = max_addr; dprintf("brk at %08x\n", proc->brk); } m->entry_point = m->base - m->min_vaddr + m->ehdr.e_entry; return 0; error: return -1; }
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; }
Elf* elf_begin(int fd, Elf_Cmd cmd, Elf* usrelf) { Elf* relf; Elf64_Ehdr* ehdrp; /* at the current time we are only dealing with the reading of ELF files */ if (cmd != ELF_C_READ) { elf_error("we can only read ELF files"); return NULL; } if (usrelf) { relf = usrelf; } else { relf = (Elf*)malloc(sizeof(Elf)); if (relf == NULL) { elf_error("No memory for Elf header structure"); return NULL; } } /* initialization of the structure */ memset(relf,0,sizeof(Elf)); relf->fd = fd; relf->allocated = !usrelf; /* expect the file to be open, reset the file pointer */ lseek(fd,0,SEEK_SET); ehdrp = &relf->ehdr; elf_read(relf,0,ehdrp,sizeof(Elf64_Ehdr)); /* verify some information on the hdr */ if (! (IS_ELF(*ehdrp)) ) { elf_error("file is not ELF"); return NULL; } if (ehdrp->e_ident[EI_CLASS] != ELFCLASS64) { elf_error("Elf file is not 64 bit"); return NULL; } if (ehdrp->e_ident[EI_VERSION] != EV_CURRENT) { elf_error("Elf file is not current version"); return NULL; } /* determine if little-endian or big-endian -- must know before we try to access multi-byte fields */ if (ehdrp->e_ident[EI_DATA] == ELFDATA2LSB) { endian_elf = ELFDATA2LSB; DPRINTF((stderr,"Elf is little endian\n")); } else if (ehdrp->e_ident[EI_DATA] == ELFDATA2MSB) { endian_elf = ELFDATA2MSB; DPRINTF((stderr,"Elf is big endian\n")); } else { elf_error("Elf file is neither big nor little endian?"); return NULL; } { /* preparing the section header structures */ int recs = E_HALF(relf->ehdr.e_shnum); int size = recs * sizeof(Elf_Scn); int i; relf->scns = (Elf_Scn*)malloc(size); if (relf->scns == NULL) { elf_error("No memory for Elf section headers"); return NULL; } memset(relf->scns,0,size); DPRINTF((stderr,"Elf has %d sections\n", recs)); for (i=0;i<recs;i++) { long ofs; long n; relf->scns[i].elf = relf; relf->scns[i].idx = i; ofs = E_OFF(relf->ehdr.e_shoff) + i*E_HALF(relf->ehdr.e_shentsize); n = sizeof(Elf64_Shdr); DPRINTF((stderr," section %d is %d bytes at offset %ld\n", i, n, ofs)); elf_read(relf,ofs, &relf->scns[i].shdr,n); } } theElf = relf; return (relf); }
struct elf_module *elf_module_load(const char *path) { bool dynamic_seen = false; int r; int i; struct elf_module *m; m = malloc(sizeof *m); if (!m) return m; memset(m, 0, sizeof *m); m->base = _l_MAP_FAILED; m->min_vaddr = 0xfffff000; m->max_vaddr = 0; m->fp = filp_open(path, _l_O_RDONLY, 0, 1); r = L_PTR_ERROR(m->fp); if (r < 0) { dprintf("open() failed\n"); m->fp = NULL; goto error; } if (!m->fp->ops->fn_read) { r = -_L(EPERM); goto error; } r = elf_read(m->fp, &m->ehdr, sizeof m->ehdr, 0); if (r < 0) { dprintf("read() failed\n"); goto error; } if (memcmp(&m->ehdr, ELFMAG, SELFMAG)) { dprintf("not an ELF file\n"); goto error; } if (m->ehdr.e_type != ET_EXEC && m->ehdr.e_type != ET_REL && m->ehdr.e_type != ET_DYN) { dprintf("not an ELF executable\n"); goto error; } if (m->ehdr.e_machine != EM_386) { dprintf("not an i386 ELF executable\n"); goto error; } dprintf("opened ELF file, entry=%08x\n", m->ehdr.e_entry); dprintf("Program headers (%d)\n", m->ehdr.e_phnum); dprintf("%-4s %-8s %-8s %-8s %-8s %-8s %-8s\n", "type", "offset", "vaddr", "filesz", "memsz", "flags", "align"); for (i = 0; i < m->ehdr.e_phnum; i++) { Elf32_Phdr phdr; r = elf_read(m->fp, &phdr, sizeof phdr, m->ehdr.e_phoff + i * sizeof phdr); if (r < 0) break; dprintf("[%2d] %08x %08x %08x %08x %08x %08x\n", i, phdr.p_offset, phdr.p_vaddr, phdr.p_filesz, phdr.p_memsz, phdr.p_flags, phdr.p_align); /* load segments */ if (phdr.p_type == PT_LOAD) { if (m->num_to_load >= sizeof m->to_load/ sizeof m->to_load[0]) { dprintf("too many PT_LOAD entries\n"); goto error; } memcpy(&m->to_load[m->num_to_load], &phdr, sizeof phdr); m->num_to_load++; } if (phdr.p_type == PT_DYNAMIC) { if (dynamic_seen) { fprintf(stderr, "two PT_DYNAMIC sections\n"); goto error; } dynamic_seen = true; } if (phdr.p_type == PT_INTERP) { size_t sz = phdr.p_filesz; if (sz > sizeof m->interpreter - 1) { dprintf("interpreter name too big\n"); goto error; } r = elf_read(m->fp, &m->interpreter, sz, phdr.p_offset); if (r != sz) { dprintf("interpreter name read failed\n"); goto error; } m->interpreter[sz] = 0; } } return m; error: filp_close(m->fp); free(m); return NULL; }
int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo) { FAR Elf32_Shdr *shdr; size_t ctorsize; int ctoridx; int ret; int i; DEBUGASSERT(loadinfo->ctors == NULL); /* Allocate an I/O buffer if necessary. This buffer is used by * elf_sectname() to accumulate the variable length symbol name. */ ret = elf_allocbuffer(loadinfo); if (ret < 0) { bdbg("elf_allocbuffer failed: %d\n", ret); return -ENOMEM; } /* Find the index to the section named ".ctors." NOTE: On old ABI system, * .ctors is the name of the section containing the list of constructors; * On newer systems, the similar section is called .init_array. It is * expected that the linker script will force the section name to be ".ctors" * in either case. */ ctoridx = elf_findsection(loadinfo, ".ctors"); if (ctoridx < 0) { /* This may not be a failure. -ENOENT indicates that the file has no * static constructor section. */ bvdbg("elf_findsection .ctors section failed: %d\n", ctoridx); return ret == -ENOENT ? OK : ret; } /* Now we can get a pointer to the .ctor section in the section header * table. */ shdr = &loadinfo->shdr[ctoridx]; /* Get the size of the .ctor section and the number of constructors that * will need to be called. */ ctorsize = shdr->sh_size; loadinfo->nctors = ctorsize / sizeof(binfmt_ctor_t); bvdbg("ctoridx=%d ctorsize=%d sizeof(binfmt_ctor_t)=%d nctors=%d\n", ctoridx, ctorsize, sizeof(binfmt_ctor_t), loadinfo->nctors); /* Check if there are any constructors. It is not an error if there * are none. */ if (loadinfo->nctors > 0) { /* Check an assumption that we made above */ DEBUGASSERT(shdr->sh_size == loadinfo->nctors * sizeof(binfmt_ctor_t)); /* In the old ABI, the .ctors section is not allocated. In that case, * we need to allocate memory to hold the .ctors and then copy the * from the file into the allocated memory. * * SHF_ALLOC indicates that the section requires memory during * execution. */ if ((shdr->sh_flags & SHF_ALLOC) == 0) { /* Allocate memory to hold a copy of the .ctor section */ loadinfo->ctoralloc = (binfmt_ctor_t*)kmalloc(ctorsize); if (!loadinfo->ctoralloc) { bdbg("Failed to allocate memory for .ctors\n"); return -ENOMEM; } loadinfo->ctors = (binfmt_ctor_t *)loadinfo->ctoralloc; /* Read the section header table into memory */ ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->ctors, ctorsize, shdr->sh_offset); if (ret < 0) { bdbg("Failed to allocate .ctors: %d\n", ret); return ret; } /* Fix up all of the .ctor addresses. Since the addresses * do not lie in allocated memory, there will be no relocation * section for them. */ for (i = 0; i < loadinfo->nctors; i++) { FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]); bvdbg("ctor %d: %08lx + %08lx = %08lx\n", i, *ptr, loadinfo->elfalloc, *ptr + loadinfo->elfalloc); *ptr += loadinfo->elfalloc; } } else { /* Save the address of the .ctors (actually, .init_array) where it was * loaded into memory. Since the .ctors lie in allocated memory, they * will be relocated via the normal mechanism. */ loadinfo->ctors = (binfmt_ctor_t*)shdr->sh_addr; } } return OK; }
int ELFManager::elf_canonicalize_symbol(esymbol **symbol_table, int unsigned type) { int ret; Elf_Shdr shdrs[_ehdr.e_shnum]; ret = elf_read_shdrs(shdrs, _ehdr.e_shnum); if (ret < 0) { return -1; } unsigned int i = 0; for (; i<_ehdr.e_shnum; i++) { if (shdrs[i].sh_type == type) { break; } } if (i == _ehdr.e_shnum) { return -1; } Elf_Shdr *symtab = &shdrs[i]; //读取name Elf_Shdr *link = &shdrs[symtab->sh_link]; char *sym_name = (char *)malloc(link->sh_size); if (sym_name == NULL) { fprintf(stderr, "malloc error!\n"); return -1; } ret = elf_read(link->sh_offset, sym_name, link->sh_size); if (ret < 0) { return -1; } //读取符号表 int count = symtab->sh_size/symtab->sh_entsize; esymbol *esym = (esymbol *)&symbol_table[count]; if(_is_32_bit) { Elf32_Sym syms[count]; ret = elf_read(symtab->sh_offset, syms, symtab->sh_size); if (ret < 0) { return -1; } for (int idx=0; idx<count; idx++) { symbol_table[idx] = &esym[idx]; //printf("name:%s!, symbol_table:%llx\n", &sym_name[syms[idx].st_name], symbol_table[idx]); symbol_table[idx]->name = &sym_name[syms[idx].st_name]; //printf("debug3!\n"); symbol_table[idx]->bind = ELF32_ST_BIND(syms[idx].st_info); symbol_table[idx]->type = ELF32_ST_TYPE(syms[idx].st_info); symbol_table[idx]->shndx = syms[idx].st_shndx; symbol_table[idx]->value = syms[idx].st_value; symbol_table[idx]->size = syms[idx].st_size; } } else { Elf64_Sym syms[count]; ret = elf_read(symtab->sh_offset, syms, symtab->sh_size); if (ret < 0) { return -1; } for (int idx=0; idx<count; idx++) { symbol_table[idx] = &esym[idx]; //printf("name:%s!, symbol_table:%llx\n", &sym_name[syms[idx].st_name], symbol_table[idx]); symbol_table[idx]->name = &sym_name[syms[idx].st_name]; //printf("debug3!\n"); symbol_table[idx]->bind = ELF64_ST_BIND(syms[idx].st_info); symbol_table[idx]->type = ELF64_ST_TYPE(syms[idx].st_info); symbol_table[idx]->shndx = syms[idx].st_shndx; symbol_table[idx]->value = syms[idx].st_value; symbol_table[idx]->size = syms[idx].st_size; } } return count; }
static inline int elf_loadfile(FAR struct elf_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 */ bvdbg("Loaded sections:\n"); text = (FAR uint8_t*)loadinfo->textalloc; data = (FAR uint8_t*)loadinfo->dataalloc; 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 = elf_read(loadinfo, *pptr, shdr->sh_size, shdr->sh_offset); if (ret < 0) { bdbg("ERROR: Failed to read section %d: %d\n", i, ret); return ret; } } /* Update sh_addr to point to copy in memory */ bvdbg("%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; }
int ELFManager::elf_canonicalize_relsym(erelsym **rel_table, int max_count) { int ret; Elf_Shdr shdrs[_ehdr.e_shnum]; ret = elf_read_shdrs(shdrs, _ehdr.e_shnum); if (ret < 0) { return -1; } int count = 0; int cur_idx = 0; erelsym *erel = (erelsym *)&rel_table[max_count]; for (unsigned int i = 0; i<_ehdr.e_shnum; i++) { if (shdrs[i].sh_type == SHT_REL || shdrs[i].sh_type == SHT_RELA) { char *rel = (char *)malloc(shdrs[i].sh_size); if (rel == NULL) { fprintf(stderr, "malloc error!\n"); return -1; } int num = shdrs[i].sh_size/shdrs[i].sh_entsize; count += num; ret = elf_read(shdrs[i].sh_offset, rel, shdrs[i].sh_size); if (ret < 0) { return -1; } if(_is_32_bit) { if (shdrs[i].sh_type==SHT_REL) { Elf32_Rel *prel = (Elf32_Rel *)rel; for (int idx=0; idx<num; idx++) { rel_table[cur_idx] = &erel[cur_idx]; rel_table[cur_idx]->offset = prel[idx].r_offset; rel_table[cur_idx]->type = ELF32_R_TYPE(prel[idx].r_info); rel_table[cur_idx]->symid = ELF32_R_SYM(prel[idx].r_info); cur_idx++; } } else { Elf32_Rela *prel = (Elf32_Rela *)rel; for (int idx=0; idx<num; idx++) { rel_table[cur_idx] = &erel[cur_idx]; rel_table[cur_idx]->offset = prel[idx].r_offset; rel_table[cur_idx]->type = ELF32_R_TYPE(prel[idx].r_info); rel_table[cur_idx]->symid = ELF32_R_SYM(prel[idx].r_info); //printf("rela[cur_idx:%d] offset:0x%lx, type:%d, symid:%d\n", // cur_idx, rel_table[cur_idx]->offset, rel_table[cur_idx]->type, rel_table[cur_idx]->symid); cur_idx++; } } } else { if (shdrs[i].sh_type==SHT_REL) { Elf64_Rel *prel = (Elf64_Rel *)rel; for (int idx=0; idx<num; idx++) { rel_table[cur_idx] = &erel[cur_idx]; rel_table[cur_idx]->offset = prel[idx].r_offset; rel_table[cur_idx]->type = ELF64_R_TYPE(prel[idx].r_info); rel_table[cur_idx]->symid = ELF64_R_SYM(prel[idx].r_info); cur_idx++; } } else { Elf64_Rela *prel = (Elf64_Rela *)rel; for (int idx=0; idx<num; idx++) { rel_table[cur_idx] = &erel[cur_idx]; rel_table[cur_idx]->offset = prel[idx].r_offset; rel_table[cur_idx]->type = ELF64_R_TYPE(prel[idx].r_info); rel_table[cur_idx]->symid = ELF64_R_SYM(prel[idx].r_info); //printf("rela[cur_idx:%d] offset:0x%lx, type:%d, symid:%d\n", // cur_idx, rel_table[cur_idx]->offset, rel_table[cur_idx]->type, rel_table[cur_idx]->symid); cur_idx++; } } } if(rel) { free(rel); } } } return count; }
struct libref *elf_read_main_binary(struct task *task, int was_attached) { char fname[PATH_MAX]; int ret; char *filename; struct mt_elf mte = { }; unsigned long entry; unsigned long base; struct libref *libref; filename = pid2name(task->pid); if (!filename) return NULL; libref = libref_new(LIBTYPE_MAIN); if (libref == NULL) goto fail1; ret = readlink(filename, fname, sizeof(fname) - 1); if (ret == -1) goto fail2; fname[ret] = 0; free(filename); libref_set_filename(libref, fname); if (elf_read(&mte, task, fname) == -1) goto fail3; task->is_64bit = is_64bit(&mte); if (process_get_entry(task, &entry, &base) < 0) { fprintf(stderr, "Couldn't find process entry of %s\n", filename); goto fail3; } mte.bias = entry - mte.ehdr.e_entry - mte.vstart; mte.entry_addr = entry; if (elf_lib_init(&mte, task, libref)) goto fail3; close_elf(&mte); report_attach(task, was_attached); library_add(task, libref); if (!mte.interp) return libref; struct mt_elf mte_ld = { }; if (copy_str_from_proc(task, ARCH_ADDR_T(mte.bias + mte.interp - mte.vstart), fname, sizeof(fname)) == -1) { fprintf(stderr, "fatal error: cannot get loader name for pid=%d\n", task->pid); abort(); } if (!elf_read(&mte_ld, task, fname)) { struct libref *libref; libref = libref_new(LIBTYPE_LOADER); if (libref == NULL) goto fail4; libref_set_filename(libref, fname); mte_ld.bias = base; mte_ld.entry_addr = base + mte_ld.ehdr.e_entry - mte.vstart; ret = elf_lib_init(&mte_ld, task, libref); if (!ret) { library_add(task, libref); if (linkmap_init(task, ARCH_ADDR_T(mte.bias + mte.dyn - mte.vstart))) { arch_addr_t addr = find_solib_break(&mte_ld); if (!addr) addr = ARCH_ADDR_T(entry); struct entry_breakpoint *entry_bp = (void *)breakpoint_new_ext(task, addr, NULL, 0, sizeof(*entry_bp) - sizeof(entry_bp->breakpoint)); if (!entry_bp) fprintf(stderr, "Couldn't initialize entry breakpoint for PID %d.\n" "Tracing events may be missed.\n", task->pid ); else { entry_bp->breakpoint.on_hit = entry_breakpoint_on_hit; entry_bp->breakpoint.locked = 1; entry_bp->dyn_addr = ARCH_ADDR_T(mte.bias + mte.dyn - mte.vstart); breakpoint_enable(task, &entry_bp->breakpoint); } } } else { fprintf(stderr, "Couldn't read dynamic loader `%s` for PID %d.\n" "Tracing events may be missed.\n", fname, task->pid ); } fail4: close_elf(&mte_ld); } else { fprintf(stderr, "Couldn't open dynamic loader `%s` for PID %d.\n" "Tracing events may be missed.\n", fname, task->pid ); } return libref; fail3: close_elf(&mte); fail2: libref_delete(libref); fail1: free(filename); return libref; }