1263320Sdim/*- 2263320Sdim * Copyright (c) 2006,2008 Joseph Koshy 3263320Sdim * All rights reserved. 4263320Sdim * 5263320Sdim * Redistribution and use in source and binary forms, with or without 6263320Sdim * modification, are permitted provided that the following conditions 7263320Sdim * are met: 8263320Sdim * 1. Redistributions of source code must retain the above copyright 9263320Sdim * notice, this list of conditions and the following disclaimer. 10263320Sdim * 2. Redistributions in binary form must reproduce the above copyright 11263320Sdim * notice, this list of conditions and the following disclaimer in the 12263320Sdim * documentation and/or other materials provided with the distribution. 13263320Sdim * 14263320Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15263320Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16263320Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17263320Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18263320Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19263320Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20263320Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21263320Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22263320Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23263320Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24263320Sdim * SUCH DAMAGE. 25263320Sdim */ 26263320Sdim 27263320Sdim#include <assert.h> 28263320Sdim#include <gelf.h> 29263320Sdim 30263320Sdim#include "_libelf.h" 31263320Sdim 32263320SdimELFTC_VCSID("$Id: gelf_symshndx.c,v 1.2 2020/05/18 06:46:23 jsg Exp $"); 33263320Sdim 34263320SdimGElf_Sym * 35263320Sdimgelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst, 36263320Sdim Elf32_Word *shindex) 37263320Sdim{ 38263320Sdim int ec; 39263320Sdim Elf *e; 40263320Sdim size_t msz; 41263320Sdim Elf_Scn *scn; 42263320Sdim uint32_t sh_type; 43263320Sdim struct _Libelf_Data *ld, *lid; 44263320Sdim 45263320Sdim ld = (struct _Libelf_Data *) d; 46263320Sdim lid = (struct _Libelf_Data *) id; 47263320Sdim 48263320Sdim if (gelf_getsym(d, ndx, dst) == 0) 49263320Sdim return (NULL); 50263320Sdim 51263320Sdim if (lid == NULL || (scn = lid->d_scn) == NULL || 52263320Sdim (e = scn->s_elf) == NULL || (e != ld->d_scn->s_elf) || 53263320Sdim shindex == NULL) { 54263320Sdim LIBELF_SET_ERROR(ARGUMENT, 0); 55263320Sdim return (NULL); 56263320Sdim } 57263320Sdim 58263320Sdim ec = e->e_class; 59263320Sdim assert(ec == ELFCLASS32 || ec == ELFCLASS64); 60263320Sdim 61263320Sdim if (ec == ELFCLASS32) 62263320Sdim sh_type = scn->s_shdr.s_shdr32.sh_type; 63263320Sdim else 64263320Sdim sh_type = scn->s_shdr.s_shdr64.sh_type; 65263320Sdim 66263320Sdim if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD || 67263320Sdim id->d_type != ELF_T_WORD) { 68263320Sdim LIBELF_SET_ERROR(ARGUMENT, 0); 69263320Sdim return (NULL); 70263320Sdim } 71263320Sdim 72263320Sdim if ((msz = _libelf_msize(ELF_T_WORD, ec, e->e_version)) == 0) 73263320Sdim return (NULL); 74263320Sdim 75263320Sdim assert(ndx >= 0); 76263320Sdim 77263320Sdim if (msz * (size_t) ndx >= id->d_size) { 78263320Sdim LIBELF_SET_ERROR(ARGUMENT, 0); 79263320Sdim return (NULL); 80263320Sdim } 81263320Sdim 82263320Sdim *shindex = ((Elf32_Word *) id->d_buf)[ndx]; 83263320Sdim 84263320Sdim return (dst); 85263320Sdim} 86263320Sdim 87263320Sdimint 88263320Sdimgelf_update_symshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *gs, 89263320Sdim Elf32_Word xindex) 90263320Sdim{ 91263320Sdim int ec; 92263320Sdim Elf *e; 93263320Sdim size_t msz; 94263320Sdim Elf_Scn *scn; 95263320Sdim uint32_t sh_type; 96263320Sdim struct _Libelf_Data *ld, *lid; 97263320Sdim 98263320Sdim ld = (struct _Libelf_Data *) d; 99263320Sdim lid = (struct _Libelf_Data *) id; 100263320Sdim 101263320Sdim if (gelf_update_sym(d, ndx, gs) == 0) 102263320Sdim return (0); 103263320Sdim 104263320Sdim if (lid == NULL || (scn = lid->d_scn) == NULL || 105263320Sdim (e = scn->s_elf) == NULL || (e != ld->d_scn->s_elf)) { 106263320Sdim LIBELF_SET_ERROR(ARGUMENT, 0); 107263320Sdim return (0); 108263320Sdim } 109263320Sdim 110263320Sdim ec = e->e_class; 111263320Sdim assert(ec == ELFCLASS32 || ec == ELFCLASS64); 112263320Sdim 113263320Sdim if (ec == ELFCLASS32) 114263320Sdim sh_type = scn->s_shdr.s_shdr32.sh_type; 115263320Sdim else 116263320Sdim sh_type = scn->s_shdr.s_shdr64.sh_type; 117263320Sdim 118263320Sdim if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD || 119263320Sdim d->d_type != ELF_T_WORD) { 120263320Sdim LIBELF_SET_ERROR(ARGUMENT, 0); 121263320Sdim return (0); 122263320Sdim } 123263320Sdim 124263320Sdim if ((msz = _libelf_msize(ELF_T_WORD, ec, e->e_version)) == 0) 125263320Sdim return (0); 126263320Sdim 127263320Sdim assert(ndx >= 0); 128263320Sdim 129263320Sdim if (msz * (size_t) ndx >= id->d_size) { 130263320Sdim LIBELF_SET_ERROR(ARGUMENT, 0); 131263320Sdim return (0); 132263320Sdim } 133263320Sdim 134263320Sdim *(((Elf32_Word *) id->d_buf) + ndx) = xindex; 135263320Sdim 136263320Sdim return (1); 137263320Sdim} 138263320Sdim