Passdown -S to linker.
[deliverable/binutils-gdb.git] / bfd / sunos.c
CommitLineData
0ee75d02
ILT
1/* BFD backend for SunOS binaries.
2 Copyright (C) 1990-1991 Free Software Foundation, Inc.
3 Written by Cygnus Support.
4a81b561 4
0ee75d02 5This file is part of BFD, the Binary File Descriptor library.
4a81b561 6
0ee75d02 7This program is free software; you can redistribute it and/or modify
4a81b561 8it under the terms of the GNU General Public License as published by
0ee75d02
ILT
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
4a81b561 11
0ee75d02 12This program is distributed in the hope that it will be useful,
4a81b561
DHW
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
0ee75d02
ILT
18along with this program; if not, write to the Free Software
19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
4a81b561 20
0ee75d02
ILT
21#define ARCH 32
22#define TARGETNAME "a.out-sunos-big"
23#define MY(OP) CAT(sunos_big_,OP)
4a81b561 24
4a81b561 25#include "bfd.h"
78aa64b1 26
0ee75d02 27/* Static routines defined in this file. */
4a81b561 28
0ee75d02 29struct external_nlist;
4a81b561 30
0ee75d02
ILT
31static boolean sunos_read_dynamic_info PARAMS ((bfd *));
32static bfd_size_type MY(read_dynamic_symbols)
33 PARAMS ((bfd *, struct external_nlist **, char **, bfd_size_type *));
34static bfd_size_type MY(read_dynamic_relocs) PARAMS ((bfd *, PTR *));
4a81b561 35
0ee75d02
ILT
36#define MY_read_dynamic_symbols MY(read_dynamic_symbols)
37#define MY_read_dynamic_relocs MY(read_dynamic_relocs)
4a81b561 38
0ee75d02
ILT
39/* Include the usual a.out support. */
40#include "aoutf1.h"
4a81b561 41
0ee75d02
ILT
42/* SunOS shared library support. We store a pointer to this structure
43 in obj_aout_dynamic_info (abfd). */
4a81b561 44
0ee75d02 45struct sunos_dynamic_info
78aa64b1 46{
0ee75d02
ILT
47 /* Whether we found any dynamic information. */
48 boolean valid;
49 /* Dynamic information. */
50 struct internal_sun4_dynamic_link dyninfo;
51 /* Number of dynamic symbols. */
52 bfd_size_type dynsym_count;
53 /* Read in nlists for dynamic symbols. */
54 struct external_nlist *dynsym;
55 /* Read in dynamic string table. */
56 char *dynstr;
57 /* Number of dynamic relocs. */
58 bfd_size_type dynrel_count;
59 /* Read in dynamic relocs. This may be reloc_std_external or
60 reloc_ext_external. */
61 PTR dynrel;
62};
4a81b561 63
0ee75d02
ILT
64/* Read in the basic dynamic information. This locates the __DYNAMIC
65 structure and uses it to find the dynamic_link structure. It
66 creates and saves a sunos_dynamic_info structure. If it can't find
67 __DYNAMIC, it sets the valid field of the sunos_dynamic_info
68 structure to false to avoid doing this work again. */
4a81b561 69
0ee75d02
ILT
70static boolean
71sunos_read_dynamic_info (abfd)
4a81b561
DHW
72 bfd *abfd;
73{
0ee75d02
ILT
74 struct sunos_dynamic_info *info;
75 struct external_nlist dynsym;
76 char buf[sizeof "__DYNAMIC"];
77 asection *dynsec;
78 file_ptr dynoff;
79 struct external_sun4_dynamic dyninfo;
80 unsigned long dynver;
81 struct external_sun4_dynamic_link linkinfo;
82
83 if (obj_aout_dynamic_info (abfd) != (PTR) NULL)
84 return true;
85
86 info = ((struct sunos_dynamic_info *)
87 bfd_zalloc (abfd, sizeof (struct sunos_dynamic_info)));
9783e04a
DM
88 if (!info)
89 {
d7fb4531 90 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
91 return false;
92 }
0ee75d02
ILT
93 info->valid = false;
94 info->dynsym = NULL;
95 info->dynstr = NULL;
96 info->dynrel = NULL;
97 obj_aout_dynamic_info (abfd) = (PTR) info;
98
3e0b5554
PS
99 /* This code used to look for the __DYNAMIC symbol to locate the dynamic
100 linking information.
101 However this inhibits recovering the dynamic symbols from a
102 stripped object file, so blindly assume that the dynamic linking
103 information is located at the start of the data section.
104 We could verify this assumption later by looking through the dynamic
105 symbols for the __DYNAMIC symbol. */
106 if ((abfd->flags & DYNAMIC) == 0)
0ee75d02 107 return true;
3e0b5554
PS
108 if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo,
109 (file_ptr) 0, sizeof dyninfo))
0ee75d02
ILT
110 return true;
111
112 dynver = GET_WORD (abfd, dyninfo.ld_version);
113 if (dynver != 2 && dynver != 3)
114 return true;
115
116 dynoff = GET_WORD (abfd, dyninfo.ld);
117
118 /* dynoff is a virtual address. It is probably always in the .data
119 section, but this code should work even if it moves. */
120 if (dynoff < bfd_get_section_vma (abfd, obj_datasec (abfd)))
121 dynsec = obj_textsec (abfd);
122 else
123 dynsec = obj_datasec (abfd);
124 dynoff -= bfd_get_section_vma (abfd, dynsec);
125 if (dynoff < 0 || dynoff > bfd_section_size (abfd, dynsec))
126 return true;
127
128 /* This executable appears to be dynamically linked in a way that we
129 can understand. */
130 if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo, dynoff,
131 (bfd_size_type) sizeof linkinfo))
132 return true;
133
134 /* Swap in the dynamic link information. */
135 info->dyninfo.ld_loaded = GET_WORD (abfd, linkinfo.ld_loaded);
136 info->dyninfo.ld_need = GET_WORD (abfd, linkinfo.ld_need);
137 info->dyninfo.ld_rules = GET_WORD (abfd, linkinfo.ld_rules);
138 info->dyninfo.ld_got = GET_WORD (abfd, linkinfo.ld_got);
139 info->dyninfo.ld_plt = GET_WORD (abfd, linkinfo.ld_plt);
140 info->dyninfo.ld_rel = GET_WORD (abfd, linkinfo.ld_rel);
141 info->dyninfo.ld_hash = GET_WORD (abfd, linkinfo.ld_hash);
142 info->dyninfo.ld_stab = GET_WORD (abfd, linkinfo.ld_stab);
143 info->dyninfo.ld_stab_hash = GET_WORD (abfd, linkinfo.ld_stab_hash);
144 info->dyninfo.ld_buckets = GET_WORD (abfd, linkinfo.ld_buckets);
145 info->dyninfo.ld_symbols = GET_WORD (abfd, linkinfo.ld_symbols);
146 info->dyninfo.ld_symb_size = GET_WORD (abfd, linkinfo.ld_symb_size);
147 info->dyninfo.ld_text = GET_WORD (abfd, linkinfo.ld_text);
148 info->dyninfo.ld_plt_sz = GET_WORD (abfd, linkinfo.ld_plt_sz);
149
150 /* The only way to get the size of the symbol information appears to
151 be to determine the distance between it and the string table. */
152 info->dynsym_count = ((info->dyninfo.ld_symbols - info->dyninfo.ld_stab)
153 / EXTERNAL_NLIST_SIZE);
154 BFD_ASSERT (info->dynsym_count * EXTERNAL_NLIST_SIZE
155 == info->dyninfo.ld_symbols - info->dyninfo.ld_stab);
156
157 /* Similarly, the relocs end at the hash table. */
158 info->dynrel_count = ((info->dyninfo.ld_hash - info->dyninfo.ld_rel)
159 / obj_reloc_entry_size (abfd));
160 BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd)
161 == info->dyninfo.ld_hash - info->dyninfo.ld_rel);
162
163 info->valid = true;
4a81b561
DHW
164
165 return true;
166}
167
0ee75d02 168/* Read in the dynamic symbols. */
4a81b561 169
0ee75d02
ILT
170static bfd_size_type
171MY(read_dynamic_symbols) (abfd, syms, strs, strsize)
4a81b561 172 bfd *abfd;
0ee75d02
ILT
173 struct external_nlist **syms;
174 char **strs;
175 bfd_size_type *strsize;
4a81b561 176{
0ee75d02 177 struct sunos_dynamic_info *info;
4a81b561 178
0ee75d02
ILT
179 if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
180 {
181 if (! sunos_read_dynamic_info (abfd))
182 return (bfd_size_type) -1;
4a81b561 183 }
c93595dd 184
0ee75d02
ILT
185 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
186 if (! info->valid || info->dynsym_count == 0)
187 return 0;
10be52bf 188
0ee75d02
ILT
189 if (info->dynsym == (struct external_nlist *) NULL)
190 {
191 info->dynsym = ((struct external_nlist *)
192 bfd_alloc (abfd,
193 (info->dynsym_count
194 * EXTERNAL_NLIST_SIZE)));
195 info->dynstr = (char *) bfd_alloc (abfd, info->dyninfo.ld_symb_size);
9783e04a
DM
196 if (!info->dynsym || !info->dynstr)
197 {
d7fb4531 198 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
199 return 0;
200 }
0ee75d02
ILT
201 if (bfd_seek (abfd, info->dyninfo.ld_stab, SEEK_SET) != 0
202 || (bfd_read ((PTR) info->dynsym, info->dynsym_count,
203 EXTERNAL_NLIST_SIZE, abfd)
204 != info->dynsym_count * EXTERNAL_NLIST_SIZE)
205 || bfd_seek (abfd, info->dyninfo.ld_symbols, SEEK_SET) != 0
206 || (bfd_read ((PTR) info->dynstr, 1, info->dyninfo.ld_symb_size,
207 abfd)
208 != info->dyninfo.ld_symb_size))
209 return (bfd_size_type) -1;
210 }
1a602d6e 211
0ee75d02
ILT
212 *syms = info->dynsym;
213 *strs = info->dynstr;
214 *strsize = info->dyninfo.ld_symb_size;
4a81b561 215
0ee75d02
ILT
216#ifdef CHECK_DYNAMIC_HASH
217 /* Check my understanding of the dynamic hash table by making sure
218 that each symbol can be located in the hash table. */
219 {
220 bfd_size_type table_size;
221 bfd_byte *table;
222 bfd_size_type i;
223
224 if (info->dyninfo.ld_buckets > info->dynsym_count)
225 abort ();
226 table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash;
d7fb4531
JK
227 table = (bfd_byte *) malloc (table_size);
228 if (table == NULL)
229 abort ();
0ee75d02
ILT
230 if (bfd_seek (abfd, info->dyninfo.ld_hash, SEEK_SET) != 0
231 || bfd_read ((PTR) table, 1, table_size, abfd) != table_size)
232 abort ();
233 for (i = 0; i < info->dynsym_count; i++)
9846338e 234 {
0ee75d02
ILT
235 unsigned char *name;
236 unsigned long hash;
237
238 name = ((unsigned char *) info->dynstr
239 + GET_WORD (abfd, info->dynsym[i].e_strx));
240 hash = 0;
241 while (*name != '\0')
242 hash = (hash << 1) + *name++;
243 hash &= 0x7fffffff;
244 hash %= info->dyninfo.ld_buckets;
245 while (GET_WORD (abfd, table + 8 * hash) != i)
246 {
247 hash = GET_WORD (abfd, table + 8 * hash + 4);
248 if (hash == 0 || hash >= table_size / 8)
249 abort ();
250 }
9846338e 251 }
d7fb4531 252 free (table);
4a81b561 253 }
0ee75d02 254#endif /* CHECK_DYNAMIC_HASH */
4a81b561 255
0ee75d02 256 return info->dynsym_count;
4a81b561 257}
4a81b561 258
0ee75d02 259/* Read in the dynamic relocs for a section. */
4a81b561 260
0ee75d02
ILT
261static bfd_size_type
262MY(read_dynamic_relocs) (abfd, relocs)
4a81b561 263 bfd *abfd;
0ee75d02 264 PTR *relocs;
4a81b561 265{
0ee75d02 266 struct sunos_dynamic_info *info;
4a81b561 267
0ee75d02
ILT
268 if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
269 {
270 if (! sunos_read_dynamic_info (abfd))
271 return (bfd_size_type) -1;
272 }
4a81b561 273
0ee75d02
ILT
274 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
275 if (! info->valid || info->dynrel_count == 0)
4a81b561 276 return 0;
4a81b561 277
9783e04a 278 if (info->dynrel == NULL)
0ee75d02
ILT
279 {
280 info->dynrel = (PTR) bfd_alloc (abfd,
281 (info->dynrel_count
282 * obj_reloc_entry_size (abfd)));
9783e04a
DM
283 if (!info->dynrel)
284 {
d7fb4531 285 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
286 return (bfd_size_type) -1;
287 }
0ee75d02
ILT
288 if (bfd_seek (abfd, info->dyninfo.ld_rel, SEEK_SET) != 0
289 || (bfd_read ((PTR) info->dynrel, info->dynrel_count,
290 obj_reloc_entry_size (abfd), abfd)
291 != info->dynrel_count * obj_reloc_entry_size (abfd)))
292 return (bfd_size_type) -1;
293 }
4a81b561 294
0ee75d02 295 *relocs = info->dynrel;
4a81b561 296
0ee75d02 297 return info->dynrel_count;
4a81b561 298}
This page took 0.132646 seconds and 4 git commands to generate.