diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index 8651f49..bd57ab7 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -641,7 +641,22 @@ static reloc_howto_type elf_avr_howto_table[] = FALSE, /* partial_inplace */ 0xffffff, /* src_mask */ 0xffffff, /* dst_mask */ - FALSE) /* pcrel_offset */ + FALSE), /* pcrel_offset */ + + /* A 32 bit PC relative relocation. */ + HOWTO (R_AVR_32_PCREL, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_32_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ }; /* Map BFD reloc types to AVR ELF reloc types. */ @@ -689,7 +704,8 @@ static const struct avr_reloc_map avr_reloc_map[] = { BFD_RELOC_AVR_DIFF32, R_AVR_DIFF32 }, { BFD_RELOC_AVR_LDS_STS_16, R_AVR_LDS_STS_16}, { BFD_RELOC_AVR_PORT6, R_AVR_PORT6}, - { BFD_RELOC_AVR_PORT5, R_AVR_PORT5} + { BFD_RELOC_AVR_PORT5, R_AVR_PORT5}, + { BFD_RELOC_32_PCREL, R_AVR_32_PCREL} }; /* Meant to be filled one day with the wrap around address for the diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c index 5c8982c..c69a91c 100644 --- a/gas/config/tc-avr.c +++ b/gas/config/tc-avr.c @@ -1618,6 +1618,7 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) { arelent *reloc; + bfd_reloc_code_real_type code = fixp->fx_r_type; if (fixp->fx_subsy != NULL) { @@ -1631,7 +1632,21 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; - reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); + + if ((fixp->fx_r_type == BFD_RELOC_32) && (fixp->fx_pcrel)) + { + if (seg->use_rela_p) + fixp->fx_offset -= md_pcrel_from_section (fixp, seg); + else + fixp->fx_offset = reloc->address; + + code = BFD_RELOC_32_PCREL; + } + + reloc->addend = fixp->fx_offset; + + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + if (reloc->howto == (reloc_howto_type *) NULL) { as_bad_where (fixp->fx_file, fixp->fx_line, @@ -1644,7 +1659,6 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) reloc->address = fixp->fx_offset; - reloc->addend = fixp->fx_offset; return reloc; } diff --git a/gas/config/tc-avr.h b/gas/config/tc-avr.h index 21471c8..5501ef0 100644 --- a/gas/config/tc-avr.h +++ b/gas/config/tc-avr.h @@ -45,6 +45,8 @@ nonstandard escape sequences in a string. */ #define ONLY_STANDARD_ESCAPES +#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */ + /* GAS will call this function for any expression that can not be recognized. When the function is called, `input_line_pointer' will point to the start of the expression. */ diff --git a/gas/testsuite/gas/avr/pc-relative-reloc.d b/gas/testsuite/gas/avr/pc-relative-reloc.d new file mode 100644 index 0000000..cc22b0b --- /dev/null +++ b/gas/testsuite/gas/avr/pc-relative-reloc.d @@ -0,0 +1,19 @@ +#name: 32 bit PC relative reloc +#as: -mmcu=avr51 -gdwarf-sections -g +#objdump: -r +#source: per-function-debugline.s +#target: avr-*-* + +.*: file format elf32-avr + +RELOCATION RECORDS FOR \[.text.main\]: +#... + + +RELOCATION RECORDS FOR \[.debug_line\]: +OFFSET TYPE VALUE +00000000 R_AVR_32_PCREL .debug_line_end-0x00000004 + + +RELOCATION RECORDS FOR \[.debug_line.text.main\]: +#... diff --git a/gas/testsuite/gas/avr/per-function-debugline.s b/gas/testsuite/gas/avr/per-function-debugline.s new file mode 100644 index 0000000..4db56e5 --- /dev/null +++ b/gas/testsuite/gas/avr/per-function-debugline.s @@ -0,0 +1,35 @@ + .file "per-function-debugline.s" +__SP_H__ = 0x3e +__SP_L__ = 0x3d +__SREG__ = 0x3f +__RAMPZ__ = 0x3b +__tmp_reg__ = 0 +__zero_reg__ = 1 + .comm g,2,1 + .section .text.main,"ax",@progbits +.global main + .type main, @function +main: + push r28 + push r29 + in r28,__SP_L__ + in r29,__SP_H__ +/* prologue: function */ +/* frame size = 0 */ +/* stack size = 2 */ +.L__stack_usage = 2 + call foo + lds r24,g + lds r25,g+1 + sbiw r24,1 + sts g+1,r25 + sts g,r24 + lds r24,g + lds r25,g+1 +/* epilogue start */ + pop r29 + pop r28 + ret + .size main, .-main + .ident "GCC: (GNU) 6.0.0 20150630 (experimental)" +.global __do_clear_bss diff --git a/include/elf/avr.h b/include/elf/avr.h index 115296d..f0ef479 100644 --- a/include/elf/avr.h +++ b/include/elf/avr.h @@ -87,6 +87,7 @@ START_RELOC_NUMBERS (elf_avr_reloc_type) RELOC_NUMBER (R_AVR_LDS_STS_16, 33) RELOC_NUMBER (R_AVR_PORT6, 34) RELOC_NUMBER (R_AVR_PORT5, 35) + RELOC_NUMBER (R_AVR_32_PCREL, 36) END_RELOC_NUMBERS (R_AVR_max) #endif /* _ELF_AVR_H */ diff --git a/ld/testsuite/ld-avr/gc-section-debugline.d b/ld/testsuite/ld-avr/gc-section-debugline.d new file mode 100644 index 0000000..e98ff6c --- /dev/null +++ b/ld/testsuite/ld-avr/gc-section-debugline.d @@ -0,0 +1,70 @@ +#name: dwarf decoded line after gc-sections +#as: -mmcu=avr51 -gdwarf-sections -g +#ld: -mavr51 -gc-sections -u main +#objdump: --dwarf=decodedline +#source: per-function-debugline.s +#target: avr-*-* + +.*: file format elf32-avr + +Decoded dump of debug contents of section .debug_line: + +CU: .*: +File name Line number Starting address +per-function-debugline.s 39 0 + +per-function-debugline.s 40 0x2 + +per-function-debugline.s 41 0x4 + +per-function-debugline.s 42 0x6 + +per-function-debugline.s 47 0x8 + +per-function-debugline.s 48 0xc + +per-function-debugline.s 49 0x10 + +per-function-debugline.s 50 0x12 + +per-function-debugline.s 51 0x16 + +per-function-debugline.s 52 0x1a + +per-function-debugline.s 54 0x1c + +per-function-debugline.s 55 0x1e + +per-function-debugline.s 56 0x20 + +per-function-debugline.s 62 0x22 + +per-function-debugline.s 63 0x24 + +per-function-debugline.s 64 0x26 + +per-function-debugline.s 65 0x28 + +per-function-debugline.s 70 0x2a + +per-function-debugline.s 71 0x2e + +per-function-debugline.s 72 0x32 + +per-function-debugline.s 73 0x36 + +per-function-debugline.s 74 0x38 + +per-function-debugline.s 75 0x3c + +per-function-debugline.s 76 0x40 + +per-function-debugline.s 77 0x44 + +per-function-debugline.s 79 0x48 + +per-function-debugline.s 80 0x4a + +per-function-debugline.s 81 0x4c + + diff --git a/ld/testsuite/ld-avr/per-function-debugline.s b/ld/testsuite/ld-avr/per-function-debugline.s new file mode 100644 index 0000000..361cb00 --- /dev/null +++ b/ld/testsuite/ld-avr/per-function-debugline.s @@ -0,0 +1,84 @@ + .file "per-function-debugline.s" +__SP_H__ = 0x3e +__SP_L__ = 0x3d +__SREG__ = 0x3f +__RAMPZ__ = 0x3b +__tmp_reg__ = 0 +__zero_reg__ = 1 + .comm g,2,1 + .section .text.bar,"ax",@progbits +.global bar + .type bar, @function +bar: + push r28 + push r29 + rcall . + in r28,__SP_L__ + in r29,__SP_H__ +/* prologue: function */ +/* frame size = 2 */ +/* stack size = 4 */ +.L__stack_usage = 4 + ldd r24,Y+1 + ldd r25,Y+2 + adiw r24,1 + std Y+2,r25 + std Y+1,r24 + nop +/* epilogue start */ + pop __tmp_reg__ + pop __tmp_reg__ + pop r29 + pop r28 + ret + .size bar, .-bar + .section .text.foo,"ax",@progbits +.global foo + .type foo, @function +foo: + push r28 + push r29 + in r28,__SP_L__ + in r29,__SP_H__ +/* prologue: function */ +/* frame size = 0 */ +/* stack size = 2 */ +.L__stack_usage = 2 + lds r24,g + lds r25,g+1 + adiw r24,1 + sts g+1,r25 + sts g,r24 + nop +/* epilogue start */ + pop r29 + pop r28 + ret + .size foo, .-foo + .section .text.main,"ax",@progbits +.global main + .type main, @function +main: + push r28 + push r29 + in r28,__SP_L__ + in r29,__SP_H__ +/* prologue: function */ +/* frame size = 0 */ +/* stack size = 2 */ +.L__stack_usage = 2 + call foo + lds r24,g + lds r25,g+1 + sbiw r24,1 + sts g+1,r25 + sts g,r24 + lds r24,g + lds r25,g+1 +/* epilogue start */ + pop r29 + pop r28 + ret + .size main, .-main + .ident "GCC: (GNU) 6.0.0 20150630 (experimental)" +.global __do_clear_bss