Implement finding main symbol from .dynsym 23/264923/5
authorHwankyu Jhun <h.jhun@samsung.com>
Tue, 5 Oct 2021 07:48:33 +0000 (16:48 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Wed, 6 Oct 2021 02:44:59 +0000 (11:44 +0900)
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>
parser/exec-checker/src/exec_checker.cc
parser/exec-checker/src/plugin_manager.cc

index de48835..7f44813 100644 (file)
@@ -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() {
index 24566dd..01d90e8 100644 (file)
@@ -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;
   }