/ external / libelf / libelf_extended.c
libelf_extended.c
  1  /*-
  2   * Copyright (c) 2006,2008 Joseph Koshy
  3   * All rights reserved.
  4   *
  5   * Redistribution and use in source and binary forms, with or without
  6   * modification, are permitted provided that the following conditions
  7   * are met:
  8   * 1. Redistributions of source code must retain the above copyright
  9   *    notice, this list of conditions and the following disclaimer.
 10   * 2. Redistributions in binary form must reproduce the above copyright
 11   *    notice, this list of conditions and the following disclaimer in the
 12   *    documentation and/or other materials provided with the distribution.
 13   *
 14   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 15   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 16   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 17   * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 18   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 19   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 20   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 21   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 22   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 23   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 24   * SUCH DAMAGE.
 25   */
 26  
 27  #include <sys/cdefs.h>
 28  
 29  #include <assert.h>
 30  #include <libelf.h>
 31  
 32  #include "_libelf.h"
 33  
 34  ELFTC_VCSID("$Id$");
 35  
 36  /*
 37   * Retrieve section #0, allocating a new section if needed.
 38   */
 39  static Elf_Scn *
 40  _libelf_getscn0(Elf *e)
 41  {
 42  	Elf_Scn *s;
 43  
 44  	if ((s = STAILQ_FIRST(&e->e_u.e_elf.e_scn)) != NULL)
 45  		return (s);
 46  
 47  	return (_libelf_allocate_scn(e, (size_t) SHN_UNDEF));
 48  }
 49  
 50  int
 51  _libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum)
 52  {
 53  	Elf_Scn *scn;
 54  
 55  	if (shnum >= SHN_LORESERVE) {
 56  		if ((scn = _libelf_getscn0(e)) == NULL)
 57  			return (0);
 58  
 59  		assert(scn->s_ndx == SHN_UNDEF);
 60  
 61  		if (ec == ELFCLASS32)
 62  			scn->s_shdr.s_shdr32.sh_size = shnum;
 63  		else
 64  			scn->s_shdr.s_shdr64.sh_size = shnum;
 65  
 66  		(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
 67  
 68  		shnum = 0;
 69  	}
 70  
 71  	if (ec == ELFCLASS32)
 72  		((Elf32_Ehdr *) eh)->e_shnum = shnum & 0xFFFFU;
 73  	else
 74  		((Elf64_Ehdr *) eh)->e_shnum = shnum & 0xFFFFU;
 75  
 76  
 77  	return (1);
 78  }
 79  
 80  int
 81  _libelf_setshstrndx(Elf *e, void *eh, int ec, size_t shstrndx)
 82  {
 83  	Elf_Scn *scn;
 84  
 85  	if (shstrndx >= SHN_LORESERVE) {
 86  		if ((scn = _libelf_getscn0(e)) == NULL)
 87  			return (0);
 88  
 89  		assert(scn->s_ndx == SHN_UNDEF);
 90  
 91  		if (ec == ELFCLASS32)
 92  			scn->s_shdr.s_shdr32.sh_link = shstrndx;
 93  		else
 94  			scn->s_shdr.s_shdr64.sh_link = shstrndx;
 95  
 96  		(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
 97  
 98  		shstrndx = SHN_XINDEX;
 99  	}
100  
101  	if (ec == ELFCLASS32)
102  		((Elf32_Ehdr *) eh)->e_shstrndx = shstrndx & 0xFFFFU;
103  	else
104  		((Elf64_Ehdr *) eh)->e_shstrndx = shstrndx & 0xFFFFU;
105  
106  	return (1);
107  }
108  
109  int
110  _libelf_setphnum(Elf *e, void *eh, int ec, size_t phnum)
111  {
112  	Elf_Scn *scn;
113  
114  	if (phnum >= PN_XNUM) {
115  		if ((scn = _libelf_getscn0(e)) == NULL)
116  			return (0);
117  
118  		assert(scn->s_ndx == SHN_UNDEF);
119  
120  		if (ec == ELFCLASS32)
121  			scn->s_shdr.s_shdr32.sh_info = phnum;
122  		else
123  			scn->s_shdr.s_shdr64.sh_info = phnum;
124  
125  		(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
126  
127  		phnum = PN_XNUM;
128  	}
129  
130  	if (ec == ELFCLASS32)
131  		((Elf32_Ehdr *) eh)->e_phnum = phnum & 0xFFFFU;
132  	else
133  		((Elf64_Ehdr *) eh)->e_phnum = phnum & 0xFFFFU;
134  
135  	return (1);
136  }