1 /* BFD backend for SunOS binaries.
2 Copyright (C) 1990-1991 Free Software Foundation, Inc.
3 Written by Cygnus Support.
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
22 #define TARGETNAME "a.out-sunos-big"
23 #define MY(OP) CAT(sunos_big_,OP)
27 /* Static routines defined in this file. */
29 struct external_nlist;
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 *));
36 #define MY_read_dynamic_symbols MY(read_dynamic_symbols)
37 #define MY_read_dynamic_relocs MY(read_dynamic_relocs)
39 /* Include the usual a.out support. */
42 /* SunOS shared library support. We store a pointer to this structure
43 in obj_aout_dynamic_info (abfd). */
45 struct sunos_dynamic_info
47 /* Whether we found any dynamic information. */
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. */
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. */
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. */
71 sunos_read_dynamic_info (abfd)
74 struct sunos_dynamic_info *info;
75 struct external_nlist dynsym;
76 char buf[sizeof "__DYNAMIC"];
79 struct external_sun4_dynamic dyninfo;
81 struct external_sun4_dynamic_link linkinfo;
83 if (obj_aout_dynamic_info (abfd) != (PTR) NULL)
86 info = ((struct sunos_dynamic_info *)
87 bfd_zalloc (abfd, sizeof (struct sunos_dynamic_info)));
90 bfd_set_error (bfd_error_no_memory);
97 obj_aout_dynamic_info (abfd) = (PTR) info;
99 /* This code used to look for the __DYNAMIC symbol to locate the dynamic
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)
108 if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo,
109 (file_ptr) 0, sizeof dyninfo))
112 dynver = GET_WORD (abfd, dyninfo.ld_version);
113 if (dynver != 2 && dynver != 3)
116 dynoff = GET_WORD (abfd, dyninfo.ld);
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);
123 dynsec = obj_datasec (abfd);
124 dynoff -= bfd_get_section_vma (abfd, dynsec);
125 if (dynoff < 0 || dynoff > bfd_section_size (abfd, dynsec))
128 /* This executable appears to be dynamically linked in a way that we
130 if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo, dynoff,
131 (bfd_size_type) sizeof linkinfo))
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);
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);
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);
168 /* Read in the dynamic symbols. */
171 MY(read_dynamic_symbols) (abfd, syms, strs, strsize)
173 struct external_nlist **syms;
175 bfd_size_type *strsize;
177 struct sunos_dynamic_info *info;
179 if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
181 if (! sunos_read_dynamic_info (abfd))
182 return (bfd_size_type) -1;
185 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
186 if (! info->valid || info->dynsym_count == 0)
189 if (info->dynsym == (struct external_nlist *) NULL)
191 info->dynsym = ((struct external_nlist *)
194 * EXTERNAL_NLIST_SIZE)));
195 info->dynstr = (char *) bfd_alloc (abfd, info->dyninfo.ld_symb_size);
196 if (!info->dynsym || !info->dynstr)
198 bfd_set_error (bfd_error_no_memory);
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,
208 != info->dyninfo.ld_symb_size))
209 return (bfd_size_type) -1;
212 *syms = info->dynsym;
213 *strs = info->dynstr;
214 *strsize = info->dyninfo.ld_symb_size;
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. */
220 bfd_size_type table_size;
224 if (info->dyninfo.ld_buckets > info->dynsym_count)
226 table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash;
227 table = (bfd_byte *) malloc (table_size);
230 if (bfd_seek (abfd, info->dyninfo.ld_hash, SEEK_SET) != 0
231 || bfd_read ((PTR) table, 1, table_size, abfd) != table_size)
233 for (i = 0; i < info->dynsym_count; i++)
238 name = ((unsigned char *) info->dynstr
239 + GET_WORD (abfd, info->dynsym[i].e_strx));
241 while (*name != '\0')
242 hash = (hash << 1) + *name++;
244 hash %= info->dyninfo.ld_buckets;
245 while (GET_WORD (abfd, table + 8 * hash) != i)
247 hash = GET_WORD (abfd, table + 8 * hash + 4);
248 if (hash == 0 || hash >= table_size / 8)
254 #endif /* CHECK_DYNAMIC_HASH */
256 return info->dynsym_count;
259 /* Read in the dynamic relocs for a section. */
262 MY(read_dynamic_relocs) (abfd, relocs)
266 struct sunos_dynamic_info *info;
268 if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
270 if (! sunos_read_dynamic_info (abfd))
271 return (bfd_size_type) -1;
274 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
275 if (! info->valid || info->dynrel_count == 0)
278 if (info->dynrel == NULL)
280 info->dynrel = (PTR) bfd_alloc (abfd,
282 * obj_reloc_entry_size (abfd)));
285 bfd_set_error (bfd_error_no_memory);
286 return (bfd_size_type) -1;
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;
295 *relocs = info->dynrel;
297 return info->dynrel_count;