Branch data Line data Source code
1 : : /* Return program header table entry.
2 : : Copyright (C) 1998-2010, 2015 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include <gelf.h>
35 : : #include <string.h>
36 : : #include <stdbool.h>
37 : :
38 : : #include "libelfP.h"
39 : :
40 : :
41 : : GElf_Phdr *
42 : 136134 : gelf_getphdr (Elf *elf, int ndx, GElf_Phdr *dst)
43 : : {
44 : 136134 : GElf_Phdr *result = NULL;
45 : :
46 [ - + ]: 136134 : if (elf == NULL)
47 : : return NULL;
48 : :
49 [ - + ]: 136134 : if (unlikely (elf->kind != ELF_K_ELF))
50 : : {
51 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
52 : 0 : return NULL;
53 : : }
54 : :
55 [ - + ]: 136134 : if (dst == NULL)
56 : : {
57 : 0 : __libelf_seterrno (ELF_E_INVALID_OPERAND);
58 : 0 : return NULL;
59 : : }
60 : :
61 : 136134 : rwlock_rdlock (elf->lock);
62 : :
63 [ + + ]: 136134 : if (elf->class == ELFCLASS32)
64 : : {
65 : : /* Copy the elements one-by-one. */
66 : 23244 : Elf32_Phdr *phdr = elf->state.elf32.phdr;
67 : :
68 [ + + ]: 23244 : if (phdr == NULL)
69 : : {
70 : 1368 : rwlock_unlock (elf->lock);
71 : 1368 : phdr = INTUSE(elf32_getphdr) (elf);
72 [ - + ]: 1368 : if (phdr == NULL)
73 : : /* The error number is already set. */
74 : 0 : return NULL;
75 : 23244 : rwlock_rdlock (elf->lock);
76 : : }
77 : :
78 : : /* Test whether the index is ok. */
79 : 23244 : size_t phnum;
80 [ + - ]: 23244 : if (__elf_getphdrnum_chk_rdlock (elf, &phnum) != 0
81 [ - + ]: 23244 : || (size_t) ndx >= phnum)
82 : : {
83 : 0 : __libelf_seterrno (ELF_E_INVALID_INDEX);
84 : 0 : goto out;
85 : : }
86 : :
87 : : /* We know the result now. */
88 : 23244 : result = dst;
89 : :
90 : : /* Now correct the pointer to point to the correct element. */
91 : 23244 : phdr += ndx;
92 : :
93 : : #define COPY(Name) result->Name = phdr->Name
94 : 23244 : COPY (p_type);
95 : 23244 : COPY (p_offset);
96 : 23244 : COPY (p_vaddr);
97 : 23244 : COPY (p_paddr);
98 : 23244 : COPY (p_filesz);
99 : 23244 : COPY (p_memsz);
100 : 23244 : COPY (p_flags);
101 : 23244 : COPY (p_align);
102 : : }
103 : : else
104 : : {
105 : : /* Copy the elements one-by-one. */
106 : 112890 : Elf64_Phdr *phdr = elf->state.elf64.phdr;
107 : :
108 [ + + ]: 112890 : if (phdr == NULL)
109 : : {
110 : 12822 : rwlock_unlock (elf->lock);
111 : 12822 : phdr = INTUSE(elf64_getphdr) (elf);
112 [ - + ]: 12822 : if (phdr == NULL)
113 : : /* The error number is already set. */
114 : 0 : return NULL;
115 : 112890 : rwlock_rdlock (elf->lock);
116 : : }
117 : :
118 : : /* Test whether the index is ok. */
119 : 112890 : size_t phnum;
120 [ + - ]: 112890 : if (__elf_getphdrnum_chk_rdlock (elf, &phnum) != 0
121 [ - + ]: 112890 : || (size_t) ndx >= phnum)
122 : : {
123 : 0 : __libelf_seterrno (ELF_E_INVALID_INDEX);
124 : 0 : goto out;
125 : : }
126 : :
127 : : /* We only have to copy the data. */
128 : 112890 : result = memcpy (dst, phdr + ndx, sizeof (GElf_Phdr));
129 : : }
130 : :
131 : : out:
132 : : rwlock_unlock (elf->lock);
133 : :
134 : : return result;
135 : : }
|