X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-elf.c;h=52078d9629f34df177e88857ccd82690a6fb6c4e;hb=c0c0989ab70574e09b2f7e8b48c2da6af664a849;hp=dcae966ca2b815513b2b0a2d04c89d714174bbae;hpb=82ee1ee4a147de031957bfcb8a1908b926bac603;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-elf.c b/liblttng-ust/lttng-ust-elf.c index dcae966c..52078d96 100644 --- a/liblttng-ust/lttng-ust-elf.c +++ b/liblttng-ust/lttng-ust-elf.c @@ -1,33 +1,31 @@ /* - * Copyright (C) 2015 Antoine Busque + * SPDX-License-Identifier: LGPL-2.1-or-later * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Copyright (C) 2015 Antoine Busque */ +#define _LGPL_SOURCE +#include #include -#include #include #include -#include +#include +#include +#include #include -#include +#include #include + +#include + #include "lttng-tracer-core.h" #define BUF_LEN 4096 +#ifndef NT_GNU_BUILD_ID +# define NT_GNU_BUILD_ID 3 +#endif + /* * Retrieve the nth (where n is the `index` argument) phdr (program * header) from the given elf instance. @@ -235,21 +233,40 @@ struct lttng_ust_elf *lttng_ust_elf_create(const char *path) uint8_t e_ident[EI_NIDENT]; struct lttng_ust_elf_shdr *section_names_shdr; struct lttng_ust_elf *elf = NULL; + int ret, fd; elf = zmalloc(sizeof(struct lttng_ust_elf)); if (!elf) { goto error; } + /* Initialize fd field to -1. 0 is a valid fd number */ + elf->fd = -1; + elf->path = strdup(path); if (!elf->path) { goto error; } - elf->fd = open(elf->path, O_RDONLY | O_CLOEXEC); - if (elf->fd < 0) { + lttng_ust_lock_fd_tracker(); + fd = open(elf->path, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + lttng_ust_unlock_fd_tracker(); + goto error; + } + + ret = lttng_ust_add_fd_to_tracker(fd); + if (ret < 0) { + ret = close(fd); + if (ret) { + PERROR("close on elf->fd"); + } + ret = -1; + lttng_ust_unlock_fd_tracker(); goto error; } + elf->fd = ret; + lttng_ust_unlock_fd_tracker(); if (lttng_ust_read(elf->fd, e_ident, EI_NIDENT) < EI_NIDENT) { goto error; @@ -302,32 +319,46 @@ struct lttng_ust_elf *lttng_ust_elf_create(const char *path) return elf; error: - if (elf) { - free(elf->ehdr); - if (elf->fd >= 0) { - if (close(elf->fd)) { - abort(); - } - } - free(elf->path); - free(elf); - } + lttng_ust_elf_destroy(elf); 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. */ void lttng_ust_elf_destroy(struct lttng_ust_elf *elf) { + int ret; + if (!elf) { return; } - free(elf->ehdr); - if (close(elf->fd)) { - abort(); + if (elf->fd >= 0) { + lttng_ust_lock_fd_tracker(); + ret = close(elf->fd); + if (!ret) { + lttng_ust_delete_fd_from_tracker(elf->fd); + } else { + PERROR("close"); + abort(); + } + lttng_ust_unlock_fd_tracker(); } + + free(elf->ehdr); free(elf->path); free(elf); } @@ -341,7 +372,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 +380,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 +394,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; @@ -415,7 +437,7 @@ int lttng_ust_elf_get_build_id_from_segment( size_t read_len; /* Align start of note entry */ - offset += offset_align(offset, ELF_NOTE_ENTRY_ALIGN); + offset += lttng_ust_offset_align(offset, ELF_NOTE_ENTRY_ALIGN); if (offset >= segment_end) { break; } @@ -440,7 +462,7 @@ int lttng_ust_elf_get_build_id_from_segment( offset += sizeof(nhdr) + nhdr.n_namesz; /* Align start of desc entry */ - offset += offset_align(offset, ELF_NOTE_DESC_ALIGN); + offset += lttng_ust_offset_align(offset, ELF_NOTE_DESC_ALIGN); if (nhdr.n_type != NT_GNU_BUILD_ID) { /*