Kernel dso support for 'dl_iterate_phdr' function

Kernel provides virtual DSO for stack unwinding/exception handlind info for
signal usage case. Stack unwinding routines use 'dl_iterate_phdr' function
for additional DWARF info gathering from DSOs. Patch enables virtual DSO
enumeration via dl_iterate_phdr function.

Signed-off-by: Sergey Melnikov <sergey.melnikov@intel.com>
Change-Id: Ic2882b28f40b456a088bc1e63c50cbfda7e4a102
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 9c35cfc..386f6dc 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1586,6 +1586,28 @@
 }
 
 /*
+ * This function add vdso to internal dso list.
+ * It helps to stack unwinding through signal handlers.
+ * Also, it makes bionic more like glibc.
+ */
+static void add_vdso(KernelArgumentBlock& args UNUSED) {
+#ifdef AT_SYSINFO_EHDR
+    Elf32_Ehdr* ehdr_vdso = reinterpret_cast<Elf32_Ehdr*>(args.getauxval(AT_SYSINFO_EHDR));
+
+    soinfo* si = soinfo_alloc("[vdso]");
+    si->phdr = reinterpret_cast<Elf32_Phdr*>(reinterpret_cast<char*>(ehdr_vdso) + ehdr_vdso->e_phoff);
+    si->phnum = ehdr_vdso->e_phnum;
+    si->link_map.l_name = si->name;
+    for (size_t i = 0; i < si->phnum; ++i) {
+        if (si->phdr[i].p_type == PT_LOAD) {
+            si->link_map.l_addr = reinterpret_cast<Elf32_Addr>(ehdr_vdso) - si->phdr[i].p_vaddr;
+            break;
+        }
+    }
+#endif
+}
+
+/*
  * This code is called after the linker has linked itself and
  * fixed it's own GOT. It is safe to make references to externs
  * and other non-local data at this point.
@@ -1710,6 +1732,8 @@
         exit(EXIT_FAILURE);
     }
 
+    add_vdso(args);
+
     si->CallPreInitConstructors();
 
     for (size_t i = 0; gLdPreloads[i] != NULL; ++i) {