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_error
= no_memory
;
97 obj_aout_dynamic_info (abfd
) = (PTR
) info
;
99 /* We look for the __DYNAMIC symbol to locate the dynamic linking
100 information. It should be the first symbol if it is defined. If
101 we can't find it, don't sweat it. */
102 if ((abfd
->flags
& DYNAMIC
) == 0
103 || bfd_get_symcount (abfd
) <= 0
104 || bfd_seek (abfd
, obj_sym_filepos (abfd
), SEEK_SET
) != 0
105 || (bfd_read ((PTR
) &dynsym
, 1, EXTERNAL_NLIST_SIZE
, abfd
)
106 != EXTERNAL_NLIST_SIZE
)
107 || ((dynsym
.e_type
[0] & N_TYPE
) != N_DATA
108 && (dynsym
.e_type
[0] & N_TYPE
) != N_TEXT
)
110 obj_str_filepos (abfd
) + GET_WORD (abfd
, dynsym
.e_strx
),
112 || bfd_read ((PTR
) buf
, 1, sizeof buf
, abfd
) != sizeof buf
113 || buf
[sizeof buf
- 1] != '\0'
114 || strcmp (buf
, "__DYNAMIC") != 0)
117 if ((dynsym
.e_type
[0] & N_TYPE
) == N_DATA
)
118 dynsec
= obj_datasec (abfd
);
120 dynsec
= obj_textsec (abfd
);
121 if (! bfd_get_section_contents (abfd
, dynsec
, (PTR
) &dyninfo
,
122 (GET_WORD (abfd
, dynsym
.e_value
)
123 - bfd_get_section_vma (abfd
, dynsec
)),
127 dynver
= GET_WORD (abfd
, dyninfo
.ld_version
);
128 if (dynver
!= 2 && dynver
!= 3)
131 dynoff
= GET_WORD (abfd
, dyninfo
.ld
);
133 /* dynoff is a virtual address. It is probably always in the .data
134 section, but this code should work even if it moves. */
135 if (dynoff
< bfd_get_section_vma (abfd
, obj_datasec (abfd
)))
136 dynsec
= obj_textsec (abfd
);
138 dynsec
= obj_datasec (abfd
);
139 dynoff
-= bfd_get_section_vma (abfd
, dynsec
);
140 if (dynoff
< 0 || dynoff
> bfd_section_size (abfd
, dynsec
))
143 /* This executable appears to be dynamically linked in a way that we
145 if (! bfd_get_section_contents (abfd
, dynsec
, (PTR
) &linkinfo
, dynoff
,
146 (bfd_size_type
) sizeof linkinfo
))
149 /* Swap in the dynamic link information. */
150 info
->dyninfo
.ld_loaded
= GET_WORD (abfd
, linkinfo
.ld_loaded
);
151 info
->dyninfo
.ld_need
= GET_WORD (abfd
, linkinfo
.ld_need
);
152 info
->dyninfo
.ld_rules
= GET_WORD (abfd
, linkinfo
.ld_rules
);
153 info
->dyninfo
.ld_got
= GET_WORD (abfd
, linkinfo
.ld_got
);
154 info
->dyninfo
.ld_plt
= GET_WORD (abfd
, linkinfo
.ld_plt
);
155 info
->dyninfo
.ld_rel
= GET_WORD (abfd
, linkinfo
.ld_rel
);
156 info
->dyninfo
.ld_hash
= GET_WORD (abfd
, linkinfo
.ld_hash
);
157 info
->dyninfo
.ld_stab
= GET_WORD (abfd
, linkinfo
.ld_stab
);
158 info
->dyninfo
.ld_stab_hash
= GET_WORD (abfd
, linkinfo
.ld_stab_hash
);
159 info
->dyninfo
.ld_buckets
= GET_WORD (abfd
, linkinfo
.ld_buckets
);
160 info
->dyninfo
.ld_symbols
= GET_WORD (abfd
, linkinfo
.ld_symbols
);
161 info
->dyninfo
.ld_symb_size
= GET_WORD (abfd
, linkinfo
.ld_symb_size
);
162 info
->dyninfo
.ld_text
= GET_WORD (abfd
, linkinfo
.ld_text
);
163 info
->dyninfo
.ld_plt_sz
= GET_WORD (abfd
, linkinfo
.ld_plt_sz
);
165 /* The only way to get the size of the symbol information appears to
166 be to determine the distance between it and the string table. */
167 info
->dynsym_count
= ((info
->dyninfo
.ld_symbols
- info
->dyninfo
.ld_stab
)
168 / EXTERNAL_NLIST_SIZE
);
169 BFD_ASSERT (info
->dynsym_count
* EXTERNAL_NLIST_SIZE
170 == info
->dyninfo
.ld_symbols
- info
->dyninfo
.ld_stab
);
172 /* Similarly, the relocs end at the hash table. */
173 info
->dynrel_count
= ((info
->dyninfo
.ld_hash
- info
->dyninfo
.ld_rel
)
174 / obj_reloc_entry_size (abfd
));
175 BFD_ASSERT (info
->dynrel_count
* obj_reloc_entry_size (abfd
)
176 == info
->dyninfo
.ld_hash
- info
->dyninfo
.ld_rel
);
183 /* Read in the dynamic symbols. */
186 MY(read_dynamic_symbols
) (abfd
, syms
, strs
, strsize
)
188 struct external_nlist
**syms
;
190 bfd_size_type
*strsize
;
192 struct sunos_dynamic_info
*info
;
194 if (obj_aout_dynamic_info (abfd
) == (PTR
) NULL
)
196 if (! sunos_read_dynamic_info (abfd
))
197 return (bfd_size_type
) -1;
200 info
= (struct sunos_dynamic_info
*) obj_aout_dynamic_info (abfd
);
201 if (! info
->valid
|| info
->dynsym_count
== 0)
204 if (info
->dynsym
== (struct external_nlist
*) NULL
)
206 info
->dynsym
= ((struct external_nlist
*)
209 * EXTERNAL_NLIST_SIZE
)));
210 info
->dynstr
= (char *) bfd_alloc (abfd
, info
->dyninfo
.ld_symb_size
);
211 if (!info
->dynsym
|| !info
->dynstr
)
213 bfd_error
= no_memory
;
216 if (bfd_seek (abfd
, info
->dyninfo
.ld_stab
, SEEK_SET
) != 0
217 || (bfd_read ((PTR
) info
->dynsym
, info
->dynsym_count
,
218 EXTERNAL_NLIST_SIZE
, abfd
)
219 != info
->dynsym_count
* EXTERNAL_NLIST_SIZE
)
220 || bfd_seek (abfd
, info
->dyninfo
.ld_symbols
, SEEK_SET
) != 0
221 || (bfd_read ((PTR
) info
->dynstr
, 1, info
->dyninfo
.ld_symb_size
,
223 != info
->dyninfo
.ld_symb_size
))
224 return (bfd_size_type
) -1;
227 *syms
= info
->dynsym
;
228 *strs
= info
->dynstr
;
229 *strsize
= info
->dyninfo
.ld_symb_size
;
231 #ifdef CHECK_DYNAMIC_HASH
232 /* Check my understanding of the dynamic hash table by making sure
233 that each symbol can be located in the hash table. */
235 bfd_size_type table_size
;
239 if (info
->dyninfo
.ld_buckets
> info
->dynsym_count
)
241 table_size
= info
->dyninfo
.ld_stab
- info
->dyninfo
.ld_hash
;
242 table
= (bfd_byte
*) alloca (table_size
);
243 if (bfd_seek (abfd
, info
->dyninfo
.ld_hash
, SEEK_SET
) != 0
244 || bfd_read ((PTR
) table
, 1, table_size
, abfd
) != table_size
)
246 for (i
= 0; i
< info
->dynsym_count
; i
++)
251 name
= ((unsigned char *) info
->dynstr
252 + GET_WORD (abfd
, info
->dynsym
[i
].e_strx
));
254 while (*name
!= '\0')
255 hash
= (hash
<< 1) + *name
++;
257 hash
%= info
->dyninfo
.ld_buckets
;
258 while (GET_WORD (abfd
, table
+ 8 * hash
) != i
)
260 hash
= GET_WORD (abfd
, table
+ 8 * hash
+ 4);
261 if (hash
== 0 || hash
>= table_size
/ 8)
266 #endif /* CHECK_DYNAMIC_HASH */
268 return info
->dynsym_count
;
271 /* Read in the dynamic relocs for a section. */
274 MY(read_dynamic_relocs
) (abfd
, relocs
)
278 struct sunos_dynamic_info
*info
;
280 if (obj_aout_dynamic_info (abfd
) == (PTR
) NULL
)
282 if (! sunos_read_dynamic_info (abfd
))
283 return (bfd_size_type
) -1;
286 info
= (struct sunos_dynamic_info
*) obj_aout_dynamic_info (abfd
);
287 if (! info
->valid
|| info
->dynrel_count
== 0)
290 if (info
->dynrel
== NULL
)
292 info
->dynrel
= (PTR
) bfd_alloc (abfd
,
294 * obj_reloc_entry_size (abfd
)));
297 bfd_error
= no_memory
;
298 return (bfd_size_type
) -1;
300 if (bfd_seek (abfd
, info
->dyninfo
.ld_rel
, SEEK_SET
) != 0
301 || (bfd_read ((PTR
) info
->dynrel
, info
->dynrel_count
,
302 obj_reloc_entry_size (abfd
), abfd
)
303 != info
->dynrel_count
* obj_reloc_entry_size (abfd
)))
304 return (bfd_size_type
) -1;
307 *relocs
= info
->dynrel
;
309 return info
->dynrel_count
;