1 /*
2 * strptr.c - implementation of the elf_strptr(3) function.
3 * Copyright (C) 1995 - 2007 Michael Riepe
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include <private.h>
21
22 #ifndef lint
23 static const char rcsid[] = "@(#) $Id: strptr.c,v 1.12 2008/05/23 08:15:35 michael Exp $";
24 #endif /* lint */
25
26 char*
elf_strptr(Elf * elf,size_t section,size_t offset)27 elf_strptr(Elf *elf, size_t section, size_t offset) {
28 Elf_Data *data;
29 Elf_Scn *scn;
30 size_t n;
31 char *s;
32
33 if (!elf) {
34 return NULL;
35 }
36 elf_assert(elf->e_magic == ELF_MAGIC);
37 if (!(scn = elf_getscn(elf, section))) {
38 return NULL;
39 }
40 if (scn->s_index == SHN_UNDEF) {
41 seterr(ERROR_NOSTRTAB);
42 return NULL;
43 }
44 /*
45 * checking the section header is more appropriate
46 */
47 if (elf->e_class == ELFCLASS32) {
48 if (scn->s_shdr32.sh_type != SHT_STRTAB) {
49 seterr(ERROR_NOSTRTAB);
50 return NULL;
51 }
52 }
53 #if __LIBELF64
54 else if (elf->e_class == ELFCLASS64) {
55 if (scn->s_shdr64.sh_type != SHT_STRTAB) {
56 seterr(ERROR_NOSTRTAB);
57 return NULL;
58 }
59 }
60 #endif /* __LIBELF64 */
61 else if (valid_class(elf->e_class)) {
62 seterr(ERROR_UNIMPLEMENTED);
63 return NULL;
64 }
65 else {
66 seterr(ERROR_UNKNOWN_CLASS);
67 return NULL;
68 }
69 /*
70 * Find matching buffer
71 */
72 n = 0;
73 data = NULL;
74 if (elf->e_elf_flags & ELF_F_LAYOUT) {
75 /*
76 * Programmer is responsible for d_off
77 * Note: buffers may be in any order!
78 */
79 while ((data = elf_getdata(scn, data))) {
80 n = data->d_off;
81 if (offset >= n && offset - n < data->d_size) {
82 /*
83 * Found it
84 */
85 break;
86 }
87 }
88 }
89 else {
90 /*
91 * Calculate offsets myself
92 */
93 while ((data = elf_getdata(scn, data))) {
94 if (data->d_align > 1) {
95 n += data->d_align - 1;
96 n -= n % data->d_align;
97 }
98 if (offset < n) {
99 /*
100 * Invalid offset: points into a hole
101 */
102 seterr(ERROR_BADSTROFF);
103 return NULL;
104 }
105 if (offset - n < data->d_size) {
106 /*
107 * Found it
108 */
109 break;
110 }
111 n += data->d_size;
112 }
113 }
114 if (data == NULL) {
115 /*
116 * Not found
117 */
118 seterr(ERROR_BADSTROFF);
119 return NULL;
120 }
121 if (data->d_buf == NULL) {
122 /*
123 * Buffer is NULL (usually the programmers' fault)
124 */
125 seterr(ERROR_NULLBUF);
126 return NULL;
127 }
128 offset -= n;
129 s = (char*)data->d_buf;
130 if (!(_elf_sanity_checks & SANITY_CHECK_STRPTR)) {
131 return s + offset;
132 }
133 /*
134 * Perform extra sanity check
135 */
136 for (n = offset; n < data->d_size; n++) {
137 if (s[n] == '\0') {
138 /*
139 * Return properly NUL terminated string
140 */
141 return s + offset;
142 }
143 }
144 /*
145 * String is not NUL terminated
146 * Return error to avoid SEGV in application
147 */
148 seterr(ERROR_UNTERM);
149 return NULL;
150 }
151