Home | History | Annotate | Line # | Download | only in libelf
      1 /*	$NetBSD: gelf_phdr.c,v 1.6 2025/12/25 18:58:13 jkoshy Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2006,2008 Joseph Koshy
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 
     31 #include <gelf.h>
     32 #include <libelf.h>
     33 #include <limits.h>
     34 #include <stdint.h>
     35 
     36 #include "_libelf.h"
     37 
     38 ELFTC_VCSID("Id: gelf_phdr.c 4074 2025-01-07 15:34:21Z jkoshy");
     39 
     40 __RCSID("$NetBSD: gelf_phdr.c,v 1.6 2025/12/25 18:58:13 jkoshy Exp $");
     41 
     42 Elf32_Phdr *
     43 elf32_getphdr(Elf *e)
     44 {
     45 	return (_libelf_getphdr(e, ELFCLASS32));
     46 }
     47 
     48 Elf64_Phdr *
     49 elf64_getphdr(Elf *e)
     50 {
     51 	return (_libelf_getphdr(e, ELFCLASS64));
     52 }
     53 
     54 GElf_Phdr *
     55 gelf_getphdr(Elf *e, int index, GElf_Phdr *d)
     56 {
     57 	unsigned int ec;
     58 	Elf32_Ehdr *eh32;
     59 	Elf64_Ehdr *eh64;
     60 	Elf32_Phdr *ep32;
     61 	Elf64_Phdr *ep64;
     62 	size_t phnum;
     63 
     64 	if (d == NULL || e == NULL ||
     65 	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
     66 	    (e->e_kind != ELF_K_ELF) || index < 0 ||
     67 	    elf_getphdrnum(e, &phnum) < 0) {
     68 		LIBELF_SET_ERROR(ARGUMENT, 0);
     69 		return (NULL);
     70 	}
     71 
     72 	if ((size_t)index >= phnum) {
     73 		LIBELF_SET_ERROR(ARGUMENT, 0);
     74 		return (NULL);
     75 	}
     76 
     77 	if (ec == ELFCLASS32) {
     78 		if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL ||
     79 		    ((ep32 = _libelf_getphdr(e, ELFCLASS32)) == NULL))
     80 			return (NULL);
     81 
     82 		ep32 += index;
     83 
     84 		d->p_type   = ep32->p_type;
     85 		d->p_offset = ep32->p_offset;
     86 		d->p_vaddr  = (Elf64_Addr) ep32->p_vaddr;
     87 		d->p_paddr  = (Elf64_Addr) ep32->p_paddr;
     88 		d->p_filesz = (Elf64_Xword) ep32->p_filesz;
     89 		d->p_memsz  = (Elf64_Xword) ep32->p_memsz;
     90 		d->p_flags  = ep32->p_flags;
     91 		d->p_align  = (Elf64_Xword) ep32->p_align;
     92 
     93 	} else {
     94 		if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL ||
     95 		    (ep64 = _libelf_getphdr(e, ELFCLASS64)) == NULL)
     96 			return (NULL);
     97 
     98 		ep64 += index;
     99 
    100 		*d = *ep64;
    101 	}
    102 
    103 	return (d);
    104 }
    105 
    106 Elf32_Phdr *
    107 elf32_newphdr(Elf *e, size_t count)
    108 {
    109 	return (_libelf_newphdr(e, ELFCLASS32, count));
    110 }
    111 
    112 Elf64_Phdr *
    113 elf64_newphdr(Elf *e, size_t count)
    114 {
    115 	return (_libelf_newphdr(e, ELFCLASS64, count));
    116 }
    117 
    118 void *
    119 gelf_newphdr(Elf *e, size_t count)
    120 {
    121 	if (e == NULL) {
    122 		LIBELF_SET_ERROR(ARGUMENT, 0);
    123 		return (NULL);
    124 	}
    125 	return (_libelf_newphdr(e, e->e_class, count));
    126 }
    127 
    128 int
    129 gelf_update_phdr(Elf *e, int ndx, GElf_Phdr *s)
    130 {
    131 	void *ehdr;
    132 	size_t phnum;
    133 	unsigned int ec;
    134 	Elf32_Phdr *ph32;
    135 	Elf64_Phdr *ph64;
    136 
    137 	if (s == NULL || e == NULL || e->e_kind != ELF_K_ELF ||
    138 	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
    139 	    elf_getphdrnum(e, &phnum) < 0) {
    140 		LIBELF_SET_ERROR(ARGUMENT, 0);
    141 		return (0);
    142 	}
    143 
    144 	if (e->e_cmd == ELF_C_READ) {
    145 		LIBELF_SET_ERROR(MODE, 0);
    146 		return (0);
    147 	}
    148 
    149 	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
    150 		return (0);
    151 
    152 	if (ndx < 0 || (size_t)ndx > phnum) {
    153 		LIBELF_SET_ERROR(ARGUMENT, 0);
    154 		return (0);
    155 	}
    156 
    157 	(void) elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY);
    158 
    159 	if (ec == ELFCLASS64) {
    160 		ph64 = e->e_u.e_elf.e_phdr.e_phdr64 + ndx;
    161 		*ph64 = *s;
    162 		return (1);
    163 	}
    164 
    165 	ph32 = e->e_u.e_elf.e_phdr.e_phdr32 + ndx;
    166 
    167 	ph32->p_type     =  s->p_type;
    168 	ph32->p_flags    =  s->p_flags;
    169 	LIBELF_COPY_U32(ph32, s, p_offset);
    170 	LIBELF_COPY_U32(ph32, s, p_vaddr);
    171 	LIBELF_COPY_U32(ph32, s, p_paddr);
    172 	LIBELF_COPY_U32(ph32, s, p_filesz);
    173 	LIBELF_COPY_U32(ph32, s, p_memsz);
    174 	LIBELF_COPY_U32(ph32, s, p_align);
    175 
    176 	return (1);
    177 }
    178