16258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper/* Update program header program header table entry.
2159ac52b061c60947a943c102298cd692223274fMark Wielaard   Copyright (C) 2000-2010 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
46258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
76258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   it under the terms of either
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
216258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   elfutils is distributed in the hope that it will be useful, but
226258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
236258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
246258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   General Public License for more details.
25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
286258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   not, see <http://www.gnu.org/licenses/>.  */
296258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
306258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper#ifdef HAVE_CONFIG_H
31b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh# include <config.h>
326258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper#endif
33b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
34b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh#include <gelf.h>
356258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper#include <string.h>
36b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
37b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh#include "libelfP.h"
38b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
39b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
40159ac52b061c60947a943c102298cd692223274fMark Wielaardint
41b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehgelf_update_phdr (Elf *elf, int ndx, GElf_Phdr *src)
42b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh{
43b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  int result = 0;
44b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
45b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  if (elf == NULL)
46b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    return 0;
47159ac52b061c60947a943c102298cd692223274fMark Wielaard
48b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  if (unlikely (elf->kind != ELF_K_ELF))
49b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    {
50b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      __libelf_seterrno (ELF_E_INVALID_HANDLE);
51b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      return 0;
52b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    }
53b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
546258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  rwlock_wrlock (elf->lock);
55b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
56b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  if (elf->class == ELFCLASS32)
57b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    {
586258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      Elf32_Phdr *phdr = elf->state.elf32.phdr;
59b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
60b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      /* We have to convert the data to the 32 bit format.  This might
61b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	 overflow some fields so we have to test for this case before
62b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	 copying.  */
63b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      if (unlikely (src->p_offset > 0xffffffffull)
64b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  || unlikely (src->p_vaddr > 0xffffffffull)
65b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  || unlikely (src->p_paddr > 0xffffffffull)
66b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  || unlikely (src->p_filesz > 0xffffffffull)
67b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  || unlikely (src->p_memsz > 0xffffffffull)
68b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  || unlikely (src->p_align > 0xffffffffull))
69b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	{
70b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  __libelf_seterrno (ELF_E_INVALID_DATA);
71b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  goto out;
72b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	}
73b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
74b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      if (phdr == NULL)
75b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	{
76b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  phdr = __elf32_getphdr_wrlock (elf);
77b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  if (phdr == NULL)
78b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    /* The error number is already set.  */
79b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    goto out;
80b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	}
816258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
826258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      /* Test whether the index is ok.  */
83b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      size_t phnum;
84b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      if (ndx >= elf->state.elf32.ehdr->e_phnum
85b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  && (elf->state.elf32.ehdr->e_phnum != PN_XNUM
86b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	      || __elf_getphdrnum_rdlock (elf, &phnum) != 0
87b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	      || (size_t) ndx >= phnum))
88b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	{
89b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  __libelf_seterrno (ELF_E_INVALID_INDEX);
90b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  goto out;
91b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	}
92b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
93b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      /* Now correct the pointer to point to the correct element.  */
94b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      phdr += ndx;
95b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
96b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh#define COPY(name) \
97b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      phdr->name = src->name
98b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      COPY (p_type);
99b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      COPY (p_offset);
100b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      COPY (p_vaddr);
101b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      COPY (p_paddr);
102b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      COPY (p_filesz);
103b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      COPY (p_memsz);
10442f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath      COPY (p_flags);
105b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      COPY (p_align);
106b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    }
10742f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath  else
108b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    {
109b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      Elf64_Phdr *phdr = elf->state.elf64.phdr;
110b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
111b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      if (phdr == NULL)
112b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	{
113b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  phdr = __elf64_getphdr_wrlock (elf);
114b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  if (phdr == NULL)
115b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    /* The error number is already set.  */
116b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    goto out;
117b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	}
118b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
119b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      /* Test whether the index is ok.  */
120b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      size_t phnum;
121b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      if (ndx >= elf->state.elf64.ehdr->e_phnum
122b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  && (elf->state.elf64.ehdr->e_phnum != PN_XNUM
123b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	      || __elf_getphdrnum_rdlock (elf, &phnum) != 0
12442f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath	      || (size_t) ndx >= phnum))
125b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	{
126b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  __libelf_seterrno (ELF_E_INVALID_INDEX);
127b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  goto out;
128b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	}
129b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
130b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      /* Just copy the data.  */
131b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      memcpy (phdr + ndx, src, sizeof (Elf64_Phdr));
132159ac52b061c60947a943c102298cd692223274fMark Wielaard    }
133159ac52b061c60947a943c102298cd692223274fMark Wielaard
134159ac52b061c60947a943c102298cd692223274fMark Wielaard  /* Mark the program header as modified.  */
135b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  elf->state.elf.phdr_flags |= ELF_F_DIRTY;
136b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
137159ac52b061c60947a943c102298cd692223274fMark Wielaard  result = 1;
138b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
139159ac52b061c60947a943c102298cd692223274fMark Wielaard out:
140159ac52b061c60947a943c102298cd692223274fMark Wielaard  rwlock_unlock (elf->lock);
141159ac52b061c60947a943c102298cd692223274fMark Wielaard
142b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  return result;
143b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh}
144b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh