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 "@(#)strptr.c 1.12 08/05/31 SMI" 31 32#include "libelf.h" 33#include "decl.h" 34#include "msg.h" 35 36 37char * 38elf_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 47#if defined(__APPLE__) 48 extern const char *elf_macho_str_off(size_t off); 49 50 if (elf->ed_kind == ELF_K_MACHO && (ndx == SHN_MACHO || ndx == SHN_MACHO_64)) 51 return (char *)elf_macho_str_off(off); 52#endif /* __APPLE__ */ 53 54 if ((s = elf_getscn(elf, ndx)) == 0) { 55 _elf_seterr(EREQ_STRSCN, 0); 56 return (0); 57 } 58 READLOCKS(elf, s) 59 if (elf->ed_class == ELFCLASS32) { 60 Elf32_Shdr* sh = (Elf32_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 if (elf->ed_class == ELFCLASS64) { 68 Elf64_Shdr* sh = (Elf64_Shdr*)s->s_shdr; 69 70 if ((sh == 0) || (sh->sh_type != SHT_STRTAB)) { 71 _elf_seterr(EREQ_STRSCN, 0); 72 READUNLOCKS(elf, s) 73 return (0); 74 } 75 } else { 76 _elf_seterr(EREQ_STRSCN, 0); 77 READUNLOCKS(elf, s) 78 return (0); 79 } 80 81 82 /* 83 * If the layout bit is set, use the offsets and 84 * sizes in the data buffers. Otherwise, take 85 * data buffers in order. 86 */ 87 88 d = 0; 89 if (elf->ed_uflags & ELF_F_LAYOUT) { 90 while ((d = _elf_locked_getdata(s, d)) != 0) { 91 if (d->d_buf == 0) 92 continue; 93 if ((off >= d->d_off) && 94 (off < d->d_off + d->d_size)) { 95 rc = (char *)d->d_buf + off - d->d_off; 96 READUNLOCKS(elf, s) 97 return (rc); 98 } 99 } 100 } else { 101 size_t sz = 0, j; 102 while ((d = _elf_locked_getdata(s, d)) != 0) { 103 if (((j = d->d_align) > 1) && (sz % j != 0)) { 104 j -= sz % j; 105 sz += j; 106 if (off < j) 107 break; 108 off -= j; 109 } 110 if (d->d_buf != 0) { 111 if (off < d->d_size) { 112 rc = (char *)d->d_buf + off; 113 READUNLOCKS(elf, s) 114 return (rc); 115 } 116 } 117 sz += d->d_size; 118 if (off < d->d_size) 119 break; 120 off -= d->d_size; 121 } 122 } 123 _elf_seterr(EREQ_STROFF, 0); 124 READUNLOCKS(elf, s) 125 return (0); 126} 127