21e4b2fd3f72ff8599916f91a62956a5f9f028b3
[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 if (!info)
89 {
90 bfd_set_error (bfd_error_no_memory);
91 return false;
92 }
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
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)
107 return true;
108 if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo,
109 (file_ptr) 0, sizeof dyninfo))
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;
164
165 return true;
166 }
167
168 /* Read in the dynamic symbols. */
169
170 static bfd_size_type
171 MY(read_dynamic_symbols) (abfd, syms, strs, strsize)
172 bfd *abfd;
173 struct external_nlist **syms;
174 char **strs;
175 bfd_size_type *strsize;
176 {
177 struct sunos_dynamic_info *info;
178
179 if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
180 {
181 if (! sunos_read_dynamic_info (abfd))
182 return (bfd_size_type) -1;
183 }
184
185 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
186 if (! info->valid || info->dynsym_count == 0)
187 return 0;
188
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);
196 if (!info->dynsym || !info->dynstr)
197 {
198 bfd_set_error (bfd_error_no_memory);
199 return 0;
200 }
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 }
211
212 *syms = info->dynsym;
213 *strs = info->dynstr;
214 *strsize = info->dyninfo.ld_symb_size;
215
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;
227 table = (bfd_byte *) malloc (table_size);
228 if (table == NULL)
229 abort ();
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++)
234 {
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 }
251 }
252 free (table);
253 }
254 #endif /* CHECK_DYNAMIC_HASH */
255
256 return info->dynsym_count;
257 }
258
259 /* Read in the dynamic relocs for a section. */
260
261 static bfd_size_type
262 MY(read_dynamic_relocs) (abfd, relocs)
263 bfd *abfd;
264 PTR *relocs;
265 {
266 struct sunos_dynamic_info *info;
267
268 if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
269 {
270 if (! sunos_read_dynamic_info (abfd))
271 return (bfd_size_type) -1;
272 }
273
274 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
275 if (! info->valid || info->dynrel_count == 0)
276 return 0;
277
278 if (info->dynrel == NULL)
279 {
280 info->dynrel = (PTR) bfd_alloc (abfd,
281 (info->dynrel_count
282 * obj_reloc_entry_size (abfd)));
283 if (!info->dynrel)
284 {
285 bfd_set_error (bfd_error_no_memory);
286 return (bfd_size_type) -1;
287 }
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 }
294
295 *relocs = info->dynrel;
296
297 return info->dynrel_count;
298 }
This page took 0.036374 seconds and 4 git commands to generate.