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 40815 : gelf_getphdr (Elf *elf, int ndx, GElf_Phdr *dst)
43 : {
44 40815 : GElf_Phdr *result = NULL;
45 :
46 40815 : if (elf == NULL)
47 : return NULL;
48 :
49 40815 : if (unlikely (elf->kind != ELF_K_ELF))
50 : {
51 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
52 0 : return NULL;
53 : }
54 :
55 40815 : if (dst == NULL)
56 : {
57 0 : __libelf_seterrno (ELF_E_INVALID_OPERAND);
58 0 : return NULL;
59 : }
60 :
61 : rwlock_rdlock (elf->lock);
62 :
63 40815 : if (elf->class == ELFCLASS32)
64 : {
65 : /* Copy the elements one-by-one. */
66 8235 : Elf32_Phdr *phdr = elf->state.elf32.phdr;
67 :
68 8235 : if (phdr == NULL)
69 : {
70 : rwlock_unlock (elf->lock);
71 329 : phdr = INTUSE(elf32_getphdr) (elf);
72 329 : if (phdr == NULL)
73 : /* The error number is already set. */
74 0 : return NULL;
75 : rwlock_rdlock (elf->lock);
76 : }
77 :
78 : /* Test whether the index is ok. */
79 : size_t phnum;
80 8235 : if (__elf_getphdrnum_chk_rdlock (elf, &phnum) != 0
81 8235 : || (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 8235 : result = dst;
89 :
90 : /* Now correct the pointer to point to the correct element. */
91 8235 : phdr += ndx;
92 :
93 : #define COPY(Name) result->Name = phdr->Name
94 8235 : COPY (p_type);
95 8235 : COPY (p_offset);
96 8235 : COPY (p_vaddr);
97 8235 : COPY (p_paddr);
98 8235 : COPY (p_filesz);
99 8235 : COPY (p_memsz);
100 8235 : COPY (p_flags);
101 8235 : COPY (p_align);
102 : }
103 : else
104 : {
105 : /* Copy the elements one-by-one. */
106 32580 : Elf64_Phdr *phdr = elf->state.elf64.phdr;
107 :
108 32580 : if (phdr == NULL)
109 : {
110 : rwlock_unlock (elf->lock);
111 5635 : phdr = INTUSE(elf64_getphdr) (elf);
112 5635 : if (phdr == NULL)
113 : /* The error number is already set. */
114 0 : return NULL;
115 : rwlock_rdlock (elf->lock);
116 : }
117 :
118 : /* Test whether the index is ok. */
119 : size_t phnum;
120 32580 : if (__elf_getphdrnum_chk_rdlock (elf, &phnum) != 0
121 32580 : || (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 65160 : result = memcpy (dst, phdr + ndx, sizeof (GElf_Phdr));
129 : }
130 :
131 : out:
132 : rwlock_unlock (elf->lock);
133 :
134 : return result;
135 : }
|