1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #define I960 1
24: #define BADMAG(x) I960BADMAG(x)
25:
26: #include "sysdep.h"
27: #include "bfd.h"
28: #include "libbfd.h"
29: #include "coff/i960.h"
30: #include "coff/internal.h"
31: #include "libcoff.h"
32:
33: static bfd_boolean coff_i960_is_local_label_name
34: PARAMS ((bfd *, const char *));
35: static bfd_reloc_status_type optcall_callback
36: PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
37: static bfd_reloc_status_type coff_i960_relocate
38: PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
39: static reloc_howto_type *coff_i960_reloc_type_lookup
40: PARAMS ((bfd *, bfd_reloc_code_real_type));
41: static bfd_boolean coff_i960_start_final_link
42: PARAMS ((bfd *, struct bfd_link_info *));
43: static bfd_boolean coff_i960_relocate_section
44: PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
45: struct internal_reloc *, struct internal_syment *, asection **));
46: static bfd_boolean coff_i960_adjust_symndx
47: PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
48: struct internal_reloc *, bfd_boolean *));
49:
50: #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
51: #define COFF_ALIGN_IN_SECTION_HEADER 1
52:
53: #define GET_SCNHDR_ALIGN H_GET_32
54: #define PUT_SCNHDR_ALIGN H_PUT_32
55:
56:
57:
58: #define COFF_PAGE_SIZE 1
59:
60: #define COFF_LONG_FILENAMES
61:
62:
63:
64: static bfd_boolean
65: coff_i960_is_local_label_name (abfd, name)
66: bfd *abfd ATTRIBUTE_UNUSED;
67: const char *name;
68: {
69: return (name[0] == 'L'
70: || (name[0] == '.'
71: && (name[1] == 'C'
72: || name[1] == 'I'
73: || name[1] == '.')));
74: }
75:
76:
77:
78: #ifndef CALC_ADDEND
79: #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
80: { \
81: coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
82: if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
83: coffsym = (obj_symbols (abfd) \
84: + (cache_ptr->sym_ptr_ptr - symbols)); \
85: else if (ptr) \
86: coffsym = coff_symbol_from (abfd, ptr); \
87: if (coffsym != (coff_symbol_type *) NULL \
88: && coffsym->native->u.syment.n_scnum == 0) \
89: cache_ptr->addend = 0; \
90: else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
91: && ptr->section != (asection *) NULL) \
92: cache_ptr->addend = - (ptr->section->vma + ptr->value); \
93: else \
94: cache_ptr->addend = 0; \
95: if (ptr && (reloc.r_type == 25 || reloc.r_type == 27)) \
96: cache_ptr->addend += asect->vma; \
97: }
98: #endif
99:
100: #define CALLS 0x66003800
101: #define BAL 0x0b000000
102: #define BAL_MASK 0x00ffffff
103:
104: static bfd_reloc_status_type
105: optcall_callback (abfd, reloc_entry, symbol_in, data,
106: input_section, ignore_bfd, error_message)
107: bfd *abfd;
108: arelent *reloc_entry;
109: asymbol *symbol_in;
110: PTR data;
111: asection *input_section;
112: bfd *ignore_bfd ATTRIBUTE_UNUSED;
113: char **error_message;
114: {
115:
116:
117:
118: bfd_reloc_status_type result;
119: coff_symbol_type *cs = coffsymbol(symbol_in);
120:
121:
122:
123: if (bfd_is_und_section (cs->symbol.section)) {
124: reloc_entry->address += input_section->output_offset;
125: return bfd_reloc_ok;
126: }
127:
128:
129:
130: if ((bfd_asymbol_flavour(&cs->symbol) != bfd_target_coff_flavour)
131: || (cs->native == (combined_entry_type *)NULL))
132: {
133:
134:
135:
136:
137: *error_message =
138: (char *) _("uncertain calling convention for non-COFF symbol");
139: result = bfd_reloc_dangerous;
140: }
141: else
142: {
143: switch (cs->native->u.syment.n_sclass)
144: {
145: case C_LEAFSTAT:
146: case C_LEAFEXT:
147:
148:
149: {
150: union internal_auxent *aux = &((cs->native+2)->u.auxent);
151: int word = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address);
152: int olf = (aux->x_bal.x_balntry - cs->native->u.syment.n_value);
153: BFD_ASSERT(cs->native->u.syment.n_numaux==2);
154:
155:
156:
157:
158:
159:
160: word = ((word + olf) & BAL_MASK) | BAL;
161: bfd_put_32 (abfd, (bfd_vma) word,
162: (bfd_byte *) data + reloc_entry->address);
163: }
164: result = bfd_reloc_ok;
165: break;
166: case C_SCALL:
167:
168: BFD_ASSERT(0);
169: result = bfd_reloc_ok;
170: break;
171: default:
172: result = bfd_reloc_ok;
173: break;
174: }
175: }
176: return result;
177: }
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194: static bfd_reloc_status_type
195: coff_i960_relocate (abfd, reloc_entry, symbol, data, input_section,
196: output_bfd, error_message)
197: bfd *abfd;
198: arelent *reloc_entry;
199: asymbol *symbol;
200: PTR data ATTRIBUTE_UNUSED;
201: asection *input_section ATTRIBUTE_UNUSED;
202: bfd *output_bfd;
203: char **error_message ATTRIBUTE_UNUSED;
204: {
205: asection *osec;
206:
207: if (output_bfd == NULL)
208: {
209:
210: return bfd_reloc_continue;
211: }
212:
213: if (bfd_is_und_section (bfd_get_section (symbol)))
214: {
215:
216: return bfd_reloc_continue;
217: }
218:
219: if (bfd_is_com_section (bfd_get_section (symbol)))
220: {
221:
222:
223: return bfd_reloc_continue;
224: }
225:
226:
227:
228: osec = bfd_get_section (symbol)->output_section;
229: if (coff_section_data (output_bfd, osec) != NULL
230: && coff_section_data (output_bfd, osec)->tdata != NULL)
231: reloc_entry->sym_ptr_ptr =
232: (asymbol **) coff_section_data (output_bfd, osec)->tdata;
233: else
234: {
235: const char *sec_name;
236: asymbol **syms, **sym_end;
237:
238: sec_name = bfd_get_section_name (output_bfd, osec);
239: syms = bfd_get_outsymbols (output_bfd);
240: sym_end = syms + bfd_get_symcount (output_bfd);
241: for (; syms < sym_end; syms++)
242: {
243: if (bfd_asymbol_name (*syms) != NULL
244: && (*syms)->value == 0
245: && strcmp ((*syms)->section->output_section->name,
246: sec_name) == 0)
247: break;
248: }
249:
250: if (syms >= sym_end)
251: abort ();
252:
253: reloc_entry->sym_ptr_ptr = syms;
254:
255: if (coff_section_data (output_bfd, osec) == NULL)
256: {
257: bfd_size_type amt = sizeof (struct coff_section_tdata);
258: osec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
259: if (osec->used_by_bfd == NULL)
260: return bfd_reloc_overflow;
261: }
262: coff_section_data (output_bfd, osec)->tdata = (PTR) syms;
263: }
264:
265:
266:
267: return bfd_reloc_continue;
268: }
269:
270: static reloc_howto_type howto_rellong =
271: HOWTO ((unsigned int) R_RELLONG, 0, 2, 32,FALSE, 0,
272: complain_overflow_bitfield, coff_i960_relocate,"rellong", TRUE,
273: 0xffffffff, 0xffffffff, 0);
274: static reloc_howto_type howto_iprmed =
275: HOWTO (R_IPRMED, 0, 2, 24,TRUE,0, complain_overflow_signed,
276: coff_i960_relocate, "iprmed ", TRUE, 0x00ffffff, 0x00ffffff, 0);
277: static reloc_howto_type howto_optcall =
278: HOWTO (R_OPTCALL, 0,2,24,TRUE,0, complain_overflow_signed,
279: optcall_callback, "optcall", TRUE, 0x00ffffff, 0x00ffffff, 0);
280:
281: static reloc_howto_type *
282: coff_i960_reloc_type_lookup (abfd, code)
283: bfd *abfd ATTRIBUTE_UNUSED;
284: bfd_reloc_code_real_type code;
285: {
286: switch (code)
287: {
288: default:
289: return 0;
290: case BFD_RELOC_I960_CALLJ:
291: return &howto_optcall;
292: case BFD_RELOC_32:
293: case BFD_RELOC_CTOR:
294: return &howto_rellong;
295: case BFD_RELOC_24_PCREL:
296: return &howto_iprmed;
297: }
298: }
299:
300: static reloc_howto_type *
301: coff_i960_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
302: const char *r_name)
303: {
304: if (strcasecmp (howto_optcall.name, r_name) == 0)
305: return &howto_optcall;
306: if (strcasecmp (howto_rellong.name, r_name) == 0)
307: return &howto_rellong;
308: if (strcasecmp (howto_iprmed.name, r_name) == 0)
309: return &howto_iprmed;
310:
311: return NULL;
312: }
313:
314:
315:
316: #define RTYPE2HOWTO(cache_ptr, dst) \
317: { \
318: reloc_howto_type *howto_ptr; \
319: switch ((dst)->r_type) { \
320: case 17: howto_ptr = &howto_rellong; break; \
321: case 25: howto_ptr = &howto_iprmed; break; \
322: case 27: howto_ptr = &howto_optcall; break; \
323: default: howto_ptr = 0; break; \
324: } \
325: (cache_ptr)->howto = howto_ptr; \
326: }
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337: static bfd_boolean
338: coff_i960_start_final_link (abfd, info)
339: bfd *abfd;
340: struct bfd_link_info *info;
341: {
342: bfd_size_type symesz = bfd_coff_symesz (abfd);
343: asection *o;
344: bfd_byte *esym;
345:
346: if (! info->relocatable)
347: return TRUE;
348:
349: esym = (bfd_byte *) bfd_malloc (symesz);
350: if (esym == NULL)
351: return FALSE;
352:
353: if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
354: return FALSE;
355:
356: for (o = abfd->sections; o != NULL; o = o->next)
357: {
358: struct internal_syment isym;
359:
360: strncpy (isym._n._n_name, o->name, SYMNMLEN);
361: isym.n_value = 0;
362: isym.n_scnum = o->target_index;
363: isym.n_type = T_NULL;
364: isym.n_sclass = C_STAT;
365: isym.n_numaux = 0;
366:
367: bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
368:
369: if (bfd_bwrite (esym, symesz, abfd) != symesz)
370: {
371: free (esym);
372: return FALSE;
373: }
374:
375: obj_raw_syment_count (abfd) += 1;
376: }
377:
378: free (esym);
379:
380: return TRUE;
381: }
382:
383:
384:
385: static bfd_boolean
386: coff_i960_relocate_section (output_bfd, info, input_bfd, input_section,
387: contents, relocs, syms, sections)
388: bfd *output_bfd ATTRIBUTE_UNUSED;
389: struct bfd_link_info *info;
390: bfd *input_bfd;
391: asection *input_section;
392: bfd_byte *contents;
393: struct internal_reloc *relocs;
394: struct internal_syment *syms;
395: asection **sections;
396: {
397: struct internal_reloc *rel;
398: struct internal_reloc *relend;
399:
400: rel = relocs;
401: relend = rel + input_section->reloc_count;
402: for (; rel < relend; rel++)
403: {
404: long symndx;
405: struct coff_link_hash_entry *h;
406: struct internal_syment *sym;
407: bfd_vma addend;
408: bfd_vma val;
409: reloc_howto_type *howto;
410: bfd_reloc_status_type rstat = bfd_reloc_ok;
411: bfd_boolean done;
412:
413: symndx = rel->r_symndx;
414:
415: if (symndx == -1)
416: {
417: h = NULL;
418: sym = NULL;
419: }
420: else
421: {
422: h = obj_coff_sym_hashes (input_bfd)[symndx];
423: sym = syms + symndx;
424: }
425:
426: if (sym != NULL && sym->n_scnum != 0)
427: addend = - sym->n_value;
428: else
429: addend = 0;
430:
431: switch (rel->r_type)
432: {
433: case 17: howto = &howto_rellong; break;
434: case 25: howto = &howto_iprmed; break;
435: case 27: howto = &howto_optcall; break;
436: default:
437: bfd_set_error (bfd_error_bad_value);
438: return FALSE;
439: }
440:
441: val = 0;
442:
443: if (h == NULL)
444: {
445: asection *sec;
446:
447: if (symndx == -1)
448: {
449: sec = bfd_abs_section_ptr;
450: val = 0;
451: }
452: else
453: {
454: sec = sections[symndx];
455: val = (sec->output_section->vma
456: + sec->output_offset
457: + sym->n_value
458: - sec->vma);
459: }
460: }
461: else
462: {
463: if (h->root.type == bfd_link_hash_defined
464: || h->root.type == bfd_link_hash_defweak)
465: {
466: asection *sec;
467:
468: sec = h->root.u.def.section;
469: val = (h->root.u.def.value
470: + sec->output_section->vma
471: + sec->output_offset);
472: }
473: else if (! info->relocatable)
474: {
475: if (! ((*info->callbacks->undefined_symbol)
476: (info, h->root.root.string, input_bfd, input_section,
477: rel->r_vaddr - input_section->vma, TRUE)))
478: return FALSE;
479: }
480: }
481:
482: done = FALSE;
483:
484: if (howto->type == R_OPTCALL && ! info->relocatable && symndx != -1)
485: {
486: int class;
487:
488: if (h != NULL)
489: class = h->class;
490: else
491: class = sym->n_sclass;
492:
493: switch (class)
494: {
495: case C_NULL:
496:
497:
498:
499: if (! ((*info->callbacks->reloc_dangerous)
500: (info,
501: _("uncertain calling convention for non-COFF symbol"),
502: input_bfd, input_section,
503: rel->r_vaddr - input_section->vma)))
504: return FALSE;
505: break;
506: case C_LEAFSTAT:
507: case C_LEAFEXT:
508:
509:
510: {
511: long olf;
512: unsigned long word;
513:
514: if (h != NULL)
515: {
516: BFD_ASSERT (h->numaux == 2);
517: olf = h->aux[1].x_bal.x_balntry;
518: }
519: else
520: {
521: bfd_byte *esyms;
522: union internal_auxent aux;
523:
524: BFD_ASSERT (sym->n_numaux == 2);
525: esyms = (bfd_byte *) obj_coff_external_syms (input_bfd);
526: esyms += (symndx + 2) * bfd_coff_symesz (input_bfd);
527: bfd_coff_swap_aux_in (input_bfd, (PTR) esyms, sym->n_type,
528: sym->n_sclass, 1, sym->n_numaux,
529: (PTR) &aux);
530: olf = aux.x_bal.x_balntry;
531: }
532:
533: word = bfd_get_32 (input_bfd,
534: (contents
535: + (rel->r_vaddr - input_section->vma)));
536: word = ((word + olf - val) & BAL_MASK) | BAL;
537: bfd_put_32 (input_bfd,
538: (bfd_vma) word,
539: contents + (rel->r_vaddr - input_section->vma));
540: done = TRUE;
541: }
542: break;
543: case C_SCALL:
544: BFD_ASSERT (0);
545: break;
546: }
547: }
548:
549: if (! done)
550: {
551: if (howto->pc_relative)
552: addend += input_section->vma;
553: rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
554: contents,
555: rel->r_vaddr - input_section->vma,
556: val, addend);
557: }
558:
559: switch (rstat)
560: {
561: default:
562: abort ();
563: case bfd_reloc_ok:
564: break;
565: case