1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #ifndef COFF_WITH_pex64
24: #define COFF_WITH_pex64
25: #endif
26:
27: #include "sysdep.h"
28: #include "bfd.h"
29: #include "libbfd.h"
30: #include "coff/x86_64.h"
31: #include "coff/internal.h"
32: #include "coff/pe.h"
33: #include "libcoff.h"
34: #include "libiberty.h"
35:
36: #define BADMAG(x) AMD64BADMAG(x)
37:
38: #ifdef COFF_WITH_pex64
39: # undef AOUTSZ
40: # define AOUTSZ PEPAOUTSZ
41: # define PEAOUTHDR PEPAOUTHDR
42: #endif
43:
44: #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
45:
46:
47:
48: #define COFF_PAGE_SIZE 0x1000
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59: static bfd_reloc_status_type
60: coff_amd64_reloc (bfd *abfd,
61: arelent *reloc_entry,
62: asymbol *symbol,
63: void * data,
64: asection *input_section ATTRIBUTE_UNUSED,
65: bfd *output_bfd,
66: char **error_message ATTRIBUTE_UNUSED)
67: {
68: symvalue diff;
69:
70: #if !defined(COFF_WITH_PE)
71: if (output_bfd == NULL)
72: return bfd_reloc_continue;
73: #endif
74:
75: if (bfd_is_com_section (symbol->section))
76: {
77: #if !defined(COFF_WITH_PE)
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89: diff = symbol->value + reloc_entry->addend;
90: #else
91:
92: diff = reloc_entry->addend;
93: #endif
94: }
95: else
96: {
97:
98:
99:
100:
101: #if defined(COFF_WITH_PE)
102: if (output_bfd == NULL)
103: {
104: reloc_howto_type *howto = reloc_entry->howto;
105:
106:
107:
108:
109:
110:
111:
112:
113: if(howto->pc_relative && howto->pcrel_offset)
114: diff = -(1 << howto->size);
115: else if(symbol->flags & BSF_WEAK)
116: diff = reloc_entry->addend - symbol->value;
117: else
118: diff = -reloc_entry->addend;
119: }
120: else
121: #endif
122: diff = reloc_entry->addend;
123: }
124:
125: #if defined(COFF_WITH_PE)
126:
127: if (reloc_entry->howto->type == R_AMD64_IMAGEBASE
128: && output_bfd != NULL
129: && bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
130: diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
131: #endif
132:
133: #define DOIT(x) \
134: x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
135:
136: if (diff != 0)
137: {
138: reloc_howto_type *howto = reloc_entry->howto;
139: unsigned char *addr = (unsigned char *) data + reloc_entry->address;
140:
141: switch (howto->size)
142: {
143: case 0:
144: {
145: char x = bfd_get_8 (abfd, addr);
146: DOIT (x);
147: bfd_put_8 (abfd, x, addr);
148: }
149: break;
150:
151: case 1:
152: {
153: short x = bfd_get_16 (abfd, addr);
154: DOIT (x);
155: bfd_put_16 (abfd, (bfd_vma) x, addr);
156: }
157: break;
158:
159: case 2:
160: {
161: long x = bfd_get_32 (abfd, addr);
162: DOIT (x);
163: bfd_put_32 (abfd, (bfd_vma) x, addr);
164: }
165: break;
166: case 4:
167: {
168: long long x = bfd_get_64 (abfd, addr);
169: DOIT (x);
170: bfd_put_64 (abfd, (bfd_vma) x, addr);
171: }
172: break;
173:
174: default:
175: abort ();
176: }
177: }
178:
179:
180: return bfd_reloc_continue;
181: }
182:
183: #if defined(COFF_WITH_PE)
184:
185:
186:
187: static bfd_boolean
188: in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto)
189: {
190: return ! howto->pc_relative && howto->type != R_AMD64_IMAGEBASE;
191: }
192: #endif
193:
194: #ifndef PCRELOFFSET
195: #define PCRELOFFSET TRUE
196: #endif
197:
198: static reloc_howto_type howto_table[] =
199: {
200: EMPTY_HOWTO (0),
201: HOWTO (R_AMD64_DIR64,
202: 0,
203: 4,
204: 64,
205: FALSE,
206: 0,
207: complain_overflow_bitfield,
208: coff_amd64_reloc,
209: "R_X86_64_64",
210: TRUE,
211: 0xffffffffffffffffll,
212: 0xffffffffffffffffll,
213: TRUE),
214: HOWTO (R_AMD64_DIR32,
215: 0,
216: 2,
217: 32,
218: FALSE,
219: 0,
220: complain_overflow_bitfield,
221: coff_amd64_reloc,
222: "R_X86_64_32",
223: TRUE,
224: 0xffffffff,
225: 0xffffffff,
226: TRUE),
227:
228: HOWTO (R_AMD64_IMAGEBASE,
229: 0,
230: 2,
231: 32,
232: FALSE,
233: 0,
234: complain_overflow_bitfield,
235: coff_amd64_reloc,
236: "rva32",
237: TRUE,
238: 0xffffffff,
239: 0xffffffff,
240: FALSE),
241:
242: HOWTO (R_AMD64_PCRLONG,
243: 0,
244: 2,
245: 32,
246: TRUE,
247: 0,
248: complain_overflow_signed,
249: coff_amd64_reloc,
250: "R_X86_64_PC32",
251: TRUE,
252: 0xffffffff,
253: 0xffffffff,
254: PCRELOFFSET),
255:
256: HOWTO (R_AMD64_PCRLONG_1,
257: 0,
258: 2,
259: 32,
260: TRUE,
261: 0,
262: complain_overflow_signed,
263: coff_amd64_reloc,
264: "DISP32+1",
265: TRUE,
266: 0xffffffff,
267: 0xffffffff,
268: PCRELOFFSET),
269: HOWTO (R_AMD64_PCRLONG_2,
270: 0,
271: 2,
272: 32,
273: TRUE,
274: 0,
275: complain_overflow_signed,
276: coff_amd64_reloc,
277: "DISP32+2",
278: TRUE,
279: 0xffffffff,
280: 0xffffffff,
281: PCRELOFFSET),
282: HOWTO (R_AMD64_PCRLONG_3,
283: 0,
284: 2,
285: 32,
286: TRUE,
287: 0,
288: complain_overflow_signed,
289: coff_amd64_reloc,
290: "DISP32+3",
291: TRUE,
292: 0xffffffff,
293: 0xffffffff,
294: PCRELOFFSET),
295: HOWTO (R_AMD64_PCRLONG_4,
296: 0,
297: 2,
298: 32,
299: TRUE,
300: 0,
301: complain_overflow_signed,
302: coff_amd64_reloc,
303: "DISP32+4",
304: TRUE,
305: 0xffffffff,
306: 0xffffffff,
307: PCRELOFFSET),
308: HOWTO (R_AMD64_PCRLONG_5,
309: 0,
310: 2,
311: 32,
312: TRUE,
313: 0,
314: complain_overflow_signed,
315: coff_amd64_reloc,
316: "DISP32+5",
317: TRUE,
318: 0xffffffff,
319: 0xffffffff,
320: PCRELOFFSET),
321: EMPTY_HOWTO (10),
322: #if defined(COFF_WITH_PE)
323:
324: HOWTO (R_AMD64_SECREL,
325: 0,
326: 2,
327: 32,
328: FALSE,
329: 0,
330: complain_overflow_bitfield,
331: coff_amd64_reloc,
332: "secrel32",
333: TRUE,
334: 0xffffffff,
335: 0xffffffff,
336: TRUE),
337: #else
338: EMPTY_HOWTO (11),
339: #endif
340: EMPTY_HOWTO (12),
341: EMPTY_HOWTO (13),
342: #ifndef DONT_EXTEND_AMD64
343: HOWTO (R_AMD64_PCRQUAD,
344: 0,
345: 4,
346: 64,
347: TRUE,
348: 0,
349: complain_overflow_signed,
350: coff_amd64_reloc,
351: "R_X86_64_PC64",
352: TRUE,
353: 0xffffffffffffffffll,
354: 0xffffffffffffffffll,
355: PCRELOFFSET),
356: #else
357: EMPTY_HOWTO (14),
358: #endif
359:
360: HOWTO (R_RELBYTE,
361: 0,
362: 0,
363: 8,
364: FALSE,
365: 0,
366: complain_overflow_bitfield,
367: coff_amd64_reloc,
368: "R_X86_64_8",
369: TRUE,
370: 0x000000ff,
371: 0x000000ff,
372: PCRELOFFSET),
373:
374: HOWTO (R_RELWORD,
375: 0,
376: 1,
377: 16,
378: FALSE,
379: 0,
380: complain_overflow_bitfield,
381: coff_amd64_reloc,
382: "R_X86_64_16",
383: TRUE,
384: 0x0000ffff,
385: 0x0000ffff,
386: PCRELOFFSET),
387:
388: HOWTO (R_RELLONG,
389: 0,
390: 2,
391: 32,
392: FALSE,
393: 0,
394: complain_overflow_bitfield,
395: coff_amd64_reloc,
396: "R_X86_64_32S",
397: TRUE,
398: 0xffffffff,
399: 0xffffffff,
400: PCRELOFFSET),
401:
402: HOWTO (R_PCRBYTE,
403: 0,
404: 0,
405: 8,
406: TRUE,
407: 0,
408: complain_overflow_signed,
409: coff_amd64_reloc,
410: "R_X86_64_PC8",
411: TRUE,
412: 0x000000ff,
413: 0x000000ff,
414: PCRELOFFSET),
415:
416: HOWTO (R_PCRWORD,
417: 0,
418: 1,
419: 16,
420: TRUE,
421: 0,
422: complain_overflow_signed,
423: coff_amd64_reloc,
424: "R_X86_64_PC16",
425: TRUE,
426: 0x0000ffff,
427: 0x0000ffff,
428: PCRELOFFSET),
429:
430: HOWTO (R_PCRLONG,
431: 0,
432: 2,
433: 32,
434: TRUE,
435: 0,
436: complain_overflow_signed,
437: coff_amd64_reloc,
438: "R_X86_64_PC32",
439: TRUE,
440: 0xffffffff,
441: 0xffffffff,
442: PCRELOFFSET)
443: };
444:
445:
446:
447: #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
448: #define I386 1
449: #define AMD64 1
450:
451: #define RTYPE2HOWTO(cache_ptr, dst) \
452: ((cache_ptr)->howto = \
453: ((dst)->r_type < ARRAY_SIZE (howto_table)) \
454: ? howto_table + (dst)->r_type \
455: : NULL)
456:
457:
458:
459:
460: #define BSS_NOLOAD_IS_SHARED_LIBRARY
461:
462:
463:
464:
465:
466:
467:
468:
469:
470:
471:
472:
473:
474:
475: #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
476: { \
477: coff_symbol_type *coffsym = NULL; \
478: \
479: if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
480: coffsym = (obj_symbols (abfd) \
481: + (cache_ptr->sym_ptr_ptr - symbols)); \
482: else if (ptr) \
483: coffsym = coff_symbol_from (abfd, ptr); \
484: \
485: if (coffsym != NULL \
486: && coffsym->native->u.syment.n_scnum == 0) \
487: cache_ptr->addend = - coffsym->native->u.syment.n_value; \
488: else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
489: && ptr->section != NULL) \
490: cache_ptr->addend = - (ptr->section->vma + ptr->value); \
491: else \
492: cache_ptr->addend = 0; \
493: if (ptr && howto_table[reloc.r_type].pc_relative) \
494: cache_ptr->addend += asect->vma; \
495: }
496:
497:
498:
499:
500:
501: #if !defined(COFF_WITH_PE)
502:
503: #define coff_relocate_section _bfd_coff_generic_relocate_section
504:
505: #else
506:
507:
508:
509:
510:
511: static bfd_boolean
512: coff_pe_amd64_relocate_section (bfd *output_bfd,
513: struct bfd_link_info *info,
514: bfd *input_bfd,
515: asection *input_section,
516: bfd_byte *contents,
517: struct internal_reloc *relocs,
518: struct internal_syment *syms,
519: asection **sections)
520: {
521: if (info->relocatable)
522: return TRUE;
523:
524: return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
525: }
526:
527: #define coff_relocate_section coff_pe_amd64_relocate_section
528:
529: #endif
530:
531:
532:
533: static reloc_howto_type *
534: coff_amd64_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
535: asection *sec,
536: struct internal_reloc *rel,
537: struct coff_link_hash_entry *h,
538: struct internal_syment *sym,
539: bfd_vma *addendp)
540: {
541: reloc_howto_type *howto;
542:
543: if (rel->r_type > ARRAY_SIZE (howto_table))
544: {
545: bfd_set_error (bfd_error_bad_value);