gelf_sym.c revision 4484
13569Sgblack@eecs.umich.edu/*-
23569Sgblack@eecs.umich.edu * Copyright (c) 2006 Joseph Koshy
33569Sgblack@eecs.umich.edu * All rights reserved.
43569Sgblack@eecs.umich.edu *
53569Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
63569Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions
73569Sgblack@eecs.umich.edu * are met:
83569Sgblack@eecs.umich.edu * 1. Redistributions of source code must retain the above copyright
93569Sgblack@eecs.umich.edu *    notice, this list of conditions and the following disclaimer.
103569Sgblack@eecs.umich.edu * 2. Redistributions in binary form must reproduce the above copyright
113569Sgblack@eecs.umich.edu *    notice, this list of conditions and the following disclaimer in the
123569Sgblack@eecs.umich.edu *    documentation and/or other materials provided with the distribution.
133569Sgblack@eecs.umich.edu *
143569Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
153569Sgblack@eecs.umich.edu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
163569Sgblack@eecs.umich.edu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
173569Sgblack@eecs.umich.edu * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
183569Sgblack@eecs.umich.edu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
193569Sgblack@eecs.umich.edu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
203569Sgblack@eecs.umich.edu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
213569Sgblack@eecs.umich.edu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
223569Sgblack@eecs.umich.edu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
233569Sgblack@eecs.umich.edu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
243569Sgblack@eecs.umich.edu * SUCH DAMAGE.
253569Sgblack@eecs.umich.edu */
263569Sgblack@eecs.umich.edu
273569Sgblack@eecs.umich.edu#include <limits.h>
283804Ssaidi@eecs.umich.edu
293569Sgblack@eecs.umich.edu#include <assert.h>
303569Sgblack@eecs.umich.edu#include "gelf.h"
313804Ssaidi@eecs.umich.edu
323811Ssaidi@eecs.umich.edu#include "_libelf.h"
333569Sgblack@eecs.umich.edu
343824Ssaidi@eecs.umich.eduGElf_Sym *
353811Ssaidi@eecs.umich.edugelf_getsym(Elf_Data *d, int ndx, GElf_Sym *dst)
363811Ssaidi@eecs.umich.edu{
373823Ssaidi@eecs.umich.edu        int ec;
383823Ssaidi@eecs.umich.edu        Elf *e;
393823Ssaidi@eecs.umich.edu        Elf_Scn *scn;
403569Sgblack@eecs.umich.edu        Elf32_Sym *sym32;
413569Sgblack@eecs.umich.edu        Elf64_Sym *sym64;
423804Ssaidi@eecs.umich.edu        size_t msz;
433804Ssaidi@eecs.umich.edu        uint32_t sh_type;
443569Sgblack@eecs.umich.edu
453569Sgblack@eecs.umich.edu        if (d == NULL || ndx < 0 || dst == NULL ||
463569Sgblack@eecs.umich.edu            (scn = d->d_scn) == NULL ||
473804Ssaidi@eecs.umich.edu            (e = scn->s_elf) == NULL) {
483881Ssaidi@eecs.umich.edu                LIBELF_SET_ERROR(ARGUMENT, 0);
493881Ssaidi@eecs.umich.edu                return (NULL);
503804Ssaidi@eecs.umich.edu        }
513804Ssaidi@eecs.umich.edu
523804Ssaidi@eecs.umich.edu        ec = e->e_class;
533804Ssaidi@eecs.umich.edu        assert(ec == ELFCLASS32 || ec == ELFCLASS64);
543569Sgblack@eecs.umich.edu
553804Ssaidi@eecs.umich.edu        if (ec == ELFCLASS32)
563804Ssaidi@eecs.umich.edu                sh_type = scn->s_shdr.s_shdr32.sh_type;
573881Ssaidi@eecs.umich.edu        else
583881Ssaidi@eecs.umich.edu                sh_type = scn->s_shdr.s_shdr64.sh_type;
593881Ssaidi@eecs.umich.edu
603804Ssaidi@eecs.umich.edu        if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
613569Sgblack@eecs.umich.edu                LIBELF_SET_ERROR(ARGUMENT, 0);
623804Ssaidi@eecs.umich.edu                return (NULL);
633804Ssaidi@eecs.umich.edu        }
643804Ssaidi@eecs.umich.edu
653804Ssaidi@eecs.umich.edu        msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
663881Ssaidi@eecs.umich.edu
673804Ssaidi@eecs.umich.edu        assert(msz > 0);
683804Ssaidi@eecs.umich.edu
693804Ssaidi@eecs.umich.edu        if (msz * ndx >= d->d_size) {
703804Ssaidi@eecs.umich.edu                LIBELF_SET_ERROR(ARGUMENT, 0);
713804Ssaidi@eecs.umich.edu                return (NULL);
723804Ssaidi@eecs.umich.edu        }
733804Ssaidi@eecs.umich.edu
743569Sgblack@eecs.umich.edu        if (ec == ELFCLASS32) {
753569Sgblack@eecs.umich.edu
763804Ssaidi@eecs.umich.edu                sym32 = (Elf32_Sym *) d->d_buf + ndx;
773804Ssaidi@eecs.umich.edu
783826Ssaidi@eecs.umich.edu                dst->st_name  = sym32->st_name;
793804Ssaidi@eecs.umich.edu                dst->st_value = (Elf64_Addr) sym32->st_value;
803569Sgblack@eecs.umich.edu                dst->st_size  = (Elf64_Xword) sym32->st_size;
813569Sgblack@eecs.umich.edu                dst->st_info  = ELF64_ST_INFO(ELF32_ST_BIND(sym32->st_info),
823804Ssaidi@eecs.umich.edu                    ELF32_ST_TYPE(sym32->st_info));
833826Ssaidi@eecs.umich.edu                dst->st_other = sym32->st_other;
843907Ssaidi@eecs.umich.edu                dst->st_shndx = sym32->st_shndx;
853826Ssaidi@eecs.umich.edu        } else {
863811Ssaidi@eecs.umich.edu
873836Ssaidi@eecs.umich.edu                sym64 = (Elf64_Sym *) d->d_buf + ndx;
883915Ssaidi@eecs.umich.edu
893907Ssaidi@eecs.umich.edu                *dst = *sym64;
903881Ssaidi@eecs.umich.edu        }
913881Ssaidi@eecs.umich.edu
923881Ssaidi@eecs.umich.edu        return (dst);
933881Ssaidi@eecs.umich.edu}
943907Ssaidi@eecs.umich.edu
953881Ssaidi@eecs.umich.eduint
963881Ssaidi@eecs.umich.edugelf_update_sym(Elf_Data *d, int ndx, GElf_Sym *gs)
973881Ssaidi@eecs.umich.edu{
983881Ssaidi@eecs.umich.edu        int ec;
993881Ssaidi@eecs.umich.edu        Elf *e;
1003907Ssaidi@eecs.umich.edu        Elf_Scn *scn;
1013907Ssaidi@eecs.umich.edu        Elf32_Sym *sym32;
1023907Ssaidi@eecs.umich.edu        Elf64_Sym *sym64;
1033907Ssaidi@eecs.umich.edu        size_t msz;
1043907Ssaidi@eecs.umich.edu        uint32_t sh_type;
1053907Ssaidi@eecs.umich.edu
1063907Ssaidi@eecs.umich.edu        if (d == NULL || ndx < 0 || gs == NULL ||
1073907Ssaidi@eecs.umich.edu            (scn = d->d_scn) == NULL ||
1083907Ssaidi@eecs.umich.edu            (e = scn->s_elf) == NULL) {
1093907Ssaidi@eecs.umich.edu                LIBELF_SET_ERROR(ARGUMENT, 0);
1103907Ssaidi@eecs.umich.edu                return (0);
1113907Ssaidi@eecs.umich.edu        }
1123907Ssaidi@eecs.umich.edu
1133907Ssaidi@eecs.umich.edu        ec = e->e_class;
1143907Ssaidi@eecs.umich.edu        assert(ec == ELFCLASS32 || ec == ELFCLASS64);
1153907Ssaidi@eecs.umich.edu
1163907Ssaidi@eecs.umich.edu        if (ec == ELFCLASS32)
1173907Ssaidi@eecs.umich.edu                sh_type = scn->s_shdr.s_shdr32.sh_type;
1183907Ssaidi@eecs.umich.edu        else
1193907Ssaidi@eecs.umich.edu                sh_type = scn->s_shdr.s_shdr64.sh_type;
1203907Ssaidi@eecs.umich.edu
1213907Ssaidi@eecs.umich.edu        if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
1223907Ssaidi@eecs.umich.edu                LIBELF_SET_ERROR(ARGUMENT, 0);
1233881Ssaidi@eecs.umich.edu                return (0);
1243881Ssaidi@eecs.umich.edu        }
1253881Ssaidi@eecs.umich.edu
1263881Ssaidi@eecs.umich.edu        msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
1273881Ssaidi@eecs.umich.edu        assert(msz > 0);
1283881Ssaidi@eecs.umich.edu
1293881Ssaidi@eecs.umich.edu        if (msz * ndx >= d->d_size) {
1303881Ssaidi@eecs.umich.edu                LIBELF_SET_ERROR(ARGUMENT, 0);
1313881Ssaidi@eecs.umich.edu                return (0);
1323881Ssaidi@eecs.umich.edu        }
1333881Ssaidi@eecs.umich.edu
1343881Ssaidi@eecs.umich.edu        if (ec == ELFCLASS32) {
1353907Ssaidi@eecs.umich.edu                sym32 = (Elf32_Sym *) d->d_buf + ndx;
1363811Ssaidi@eecs.umich.edu
1373826Ssaidi@eecs.umich.edu                sym32->st_name  = gs->st_name;
1383826Ssaidi@eecs.umich.edu                sym32->st_info  = gs->st_info;
1393826Ssaidi@eecs.umich.edu                sym32->st_other = gs->st_other;
1403826Ssaidi@eecs.umich.edu                sym32->st_shndx = gs->st_shndx;
1413881Ssaidi@eecs.umich.edu
1423881Ssaidi@eecs.umich.edu                LIBELF_COPY_U32(sym32, gs, st_value);
1433881Ssaidi@eecs.umich.edu                LIBELF_COPY_U32(sym32, gs, st_size);
1443881Ssaidi@eecs.umich.edu        } else {
1453881Ssaidi@eecs.umich.edu                sym64 = (Elf64_Sym *) d->d_buf + ndx;
1463881Ssaidi@eecs.umich.edu
1473881Ssaidi@eecs.umich.edu                *sym64 = *gs;
1483881Ssaidi@eecs.umich.edu        }
1493881Ssaidi@eecs.umich.edu
1503881Ssaidi@eecs.umich.edu        return (1);
1513881Ssaidi@eecs.umich.edu}
1523881Ssaidi@eecs.umich.edu