Home | History | Annotate | Line # | Download | only in libelf
gelf_rel.c revision 1.1.1.3
      1  1.1.1.2  christos /*	$NetBSD: gelf_rel.c,v 1.1.1.3 2024/03/03 14:41:47 christos Exp $	*/
      2  1.1.1.3  christos 
      3      1.1  christos /*-
      4      1.1  christos  * Copyright (c) 2006,2008 Joseph Koshy
      5      1.1  christos  * All rights reserved.
      6      1.1  christos  *
      7      1.1  christos  * Redistribution and use in source and binary forms, with or without
      8      1.1  christos  * modification, are permitted provided that the following conditions
      9      1.1  christos  * are met:
     10      1.1  christos  * 1. Redistributions of source code must retain the above copyright
     11      1.1  christos  *    notice, this list of conditions and the following disclaimer.
     12      1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13      1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     14      1.1  christos  *    documentation and/or other materials provided with the distribution.
     15      1.1  christos  *
     16      1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17      1.1  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18      1.1  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19      1.1  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20      1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21      1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22      1.1  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23      1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24      1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25      1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26      1.1  christos  * SUCH DAMAGE.
     27      1.1  christos  */
     28      1.1  christos 
     29  1.1.1.3  christos #include <sys/cdefs.h>
     30  1.1.1.3  christos 
     31      1.1  christos #include <assert.h>
     32      1.1  christos #include <gelf.h>
     33      1.1  christos #include <limits.h>
     34  1.1.1.2  christos #include <stdint.h>
     35      1.1  christos 
     36      1.1  christos #include "_libelf.h"
     37      1.1  christos 
     38  1.1.1.3  christos ELFTC_VCSID("Id: gelf_rel.c 3977 2022-05-01 06:45:34Z jkoshy");
     39  1.1.1.3  christos 
     40  1.1.1.3  christos __RCSID("$NetBSD: gelf_rel.c,v 1.1.1.3 2024/03/03 14:41:47 christos Exp $");
     41      1.1  christos 
     42      1.1  christos GElf_Rel *
     43      1.1  christos gelf_getrel(Elf_Data *ed, int ndx, GElf_Rel *dst)
     44      1.1  christos {
     45      1.1  christos 	int ec;
     46      1.1  christos 	Elf *e;
     47      1.1  christos 	size_t msz;
     48      1.1  christos 	Elf_Scn *scn;
     49      1.1  christos 	uint32_t sh_type;
     50      1.1  christos 	Elf32_Rel *rel32;
     51      1.1  christos 	Elf64_Rel *rel64;
     52      1.1  christos 	struct _Libelf_Data *d;
     53      1.1  christos 
     54      1.1  christos 	d = (struct _Libelf_Data *) ed;
     55      1.1  christos 
     56      1.1  christos 	if (d == NULL || ndx < 0 || dst == NULL ||
     57      1.1  christos 	    (scn = d->d_scn) == NULL ||
     58      1.1  christos 	    (e = scn->s_elf) == NULL) {
     59      1.1  christos 		LIBELF_SET_ERROR(ARGUMENT, 0);
     60      1.1  christos 		return (NULL);
     61      1.1  christos 	}
     62      1.1  christos 
     63      1.1  christos 	ec = e->e_class;
     64      1.1  christos 	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
     65      1.1  christos 
     66      1.1  christos 	if (ec == ELFCLASS32)
     67      1.1  christos 		sh_type = scn->s_shdr.s_shdr32.sh_type;
     68      1.1  christos 	else
     69      1.1  christos 		sh_type = scn->s_shdr.s_shdr64.sh_type;
     70      1.1  christos 
     71      1.1  christos 	if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) {
     72      1.1  christos 		LIBELF_SET_ERROR(ARGUMENT, 0);
     73      1.1  christos 		return (NULL);
     74      1.1  christos 	}
     75      1.1  christos 
     76  1.1.1.3  christos 	if ((msz = _libelf_msize(ELF_T_REL, ec, e->e_version)) == 0)
     77  1.1.1.3  christos 		return (NULL);
     78      1.1  christos 
     79  1.1.1.2  christos 	assert(ndx >= 0);
     80      1.1  christos 
     81  1.1.1.2  christos 	if (msz * (size_t) ndx >= d->d_data.d_size) {
     82      1.1  christos 		LIBELF_SET_ERROR(ARGUMENT, 0);
     83      1.1  christos 		return (NULL);
     84      1.1  christos 	}
     85      1.1  christos 
     86      1.1  christos 	if (ec == ELFCLASS32) {
     87      1.1  christos 		rel32 = (Elf32_Rel *) d->d_data.d_buf + ndx;
     88      1.1  christos 
     89      1.1  christos 		dst->r_offset = (Elf64_Addr) rel32->r_offset;
     90      1.1  christos 		dst->r_info   = ELF64_R_INFO(
     91      1.1  christos 		    (Elf64_Xword) ELF32_R_SYM(rel32->r_info),
     92      1.1  christos 		    ELF32_R_TYPE(rel32->r_info));
     93      1.1  christos 
     94      1.1  christos 	} else {
     95      1.1  christos 
     96      1.1  christos 		rel64 = (Elf64_Rel *) d->d_data.d_buf + ndx;
     97      1.1  christos 
     98      1.1  christos 		*dst = *rel64;
     99      1.1  christos 	}
    100      1.1  christos 
    101      1.1  christos 	return (dst);
    102      1.1  christos }
    103      1.1  christos 
    104      1.1  christos int
    105      1.1  christos gelf_update_rel(Elf_Data *ed, int ndx, GElf_Rel *dr)
    106      1.1  christos {
    107      1.1  christos 	int ec;
    108      1.1  christos 	Elf *e;
    109      1.1  christos 	size_t msz;
    110      1.1  christos 	Elf_Scn *scn;
    111      1.1  christos 	uint32_t sh_type;
    112      1.1  christos 	Elf32_Rel *rel32;
    113      1.1  christos 	Elf64_Rel *rel64;
    114      1.1  christos 	struct _Libelf_Data *d;
    115      1.1  christos 
    116      1.1  christos 	d = (struct _Libelf_Data *) ed;
    117      1.1  christos 
    118      1.1  christos 	if (d == NULL || ndx < 0 || dr == NULL ||
    119      1.1  christos 	    (scn = d->d_scn) == NULL ||
    120      1.1  christos 	    (e = scn->s_elf) == NULL) {
    121      1.1  christos 		LIBELF_SET_ERROR(ARGUMENT, 0);
    122      1.1  christos 		return (0);
    123      1.1  christos 	}
    124      1.1  christos 
    125      1.1  christos 	ec = e->e_class;
    126      1.1  christos 	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
    127      1.1  christos 
    128      1.1  christos 	if (ec == ELFCLASS32)
    129      1.1  christos 		sh_type = scn->s_shdr.s_shdr32.sh_type;
    130      1.1  christos 	else
    131      1.1  christos 		sh_type = scn->s_shdr.s_shdr64.sh_type;
    132      1.1  christos 
    133      1.1  christos 	if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) {
    134      1.1  christos 		LIBELF_SET_ERROR(ARGUMENT, 0);
    135      1.1  christos 		return (0);
    136      1.1  christos 	}
    137      1.1  christos 
    138  1.1.1.3  christos 	if ((msz = _libelf_msize(ELF_T_REL, ec, e->e_version)) == 0)
    139  1.1.1.3  christos 		return (0);
    140  1.1.1.2  christos 
    141  1.1.1.2  christos 	assert(ndx >= 0);
    142      1.1  christos 
    143  1.1.1.2  christos 	if (msz * (size_t) ndx >= d->d_data.d_size) {
    144      1.1  christos 		LIBELF_SET_ERROR(ARGUMENT, 0);
    145      1.1  christos 		return (0);
    146      1.1  christos 	}
    147      1.1  christos 
    148      1.1  christos 	if (ec == ELFCLASS32) {
    149      1.1  christos 		rel32 = (Elf32_Rel *) d->d_data.d_buf + ndx;
    150      1.1  christos 
    151      1.1  christos 		LIBELF_COPY_U32(rel32, dr, r_offset);
    152      1.1  christos 
    153  1.1.1.3  christos 		if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0U) ||
    154      1.1  christos 		    ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) {
    155      1.1  christos 			LIBELF_SET_ERROR(RANGE, 0);
    156      1.1  christos 			return (0);
    157      1.1  christos 		}
    158  1.1.1.2  christos 		rel32->r_info = ELF32_R_INFO(
    159  1.1.1.2  christos 			(Elf32_Word) ELF64_R_SYM(dr->r_info),
    160  1.1.1.2  christos 			(Elf32_Word) ELF64_R_TYPE(dr->r_info));
    161      1.1  christos 	} else {
    162      1.1  christos 		rel64 = (Elf64_Rel *) d->d_data.d_buf + ndx;
    163      1.1  christos 
    164      1.1  christos 		*rel64 = *dr;
    165      1.1  christos 	}
    166      1.1  christos 
    167      1.1  christos 	return (1);
    168      1.1  christos }
    169