Performance: define _LGPL_SOURCE in LGPL c files
[lttng-ust.git] / liblttng-ust / lttng-ust-elf.c
index 026d65cec362ce757994d2d500a295d6839ba44b..663699b7ce91a5d9febf0d9903b64d042a580782 100644 (file)
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <helper.h>
 #include <string.h>
 #include <lttng/align.h>
@@ -24,6 +26,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <stdbool.h>
 #include "lttng-tracer-core.h"
 
 #define BUF_LEN        4096
@@ -315,6 +318,18 @@ error:
        return NULL;
 }
 
+/*
+ * Test whether the ELF file is position independent code (PIC)
+ */
+uint8_t lttng_ust_elf_is_pic(struct lttng_ust_elf *elf)
+{
+       /*
+        * PIC has and e_type value of ET_DYN, see ELF specification
+        * version 1.1 p. 1-3.
+        */
+       return elf->ehdr->e_type == ET_DYN;
+}
+
 /*
  * Destroy the given lttng_ust_elf instance.
  */
@@ -341,7 +356,7 @@ void lttng_ust_elf_destroy(struct lttng_ust_elf *elf)
 int lttng_ust_elf_get_memsz(struct lttng_ust_elf *elf, uint64_t *memsz)
 {
        uint16_t i;
-       uint64_t _memsz = 0;
+       uint64_t low_addr = UINT64_MAX, high_addr = 0;
 
        if (!elf || !memsz) {
                goto error;
@@ -349,7 +364,6 @@ int lttng_ust_elf_get_memsz(struct lttng_ust_elf *elf, uint64_t *memsz)
 
        for (i = 0; i < elf->ehdr->e_phnum; ++i) {
                struct lttng_ust_elf_phdr *phdr;
-               uint64_t align;
 
                phdr = lttng_ust_elf_get_phdr(elf, i);
                if (!phdr) {
@@ -364,27 +378,19 @@ int lttng_ust_elf_get_memsz(struct lttng_ust_elf *elf, uint64_t *memsz)
                        goto next_loop;
                }
 
-               /*
-                * A p_align of 0 means no alignment, i.e. aligned to
-                * 1 byte.
-                */
-               align = phdr->p_align == 0 ? 1 : phdr->p_align;
-               /* Align the start of the segment. */
-               _memsz += offset_align(_memsz, align);
-               _memsz += phdr->p_memsz;
-               /*
-                * Add padding at the end of the segment, so it ends
-                * on a multiple of the align value (which usually
-                * means a page boundary). This makes the computation
-                * valid even in cases where p_align would change from
-                * one segment to the next.
-                */
-               _memsz += offset_align(_memsz, align);
+               low_addr = min_t(uint64_t, low_addr, phdr->p_vaddr);
+               high_addr = max_t(uint64_t, high_addr,
+                               phdr->p_vaddr + phdr->p_memsz);
        next_loop:
                free(phdr);
        }
 
-       *memsz = _memsz;
+       if (high_addr < low_addr) {
+               /* No PT_LOAD segments or corrupted data. */
+               goto error;
+       }
+
+       *memsz = high_addr - low_addr;
        return 0;
 error:
        return -1;
@@ -405,11 +411,10 @@ error:
 static
 int lttng_ust_elf_get_build_id_from_segment(
        struct lttng_ust_elf *elf, uint8_t **build_id, size_t *length,
-       off_t offset, off_t segment_end, int *found)
+       off_t offset, off_t segment_end)
 {
        uint8_t *_build_id = NULL;      /* Silence old gcc warning. */
        size_t _length = 0;             /* Silence old gcc warning. */
-       int _found = 0;
 
        while (offset < segment_end) {
                struct lttng_ust_elf_nhdr nhdr;
@@ -466,18 +471,17 @@ int lttng_ust_elf_get_build_id_from_segment(
                        goto error;
                }
 
-               _found = 1;
                break;
        }
 
-       if (_found) {
+       if (_build_id) {
                *build_id = _build_id;
                *length = _length;
        }
 
-       *found = _found;
        return 0;
 error:
+       free(_build_id);
        return -1;
 }
 
@@ -500,7 +504,6 @@ int lttng_ust_elf_get_build_id(struct lttng_ust_elf *elf, uint8_t **build_id,
        uint16_t i;
        uint8_t *_build_id = NULL;      /* Silence old gcc warning. */
        size_t _length = 0;             /* Silence old gcc warning. */
-       int _found = 0;
 
        if (!elf || !build_id || !length || !found) {
                goto error;
@@ -524,26 +527,28 @@ int lttng_ust_elf_get_build_id(struct lttng_ust_elf *elf, uint8_t **build_id,
                offset = phdr->p_offset;
                segment_end = offset + phdr->p_filesz;
                ret = lttng_ust_elf_get_build_id_from_segment(
-                       elf, &_build_id, &_length, offset, segment_end,
-                       &_found);
+                       elf, &_build_id, &_length, offset, segment_end);
        next_loop:
                free(phdr);
                if (ret) {
                        goto error;
                }
-               if (_found) {
+               if (_build_id) {
                        break;
                }
        }
 
-       if (_found) {
+       if (_build_id) {
                *build_id = _build_id;
                *length = _length;
+               *found = 1;
+       } else {
+               *found = 0;
        }
 
-       *found = _found;
        return 0;
 error:
+       free(_build_id);
        return -1;
 }
 
@@ -559,16 +564,14 @@ error:
  */
 int lttng_ust_elf_get_debug_link_from_section(struct lttng_ust_elf *elf,
                                        char **filename, uint32_t *crc,
-                                       int *found,
                                        struct lttng_ust_elf_shdr *shdr)
 {
-       int _found = 0;
        char *_filename = NULL;         /* Silence old gcc warning. */
        size_t filename_len;
        char *section_name = NULL;
        uint32_t _crc = 0;              /* Silence old gcc warning. */
 
-       if (!elf || !filename || !crc || !found || !shdr) {
+       if (!elf || !filename || !crc || !shdr) {
                goto error;
        }
 
@@ -611,23 +614,18 @@ int lttng_ust_elf_get_debug_link_from_section(struct lttng_ust_elf *elf,
                _crc = bswap_32(_crc);
        }
 
-       _found = 1;
-
 end:
        free(section_name);
-       if (_found) {
+       if (_filename) {
                *filename = _filename;
                *crc = _crc;
        }
-       *found = _found;
 
        return 0;
 
 error:
-       if (section_name) {
-               free(section_name);
-       }
-
+       free(_filename);
+       free(section_name);
        return -1;
 }
 
@@ -646,7 +644,6 @@ int lttng_ust_elf_get_debug_link(struct lttng_ust_elf *elf, char **filename,
 {
        int ret;
        uint16_t i;
-       int _found = 0;
        char *_filename = NULL;         /* Silence old gcc warning. */
        uint32_t _crc = 0;              /* Silence old gcc warning. */
 
@@ -663,24 +660,28 @@ int lttng_ust_elf_get_debug_link(struct lttng_ust_elf *elf, char **filename,
                }
 
                ret = lttng_ust_elf_get_debug_link_from_section(
-                       elf, &_filename, &_crc, &_found, shdr);
+                       elf, &_filename, &_crc, shdr);
                free(shdr);
 
                if (ret) {
                        goto error;
                }
-               if (_found) {
+               if (_filename) {
                        break;
                }
        }
 
-       if (_found) {
+       if (_filename) {
                *filename = _filename;
                *crc = _crc;
+               *found = 1;
+       } else {
+               *found = 0;
        }
 
-       *found = _found;
        return 0;
+
 error:
+       free(_filename);
        return -1;
 }
This page took 0.025828 seconds and 4 git commands to generate.