/ external / libelf / gelf_shdr.c
gelf_shdr.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 <gelf.h>
 31  #include <libelf.h>
 32  #include <limits.h>
 33  
 34  #include "_libelf.h"
 35  
 36  ELFTC_VCSID("$Id$");
 37  
 38  Elf32_Shdr *
 39  elf32_getshdr(Elf_Scn *s)
 40  {
 41  	return (_libelf_getshdr(s, ELFCLASS32));
 42  }
 43  
 44  Elf64_Shdr *
 45  elf64_getshdr(Elf_Scn *s)
 46  {
 47  	return (_libelf_getshdr(s, ELFCLASS64));
 48  }
 49  
 50  GElf_Shdr *
 51  gelf_getshdr(Elf_Scn *s, GElf_Shdr *d)
 52  {
 53  	int ec;
 54  	void *sh;
 55  	Elf32_Shdr *sh32;
 56  	Elf64_Shdr *sh64;
 57  
 58  	if (d == NULL) {
 59  		LIBELF_SET_ERROR(ARGUMENT, 0);
 60  		return (NULL);
 61  	}
 62  
 63  	if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL)
 64  		return (NULL);
 65  
 66  	ec = s->s_elf->e_class;
 67  	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
 68  
 69  	if (ec == ELFCLASS32) {
 70  		sh32 = (Elf32_Shdr *) sh;
 71  
 72  		d->sh_name      = sh32->sh_name;
 73  		d->sh_type      = sh32->sh_type;
 74  		d->sh_flags     = (Elf64_Xword) sh32->sh_flags;
 75  		d->sh_addr      = (Elf64_Addr) sh32->sh_addr;
 76  		d->sh_offset    = (Elf64_Off) sh32->sh_offset;
 77  		d->sh_size      = (Elf64_Xword) sh32->sh_size;
 78  		d->sh_link      = sh32->sh_link;
 79  		d->sh_info      = sh32->sh_info;
 80  		d->sh_addralign = (Elf64_Xword) sh32->sh_addralign;
 81  		d->sh_entsize   = (Elf64_Xword) sh32->sh_entsize;
 82  	} else {
 83  		sh64 = (Elf64_Shdr *) sh;
 84  		*d = *sh64;
 85  	}
 86  
 87  	return (d);
 88  }
 89  
 90  int
 91  gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *s)
 92  {
 93  	int ec;
 94  	Elf *e;
 95  	Elf32_Shdr *sh32;
 96  
 97  
 98  	if (s == NULL || scn == NULL || (e = scn->s_elf) == NULL ||
 99  	    e->e_kind != ELF_K_ELF ||
100  	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
101  		LIBELF_SET_ERROR(ARGUMENT, 0);
102  		return (0);
103  	}
104  
105  	if (e->e_cmd == ELF_C_READ) {
106  		LIBELF_SET_ERROR(MODE, 0);
107  		return (0);
108  	}
109  
110  	(void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY);
111  
112  	if (ec == ELFCLASS64) {
113  		scn->s_shdr.s_shdr64 = *s;
114  		return (1);
115  	}
116  
117  	sh32 = &scn->s_shdr.s_shdr32;
118  
119  	sh32->sh_name	 =  s->sh_name;
120  	sh32->sh_type	 =  s->sh_type;
121  	LIBELF_COPY_U32(sh32, s, sh_flags);
122  	LIBELF_COPY_U32(sh32, s, sh_addr);
123  	LIBELF_COPY_U32(sh32, s, sh_offset);
124  	LIBELF_COPY_U32(sh32, s, sh_size);
125  	sh32->sh_link	 =  s->sh_link;
126  	sh32->sh_info	 =  s->sh_info;
127  	LIBELF_COPY_U32(sh32, s, sh_addralign);
128  	LIBELF_COPY_U32(sh32, s, sh_entsize);
129  
130  	return (1);
131  }