Line data Source code
1 : /* Get note information at the supplied offset.
2 : Copyright (C) 2007, 2014, 2015 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 1787 : gelf_getnote (Elf_Data *data, size_t offset, GElf_Nhdr *result,
41 : size_t *name_offset, size_t *desc_offset)
42 : {
43 1787 : if (data == NULL)
44 : return 0;
45 :
46 1787 : if (unlikely (data->d_type != ELF_T_NHDR))
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 1787 : if (unlikely (offset > data->d_size
62 : || data->d_size - offset < sizeof (GElf_Nhdr)))
63 : {
64 146 : __libelf_seterrno (ELF_E_OFFSET_RANGE);
65 146 : offset = 0;
66 : }
67 : else
68 : {
69 1641 : const GElf_Nhdr *n = data->d_buf + offset;
70 1641 : offset += sizeof *n;
71 :
72 : /* Include padding. Check below for overflow. */
73 1641 : GElf_Word namesz = NOTE_ALIGN (n->n_namesz);
74 1641 : GElf_Word descsz = NOTE_ALIGN (n->n_descsz);
75 :
76 1641 : if (unlikely (offset > data->d_size
77 : || data->d_size - offset < namesz
78 : || (namesz == 0 && n->n_namesz != 0)))
79 : offset = 0;
80 : else
81 : {
82 1641 : *name_offset = offset;
83 1641 : offset += namesz;
84 1641 : if (unlikely (offset > data->d_size
85 : || data->d_size - offset < descsz
86 : || (descsz == 0 && n->n_descsz != 0)))
87 : offset = 0;
88 : else
89 : {
90 1641 : *desc_offset = offset;
91 1641 : offset += descsz;
92 1641 : *result = *n;
93 : }
94 : }
95 : }
96 :
97 : rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock);
98 :
99 1787 : return offset;
100 : }
|