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 41226 : gelf_getphdr (Elf *elf, int ndx, GElf_Phdr *dst)
43 : {
44 41226 : GElf_Phdr *result = NULL;
45 :
46 41226 : if (elf == NULL)
47 : return NULL;
48 :
49 41226 : if (unlikely (elf->kind != ELF_K_ELF))
50 : {
51 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
52 0 : return NULL;
53 : }
54 :
55 41226 : 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 41226 : if (elf->class == ELFCLASS32)
64 : {
65 : /* Copy the elements one-by-one. */
66 7919 : Elf32_Phdr *phdr = elf->state.elf32.phdr;
67 :
68 7919 : if (phdr == NULL)
69 : {
70 : rwlock_unlock (elf->lock);
71 335 : phdr = INTUSE(elf32_getphdr) (elf);
72 335 : 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 7919 : if (__elf_getphdrnum_chk_rdlock (elf, &phnum) != 0
81 7919 : || (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 7919 : result = dst;
89 :
90 : /* Now correct the pointer to point to the correct element. */
91 7919 : phdr += ndx;
92 :
93 : #define COPY(Name) result->Name = phdr->Name
94 7919 : COPY (p_type);
95 7919 : COPY (p_offset);
96 7919 : COPY (p_vaddr);
97 7919 : COPY (p_paddr);
98 7919 : COPY (p_filesz);
99 7919 : COPY (p_memsz);
100 7919 : COPY (p_flags);
101 7919 : COPY (p_align);
102 : }
103 : else
104 : {
105 : /* Copy the elements one-by-one. */
106 33307 : Elf64_Phdr *phdr = elf->state.elf64.phdr;
107 :
108 33307 : if (phdr == NULL)
109 : {
110 : rwlock_unlock (elf->lock);
111 5683 : phdr = INTUSE(elf64_getphdr) (elf);
112 5683 : 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 33307 : if (__elf_getphdrnum_chk_rdlock (elf, &phnum) != 0
121 33307 : || (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 66614 : result = memcpy (dst, phdr + ndx, sizeof (GElf_Phdr));
129 : }
130 :
131 : out:
132 : rwlock_unlock (elf->lock);
133 :
134 41226 : return result;
135 : }
|