1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29
30 #include "libelf.h"
31 #include "decl.h"
32 #include "msg.h"
33
34
35 char *
elf_strptr(Elf * elf,size_t ndx,size_t off)36 elf_strptr(Elf * elf, size_t ndx, size_t off)
37 {
38 Elf_Scn *s;
39 Elf_Data *d;
40 char *rc;
41
42 if (elf == 0)
43 return (0);
44 if ((s = elf_getscn(elf, ndx)) == 0) {
45 _elf_seterr(EREQ_STRSCN, 0);
46 return (0);
47 }
48 READLOCKS(elf, s)
49 if (elf->ed_class == ELFCLASS32) {
50 Elf32_Shdr* sh = (Elf32_Shdr*)s->s_shdr;
51
52 if ((sh == 0) || (sh->sh_type != SHT_STRTAB)) {
53 _elf_seterr(EREQ_STRSCN, 0);
54 READUNLOCKS(elf, s)
55 return (0);
56 }
57 } else if (elf->ed_class == ELFCLASS64) {
58 Elf64_Shdr* sh = (Elf64_Shdr*)s->s_shdr;
59
60 if ((sh == 0) || (sh->sh_type != SHT_STRTAB)) {
61 _elf_seterr(EREQ_STRSCN, 0);
62 READUNLOCKS(elf, s)
63 return (0);
64 }
65 } else {
66 _elf_seterr(EREQ_STRSCN, 0);
67 READUNLOCKS(elf, s)
68 return (0);
69 }
70
71
72 /*
73 * If the layout bit is set, use the offsets and
74 * sizes in the data buffers. Otherwise, take
75 * data buffers in order.
76 */
77
78 d = 0;
79 if (elf->ed_uflags & ELF_F_LAYOUT) {
80 while ((d = _elf_locked_getdata(s, d)) != 0) {
81 if (d->d_buf == 0)
82 continue;
83 if ((off >= d->d_off) &&
84 (off < d->d_off + d->d_size)) {
85 rc = (char *)d->d_buf + off - d->d_off;
86 READUNLOCKS(elf, s)
87 return (rc);
88 }
89 }
90 } else {
91 size_t sz = 0, j;
92 while ((d = _elf_locked_getdata(s, d)) != 0) {
93 if (((j = d->d_align) > 1) && (sz % j != 0)) {
94 j -= sz % j;
95 sz += j;
96 if (off < j)
97 break;
98 off -= j;
99 }
100 if (d->d_buf != 0) {
101 if (off < d->d_size) {
102 rc = (char *)d->d_buf + off;
103 READUNLOCKS(elf, s)
104 return (rc);
105 }
106 }
107 sz += d->d_size;
108 if (off < d->d_size)
109 break;
110 off -= d->d_size;
111 }
112 }
113 _elf_seterr(EREQ_STROFF, 0);
114 READUNLOCKS(elf, s)
115 return (0);
116 }
117