Branch data Line data Source code
1 : : /* Get section at specific index.
2 : : Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2015 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Contributed 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 <assert.h>
35 : : #include <stddef.h>
36 : : #include <stdlib.h>
37 : :
38 : : #include "libelfP.h"
39 : :
40 : :
41 : : Elf_Scn *
42 : 45260042 : elf_getscn (Elf *elf, size_t idx)
43 : : {
44 [ - + ]: 45260042 : if (elf == NULL)
45 : : return NULL;
46 : :
47 [ - + ]: 45260042 : if (unlikely (elf->kind != ELF_K_ELF))
48 : : {
49 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
50 : 0 : return NULL;
51 : : }
52 : :
53 : 45260042 : rwlock_rdlock (elf->lock);
54 : :
55 : 45260042 : Elf_Scn *result = NULL;
56 : :
57 : : /* Find the section in the list. */
58 : 45260042 : Elf_ScnList *runp = (elf->class == ELFCLASS32
59 : : || (offsetof (struct Elf, state.elf32.scns)
60 : : == offsetof (struct Elf, state.elf64.scns))
61 : : ? &elf->state.elf32.scns : &elf->state.elf64.scns);
62 : :
63 : : /* Section zero is special. It always exists even if there is no
64 : : "first" section. And it is needed to store "overflow" values
65 : : from the Elf header. */
66 [ + + + + : 45260042 : if (idx == 0 && runp->cnt == 0 && runp->max > 0)
+ - ]
67 : : {
68 : 2 : Elf_Scn *scn0 = &runp->data[0];
69 [ + - ]: 2 : if (elf->class == ELFCLASS32)
70 : : {
71 : 2 : scn0->shdr.e32 = calloc (1, sizeof (Elf32_Shdr));
72 [ - + ]: 2 : if (scn0->shdr.e32 == NULL)
73 : : {
74 : 0 : __libelf_seterrno (ELF_E_NOMEM);
75 : 0 : goto out;
76 : : }
77 : : }
78 : : else
79 : : {
80 : 0 : scn0->shdr.e64 = calloc (1, sizeof (Elf64_Shdr));
81 [ # # ]: 0 : if (scn0->shdr.e64 == NULL)
82 : : {
83 : 0 : __libelf_seterrno (ELF_E_NOMEM);
84 : 0 : goto out;
85 : : }
86 : : }
87 : 2 : scn0->elf = elf;
88 : 2 : scn0->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED;
89 : 2 : scn0->list = elf->state.elf.scns_last;
90 : 2 : scn0->data_read = 1;
91 : 2 : runp->cnt = 1;
92 : : }
93 : :
94 : 49576142 : while (1)
95 : : {
96 [ + + ]: 49576142 : if (idx < runp->max)
97 : : {
98 [ + - ]: 45259958 : if (idx < runp->cnt)
99 : 45259958 : result = &runp->data[idx];
100 : : else
101 : 0 : __libelf_seterrno (ELF_E_INVALID_INDEX);
102 : : break;
103 : : }
104 : :
105 : 4316184 : idx -= runp->max;
106 : :
107 : 4316184 : runp = runp->next;
108 [ + + ]: 4316184 : if (runp == NULL)
109 : : {
110 : 84 : __libelf_seterrno (ELF_E_INVALID_INDEX);
111 : 84 : break;
112 : : }
113 : : }
114 : :
115 : : out:
116 : : rwlock_unlock (elf->lock);
117 : :
118 : : return result;
119 : : }
120 : : INTDEF(elf_getscn)
|