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
)));
92 obj_aout_dynamic_info (abfd
) = (PTR
) info
;
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
)
105 obj_str_filepos (abfd
) + GET_WORD (abfd
, dynsym
.e_strx
),
107 || bfd_read ((PTR
) buf
, 1, sizeof buf
, abfd
) != sizeof buf
108 || buf
[sizeof buf
- 1] != '\0'
109 || strcmp (buf
, "__DYNAMIC") != 0)
112 if ((dynsym
.e_type
[0] & N_TYPE
) == N_DATA
)
113 dynsec
= obj_datasec (abfd
);
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
)),
122 dynver
= GET_WORD (abfd
, dyninfo
.ld_version
);
123 if (dynver
!= 2 && dynver
!= 3)
126 dynoff
= GET_WORD (abfd
, dyninfo
.ld
);
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
);
133 dynsec
= obj_datasec (abfd
);
134 dynoff
-= bfd_get_section_vma (abfd
, dynsec
);
135 if (dynoff
< 0 || dynoff
> bfd_section_size (abfd
, dynsec
))
138 /* This executable appears to be dynamically linked in a way that we
140 if (! bfd_get_section_contents (abfd
, dynsec
, (PTR
) &linkinfo
, dynoff
,
141 (bfd_size_type
) sizeof linkinfo
))
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
);
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
);
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
);
178 /* Read in the dynamic symbols. */
181 MY(read_dynamic_symbols
) (abfd
, syms
, strs
, strsize
)
183 struct external_nlist
**syms
;
185 bfd_size_type
*strsize
;
187 struct sunos_dynamic_info
*info
;
189 if (obj_aout_dynamic_info (abfd
) == (PTR
) NULL
)
191 if (! sunos_read_dynamic_info (abfd
))
192 return (bfd_size_type
) -1;
195 info
= (struct sunos_dynamic_info
*) obj_aout_dynamic_info (abfd
);
196 if (! info
->valid
|| info
->dynsym_count
== 0)
199 if (info
->dynsym
== (struct external_nlist
*) NULL
)
201 info
->dynsym
= ((struct external_nlist
*)
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
,
213 != info
->dyninfo
.ld_symb_size
))
214 return (bfd_size_type
) -1;
217 *syms
= info
->dynsym
;
218 *strs
= info
->dynstr
;
219 *strsize
= info
->dyninfo
.ld_symb_size
;
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. */
225 bfd_size_type table_size
;
229 if (info
->dyninfo
.ld_buckets
> info
->dynsym_count
)
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
)
236 for (i
= 0; i
< info
->dynsym_count
; i
++)
241 name
= ((unsigned char *) info
->dynstr
242 + GET_WORD (abfd
, info
->dynsym
[i
].e_strx
));
244 while (*name
!= '\0')
245 hash
= (hash
<< 1) + *name
++;
247 hash
%= info
->dyninfo
.ld_buckets
;
248 while (GET_WORD (abfd
, table
+ 8 * hash
) != i
)
250 hash
= GET_WORD (abfd
, table
+ 8 * hash
+ 4);
251 if (hash
== 0 || hash
>= table_size
/ 8)
256 #endif /* CHECK_DYNAMIC_HASH */
258 return info
->dynsym_count
;
261 /* Read in the dynamic relocs for a section. */
264 MY(read_dynamic_relocs
) (abfd
, relocs
)
268 struct sunos_dynamic_info
*info
;
270 if (obj_aout_dynamic_info (abfd
) == (PTR
) NULL
)
272 if (! sunos_read_dynamic_info (abfd
))
273 return (bfd_size_type
) -1;
276 info
= (struct sunos_dynamic_info
*) obj_aout_dynamic_info (abfd
);
277 if (! info
->valid
|| info
->dynrel_count
== 0)
280 if (info
->dynrel
== (struct external_nlist
*) NULL
)
282 info
->dynrel
= (PTR
) bfd_alloc (abfd
,
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;
292 *relocs
= info
->dynrel
;
294 return info
->dynrel_count
;