update.
[chise/xemacs-chise.git.1] / dynodump / ppc / _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 #pragma ident "@(#) $Id: _relocate.c,v 1.3 1995/06/26 20:16:39 georgn Exp $ - SMI"
36
37 /* LINTLIBRARY */
38
39 #include        <string.h>
40 #include        <sys/elf_ppc.h>
41 #include        "_dynodump.h"
42
43
44 /*
45  *      NOTE: These macros will work reliably only on 32-bit 2's
46  *      complement machines. The type of P in all cases should
47  *      by unsigned char *
48  */
49 #if defined(_BIG_ENDIAN)
50
51 #define GET4(P) ((long)(((unsigned long)(P)[0] << 24) | \
52                         ((unsigned long)(P)[1] << 16) | \
53                         ((unsigned long)(P)[2] << 8) | \
54                         (unsigned long)(P)[3]))
55 #define PUT4(V, P)      { \
56                                 (P)[0] = (unsigned char)((V) >> 24); \
57                                 (P)[1] = (unsigned char)((V) >> 16); \
58                                 (P)[2] = (unsigned char)((V) >> 8); \
59                                 (P)[3] = (unsigned char)(V); \
60                         }
61 #define GEThalf(P)      ((long) (((unsigned long) (P)[0] << 8) | \
62                                 ((unsigned long) (P)[1])))
63 #define GETword(P)      GET4(P)
64 #define PUThalf(V, P)   { \
65                                 (P)[0] = ((V) >> 8); \
66                                 (P)[1] = ((V)); \
67                         }
68 #define PUTword(V, P)   PUT4(V, P)
69
70 #elif defined(_LITTLE_ENDIAN)
71
72 #define GET4(P) ((long)(((unsigned long)(P)[0]) | \
73                         ((unsigned long)(P)[1] << 8) | \
74                         ((unsigned long)(P)[2] << 16) | \
75                         ((unsigned long)(P)[3]) << 24))
76 #define PUT4(V, P)      { \
77                                 (P)[0] = (unsigned char)(V); \
78                                 (P)[1] = (unsigned char)((V) >> 8); \
79                                 (P)[2] = (unsigned char)((V) >> 16); \
80                                 (P)[3] = (unsigned char)((V) >> 24); \
81                         }
82 #define GEThalf(P)      ((long) (((unsigned long) (P)[0]) | \
83                                 ((unsigned long) (P)[1] << 8)))
84 #define GETword(P)      GET4(P)
85 #define PUThalf(V, P)   { \
86                                 (P)[0] = (V); \
87                                 (P)[1] = ((V) >> 8); \
88                         }
89 #define PUTword(V, P)   PUT4(V, P)
90
91 #endif /* defined(_LITTLE_ENDIAN) */
92
93 /*
94  * NAME                 VALUE   FIELD           CALCULATION
95  *
96  * R_PPC_NONE                   0       none            none
97  * R_PPC_ADDR32                 1       word32          S + A
98  * R_PPC_ADDR24                 2       low24           (S + A) >> 2
99  * R_PPC_ADDR16                 3       half16          S + A
100  * R_PPC_ADDR16_LO              4       half16          #lo(S + A)
101  * R_PPC_ADDR16_HI              5       half16          #hi(S + A)
102  * R_PPC_ADDR16_HA              6       half16          #ha(S + A)
103  * R_PPC_ADDR14                 7       low14           (S + A) >> 2
104  * R_PPC_ADDR14_BRTAKEN         8       low14           (S + A) >> 2
105  * R_PPC_ADDR14_BRNTAKEN        9       low14           (S + A) >> 2
106  * R_PPC_REL24                  10      low24           (S + A - P) >> 2
107  * R_PPC_REL14                  11      low14           (S + A - P) >> 2
108  * R_PPC_REL14_BRTAKEN          12      low14           (S + A - P) >> 2
109  * R_PPC_REL14_BRNTAKEN         13      low14           (S + A - P) >> 2
110  * R_PPC_GOT16                  14      half16          G + A
111  * R_PPC_GOT16_LO               15      half16          #lo(G + A)
112  * R_PPC_GOT16_HI               16      half16          #hi(G + A)
113  * R_PPC_GOT16_HA               17      half16          #ha(G + A)
114  * R_PPC_PLT24                  18      low24           (L + A - P) >> 2
115  * R_PPC_COPY                   19      none            none
116  * R_PPC_GLOB_DAT               20      word32          S + A
117  * R_PPC_JMP_SLOT               21      none            see below
118  * R_PPC_RELATIVE               22      word32          B + A
119  * R_PPC_LOCAL24PC              23      low24           see below
120  * R_PPC_UADDR32                24      word32          S + A
121  * R_PPC_UADDR16                25      half16          S + A
122  *
123  *      This is Figure 4-3: Relocation Types from the Draft Copy of
124  * the ABI, Printed on 7/25/94.
125  *
126  *      The field column specifies how much of the data
127  * at the reference address is to be used. The data are assumed to be
128  * right-justified with the least significant bit at the right.
129  *      In the case of plt24 addresses, the reference address is
130  * assumed to be that of a 6-word PLT entry. The address is the right-
131  * most 24 bits of the third word.
132  */
133 static void
134 move_reloc(unsigned char *iaddr, unsigned char *oaddr, unsigned char type)
135 {
136     switch(type) {
137     case R_PPC_NONE:
138         break;
139
140     case R_PPC_ADDR32:
141     case R_PPC_UADDR32:
142         PUTword(GETword(iaddr), oaddr);
143         break;
144
145     case R_PPC_ADDR24:
146     case R_PPC_REL24:
147     case R_PPC_PLT24:
148     case R_PPC_LOCAL24PC:
149         /* XXX - big assumption here that the original contents were masked
150          * properly.  If this assumption proves correct, then these 24bit
151          * cases can be folded into the above 32bit cases.
152          */
153         PUTword(GETword(iaddr), oaddr);
154         break;
155
156     case R_PPC_ADDR16:
157     case R_PPC_UADDR16:
158     case R_PPC_GOT16:
159         PUThalf(GEThalf(iaddr), oaddr);
160         break;
161
162     case R_PPC_ADDR16_LO:
163     case R_PPC_GOT16_LO:
164         /* XXX - more assumptions which if proved correct, we can
165          * do some folding with above cases
166          */
167         PUThalf(GEThalf(iaddr), oaddr);
168         break;
169
170     case R_PPC_ADDR16_HI:
171     case R_PPC_GOT16_HI:
172         /* XXX - more assumptions which if proved correct, we can
173          * do some folding with above cases
174          */
175         PUThalf(GEThalf(iaddr), oaddr);
176         break;
177
178     case R_PPC_ADDR16_HA:
179     case R_PPC_GOT16_HA:
180         /* XXX - more assumptions which if proved correct, we can
181          * do some folding with above cases
182          */
183         PUThalf(GEThalf(iaddr), oaddr);
184         break;
185
186     case R_PPC_ADDR14:
187     case R_PPC_ADDR14_BRTAKEN:
188     case R_PPC_ADDR14_BRNTAKEN:
189     case R_PPC_REL14:
190     case R_PPC_REL14_BRTAKEN:
191     case R_PPC_REL14_BRNTAKEN:
192         /* XXX - big assumption here that the original contents were masked
193          * properly.  If this assumption proves correct, then these 14bit
194          * cases can be folded into the above 32bit cases.
195          */
196         PUTword(GETword(iaddr), oaddr);
197         break;
198
199     case R_PPC_COPY:
200         break;
201
202     case R_PPC_GLOB_DAT:
203     case R_PPC_RELATIVE:
204         PUTword(GETword(iaddr), oaddr);
205         break;
206
207     case R_PPC_JMP_SLOT:
208         break;
209
210     default:
211         break;
212     }
213 }
214
215 void
216 update_reloc(Cache *ocache, Cache *_ocache, Cache *icache, Cache *_icache, Half shnum)
217 {
218     Shdr *shdr;
219     Rel *rels;
220     int reln, cnt;
221     Cache *orcache, * ircache;
222
223     /*
224      * Set up to read the output relocation table.
225      */
226     shdr = _ocache->c_shdr;
227     rels = (Rel *)_ocache->c_data->d_buf;
228     reln = shdr->sh_size / shdr->sh_entsize;
229
230     /*
231      * Determine the section that is being relocated.
232      */
233     orcache = &ocache[shdr->sh_info];
234     shdr = _icache->c_shdr;
235     ircache = &icache[shdr->sh_info];
236
237     /*
238      * Loop through the relocation table.
239      */
240     for (cnt = 0; cnt < reln; cnt++, rels++) {
241         unsigned char   type = ELF_R_TYPE(rels->r_info);
242
243         /*
244          * Ignore some relocations as these can safely be carried out
245          * twice (they simply override any existing data).  In fact,
246          * some relocations like __iob's copy relocation must be carried
247          * out each time the process restarts otherwise stdio blows up.
248          */
249         if ((type == R_PPC_COPY) || (type == R_PPC_JMP_SLOT) ||
250             (type == R_PPC_NONE))
251             continue;
252
253         {
254             unsigned char *iaddr, *oaddr;
255             Addr off;
256
257             /*
258              * If we are required to restore the relocation location
259              * to its value prior to relocation, then read the
260              * locations original contents from the input image and
261              * copy it to the output image.
262              */
263             off = rels->r_offset - ircache->c_shdr->sh_addr;
264             iaddr = (unsigned char *)ircache->c_data->d_buf + off;
265             oaddr = (unsigned char *)orcache->c_data->d_buf + off;
266             move_reloc(iaddr, oaddr, type);
267         }
268     }
269 }