1da0c48c4Sopenharmony_ci/* Get note information at the supplied offset. 2da0c48c4Sopenharmony_ci Copyright (C) 2007, 2014, 2015, 2018 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of either 7da0c48c4Sopenharmony_ci 8da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 9da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 10da0c48c4Sopenharmony_ci your option) any later version 11da0c48c4Sopenharmony_ci 12da0c48c4Sopenharmony_ci or 13da0c48c4Sopenharmony_ci 14da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 15da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 16da0c48c4Sopenharmony_ci your option) any later version 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci or both in parallel, as here. 19da0c48c4Sopenharmony_ci 20da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 21da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23da0c48c4Sopenharmony_ci General Public License for more details. 24da0c48c4Sopenharmony_ci 25da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 26da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 27da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 28da0c48c4Sopenharmony_ci 29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 30da0c48c4Sopenharmony_ci# include <config.h> 31da0c48c4Sopenharmony_ci#endif 32da0c48c4Sopenharmony_ci 33da0c48c4Sopenharmony_ci#include <assert.h> 34da0c48c4Sopenharmony_ci#include <gelf.h> 35da0c48c4Sopenharmony_ci#include <string.h> 36da0c48c4Sopenharmony_ci 37da0c48c4Sopenharmony_ci#include "libelfP.h" 38da0c48c4Sopenharmony_ci 39da0c48c4Sopenharmony_cisize_t 40da0c48c4Sopenharmony_cigelf_getnote (Elf_Data *data, size_t offset, GElf_Nhdr *result, 41da0c48c4Sopenharmony_ci size_t *name_offset, size_t *desc_offset) 42da0c48c4Sopenharmony_ci{ 43da0c48c4Sopenharmony_ci if (data == NULL) 44da0c48c4Sopenharmony_ci return 0; 45da0c48c4Sopenharmony_ci 46da0c48c4Sopenharmony_ci if (unlikely (data->d_type != ELF_T_NHDR && data->d_type != ELF_T_NHDR8)) 47da0c48c4Sopenharmony_ci { 48da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_INVALID_HANDLE); 49da0c48c4Sopenharmony_ci return 0; 50da0c48c4Sopenharmony_ci } 51da0c48c4Sopenharmony_ci 52da0c48c4Sopenharmony_ci /* It's easy to handle this type. It has the same size for 32 and 53da0c48c4Sopenharmony_ci 64 bit objects. */ 54da0c48c4Sopenharmony_ci assert (sizeof (GElf_Nhdr) == sizeof (Elf32_Nhdr)); 55da0c48c4Sopenharmony_ci assert (sizeof (GElf_Nhdr) == sizeof (Elf64_Nhdr)); 56da0c48c4Sopenharmony_ci 57da0c48c4Sopenharmony_ci rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock); 58da0c48c4Sopenharmony_ci 59da0c48c4Sopenharmony_ci /* The data is already in the correct form. Just make sure the 60da0c48c4Sopenharmony_ci offset is OK. */ 61da0c48c4Sopenharmony_ci if (unlikely (offset > data->d_size 62da0c48c4Sopenharmony_ci || data->d_size - offset < sizeof (GElf_Nhdr))) 63da0c48c4Sopenharmony_ci { 64da0c48c4Sopenharmony_ci __libelf_seterrno (ELF_E_OFFSET_RANGE); 65da0c48c4Sopenharmony_ci offset = 0; 66da0c48c4Sopenharmony_ci } 67da0c48c4Sopenharmony_ci else 68da0c48c4Sopenharmony_ci { 69da0c48c4Sopenharmony_ci const GElf_Nhdr *n = data->d_buf + offset; 70da0c48c4Sopenharmony_ci offset += sizeof *n; 71da0c48c4Sopenharmony_ci 72da0c48c4Sopenharmony_ci if (offset > data->d_size) 73da0c48c4Sopenharmony_ci offset = 0; 74da0c48c4Sopenharmony_ci else 75da0c48c4Sopenharmony_ci { 76da0c48c4Sopenharmony_ci /* This is slightly tricky, offset is guaranteed to be 4 77da0c48c4Sopenharmony_ci byte aligned, which is what we need for the name_offset. 78da0c48c4Sopenharmony_ci And normally desc_offset is also 4 byte aligned, but not 79da0c48c4Sopenharmony_ci for GNU Property notes, then it should be 8. So align 80da0c48c4Sopenharmony_ci the offset, after adding the namesz, and include padding 81da0c48c4Sopenharmony_ci in descsz to get to the end. */ 82da0c48c4Sopenharmony_ci *name_offset = offset; 83da0c48c4Sopenharmony_ci if (n->n_namesz > data->d_size 84da0c48c4Sopenharmony_ci || offset > data->d_size - n->n_namesz) 85da0c48c4Sopenharmony_ci offset = 0; 86da0c48c4Sopenharmony_ci else 87da0c48c4Sopenharmony_ci { 88da0c48c4Sopenharmony_ci offset += n->n_namesz; 89da0c48c4Sopenharmony_ci /* Include padding. Check below for overflow. */ 90da0c48c4Sopenharmony_ci GElf_Word descsz = (data->d_type == ELF_T_NHDR8 91da0c48c4Sopenharmony_ci ? NOTE_ALIGN8 (n->n_descsz) 92da0c48c4Sopenharmony_ci : NOTE_ALIGN4 (n->n_descsz)); 93da0c48c4Sopenharmony_ci 94da0c48c4Sopenharmony_ci if (data->d_type == ELF_T_NHDR8) 95da0c48c4Sopenharmony_ci offset = NOTE_ALIGN8 (offset); 96da0c48c4Sopenharmony_ci else 97da0c48c4Sopenharmony_ci offset = NOTE_ALIGN4 (offset); 98da0c48c4Sopenharmony_ci 99da0c48c4Sopenharmony_ci if (unlikely (offset > data->d_size 100da0c48c4Sopenharmony_ci || data->d_size - offset < descsz 101da0c48c4Sopenharmony_ci || (descsz == 0 && n->n_descsz != 0))) 102da0c48c4Sopenharmony_ci offset = 0; 103da0c48c4Sopenharmony_ci else 104da0c48c4Sopenharmony_ci { 105da0c48c4Sopenharmony_ci *desc_offset = offset; 106da0c48c4Sopenharmony_ci offset += descsz; 107da0c48c4Sopenharmony_ci *result = *n; 108da0c48c4Sopenharmony_ci } 109da0c48c4Sopenharmony_ci } 110da0c48c4Sopenharmony_ci } 111da0c48c4Sopenharmony_ci } 112da0c48c4Sopenharmony_ci 113da0c48c4Sopenharmony_ci rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock); 114da0c48c4Sopenharmony_ci 115da0c48c4Sopenharmony_ci return offset; 116da0c48c4Sopenharmony_ci} 117