--- /dev/null
+/*
+ * Copyright (C) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <elf.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+
+#include "telf.h"
+
+static void set_error(Elf *elf, const char *fmt, ...)
+{
+ assert(elf);
+
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(elf->last_error, sizeof(elf->last_error), fmt, args);
+ va_end(args);
+}
+
+static bool set_offset(Elf *elf, off64_t offset)
+{
+ assert(elf);
+
+ if (lseek64(elf->fd, offset, SEEK_SET) == (off64_t)-1) {
+ set_error(elf, "set file offset error: %m");
+ return false;
+ }
+ return true;
+}
+
+static bool readehdr(Elf *elf, Elf64_Ehdr *ehdr)
+{
+ assert(elf);
+ assert(ehdr);
+
+ if (teu_class(elf) == ELFCLASS32) {
+ Elf32_Ehdr *ehdr32 = elf->data;
+
+ memcpy(ehdr->e_ident, ehdr32->e_ident, sizeof(ehdr->e_ident));
+ ehdr->e_type = ehdr32->e_type;
+ ehdr->e_machine = ehdr32->e_machine;
+ ehdr->e_version = ehdr32->e_version;
+ ehdr->e_entry = (Elf64_Addr)ehdr32->e_entry;
+ ehdr->e_phoff = (Elf64_Off)ehdr32->e_phoff;
+ ehdr->e_shoff = (Elf64_Off)ehdr32->e_shoff;
+ ehdr->e_flags = ehdr32->e_flags;
+ ehdr->e_ehsize = ehdr32->e_ehsize;
+ ehdr->e_phentsize = ehdr32->e_phentsize;
+ ehdr->e_phnum = ehdr32->e_phnum;
+ ehdr->e_shentsize = ehdr32->e_shentsize;
+ ehdr->e_shnum = ehdr32->e_shnum;
+ ehdr->e_shstrndx = ehdr32->e_shstrndx;
+
+ } else if (teu_class(elf) == ELFCLASS64) {
+ memcpy(ehdr, elf->data, sizeof(*ehdr));
+ } else {
+ set_error(elf, "Unknown ELF class");
+ return false;
+ }
+
+ return true;
+}
+
+char *teu_errmsg(Elf *elf)
+{
+ assert(elf);
+ return elf->last_error;
+}
+
+bool teu_iself(Elf *elf)
+{
+ assert(elf);
+
+ return elf->ident[EI_MAG0] == ELFMAG0 &&
+ elf->ident[EI_MAG1] == ELFMAG1 &&
+ elf->ident[EI_MAG2] == ELFMAG2 &&
+ elf->ident[EI_MAG3] == ELFMAG3;
+}
+
+uint8_t teu_class(Elf *elf)
+{
+ assert(elf);
+
+ return (uint8_t)elf->ident[EI_CLASS];
+}
+
+off64_t get_file_size(Elf *elf, int fd)
+{
+ off64_t end = lseek64(fd, 0, SEEK_END);
+
+ if (end == (off64_t)-1) {
+ set_error(elf, "set file offset error: %m");
+ return (off64_t)-1;
+ }
+
+ if (lseek64(fd, 0, SEEK_SET) == (off64_t)-1) {
+ set_error(elf, "set file offset error: %m");
+ return (off64_t)-1;
+ }
+
+ return end;
+}
+
+static bool teu_init(Elf *elf)
+{
+ elf->ident = elf->data;
+
+ if (!readehdr(elf, &elf->ehdr))
+ return false;
+
+ return true;
+}
+
+bool teu_begin(int fd, Elf *elf)
+{
+ assert(elf);
+ assert(fd >= 0);
+
+ elf->fd = fd;
+
+ if (!set_offset(elf, 0))
+ return false;
+
+ elf->data_size = get_file_size(elf, fd);
+ if (elf->data_size == (off64_t)-1)
+ return false;
+
+ elf->data = mmap(NULL, (elf->data_size + (1024-1)) & ~(1024-1),
+ PROT_READ, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
+ if (elf->data == NULL) {
+ set_error(elf, "Can not allocate memory for file: %m");
+ return false;
+ }
+
+ elf->status = TEU_FILE;
+
+ if (!teu_init(elf))
+ return false;
+
+ return true;
+}
+
+bool teu_begin_memory(void *memory, Elf *elf)
+{
+ assert(memory);
+ assert(elf);
+
+ elf->status = TEU_MEMORY;
+
+ if (!teu_init(elf))
+ return false;
+
+ return true;
+}
+
+bool teu_getehdr(Elf *elf, Elf64_Ehdr *ehdr)
+{
+ assert(elf);
+ assert(ehdr);
+
+ memcpy(ehdr, &elf->ehdr, sizeof(*ehdr));
+ return true;
+}
+
+bool teu_getphdr(Elf *elf, uint64_t index, Elf64_Phdr *phdr)
+{
+ assert(elf);
+ assert(phdr);
+
+ if (index >= elf->ehdr.e_phnum) {
+ set_error(elf, "index is out of range of program headers");
+ return false;
+ }
+
+ void *phdr_data = elf->data + elf->ehdr.e_phoff + index*elf->ehdr.e_phentsize;
+
+ if (teu_class(elf) == ELFCLASS32) {
+ Elf32_Phdr *phdr32 = phdr_data;
+
+ phdr->p_type = phdr32->p_type;
+ phdr->p_flags = phdr32->p_flags;
+ phdr->p_offset = (Elf64_Off)phdr32->p_offset;
+ phdr->p_vaddr = (Elf64_Addr)phdr32->p_vaddr;
+ phdr->p_paddr = (Elf64_Addr)phdr32->p_paddr;
+ phdr->p_filesz = (uint64_t)phdr32->p_filesz;
+ phdr->p_memsz = (uint64_t)phdr32->p_memsz;
+ phdr->p_align = (uint64_t)phdr32->p_align;
+ } else if (teu_class(elf) == ELFCLASS64) {
+ memcpy(phdr, phdr_data, elf->ehdr.e_phentsize);
+ } else {
+ set_error(elf, "Unknown ELF class");
+ return false;
+ }
+
+ return true;
+}
+
+bool teu_getshdr(Elf *elf, uint64_t index, Elf64_Shdr *shdr)
+{
+ assert(elf);
+ assert(shdr);
+
+ if (index >= elf->ehdr.e_shnum) {
+ set_error(elf, "index is out of range of section headers");
+ return false;
+ }
+
+ void *shdr_data = elf->data + elf->ehdr.e_shoff + index*elf->ehdr.e_shentsize;
+
+ if (teu_class(elf) == ELFCLASS32) {
+ Elf32_Shdr *shdr32 = shdr_data;
+
+ shdr->sh_name = shdr32->sh_name;
+ shdr->sh_type = shdr32->sh_type;
+ shdr->sh_flags = (uint64_t)shdr32->sh_flags;
+ shdr->sh_addr = (Elf64_Addr)shdr32->sh_addr;
+ shdr->sh_offset = (Elf64_Off)shdr32->sh_offset;
+ shdr->sh_size = (uint64_t)shdr32->sh_size;
+ shdr->sh_link = shdr32->sh_link;
+ shdr->sh_info = shdr32->sh_info;
+ shdr->sh_addralign = (uint64_t)shdr32->sh_addralign;
+ shdr->sh_entsize = (uint64_t)shdr32->sh_entsize;
+ } else if (teu_class(elf) == ELFCLASS64) {
+ memcpy(shdr, shdr_data, elf->ehdr.e_shentsize);
+ } else {
+ set_error(elf, "Unknown ELF class");
+ return false;
+ }
+
+ return true;
+}
+
+char *teu_secname(Elf *elf, Elf64_Shdr *shdr)
+{
+ assert(elf);
+ assert(shdr);
+
+ Elf64_Shdr strsection;
+ if (!teu_getshdr(elf, elf->ehdr.e_shstrndx, &strsection)) {
+ set_error(elf, "getshdr error");
+ return false;
+ }
+
+ return (char*)(elf->data + strsection.sh_offset + shdr->sh_name);
+}
+
+void *teu_getsdata(Elf *elf, Elf64_Shdr *shdr)
+{
+ assert(elf);
+ assert(shdr);
+
+ return elf->data + shdr->sh_offset;
+}
+
+bool teu_getsym(Elf *elf, Elf64_Shdr *shdr, int index, void *data, Elf64_Sym *sym)
+{
+ assert(elf);
+ assert(shdr);
+ assert(data);
+ assert(sym);
+
+ if (index*shdr->sh_entsize >= shdr->sh_size) {
+ set_error(elf, "index is out of range");
+ return false;
+ }
+
+ if (teu_class(elf) == ELFCLASS32) {
+ Elf32_Sym sym32;
+ memcpy(&sym32, data + index*(shdr->sh_entsize), shdr->sh_entsize);
+ sym->st_name = sym32.st_name;
+ sym->st_info = sym32.st_info;
+ sym->st_other = sym32.st_other;
+ sym->st_shndx = sym32.st_shndx;
+ sym->st_value = (Elf64_Addr)sym32.st_value;
+ sym->st_size = (uint64_t)sym32.st_size;
+ } else if (teu_class(elf) == ELFCLASS64) {
+ memcpy(sym, data + index*(shdr->sh_entsize), shdr->sh_entsize);
+ } else {
+ set_error(elf, "Unknown ELF class");
+ return false;
+ }
+
+ return true;
+}
+
+char *teu_strptr(Elf *elf, int sindex, off64_t offset)
+{
+ assert(elf);
+
+ Elf64_Shdr strsection;
+ if (!teu_getshdr(elf, sindex, &strsection)) {
+ set_error(elf, "getshdr error");
+ return false;
+ }
+
+ return (char*)(elf->data + strsection.sh_offset + offset);
+}
+
+bool teu_close(Elf *elf)
+{
+ assert(elf);
+
+ if (elf->status == TEU_MEMORY)
+ munmap(elf->data, elf->data_size);
+
+ return true;
+}
+
+bool teu_getdata(Elf *elf, off64_t offset, uint64_t size, void *data)
+{
+ assert(elf);
+ assert(data);
+
+ memcpy(data, elf->data + offset, size);
+
+ return true;
+}
+
+off64_t teu_getnote(Elf *elf, void *data, off64_t offset,
+ Elf64_Nhdr *nhdr, off64_t *name_offset, off64_t *desc_offset)
+{
+ assert(elf);
+ assert(data);
+ assert(nhdr);
+ assert(name_offset);
+ assert(desc_offset);
+
+ if (teu_class(elf) == ELFCLASS32) {
+ Elf32_Nhdr *nhdr32 = data + offset;
+ nhdr->n_descsz = (Elf64_Word)nhdr32->n_descsz;
+ nhdr->n_namesz = (Elf64_Word)nhdr32->n_namesz;
+ nhdr->n_type = (Elf64_Word)nhdr32->n_type;
+ *name_offset = offset + sizeof(nhdr32);
+ } else if (teu_class(elf) == ELFCLASS64) {
+ memcpy(nhdr, data + offset, sizeof(*nhdr));
+ *name_offset = offset + sizeof(*nhdr);
+ } else {
+ set_error(elf, "Uknown ELF class");
+ return (off64_t)-1;
+ }
+
+ *desc_offset = *name_offset + ((nhdr->n_namesz + 3) & ~3);
+ return *desc_offset + ((nhdr->n_descsz + 3) & ~3);
+}
+
+// int main(int argc, char *argv[])
+// {
+// struct teu_elf elf;
+// int fd = open(argv[1], O_LARGEFILE);
+// teu_begin(fd, &elf);
+// Elf64_Ehdr ehdr;
+// if (teu_class(&elf) == ELFCLASS32)
+// printf("ELFCLASS32\n");
+//
+// if (teu_class(&elf) == ELFCLASS64)
+// printf("ELFCLASS64\n");
+//
+// if (!teu_getehdr(&elf, &ehdr)) {
+// printf("err");
+// return 1;
+// }
+// printf("PHnum: %d SHnum: %d\n", ehdr.e_phnum, ehdr.e_shnum);
+//
+// printf("PHDRS:\n");
+// for (int i = 0; i < ehdr.e_phnum; i++) {
+// Elf64_Phdr phdr;
+// if (!teu_getphdr(&elf, i, &phdr)) {
+// return 1;
+// }
+// printf("Type: %u Filesz: %lu Memsz: %lu\n", phdr.p_type, phdr.p_filesz, phdr.p_memsz);
+// if (phdr.p_type == PT_NOTE) {
+// printf("Note!!!\n");
+// char data[phdr.p_filesz];
+// if (!teu_getdata(&elf, phdr.p_offset, phdr.p_filesz, data))
+// return 1;
+//
+// off64_t offset = 0;
+// while (offset < phdr.p_filesz) {
+// Elf64_Nhdr nhdr;
+// off64_t noff, doff;
+//
+// offset = teu_getnote(&elf, data, offset, &nhdr, &noff, &doff);
+// printf("name: %s\n", (char*)&data[noff]);
+// for (int i = 0; i < nhdr.n_descsz; i++) {
+// char c = data[doff+i];
+// printf("%x", (uint8_t)c);
+// }
+// printf("\n");
+// }
+//
+// }
+// }
+//
+// printf("SHDRS:\n");
+// for (int i = 0; i < ehdr.e_shnum; i++) {
+// Elf64_Shdr shdr;
+// if (!teu_getshdr(&elf, i, &shdr)) {
+// return 1;
+// }
+// printf("Name: %u Type: %u Size: %lu Entsize: %lu\n", shdr.sh_name, shdr.sh_type, shdr.sh_size, shdr.sh_entsize);
+// if (shdr.sh_type == SHT_SYMTAB)
+// printf("SHT_SYMTAB!!!\n");
+// if (shdr.sh_type == SHT_DYNSYM)
+// printf("SHT_DYNSYM!!!\n");
+// teu_secname(&elf, &shdr);
+//
+// char data[shdr.sh_size];
+// if (!teu_getsdata(&elf, &shdr, data)) {
+// printf("getsdata error\n");
+// return 1;
+// }
+// if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
+// printf("ENTSIZE! count: %lu\n", shdr.sh_size/shdr.sh_entsize);
+// for (int i = 0; i < shdr.sh_size/shdr.sh_entsize; i++) {
+// Elf64_Sym sym;
+// if (!teu_getsym(&elf, &shdr, i, data, &sym)) {
+// printf("get sym error\n");
+// return 1;
+// }
+// // printf("sym info: %d name: %d shndx: %d size: %lu \n",
+// // sym.st_info,
+// // sym.st_name,
+// // sym.st_shndx,
+// // sym.st_size);
+// char *n = teu_strptr(&elf, shdr.sh_link, sym.st_name);
+// if (n == NULL) {
+// printf("strptr err\n");
+// return 1;
+// }
+// printf("n: stname: %d %s\n", sym.st_name, n);
+// }
+// }
+// }
+// return 0;
+// }
--- /dev/null
+/*
+ * Copyright (C) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __TELF_H
+#define __TELF_H
+#include <elf.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+#define ERR_MSG_LEN 1024
+
+enum TEU_STATUS {TEU_NOINIT = 0,
+ TEU_FILE,
+ TEU_MEMORY};
+
+struct teu_elf {
+ enum TEU_STATUS status;
+ int fd;
+ char *ident;
+ off64_t saved_offset;
+ Elf64_Ehdr ehdr;
+ char last_error[ERR_MSG_LEN];
+ void *data;
+ off64_t data_size;
+};
+
+typedef struct teu_elf Elf;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *teu_errmsg(Elf *elf);
+
+bool teu_iself(Elf *elf);
+
+uint8_t teu_class(Elf *elf);
+
+bool teu_internal_getehdr(Elf *elf, Elf64_Ehdr *ehdr);
+
+bool teu_begin(int fd, Elf *elf);
+
+bool teu_begin_memory(void *memory, Elf *elf);
+
+bool teu_getehdr(Elf *elf, Elf64_Ehdr *ehdr);
+
+bool teu_getphdr(Elf *elf, uint64_t index, Elf64_Phdr *phdr);
+
+bool teu_getshdr(Elf *elf, uint64_t index, Elf64_Shdr *shdr);
+
+char *teu_secname(Elf *elf, Elf64_Shdr *shdr);
+
+void *teu_getsdata(Elf *elf, Elf64_Shdr *shdr);
+
+bool teu_getsym(Elf *elf, Elf64_Shdr *shdr, int index, void *data, Elf64_Sym *sym);
+
+char *teu_strptr(Elf *elf, int sindex, off64_t offset);
+
+bool teu_close(Elf *elf);
+
+bool teu_getdata(Elf *elf, off64_t offset, uint64_t size, void *data);
+
+off64_t teu_getnote(Elf *elf, void *data, off64_t offset, Elf64_Nhdr *nhdr, off64_t *name_offset, off64_t *desc_offset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __TELF_H