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