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