summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHwankyu Jhun <h.jhun@samsung.com>2021-10-05 16:48:33 +0900
committerHwankyu Jhun <h.jhun@samsung.com>2021-10-06 11:44:59 +0900
commitae2d2baff6aa0064e5be6c1099869f0ebda92bf5 (patch)
tree5fedb94ad85e18fa7e31fdd33bc1306894890c59
parentdff15771eca81740d879222de729f9c1764dce0d (diff)
downloadaul-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.cc128
-rw-r--r--parser/exec-checker/src/plugin_manager.cc4
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;
}