xref: /illumos-gate/usr/src/cmd/sgs/libelf/common/strptr.c (revision 8b80e8cb6855118d46f605e91b5ed4ce83417395)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include "libelf.h"
33 #include "decl.h"
34 #include "msg.h"
35 
36 
37 char *
38 elf_strptr(Elf * elf, size_t ndx, size_t off)
39 {
40 	Elf_Scn		*s;
41 	Elf_Data	*d;
42 	char		*rc;
43 
44 	if (elf == 0)
45 		return (0);
46 	if ((s = elf_getscn(elf, ndx)) == 0) {
47 		_elf_seterr(EREQ_STRSCN, 0);
48 		return (0);
49 	}
50 	READLOCKS(elf, s)
51 	if (elf->ed_class == ELFCLASS32) {
52 		Elf32_Shdr* sh = (Elf32_Shdr*)s->s_shdr;
53 
54 		if ((sh == 0) || (sh->sh_type != SHT_STRTAB)) {
55 			_elf_seterr(EREQ_STRSCN, 0);
56 			READUNLOCKS(elf, s)
57 			return (0);
58 		}
59 	} else if (elf->ed_class == ELFCLASS64) {
60 		Elf64_Shdr* sh = (Elf64_Shdr*)s->s_shdr;
61 
62 		if ((sh == 0) || (sh->sh_type != SHT_STRTAB)) {
63 			_elf_seterr(EREQ_STRSCN, 0);
64 			READUNLOCKS(elf, s)
65 			return (0);
66 		}
67 	} else {
68 		_elf_seterr(EREQ_STRSCN, 0);
69 		READUNLOCKS(elf, s)
70 		return (0);
71 	}
72 
73 
74 	/*
75 	 * If the layout bit is set, use the offsets and
76 	 * sizes in the data buffers.  Otherwise, take
77 	 * data buffers in order.
78 	 */
79 
80 	d = 0;
81 	if (elf->ed_uflags & ELF_F_LAYOUT) {
82 		while ((d = _elf_locked_getdata(s, d)) != 0) {
83 			if (d->d_buf == 0)
84 				continue;
85 			if ((off >= d->d_off) &&
86 			    (off < d->d_off + d->d_size)) {
87 				rc = (char *)d->d_buf + off - d->d_off;
88 				READUNLOCKS(elf, s)
89 				return (rc);
90 			}
91 		}
92 	} else {
93 		size_t	sz = 0, j;
94 		while ((d = _elf_locked_getdata(s, d)) != 0) {
95 			if (((j = d->d_align) > 1) && (sz % j != 0)) {
96 				j -= sz % j;
97 				sz += j;
98 				if (off < j)
99 					break;
100 				off -= j;
101 			}
102 			if (d->d_buf != 0) {
103 				if (off < d->d_size) {
104 					rc = (char *)d->d_buf + off;
105 					READUNLOCKS(elf, s)
106 					return (rc);
107 				}
108 			}
109 			sz += d->d_size;
110 			if (off < d->d_size)
111 				break;
112 			off -= d->d_size;
113 		}
114 	}
115 	_elf_seterr(EREQ_STROFF, 0);
116 	READUNLOCKS(elf, s)
117 	return (0);
118 }
119