|
1 /* |
|
2 x.movscn.c - implementation of the elfx_movscn(3) function. |
|
3 Copyright (C) 1995 - 2001, 2003 Michael Riepe |
|
4 |
|
5 This library is free software; you can redistribute it and/or |
|
6 modify it under the terms of the GNU Library General Public |
|
7 License as published by the Free Software Foundation; either |
|
8 version 2 of the License, or (at your option) any later version. |
|
9 |
|
10 This library is distributed in the hope that it will be useful, |
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 Library General Public License for more details. |
|
14 |
|
15 You should have received a copy of the GNU Library General Public |
|
16 License along with this library; if not, write to the Free Software |
|
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
18 */ |
|
19 |
|
20 #include <private.h> |
|
21 |
|
22 #ifndef lint |
|
23 static const char rcsid[] = "@(#) $Id: x.movscn.c,v 1.13 2005/05/21 15:39:27 michael Exp $"; |
|
24 #endif /* lint */ |
|
25 |
|
26 size_t |
|
27 elfx_movscn(Elf *elf, Elf_Scn *scn, Elf_Scn *after) { |
|
28 Elf_Scn *prev; |
|
29 Elf_Scn *tmp; |
|
30 int off; |
|
31 |
|
32 if (!elf || !scn || !after) { |
|
33 return SHN_UNDEF; |
|
34 } |
|
35 elf_assert(elf->e_magic == ELF_MAGIC); |
|
36 if (elf->e_kind != ELF_K_ELF) { |
|
37 seterr(ERROR_NOTELF); |
|
38 return SHN_UNDEF; |
|
39 } |
|
40 elf_assert(scn->s_magic == SCN_MAGIC); |
|
41 elf_assert(after->s_magic == SCN_MAGIC); |
|
42 if (scn->s_elf != elf || after->s_elf != elf) { |
|
43 seterr(ERROR_ELFSCNMISMATCH); |
|
44 return SHN_UNDEF; |
|
45 } |
|
46 elf_assert(elf->e_scn_1); |
|
47 if (scn == elf->e_scn_1) { |
|
48 seterr(ERROR_NULLSCN); |
|
49 return SHN_UNDEF; |
|
50 } |
|
51 if (scn == after || scn == after->s_link) { |
|
52 /* nothing to do */ |
|
53 return scn->s_index; |
|
54 } |
|
55 |
|
56 /* |
|
57 * Find previous section. |
|
58 */ |
|
59 prev = NULL; |
|
60 for (tmp = elf->e_scn_1; tmp->s_link; tmp = tmp->s_link) { |
|
61 if (tmp->s_link == scn) { |
|
62 prev = tmp; |
|
63 break; |
|
64 } |
|
65 } |
|
66 elf_assert(prev != NULL); |
|
67 |
|
68 /* |
|
69 * Update section indices |
|
70 */ |
|
71 off = 0; |
|
72 for (tmp = elf->e_scn_1; tmp; tmp = tmp->s_link) { |
|
73 if (off) { |
|
74 tmp->s_index += off; |
|
75 } |
|
76 if (tmp == after) { |
|
77 off++; |
|
78 } |
|
79 else if (tmp == scn) { |
|
80 off--; |
|
81 } |
|
82 } |
|
83 elf_assert(off == 0); |
|
84 |
|
85 /* |
|
86 * Move section. |
|
87 */ |
|
88 prev->s_link = scn->s_link; |
|
89 scn->s_link = after->s_link; |
|
90 after->s_link = scn; |
|
91 scn->s_index = after->s_index + 1; |
|
92 if (elf->e_scn_n == scn) { |
|
93 elf->e_scn_n = prev; |
|
94 } |
|
95 else if (elf->e_scn_n == after) { |
|
96 elf->e_scn_n = scn; |
|
97 } |
|
98 |
|
99 #if ENABLE_DEBUG |
|
100 /* |
|
101 * Check section indices |
|
102 */ |
|
103 tmp = elf->e_scn_1; |
|
104 elf_assert(tmp->s_index == 0); |
|
105 while (tmp->s_link) { |
|
106 elf_assert(tmp->s_link->s_index == tmp->s_index + 1); |
|
107 tmp = tmp->s_link; |
|
108 } |
|
109 #endif /* ENABLE_DEBUG */ |
|
110 |
|
111 return scn->s_index; |
|
112 } |