xref: /illumos-gate/usr/src/cmd/sgs/libelf/common/strptr.c (revision 2a8bcb4e)
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