Branch data 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 : 12236 : gelf_getnote (Elf_Data *data, size_t offset, GElf_Nhdr *result,
41 : : size_t *name_offset, size_t *desc_offset)
42 : : {
43 [ - + ]: 12236 : if (data == NULL)
44 : : return 0;
45 : :
46 [ - + ]: 12236 : 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 : 12236 : assert (sizeof (GElf_Nhdr) == sizeof (Elf32_Nhdr));
55 : 12236 : assert (sizeof (GElf_Nhdr) == sizeof (Elf64_Nhdr));
56 : :
57 : 12236 : 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 [ + - + + ]: 12236 : if (unlikely (offset > data->d_size
62 : : || data->d_size - offset < sizeof (GElf_Nhdr)))
63 : : {
64 : 1124 : __libelf_seterrno (ELF_E_OFFSET_RANGE);
65 : 1124 : offset = 0;
66 : : }
67 : : else
68 : : {
69 : 11112 : const GElf_Nhdr *n = data->d_buf + offset;
70 : 11112 : offset += sizeof *n;
71 : :
72 [ - + ]: 11112 : 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 : 11112 : *name_offset = offset;
83 [ - + ]: 11112 : if (n->n_namesz > data->d_size
84 [ - + ]: 11112 : || offset > data->d_size - n->n_namesz)
85 : : offset = 0;
86 : : else
87 : : {
88 : 11112 : offset += n->n_namesz;
89 : : /* Include padding. Check below for overflow. */
90 [ + + ]: 11112 : GElf_Word descsz = (data->d_type == ELF_T_NHDR8
91 : 796 : ? NOTE_ALIGN8 (n->n_descsz)
92 : 10316 : : NOTE_ALIGN4 (n->n_descsz));
93 : :
94 [ + + ]: 11112 : if (data->d_type == ELF_T_NHDR8)
95 : 796 : offset = NOTE_ALIGN8 (offset);
96 : : else
97 : 10316 : offset = NOTE_ALIGN4 (offset);
98 : :
99 [ - + - + : 11112 : if (unlikely (offset > data->d_size
+ + - + ]
100 : : || data->d_size - offset < descsz
101 : : || (descsz == 0 && n->n_descsz != 0)))
102 : : offset = 0;
103 : : else
104 : : {
105 : 11112 : *desc_offset = offset;
106 : 11112 : offset += descsz;
107 : 11112 : *result = *n;
108 : : }
109 : : }
110 : : }
111 : : }
112 : :
113 : 12236 : rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock);
114 : :
115 : 12236 : return offset;
116 : : }
|