1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25: #include "sysdep.h"
26: #include "bfd.h"
27: #include "libbfd.h"
28: #include "coff/maxq.h"
29: #include "coff/internal.h"
30: #include "libcoff.h"
31: #include "libiberty.h"
32:
33: #ifndef MAXQ20
34: #define MAXQ20 1
35: #endif
36:
37: #define RTYPE2HOWTO(cache_ptr, dst) \
38: ((cache_ptr)->howto = \
39: ((dst)->r_type < 48 \
40: ? howto_table + (((dst)->r_type==47) ? 6: ((dst)->r_type)) \
41: : NULL))
42:
43: #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
44:
45:
46: #define SWAP_IN_RELOC_OFFSET H_GET_16
47: #define SWAP_OUT_RELOC_OFFSET H_PUT_16
48:
49: #define SHORT_JUMP BFD_RELOC_16_PCREL_S2
50: #define LONG_JUMP BFD_RELOC_14
51: #define ABSOLUTE_ADDR_FOR_DATA BFD_RELOC_24
52:
53:
54: #define IS_SJUMP_RANGE(x) ((x > -128) && (x < 129))
55: #define HIGH_WORD_MASK 0xff00
56: #define LOW_WORD_MASK 0x00ff
57:
58: static long
59: get_symbol_value (asymbol *symbol)
60: {
61: long relocation = 0;
62:
63: if (bfd_is_com_section (symbol->section))
64: relocation = 0;
65: else
66: relocation = symbol->value +
67: symbol->section->output_section->vma + symbol->section->output_offset;
68:
69: return relocation;
70: }
71:
72:
73:
74:
75:
76: static bfd_reloc_status_type
77: coff_maxq20_reloc (bfd * abfd,
78: arelent * reloc_entry,
79: asymbol * symbol_in,
80: void * data,
81: asection * input_section ATTRIBUTE_UNUSED,
82: bfd * output_bfd ATTRIBUTE_UNUSED,
83: char ** error_message ATTRIBUTE_UNUSED)
84: {
85: unsigned char *addr = NULL;
86: unsigned long x = 0;
87: long call_addr = 0;
88: short addend = 0;
89: long diff = 0;
90:
91:
92: if (symbol_in->section == &bfd_und_section
93: && (symbol_in->flags & BSF_WEAK) == 0)
94: return bfd_reloc_continue;
95:
96: if (data && reloc_entry)
97: {
98: addr = (unsigned char *) data + reloc_entry->address;
99: call_addr = call_addr - call_addr;
100: call_addr = get_symbol_value (symbol_in);
101:
102:
103:
104:
105:
106:
107: switch (reloc_entry->howto->type)
108: {
109:
110:
111: case SHORT_JUMP:
112:
113: addend = reloc_entry->addend;
114:
115: if (addend > call_addr || addend > 0)
116: call_addr = symbol_in->section->output_section->vma + addend;
117: else if (addend < call_addr && addend > 0)
118: call_addr = call_addr + addend;
119: else if (addend < 0)
120: call_addr = call_addr + addend;
121:
122: diff = ((call_addr << 1) - (reloc_entry->address << 1));
123:
124: if (!IS_SJUMP_RANGE (diff))
125: {
126: bfd_perror (_("Can't Make it a Short Jump"));
127: return bfd_reloc_outofrange;
128: }
129:
130: x = bfd_get_16 (abfd, addr);
131:
132: x = x & LOW_WORD_MASK;
133: x = x | (diff << 8);
134: bfd_put_16 (abfd, (bfd_vma) x, addr);
135:
136: return bfd_reloc_ok;
137:
138: case ABSOLUTE_ADDR_FOR_DATA:
139: case LONG_JUMP:
140:
141:
142:
143:
144:
145:
146:
147: addend = (reloc_entry->addend - reloc_entry->addend);
148:
149:
150: addend = reloc_entry->addend;
151:
152:
153:
154:
155:
156: addend = 0;
157:
158: if (!bfd_is_com_section (symbol_in->section) &&
159: ((symbol_in->flags & BSF_OLD_COMMON) == 0))
160: {
161: if (reloc_entry->addend > symbol_in->value)
162: addend = reloc_entry->addend - symbol_in->value;
163:
164: if ((reloc_entry->addend < symbol_in->value)
165: && (reloc_entry->addend != 0))
166: addend = reloc_entry->addend - symbol_in->value;
167:
168: if (reloc_entry->addend == symbol_in->value)
169: addend = 0;
170: }
171:
172: if (bfd_is_com_section (symbol_in->section) ||
173: ((symbol_in->flags & BSF_OLD_COMMON) != 0))
174: addend = reloc_entry->addend;
175:
176: if (addend < 0
177: && (call_addr < (long) (addend * (-1))))
178: addend = 0;
179:
180: call_addr += addend;
181:
182:
183:
184: if ((symbol_in->section->flags & SEC_CODE) == SEC_CODE)
185: {
186:
187: call_addr = call_addr >> 1;
188:
189: if (call_addr > 0xFFFF)
190: {
191: bfd_perror (_("Exceeds Long Jump Range"));
192: return bfd_reloc_outofrange;
193: }
194: }
195: else
196: {
197:
198:
199:
200: if (call_addr > 0xFFFF)
201: {
202: bfd_perror (_("Absolute address Exceeds 16 bit Range"));
203: return bfd_reloc_outofrange;
204: }
205: }
206:
207: x = bfd_get_32 (abfd, addr);
208:
209: x = (x & 0xFF00FF00);
210: x = (x | ((call_addr & HIGH_WORD_MASK) >> 8));
211: x = (x | (call_addr & LOW_WORD_MASK) << 16);
212:
213: bfd_put_32 (abfd, (bfd_vma) x, addr);
214: return bfd_reloc_ok;
215:
216: case BFD_RELOC_8:
217: addend = (reloc_entry->addend - reloc_entry->addend);
218:
219: if (!bfd_is_com_section (symbol_in->section) &&
220: ((symbol_in->flags & BSF_OLD_COMMON) == 0))
221: {
222: if (reloc_entry->addend > symbol_in->value)
223: addend = reloc_entry->addend - symbol_in->value;
224: if (reloc_entry->addend < symbol_in->value)
225: addend = reloc_entry->addend - symbol_in->value;
226: if (reloc_entry->addend == symbol_in->value)
227: addend = 0;
228: }
229:
230: if (bfd_is_com_section (symbol_in->section) ||
231: ((symbol_in->flags & BSF_OLD_COMMON) != 0))
232: addend = reloc_entry->addend;
233:
234: if (addend < 0
235: && (call_addr < (long) (addend * (-1))))
236: addend = 0;
237:
238: if (call_addr + addend > 0xFF)
239: {
240: bfd_perror (_("Absolute address Exceeds 8 bit Range"));
241: return bfd_reloc_outofrange;
242: }
243:
244: x = bfd_get_8 (abfd, addr);
245: x = x & 0x00;
246: x = x | (call_addr + addend);
247:
248: bfd_put_8 (abfd, (bfd_vma) x, addr);
249: return bfd_reloc_ok;
250:
251: case BFD_RELOC_16:
252: addend = (reloc_entry->addend - reloc_entry->addend);
253: if (!bfd_is_com_section (symbol_in->section) &&
254: ((symbol_in->flags & BSF_OLD_COMMON) == 0))
255: {
256: if (reloc_entry->addend > symbol_in->value)
257: addend = reloc_entry->addend - symbol_in->value;
258:
259: if (reloc_entry->addend < symbol_in->value)
260: addend = reloc_entry->addend - symbol_in->value;
261:
262: if (reloc_entry->addend == symbol_in->value)
263: addend = 0;
264: }
265:
266: if (bfd_is_com_section (symbol_in->section) ||
267: ((symbol_in->flags & BSF_OLD_COMMON) != 0))
268: addend = reloc_entry->addend;
269:
270: if (addend < 0
271: && (call_addr < (long) (addend * (-1))))
272: addend = 0;
273:
274: if ((call_addr + addend) > 0xFFFF)
275: {
276: bfd_perror (_("Absolute address Exceeds 16 bit Range"));
277: return bfd_reloc_outofrange;
278: }
279: else
280: {
281: unsigned short val = (call_addr + addend);
282:
283: x = bfd_get_16 (abfd, addr);
284:
285:
286: x = (x & 0x0000);
287: x = val;
288: if ((symbol_in->section->flags & SEC_CODE) == SEC_CODE)
289: x = x >> 1;
290: }
291:
292: bfd_put_16 (abfd, (bfd_vma) x, addr);
293: return bfd_reloc_ok;
294:
295: case BFD_RELOC_32:
296: addend = (reloc_entry->addend - reloc_entry->addend);
297:
298: if (!bfd_is_com_section (symbol_in->section) &&
299: ((symbol_in->flags & BSF_OLD_COMMON) == 0))
300: {
301: if (reloc_entry->addend > symbol_in->value)
302: addend = reloc_entry->addend - symbol_in->value;
303: if (reloc_entry->addend < symbol_in->value)
304: addend = reloc_entry->addend - symbol_in->value;
305: if (reloc_entry->addend == symbol_in->value)
306: addend = 0;
307: }
308:
309: if (bfd_is_com_section (symbol_in->section) ||
310: ((symbol_in->flags & BSF_OLD_COMMON) != 0))
311: addend = reloc_entry->addend;
312:
313: if (addend < 0
314: && (call_addr < (long) (addend * (-1))))
315: addend = 0;
316:
317: if ((call_addr + addend) < 0)
318: {
319: bfd_perror ("Absolute address Exceeds 32 bit Range");
320: return bfd_reloc_outofrange;
321: }
322:
323: x = bfd_get_32 (abfd, addr);
324: x = (x & 0x0000);
325: x = call_addr + addend;
326: if ((symbol_in->section->flags & SEC_CODE) == SEC_CODE)
327: x = x >> 1;
328:
329: bfd_put_32 (abfd, (bfd_vma) x, addr);
330: return bfd_reloc_ok;
331:
332: default:
333: bfd_perror (_("Unrecognized Reloc Type"));
334: return bfd_reloc_notsupported;
335: }
336: }
337:
338: return bfd_reloc_notsupported;
339: }
340:
341: static reloc_howto_type howto_table[] =
342: {
343: EMPTY_HOWTO (0),
344: EMPTY_HOWTO (1),
345: {
346: BFD_RELOC_32, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
347: coff_maxq20_reloc, "32Bit", TRUE, 0x000000ff, 0x000000ff, TRUE
348: },
349: {
350: SHORT_JUMP, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
351: coff_maxq20_reloc, "SHORT_JMP", TRUE, 0x000000ff, 0x000000ff, TRUE
352: },
353: {
354: ABSOLUTE_ADDR_FOR_DATA, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
355: coff_maxq20_reloc, "INTERSEGMENT_RELOC", TRUE, 0x00000000, 0x00000000,
356: FALSE
357: },
358: {
359: BFD_RELOC_16, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
360: coff_maxq20_reloc, "16Bit", TRUE, 0x000000ff, 0x000000ff, TRUE
361: },
362: {
363: LONG_JUMP, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
364: coff_maxq20_reloc, "LONG_JUMP", TRUE, 0x00000000, 0x00000000, FALSE
365: },
366: {
367: BFD_RELOC_8, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
368: coff_maxq20_reloc, "8bit", TRUE, 0x000000ff, 0x000000ff, TRUE
369: },
370: EMPTY_HOWTO (8),
371: EMPTY_HOWTO (9),
372: EMPTY_HOWTO (10),
373: };
374:
375: static reloc_howto_type *
376: maxq_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
377: bfd_reloc_code_real_type code)
378: {
379: switch (code)
380: {
381:
382: case BFD_RELOC_16_PCREL_S2:
383: return howto_table + 3;
384:
385:
386: case BFD_RELOC_24:
387: return howto_table + 4;
388:
389:
390: case BFD_RELOC_8:
391: return howto_table + 7;
392:
393:
394: case BFD_RELOC_16:
395: return howto_table + 5;
396:
397:
398: case BFD_RELOC_32:
399: return howto_table + 2;
400:
401:
402: case BFD_RELOC_14:
403: return howto_table + 6;
404:
405: default:
406: return NULL;
407: }
408: }
409:
410: static reloc_howto_type *
411: maxq_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
412: {
413: unsigned int i;
414:
415: for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++)
416: if (howto_table[i].name != NULL
417: && strcasecmp (howto_table[i].name, r_name) == 0)
418: return &howto_table[i];
419:
420: return NULL;
421: }
422:
423: #define coff_bfd_reloc_type_lookup maxq_reloc_type_lookup
424: #define coff_bfd_reloc_name_lookup maxq_reloc_name_lookup
425:
426:
427: #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
428: cache_ptr->addend = ext_reloc.r_offset;
429:
430: #include "coffcode.h"
431:
432: #ifndef TARGET_UNDERSCORE
433: #define TARGET_UNDERSCORE 1
434: #endif
435:
436: #ifndef EXTRA_S_FLAGS
437: #define EXTRA_S_FLAGS 0
438: #endif
439:
440:
441: CREATE_LITTLE_COFF_TARGET_VEC (maxqcoff_vec, "coff-maxq", 0, EXTRA_S_FLAGS,
442: TARGET_UNDERSCORE, NULL, COFF_SWAP_TABLE);
443: