XEmacs 21.2.10
[chise/xemacs-chise.git.1] / dynodump / sparc / _relocate.c
1 /*
2  *      Copyright (c) 1995 by Sun Microsystems, Inc.
3  *      All rights reserved.
4  *
5  * This source code is a product of Sun Microsystems, Inc. and is provided
6  * for unrestricted use provided that this legend is included on all tape
7  * media and as a part of the software program in whole or part.  Users
8  * may copy or modify this source code without charge, but are not authorized
9  * to license or distribute it to anyone else except as part of a product or
10  * program developed by the user.
11  *
12  * THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC.
13  * SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY
14  * OF SUCH SOURCE CODE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT
15  * EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  SUN MICROSYSTEMS, INC. DISCLAIMS
16  * ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN
18  * NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT,
19  * INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
20  * FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY.
21  *
22  * This source code is provided with no support and without any obligation on
23  * the part of Sun Microsystems, Inc. to assist in its use, correction,
24  * modification or enhancement.
25  *
26  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
27  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS
28  * SOURCE CODE OR ANY PART THEREOF.
29  *
30  * Sun Microsystems, Inc.
31  * 2550 Garcia Avenue
32  * Mountain View, California 94043
33  */
34
35 /*
36  * Update the value of the `_edata' and `_end' symbols.
37  */
38 #pragma ident   "@(#) $Id: _relocate.c,v 1.4 1995/06/26 20:13:26 georgn Exp $ - SMI"
39
40 #include        <libelf.h>
41 #include        <string.h>
42 #include        "machdep.h"
43 #include        "_dynodump.h"
44
45
46 #define GETbyte(P)      ((long)((unsigned long)(P)[0]))
47 #define GEThalf(P)      ((long)(((unsigned long)(P)[0] << 8) | \
48                             ((unsigned long)(P)[1])))
49 #define GETword(P)      ((long)(((unsigned long)(P)[0] << 24) | \
50                             ((unsigned long)(P)[1] << 16) | \
51                             ((unsigned long)(P)[2] << 8) | \
52                             (unsigned long)(P)[3]))
53 #define GETdisp30(P)    (GETword(P) & 0x3fffffff)
54 #define GETdisp22(P)    (GETword(P) & 0x3fffff)
55 #define GETdisp16(P)    (((GETword(P) & 0x300000) >> 6) | \
56                             (GETword(P) & 0x3fff))
57 #define GETdisp19(P)    (GETword(P) & 0x7ffff)
58 #define GETimm22(P)     (GETword(P) & 0x3fffff)
59 #define GETimm5(P)      (GEThalf((P)+2) & 0x1f)
60 #define GETimm6(P)      (GEThalf((P)+2) & 0x2f)
61 #define GETimm7(P)      (GEThalf((P)+2) & 0x3f)
62 #define GETsimm13(P)    (GEThalf((P)+2) & 0x1fff)
63 #define GETsimm10(P)    (GEThalf((P)+2) & 0x3ff)
64 #define GETsimm11(P)    (GEThalf((P)+2) & 0x7ff)
65 #define GETplt22(P)     (GETword((P)+8) & 0x3fffff)
66
67 #define PUTbyte(V, P)   (P)[0] = (V)
68 #define PUThalf(V, P)   (P)[0] = ((V) >> 8); \
69                         (P)[1] = ((V))
70 #define PUTword(V, P)   (P)[0] = (unsigned char)((V) >> 24); \
71                         (P)[1] = (unsigned char)((V) >> 16); \
72                         (P)[2] = (unsigned char)((V) >> 8); \
73                         (P)[3] = (unsigned char)(V)
74 #define PUTdisp30(V, P) { \
75                         unsigned long int temp; \
76                         temp = GETword(P) & ~0x3fffffff; \
77                         temp |= ((V) & 0x3fffffff); \
78                         PUTword(temp, P); \
79                         }
80 #define PUTdisp22(V, P) { \
81                         unsigned long int temp; \
82                         temp = GETword(P) & ~0x3fffff; \
83                         temp |= ((V) & 0x3fffff); \
84                         PUTword(temp, P); \
85                         }
86 #define PUTimm22(V, P)  { \
87                         unsigned long int temp; \
88                         temp = GETword(P) & ~0x3fffff; \
89                         temp |= ((V) & 0x3fffff); \
90                         PUTword(temp, P); \
91                         }
92 #define PUTimm5(V, P)   { \
93                         unsigned long int temp; \
94                         temp = GEThalf(P+2) & ~0x1f; \
95                         temp |= ((V) & 0x1f); \
96                         PUThalf(temp, (P+2)); \
97                         }
98 #define PUTimm6(V, P)   { \
99                         unsigned long int temp; \
100                         temp = GEThalf(P+2) & ~0x2f; \
101                         temp |= ((V) & 0x2f); \
102                         PUThalf(temp, (P+2)); \
103                         }
104 #define PUTimm7(V, P)   { \
105                         unsigned long int temp; \
106                         temp = GEThalf(P+2) & ~0x3f; \
107                         temp |= ((V) & 0x3f); \
108                         PUThalf(temp, (P+2)); \
109                         }
110 #define PUTsimm13(V, P) { \
111                         unsigned long int temp; \
112                         temp = GEThalf(P+2) & ~0x1fff; \
113                         temp |= ((V) & 0x1fff); \
114                         PUThalf(temp, (P+2)); \
115                         }
116 #define PUTplt22(V, P)  { \
117                         unsigned long int temp; \
118                         temp = GETword((P)+8) & ~0x3fffff; \
119                         temp |= ((V) & 0x3fffff); \
120                         PUTword(temp, ((P)+8)); \
121                         }
122 #define PUTsimm10(V, P) { \
123                         unsigned long int temp; \
124                         temp = GEThalf(P+2) & ~0x3ff; \
125                         temp |= ((V) & 0x3ff); \
126                         PUThalf(temp, (P+2)); \
127                         }
128 #define PUTsimm11(V, P) { \
129                         unsigned long int temp; \
130                         temp = GEThalf(P+2) & ~0x7ff; \
131                         temp |= ((V) & 0x7ff); \
132                         PUThalf(temp, (P+2)); \
133                         }
134 #define PUTdisp16(V, P) { \
135                         unsigned long int temp; \
136                         temp = GETword(P) & ~0x303fff; \
137                         temp |= ((V) & 0xc000) << 6; \
138                         temp |= ((V) & 0x3fff); \
139                         PUTword(temp, P); \
140                         }
141 #define PUTdisp19(V, P) { \
142                         unsigned long int temp; \
143                         temp = GETword(P) & ~0x7ffff; \
144                         temp |= ((V) & 0x7ffff); \
145                         PUTword(temp, P); \
146                         }
147
148 static void
149 move_reloc(unsigned char * iaddr, unsigned char * oaddr, unsigned char type)
150 {
151     switch (type) {
152     case R_SPARC_8:
153     case R_SPARC_DISP8:
154         PUTbyte(GETbyte(iaddr), oaddr);
155         break;
156
157     case R_SPARC_16:
158     case R_SPARC_DISP16:
159         PUThalf(GEThalf(iaddr), oaddr);
160         break;
161
162     case R_SPARC_32:
163     case R_SPARC_DISP32:
164     case R_SPARC_GLOB_DAT:
165     case R_SPARC_RELATIVE:
166     case R_SPARC_UA32:
167         PUTword(GETword(iaddr), oaddr);
168         break;
169
170     case R_SPARC_WDISP30:
171     case R_SPARC_WPLT30:
172         PUTdisp30(GETdisp30(iaddr), oaddr);
173         break;
174
175     case R_SPARC_WDISP22:
176     case R_SPARC_PC22:
177         PUTdisp22(GETdisp22(iaddr), oaddr);
178         break;
179
180     case R_SPARC_HI22:
181     case R_SPARC_GOT22:
182     case R_SPARC_22:
183         PUTimm22(GETimm22(iaddr), oaddr);
184         break;
185
186     case R_SPARC_13:
187     case R_SPARC_GOT13:
188         PUTsimm13(GETsimm13(iaddr), oaddr);
189         break;
190
191     case R_SPARC_LO10:
192     case R_SPARC_GOT10:
193     case R_SPARC_PC10:
194 #ifdef R_SPARC_10
195     case R_SPARC_10:
196 #endif
197         PUTsimm10(GETsimm10(iaddr), oaddr);
198         break;
199
200 #ifdef R_SPARC_11
201     case R_SPARC_11:
202         PUTsimm11(GETsimm11(iaddr), oaddr);
203         break;
204 #endif
205
206 #ifdef R_SPARC_WDISP16
207     case R_SPARC_WDISP16:
208         PUTdisp16(GETdisp16(iaddr), oaddr);
209         break;
210 #endif
211
212 #ifdef R_SPARC_WDISP19
213     case R_SPARC_WDISP19:
214         PUTdisp19(GETdisp19(iaddr), oaddr);
215         break;
216 #endif
217
218 #ifdef R_SPARC_5
219     case R_SPARC_5:
220         PUTimm5(GETimm5(iaddr), oaddr);
221         break;
222 #endif
223
224 #ifdef R_SPARC_6
225     case R_SPARC_6:
226         PUTimm6(GETimm6(iaddr), oaddr);
227         break;
228 #endif
229
230 #ifdef R_SPARC_7
231     case R_SPARC_7:
232         PUTimm7(GETimm7(iaddr), oaddr);
233         break;
234 #endif
235
236     default:
237         break;
238     }
239 }
240
241 void
242 update_reloc(Cache *ocache, Cache *_ocache,
243              Cache *icache, Cache *_icache,
244              Half shnum)
245 {
246     Shdr *shdr;
247     Rel *rels;
248     int reln, cnt;
249     Cache *orcache, *ircache;
250
251     /*
252      * Set up to read the output relocation table.
253      */
254     shdr = _ocache->c_shdr;
255     rels = (Rel *)_ocache->c_data->d_buf;
256     reln = shdr->sh_size / shdr->sh_entsize;
257
258     /*
259      * Determine the section that is being relocated.
260      */
261     orcache = &ocache[shdr->sh_info];
262     shdr = _icache->c_shdr;
263     ircache = &icache[shdr->sh_info];
264
265     /*
266      * Loop through the relocation table.
267      */
268     for (cnt = 0; cnt < reln; cnt++, rels++) {
269         unsigned char *iaddr, *oaddr;
270         Addr off;
271         unsigned char type = ELF_R_TYPE(rels->r_info);
272
273         /*
274          * Ignore some relocations as these can safely be carried out
275          * twice (they simply override any existing data).  In fact,
276          * some relocations like __iob's copy relocation must be carried
277          * out each time the process restarts otherwise stdio blows up.
278          */
279         if ((type == R_SPARC_COPY) || (type == R_SPARC_JMP_SLOT) ||
280             (type == R_SPARC_NONE))
281             continue;
282
283         /*
284          * If we are required to restore the relocation location
285          * to its value prior to relocation, then read the
286          * locations original contents from the input image and
287          * copy it to the output image.
288          */
289         off = rels->r_offset - ircache->c_shdr->sh_addr;
290         iaddr = (unsigned char *)ircache->c_data->d_buf + off;
291         oaddr = (unsigned char *)orcache->c_data->d_buf + off;
292         move_reloc(iaddr, oaddr, type);
293     }
294 }