1 /* Return string pointer from string section.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 2.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <libelf.h>
23 #include <stddef.h>
24
25 #include "libelfP.h"
26
27
28 char *
elf_strptr(elf,idx,offset)29 elf_strptr (elf, idx, offset)
30 Elf *elf;
31 size_t idx;
32 size_t offset;
33 {
34 if (elf == NULL)
35 return NULL;
36
37 if (elf->kind != ELF_K_ELF)
38 {
39 __libelf_seterrno (ELF_E_INVALID_HANDLE);
40 return NULL;
41 }
42
43 rwlock_rdlock (elf->lock);
44
45 char *result = NULL;
46 Elf_Scn *strscn;
47
48 /* Find the section in the list. */
49 Elf_ScnList *runp = (elf->class == ELFCLASS32
50 || (offsetof (struct Elf, state.elf32.scns)
51 == offsetof (struct Elf, state.elf64.scns))
52 ? &elf->state.elf32.scns : &elf->state.elf64.scns);
53 while (1)
54 {
55 if (idx < runp->max)
56 {
57 if (idx < runp->cnt)
58 strscn = &runp->data[idx];
59 else
60 {
61 __libelf_seterrno (ELF_E_INVALID_INDEX);
62 goto out;
63 }
64 break;
65 }
66
67 idx -= runp->max;
68
69 runp = runp->next;
70 if (runp == NULL)
71 {
72 __libelf_seterrno (ELF_E_INVALID_INDEX);
73 goto out;
74 }
75 }
76
77 if (elf->class == ELFCLASS32)
78 {
79 if (unlikely (strscn->shdr.e32->sh_type != SHT_STRTAB))
80 {
81 /* This is no string section. */
82 __libelf_seterrno (ELF_E_INVALID_SECTION);
83 goto out;
84 }
85
86 if (unlikely (offset >= strscn->shdr.e32->sh_size))
87 {
88 /* The given offset is too big, it is beyond this section. */
89 __libelf_seterrno (ELF_E_OFFSET_RANGE);
90 goto out;
91 }
92 }
93 else
94 {
95 if (unlikely (strscn->shdr.e64->sh_type != SHT_STRTAB))
96 {
97 /* This is no string section. */
98 __libelf_seterrno (ELF_E_INVALID_SECTION);
99 goto out;
100 }
101
102 if (unlikely (offset >= strscn->shdr.e64->sh_size))
103 {
104 /* The given offset is too big, it is beyond this section. */
105 __libelf_seterrno (ELF_E_OFFSET_RANGE);
106 goto out;
107 }
108 }
109
110 if (strscn->rawdata_base == NULL
111 /* Read the section data. */
112 && __libelf_set_rawdata (strscn) != 0)
113 goto out;
114
115 result = &strscn->rawdata_base[offset];
116
117 out:
118 rwlock_unlock (elf->lock);
119
120 return result;
121 }
122 INTDEF(elf_strptr)
123