source: trunk/src/binutils/bfd/nlm32-ppc.c@ 2302

Last change on this file since 2302 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 30.4 KB
Line 
1/* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
2 Copyright 1994, 1995, 2000, 2001, 2002 Free Software Foundation, Inc.
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "bfd.h"
21#include "sysdep.h"
22#include "libbfd.h"
23
24/* The format of a PowerPC NLM changed. Define OLDFORMAT to get the
25 old format. */
26
27#define ARCH_SIZE 32
28
29#include "nlm/ppc-ext.h"
30#define Nlm_External_Fixed_Header Nlm32_powerpc_External_Fixed_Header
31
32#include "libnlm.h"
33
34#ifdef OLDFORMAT
35static bfd_boolean nlm_powerpc_backend_object_p
36 PARAMS ((bfd *));
37static bfd_boolean nlm_powerpc_write_prefix
38 PARAMS ((bfd *));
39#endif
40
41static bfd_boolean nlm_powerpc_read_reloc
42 PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
43static bfd_boolean nlm_powerpc_mangle_relocs
44 PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
45static bfd_boolean nlm_powerpc_read_import
46 PARAMS ((bfd *, nlmNAME(symbol_type) *));
47
48#ifdef OLDFORMAT
49static bfd_boolean nlm_powerpc_write_reloc
50 PARAMS ((bfd *, asection *, arelent *, int));
51#endif
52
53static bfd_boolean nlm_powerpc_write_import
54 PARAMS ((bfd *, asection *, arelent *));
55static bfd_boolean nlm_powerpc_write_external
56 PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
57
58#ifndef OLDFORMAT
59static bfd_boolean nlm_powerpc_set_public_section
60 PARAMS ((bfd *, nlmNAME(symbol_type) *));
61static bfd_vma nlm_powerpc_get_public_offset
62 PARAMS ((bfd *, asymbol *));
63#endif
64
65
66#ifdef OLDFORMAT
67
68/* The prefix header is only used in the old format. */
69
70/* PowerPC NLM's have a prefix header before the standard NLM. This
71 function reads it in, verifies the version, and seeks the bfd to
72 the location before the regular NLM header. */
73
74static bfd_boolean
75nlm_powerpc_backend_object_p (abfd)
76 bfd *abfd;
77{
78 struct nlm32_powerpc_external_prefix_header s;
79
80 if (bfd_bread ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s)
81 return FALSE;
82
83 if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
84 || H_GET_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION)
85 return FALSE;
86
87 return TRUE;
88}
89
90/* Write out the prefix. */
91
92static bfd_boolean
93nlm_powerpc_write_prefix (abfd)
94 bfd *abfd;
95{
96 struct nlm32_powerpc_external_prefix_header s;
97
98 memset (&s, 0, sizeof s);
99 memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature);
100 H_PUT_32 (abfd, NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
101 H_PUT_32 (abfd, 0, s.origins);
102
103 /* FIXME: What should we do about the date? */
104
105 if (bfd_bwrite ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s)
106 return FALSE;
107
108 return TRUE;
109}
110
111#endif /* OLDFORMAT */
112
113
114#ifndef OLDFORMAT
115
116/* There is only one type of reloc in a PowerPC NLM. */
117
118static reloc_howto_type nlm_powerpc_howto =
119 HOWTO (0, /* type */
120 0, /* rightshift */
121 2, /* size (0 = byte, 1 = short, 2 = long) */
122 32, /* bitsize */
123 FALSE, /* pc_relative */
124 0, /* bitpos */
125 complain_overflow_bitfield, /* complain_on_overflow */
126 0, /* special_function */
127 "32", /* name */
128 TRUE, /* partial_inplace */
129 0xffffffff, /* src_mask */
130 0xffffffff, /* dst_mask */
131 FALSE); /* pcrel_offset */
132
133/* Read a PowerPC NLM reloc. */
134
135static bfd_boolean
136nlm_powerpc_read_reloc (abfd, sym, secp, rel)
137 bfd *abfd;
138 nlmNAME(symbol_type) *sym;
139 asection **secp;
140 arelent *rel;
141{
142 bfd_byte temp[4];
143 bfd_vma val;
144 const char *name;
145
146 if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
147 return FALSE;
148
149 val = bfd_get_32 (abfd, temp);
150
151 /* The value is a word offset into either the code or data segment.
152 This is the location which needs to be adjusted.
153
154 The high bit is 0 if the value is an offset into the data
155 segment, or 1 if the value is an offset into the text segment.
156
157 If this is a relocation fixup rather than an imported symbol (the
158 sym argument is NULL), then the second most significant bit is 0
159 if the address of the data segment should be added to the
160 location addressed by the value, or 1 if the address of the text
161 segment should be added.
162
163 If this is an imported symbol, the second most significant bit is
164 not used and must be 0. */
165
166 if ((val & NLM_HIBIT) == 0)
167 name = NLM_INITIALIZED_DATA_NAME;
168 else
169 {
170 name = NLM_CODE_NAME;
171 val &=~ NLM_HIBIT;
172 }
173 *secp = bfd_get_section_by_name (abfd, name);
174
175 if (sym == NULL)
176 {
177 if ((val & (NLM_HIBIT >> 1)) == 0)
178 name = NLM_INITIALIZED_DATA_NAME;
179 else
180 {
181 name = NLM_CODE_NAME;
182 val &=~ (NLM_HIBIT >> 1);
183 }
184 rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
185 }
186
187 rel->howto = &nlm_powerpc_howto;
188
189 rel->address = val << 2;
190 rel->addend = 0;
191
192 return TRUE;
193}
194
195#else /* OLDFORMAT */
196
197/* This reloc handling is only applicable to the old format. */
198
199/* How to process the various reloc types. PowerPC NLMs use XCOFF
200 reloc types, and I have just copied the XCOFF reloc table here. */
201
202static reloc_howto_type nlm_powerpc_howto_table[] =
203{
204 /* Standard 32 bit relocation. */
205 HOWTO (0, /* type */
206 0, /* rightshift */
207 2, /* size (0 = byte, 1 = short, 2 = long) */
208 32, /* bitsize */
209 FALSE, /* pc_relative */
210 0, /* bitpos */
211 complain_overflow_bitfield, /* complain_on_overflow */
212 0, /* special_function */
213 "R_POS", /* name */
214 TRUE, /* partial_inplace */
215 0xffffffff, /* src_mask */
216 0xffffffff, /* dst_mask */
217 FALSE), /* pcrel_offset */
218
219 /* 32 bit relocation, but store negative value. */
220 HOWTO (1, /* type */
221 0, /* rightshift */
222 -2, /* size (0 = byte, 1 = short, 2 = long) */
223 32, /* bitsize */
224 FALSE, /* pc_relative */
225 0, /* bitpos */
226 complain_overflow_bitfield, /* complain_on_overflow */
227 0, /* special_function */
228 "R_NEG", /* name */
229 TRUE, /* partial_inplace */
230 0xffffffff, /* src_mask */
231 0xffffffff, /* dst_mask */
232 FALSE), /* pcrel_offset */
233
234 /* 32 bit PC relative relocation. */
235 HOWTO (2, /* type */
236 0, /* rightshift */
237 2, /* size (0 = byte, 1 = short, 2 = long) */
238 32, /* bitsize */
239 TRUE, /* pc_relative */
240 0, /* bitpos */
241 complain_overflow_signed, /* complain_on_overflow */
242 0, /* special_function */
243 "R_REL", /* name */
244 TRUE, /* partial_inplace */
245 0xffffffff, /* src_mask */
246 0xffffffff, /* dst_mask */
247 FALSE), /* pcrel_offset */
248
249 /* 16 bit TOC relative relocation. */
250 HOWTO (3, /* type */
251 0, /* rightshift */
252 1, /* size (0 = byte, 1 = short, 2 = long) */
253 16, /* bitsize */
254 FALSE, /* pc_relative */
255 0, /* bitpos */
256 complain_overflow_signed, /* complain_on_overflow */
257 0, /* special_function */
258 "R_TOC", /* name */
259 TRUE, /* partial_inplace */
260 0xffff, /* src_mask */
261 0xffff, /* dst_mask */
262 FALSE), /* pcrel_offset */
263
264 /* I don't really know what this is. */
265 HOWTO (4, /* type */
266 1, /* rightshift */
267 2, /* size (0 = byte, 1 = short, 2 = long) */
268 32, /* bitsize */
269 FALSE, /* pc_relative */
270 0, /* bitpos */
271 complain_overflow_bitfield, /* complain_on_overflow */