ldctor.c revision 38889
1/* ldctor.c -- constructor support routines 2 Copyright (C) 1991, 92, 93, 94, 1995 Free Software Foundation, Inc. 3 By Steve Chamberlain <sac@cygnus.com> 4 5This file is part of GLD, the Gnu Linker. 6 7GLD is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2, or (at your option) 10any later version. 11 12GLD is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GLD; see the file COPYING. If not, write to 19the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 20 21#include "bfd.h" 22#include "sysdep.h" 23#include "bfdlink.h" 24 25#include "ld.h" 26#include "ldexp.h" 27#include "ldlang.h" 28#include "ldmisc.h" 29#include "ldgram.h" 30#include "ldmain.h" 31#include "ldctor.h" 32 33/* The list of statements needed to handle constructors. These are 34 invoked by the command CONSTRUCTORS in the linker script. */ 35lang_statement_list_type constructor_list; 36 37/* The sets we have seen. */ 38struct set_info *sets; 39 40/* Add an entry to a set. H is the entry in the linker hash table. 41 RELOC is the relocation to use for an entry in the set. SECTION 42 and VALUE are the value to add. This is called during the first 43 phase of the link, when we are still gathering symbols together. 44 We just record the information now. The ldctor_find_constructors 45 function will construct the sets. */ 46 47void 48ldctor_add_set_entry (h, reloc, name, section, value) 49 struct bfd_link_hash_entry *h; 50 bfd_reloc_code_real_type reloc; 51 const char *name; 52 asection *section; 53 bfd_vma value; 54{ 55 struct set_info *p; 56 struct set_element *e; 57 struct set_element **epp; 58 59 for (p = sets; p != (struct set_info *) NULL; p = p->next) 60 if (p->h == h) 61 break; 62 63 if (p == (struct set_info *) NULL) 64 { 65 p = (struct set_info *) xmalloc (sizeof (struct set_info)); 66 p->next = sets; 67 sets = p; 68 p->h = h; 69 p->reloc = reloc; 70 p->count = 0; 71 p->elements = NULL; 72 } 73 else 74 { 75 if (p->reloc != reloc) 76 { 77 einfo ("%P%X: Different relocs used in set %s\n", h->root.string); 78 return; 79 } 80 81 /* Don't permit a set to be constructed from different object 82 file formats. The same reloc may have different results. We 83 actually could sometimes handle this, but the case is 84 unlikely to ever arise. Sometimes constructor symbols are in 85 unusual sections, such as the absolute section--this appears 86 to be the case in Linux a.out--and in such cases we just 87 assume everything is OK. */ 88 if (p->elements != NULL 89 && section->owner != NULL 90 && p->elements->section->owner != NULL 91 && strcmp (bfd_get_target (section->owner), 92 bfd_get_target (p->elements->section->owner)) != 0) 93 { 94 einfo ("%P%X: Different object file formats composing set %s\n", 95 h->root.string); 96 return; 97 } 98 } 99 100 e = (struct set_element *) xmalloc (sizeof (struct set_element)); 101 e->next = NULL; 102 e->name = name; 103 e->section = section; 104 e->value = value; 105 106 for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next) 107 ; 108 *epp = e; 109 110 ++p->count; 111} 112 113/* This function is called after the first phase of the link and 114 before the second phase. At this point all set information has 115 been gathered. We now put the statements to build the sets 116 themselves into constructor_list. */ 117 118void 119ldctor_build_sets () 120{ 121 static boolean called; 122 lang_statement_list_type *old; 123 boolean header_printed; 124 struct set_info *p; 125 126 /* The emulation code may call us directly, but we only want to do 127 this once. */ 128 if (called) 129 return; 130 called = true; 131 132 old = stat_ptr; 133 stat_ptr = &constructor_list; 134 135 lang_list_init (stat_ptr); 136 137 header_printed = false; 138 for (p = sets; p != (struct set_info *) NULL; p = p->next) 139 { 140 struct set_element *e; 141 reloc_howto_type *howto; 142 int reloc_size, size; 143 144 /* If the symbol is defined, we may have been invoked from 145 collect, and the sets may already have been built, so we do 146 not do anything. */ 147 if (p->h->type == bfd_link_hash_defined 148 || p->h->type == bfd_link_hash_defweak) 149 continue; 150 151 /* For each set we build: 152 set: 153 .long number_of_elements 154 .long element0 155 ... 156 .long elementN 157 .long 0 158 except that we use the right size instead of .long. When 159 generating relocateable output, we generate relocs instead of 160 addresses. */ 161 howto = bfd_reloc_type_lookup (output_bfd, p->reloc); 162 if (howto == (reloc_howto_type *) NULL) 163 { 164 if (link_info.relocateable) 165 { 166 einfo ("%P%X: %s does not support reloc %s for set %s\n", 167 bfd_get_target (output_bfd), 168 bfd_get_reloc_code_name (p->reloc), 169 p->h->root.string); 170 continue; 171 } 172 173 /* If this is not a relocateable link, all we need is the 174 size, which we can get from the input BFD. */ 175 howto = bfd_reloc_type_lookup (p->elements->section->owner, 176 p->reloc); 177 if (howto == NULL) 178 { 179 einfo ("%P%X: %s does not support reloc %s for set %s\n", 180 bfd_get_target (p->elements->section->owner), 181 bfd_get_reloc_code_name (p->reloc), 182 p->h->root.string); 183 continue; 184 } 185 } 186 187 reloc_size = bfd_get_reloc_size (howto); 188 switch (reloc_size) 189 { 190 case 1: size = BYTE; break; 191 case 2: size = SHORT; break; 192 case 4: size = LONG; break; 193 case 8: 194 if (howto->complain_on_overflow == complain_overflow_signed) 195 size = SQUAD; 196 else 197 size = QUAD; 198 break; 199 default: 200 einfo ("%P%X: Unsupported size %d for set %s\n", 201 bfd_get_reloc_size (howto), p->h->root.string); 202 size = LONG; 203 break; 204 } 205 206 lang_add_assignment (exp_assop ('=', ".", 207 exp_unop (ALIGN_K, 208 exp_intop (reloc_size)))); 209 lang_add_assignment (exp_assop ('=', p->h->root.string, 210 exp_nameop (NAME, "."))); 211 lang_add_data (size, exp_intop ((bfd_vma) p->count)); 212 213 for (e = p->elements; e != (struct set_element *) NULL; e = e->next) 214 { 215 if (config.map_file != NULL) 216 { 217 int len; 218 219 if (! header_printed) 220 { 221 minfo ("\nSet Symbol\n\n"); 222 header_printed = true; 223 } 224 225 minfo ("%s", p->h->root.string); 226 len = strlen (p->h->root.string); 227 228 if (len >= 19) 229 { 230 print_nl (); 231 len = 0; 232 } 233 while (len < 20) 234 { 235 print_space (); 236 ++len; 237 } 238 239 if (e->name != NULL) 240 minfo ("%T\n", e->name); 241 else 242 minfo ("%G\n", e->section->owner, e->section, e->value); 243 } 244 245 if (link_info.relocateable) 246 lang_add_reloc (p->reloc, howto, e->section, e->name, 247 exp_intop (e->value)); 248 else 249 lang_add_data (size, exp_relop (e->section, e->value)); 250 } 251 252 lang_add_data (size, exp_intop (0)); 253 } 254 255 stat_ptr = old; 256} 257