1/* Update section header.
2   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
3   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation, version 2.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program; if not, write to the Free Software Foundation,
16   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21
22#include <gelf.h>
23#include <string.h>
24
25#include "libelfP.h"
26
27
28int
29gelf_update_shdr (Elf_Scn *scn, GElf_Shdr *src)
30{
31  int result = 0;
32  Elf *elf;
33
34  if (scn == NULL || src == NULL)
35    return 0;
36
37  elf = scn->elf;
38  rwlock_wrlock (elf->lock);
39
40  if (elf->class == ELFCLASS32)
41    {
42      Elf32_Shdr *shdr = scn->shdr.e32 ?: INTUSE(elf32_getshdr) (scn);
43
44      if (shdr == NULL)
45	{
46	  __libelf_seterrno (ELF_E_INVALID_OPERAND);
47	  goto out;
48	}
49
50      if (unlikely (src->sh_flags > 0xffffffffull)
51	  || unlikely (src->sh_addr > 0xffffffffull)
52	  || unlikely (src->sh_offset > 0xffffffffull)
53	  || unlikely (src->sh_size > 0xffffffffull)
54	  || unlikely (src->sh_addralign > 0xffffffffull)
55	  || unlikely (src->sh_entsize > 0xffffffffull))
56	{
57	  __libelf_seterrno (ELF_E_INVALID_DATA);
58	  goto out;
59	}
60
61#define COPY(name) \
62      shdr->name = src->name
63      COPY (sh_name);
64      COPY (sh_type);
65      COPY (sh_flags);
66      COPY (sh_addr);
67      COPY (sh_offset);
68      COPY (sh_size);
69      COPY (sh_link);
70      COPY (sh_info);
71      COPY (sh_addralign);
72      COPY (sh_entsize);
73    }
74  else
75    {
76      Elf64_Shdr *shdr = scn->shdr.e64 ?: INTUSE(elf64_getshdr) (scn);
77
78      if (shdr == NULL)
79	{
80	  __libelf_seterrno (ELF_E_INVALID_OPERAND);
81	  goto out;
82	}
83
84      /* We only have to copy the data.  */
85      (void) memcpy (shdr, src, sizeof (GElf_Shdr));
86    }
87
88  result = 1;
89
90 out:
91  rwlock_unlock (elf->lock);
92
93  return result;
94}
95