diff options
author | Hwankyu Jhun <h.jhun@samsung.com> | 2021-10-05 16:48:33 +0900 |
---|---|---|
committer | Hwankyu Jhun <h.jhun@samsung.com> | 2021-10-06 11:44:59 +0900 |
commit | ae2d2baff6aa0064e5be6c1099869f0ebda92bf5 (patch) | |
tree | 5fedb94ad85e18fa7e31fdd33bc1306894890c59 | |
parent | dff15771eca81740d879222de729f9c1764dce0d (diff) | |
download | aul-1-ae2d2baff6aa0064e5be6c1099869f0ebda92bf5.tar.gz aul-1-ae2d2baff6aa0064e5be6c1099869f0ebda92bf5.tar.bz2 aul-1-ae2d2baff6aa0064e5be6c1099869f0ebda92bf5.zip |
Implement finding main symbol from .dynsym
This patch finds the main symbol using Elf64_Shdr and Elf64_Sym.
If the main symbol doesn't exist, the plugin prints the warning log for
debugging.
Change-Id: Ib46bfcc66319c13be443d76773ab3f41b7496f12
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
-rw-r--r-- | parser/exec-checker/src/exec_checker.cc | 128 | ||||
-rw-r--r-- | parser/exec-checker/src/plugin_manager.cc | 4 |
2 files changed, 129 insertions, 3 deletions
diff --git a/parser/exec-checker/src/exec_checker.cc b/parser/exec-checker/src/exec_checker.cc index de488351..7f448139 100644 --- a/parser/exec-checker/src/exec_checker.cc +++ b/parser/exec-checker/src/exec_checker.cc @@ -42,6 +42,111 @@ union header { Elf64_Ehdr ehdr64; }; +template <typename Shdr> +Shdr* GetSectionFromShdr(const char* name, Shdr* shdr, + const char* shdr_names, int e_shnum) { + for (int i = 0; i < e_shnum; ++i) { + if (shdr[i].sh_size) { + if (!strcmp(&shdr_names[shdr[i].sh_name], name)) + return &shdr[i]; + } + } + + return nullptr; +} + +int Read(FILE* fp, void* ptr, long offset, size_t size) { + if (offset < 0 || size <= 0) { + LOGE_STD("Invalid parameter"); + return -1; + } + + if (fseek(fp, offset, SEEK_SET) < 0) { + LOGE_STD("fseek() is failed. errno(%d)", errno); + return -1; + } + + auto nbytes = fread(ptr, 1, size, fp); + if (nbytes <= 0) { + LOGE_STD("fread() is failed. error(%d)", nbytes); + return -1; + } + + return 0; +} + +char* GetDataFromFile(FILE* fp, long offset, size_t size) { + if (offset < 0 || size <= 0) { + LOGE_STD("Invalid parameter"); + return nullptr; + } + + void* ptr = malloc(size); + if (ptr == nullptr) { + LOGE_STD("Out of memory"); + return nullptr; + } + + if (Read(fp, ptr, offset, size) < 0) { + free(ptr); + return nullptr; + } + + return static_cast<char*>(ptr); +} + +template <typename Ehdr, typename Half, typename Shdr, typename Sym> +bool FindMainSymbolFromEhdr(FILE* fp, Ehdr* ehdr) { + rewind(fp); + Half shdr_tab_size = ehdr->e_shentsize * ehdr->e_shnum; + Shdr shdr_tab[shdr_tab_size]; + if (Read(fp, &shdr_tab, ehdr->e_shoff, shdr_tab_size) < 0) + return false; + + char* shdr_names = GetDataFromFile(fp, shdr_tab[ehdr->e_shstrndx].sh_offset, + shdr_tab[ehdr->e_shstrndx].sh_size); + if (shdr_names == nullptr) + return false; + + std::unique_ptr<char, decltype(std::free)*> shdr_names_auto( + shdr_names, std::free); + + auto* shdr_strtab = GetSectionFromShdr<Shdr>( + ".dynstr", shdr_tab, shdr_names, ehdr->e_shnum); + if (shdr_strtab == nullptr) + return false; + + auto* shdr_symtab = GetSectionFromShdr<Shdr>( + ".dynsym", shdr_tab, shdr_names, ehdr->e_shnum); + if (shdr_symtab == nullptr) + return false; + + if (shdr_symtab->sh_type == SHT_DYNSYM) { + auto* symtab = reinterpret_cast<Sym*>(GetDataFromFile(fp, + shdr_symtab->sh_offset, shdr_symtab->sh_size)); + if (symtab == nullptr) + return false; + + std::unique_ptr<Sym, decltype(std::free)*> symtab_auto(symtab, std::free); + + auto* strtab = GetDataFromFile(fp, shdr_strtab->sh_offset, + shdr_strtab->sh_size); + if (strtab == nullptr) + return false; + + std::unique_ptr<char, decltype(std::free)*> strtab_auto(strtab, std::free); + + int size = shdr_symtab->sh_size / sizeof(Sym); + for (int i = 0; i < size; ++i) { + char* name = strtab + symtab[i].st_name; + if (name && !strcmp(name, "main")) + return true; + } + } + + return false; +} + } // namespace ExecChecker::ExecChecker(std::string path) : path_(std::move(path)) { @@ -84,8 +189,27 @@ bool ExecChecker::IsShared() { } bool ExecChecker::CheckMainSymbol() { - // TODO: Implement finding main symbol using Elf64_Sym & Elf32_Sym - return false; + FILE* fp = fopen(path_.c_str(), "r"); + if (fp == nullptr) { + LOGE_STD("fopen() is failed. errno(%d)", errno); + return false; + } + + std::unique_ptr<FILE, decltype(fclose)*> fp_auto(fp, fclose); + header h; + size_t nbytes = fread(h.c, 1, sizeof(h), fp); + if (nbytes < 2) { + LOGE_STD("fread() is failed"); + return false; + } + + if (class_bit_ == 64) { + return FindMainSymbolFromEhdr<Elf64_Ehdr, Elf64_Half, Elf64_Shdr, Elf64_Sym>( + fp, &h.ehdr64); + } + + return FindMainSymbolFromEhdr<Elf32_Ehdr, Elf32_Half, Elf32_Shdr, Elf32_Sym>( + fp, &h.ehdr32); } bool ExecChecker::CheckDependencyLibs() { diff --git a/parser/exec-checker/src/plugin_manager.cc b/parser/exec-checker/src/plugin_manager.cc index 24566dd9..01d90e8a 100644 --- a/parser/exec-checker/src/plugin_manager.cc +++ b/parser/exec-checker/src/plugin_manager.cc @@ -122,7 +122,9 @@ int PluginManager::Process() { if (!checker.IsShared()) LOGW("%s is not shared object", exec); - checker.CheckMainSymbol(); + if (!checker.CheckMainSymbol()) + LOGW_STD("Failed to find main symbol"); + if (!checker.CheckDependencyLibs()) return -1; } |