Only set so info ELF file when needed
authorAntoine Busque <abusque@efficios.com>
Fri, 15 Apr 2016 21:39:24 +0000 (17:39 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 3 May 2016 19:42:41 +0000 (15:42 -0400)
Signed-off-by: Antoine Busque <abusque@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
lib/so-info.c

index a5ddfe51ed866a76ac1a71252140829b04970dd4..a82e86b809f4d8ad959ed5a1690240635af2f81d 100644 (file)
@@ -68,7 +68,6 @@ struct so_info *so_info_create(const char *path, uint64_t low_addr,
                uint64_t memsz, bool is_pic)
 {
        struct so_info *so = NULL;
-       GElf_Ehdr *ehdr = NULL;
 
        if (!path) {
                goto error;
@@ -84,45 +83,14 @@ struct so_info *so_info_create(const char *path, uint64_t low_addr,
                goto error;
        }
 
-       so->elf_fd = open(path, O_RDONLY);
-       if (so->elf_fd < 0) {
-               fprintf(stderr, "Failed to open %s\n", path);
-               goto error;
-       }
-
-       so->elf_file = elf_begin(so->elf_fd, ELF_C_READ, NULL);
-       if (!so->elf_file) {
-               fprintf(stderr, "elf_begin failed: %s\n", elf_errmsg(-1));
-               goto error;
-       }
-
-       if (elf_kind(so->elf_file) != ELF_K_ELF) {
-               fprintf(stderr, "Error: %s is not an ELF object\n",
-                               so->elf_path);
-               goto error;
-       }
-
-       ehdr = g_new0(GElf_Ehdr, 1);
-       if (!ehdr) {
-               goto error;
-       }
-
-       if (!gelf_getehdr(so->elf_file, ehdr)) {
-               fprintf(stderr, "Error: couldn't get ehdr for %s\n",
-                               so->elf_path);
-               goto error;
-       }
-
        so->is_pic = is_pic;
        so->memsz = memsz;
        so->low_addr = low_addr;
        so->high_addr = so->low_addr + so->memsz;
 
-       g_free(ehdr);
        return so;
 
 error:
-       g_free(ehdr);
        so_info_destroy(so);
        return NULL;
 }
@@ -149,6 +117,7 @@ void so_info_destroy(struct so_info *so)
        g_free(so);
 }
 
+
 BT_HIDDEN
 int so_info_set_build_id(struct so_info *so, uint8_t *build_id,
                size_t build_id_len)
@@ -512,6 +481,51 @@ end:
        return ret;
 }
 
+/**
+ * Initialize the ELF file for a given executable.
+ *
+ * @param so   so_info instance
+ * @returns    0 on success, -1 on failure
+ */
+static
+int so_info_set_elf_file(struct so_info *so)
+{
+       int elf_fd;
+       Elf *elf_file;
+
+       if (!so) {
+               goto error;
+       }
+
+       elf_fd = open(so->elf_path, O_RDONLY);
+       if (elf_fd < 0) {
+               fprintf(stderr, "Failed to open %s\n", so->elf_path);
+               goto error;
+       }
+
+       elf_file = elf_begin(elf_fd, ELF_C_READ, NULL);
+       if (!elf_file) {
+               fprintf(stderr, "elf_begin failed: %s\n", elf_errmsg(-1));
+               goto error;
+       }
+
+       if (elf_kind(elf_file) != ELF_K_ELF) {
+               fprintf(stderr, "Error: %s is not an ELF object\n",
+                               so->elf_path);
+               goto error;
+       }
+
+       so->elf_fd = elf_fd;
+       so->elf_file = elf_file;
+       return 0;
+
+error:
+       close(elf_fd);
+       elf_end(elf_file);
+       return -1;
+}
+
+
 BT_HIDDEN
 void source_location_destroy(struct source_location *src_loc)
 {
@@ -659,6 +673,15 @@ int so_info_lookup_elf_function_name(struct so_info *so, uint64_t addr,
        char *_func_name = NULL;
        char offset_str[ADDR_STR_LEN];
 
+       /* Set ELF file if it hasn't been accessed yet. */
+       if (!so->elf_file) {
+               ret = so_info_set_elf_file(so);
+               if (ret) {
+                       /* Failed to set ELF file. */
+                       goto error;
+               }
+       }
+
        scn = elf_nextscn(so->elf_file, scn);
        if (!scn) {
                goto error;
This page took 0.035743 seconds and 4 git commands to generate.