[PATCH v3] gas: support for .previous, .pushsection and .popsection pseudo ops for coff
Johannes Khoshnazar-Thoma <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
This patch adds support for the .previous, .pushsection and .popsection pseudo-ops for COFF targets. The semantics are the same as their ELF counterparts. This patch is one building block for compiling the Linux kernel as a Windows/ReactOS driver. Signed-off-by: Johannes Khoshnazar-Thoma <[email protected]> --- gas/NEWS | 6 ++ gas/config/obj-coff.c | 100 ++++++++++++++++++++++++- gas/config/obj-coff.h | 2 + gas/config/tc-ppc.c | 4 + gas/config/tc-tic4x.c | 3 + gas/doc/as.texi | 11 ++- gas/read.c | 3 + gas/testsuite/gas/coff/coff.exp | 3 + gas/testsuite/gas/coff/previous.d | 9 +++ gas/testsuite/gas/coff/previous.s | 8 ++ gas/testsuite/gas/coff/pushpop.d | 9 +++ gas/testsuite/gas/coff/pushpop.s | 6 ++ gas/testsuite/gas/ppc/aix.exp | 2 + gas/testsuite/gas/ppc/xcoff-previous.d | 9 +++ gas/testsuite/gas/ppc/xcoff-previous.s | 10 +++ 15 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 gas/testsuite/gas/coff/previous.d create mode 100644 gas/testsuite/gas/coff/previous.s create mode 100644 gas/testsuite/gas/coff/pushpop.d create mode 100644 gas/testsuite/gas/coff/pushpop.s create mode 100644 gas/testsuite/gas/ppc/xcoff-previous.d create mode 100644 gas/testsuite/gas/ppc/xcoff-previous.s diff --git a/gas/NEWS b/gas/NEWS index 165e23361bb..9d59a989f9f 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -1,5 +1,11 @@ -*- text -*- +Changes in 2.48: + +* Support for .previous, .pushsection and .popsection for COFF targets. + The semantics are the same as for ELF targets. This allows one to + compile the Linux kernel as a Windows/ReactOS driver. + Changes in 2.47: * New command line option --reloc-section-sym=[all|internal|none] diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c index 7732c0af911..21e2f6c2bf8 100644 --- a/gas/config/obj-coff.c +++ b/gas/config/obj-coff.c @@ -160,7 +160,10 @@ static void obj_coff_bss (int ignore ATTRIBUTE_UNUSED) { if (*input_line_pointer == '\n') - subseg_new (".bss", get_absolute_expression ()); + { + obj_coff_section_change_hook (); + subseg_new (".bss", get_absolute_expression ()); + } else s_lcomm (0); } @@ -1536,6 +1539,69 @@ obj_coff_finalize_section_relocs (asection *sec, arelent **relocs, return true; } +static segT previous_section; +static subsegT previous_subsection; + +/* This can be called from the processor backends if they change + sections. */ + +void +obj_coff_section_change_hook (void) +{ + previous_section = now_seg; + previous_subsection = now_subseg; +} + +void +obj_coff_previous (int ignore ATTRIBUTE_UNUSED) +{ + segT new_section; + subsegT new_subsection; + + if (previous_section == 0) + { + as_warn (_(".previous without corresponding .section; ignored")); + return; + } + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + new_section = previous_section; + new_subsection = previous_subsection; + obj_coff_section_change_hook (); + + subseg_set (new_section, new_subsection); +} + +struct section_stack +{ + struct section_stack *next; + segT seg, prev_seg; + subsegT subseg, prev_subseg; +}; + +static struct section_stack *section_stack; + +static void +obj_coff_popsection (int ignore ATTRIBUTE_UNUSED) +{ + struct section_stack *top = section_stack; + + if (top == NULL) + { + as_warn (_(".popsection without corresponding .pushsection; ignored")); + return; + } + + section_stack = top->next; + previous_section = top->prev_seg; + previous_subsection = top->prev_subseg; + subseg_set (top->seg, top->subseg); + free (top); +} + /* Implement the .section pseudo op: .section name {, "flags"} ^ ^ @@ -1559,7 +1625,7 @@ obj_coff_finalize_section_relocs (asection *sec, arelent **relocs, .section directive to be parsed in both ELF and COFF formats. */ void -obj_coff_section (int ignore ATTRIBUTE_UNUSED) +obj_coff_section (int push) { /* Strip out the section name. */ char *section_name; @@ -1691,6 +1757,18 @@ obj_coff_section (int ignore ATTRIBUTE_UNUSED) } } + if (push) + { + struct section_stack *elt = XNEW (struct section_stack); + elt->next = section_stack; + elt->seg = now_seg; + elt->prev_seg = previous_section; + elt->subseg = now_subseg; + elt->prev_subseg = previous_subsection; + section_stack = elt; + } + + obj_coff_section_change_hook (); sec = subseg_new (name, exp); if (is_bss) @@ -1898,6 +1976,9 @@ static const pseudo_typeS coff_pseudo_table[] = {"ident", obj_coff_ident, 0}, {"line", obj_coff_line, 0}, {"ln", obj_coff_ln, 0}, + {"popsection", obj_coff_popsection, 0}, + {"previous", obj_coff_previous, 0}, + {"pushsection", obj_coff_section, 1}, {"scl", obj_coff_scl, 0}, {"sect", obj_coff_section, 0}, {"sect.s", obj_coff_section, 0}, @@ -1937,13 +2018,26 @@ coff_separate_stab_sections (void) return 1; } +void +coff_end (void) +{ + if (!ENABLE_LEAK_CHECK) + return; + while (section_stack) + { + struct section_stack *top = section_stack; + section_stack = top->next; + free (top); + } +} + const struct format_ops coff_format_ops = { bfd_target_coff_flavour, 0, /* dfl_leading_underscore */ 1, /* emit_section_symbols */ 0, /* begin */ - 0, /* end. */ + coff_end, /* end. */ c_dot_file_symbol, coff_assign_symbol, coff_frob_symbol, diff --git a/gas/config/obj-coff.h b/gas/config/obj-coff.h index 0b933f467b2..052c580ffe1 100644 --- a/gas/config/obj-coff.h +++ b/gas/config/obj-coff.h @@ -318,7 +318,9 @@ extern void coff_obj_read_begin_hook (void); extern void pecoff_obj_set_weak_hook (symbolS *); extern void pecoff_obj_clear_weak_hook (symbolS *); #endif +extern void obj_coff_section_change_hook (void); extern void obj_coff_section (int); +extern void obj_coff_previous (int); extern segT obj_coff_add_segment (const char *); extern void obj_coff_def (int); extern segT s_get_segment (symbolS *); diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index b82ba2eaebd..c0382635cf4 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -4529,6 +4529,8 @@ ppc_csect (int ignore ATTRIBUTE_UNUSED) static void ppc_change_csect (symbolS *sym, offsetT align) { + obj_coff_section_change_hook (); + if (S_IS_DEFINED (sym)) subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg); else @@ -4652,6 +4654,7 @@ ppc_change_debug_section (unsigned int idx, subsegT subseg) flagword oldflags; const struct xcoff_dwsect_name *dw = &xcoff_dwsect_names[idx]; + obj_coff_section_change_hook (); sec = subseg_new (dw->xcoff_name, subseg); oldflags = bfd_section_flags (sec); if (oldflags == SEC_NO_FLAGS) @@ -5650,6 +5653,7 @@ ppc_ec (int ignore ATTRIBUTE_UNUSED) static void ppc_toc (int ignore ATTRIBUTE_UNUSED) { + obj_coff_section_change_hook (); if (ppc_toc_csect != NULL) subseg_set (data_section, symbol_get_tc (ppc_toc_csect)->subseg); else diff --git a/gas/config/tc-tic4x.c b/gas/config/tc-tic4x.c index a6f8d7a203b..7a27c06dc93 100644 --- a/gas/config/tc-tic4x.c +++ b/gas/config/tc-tic4x.c @@ -988,6 +988,9 @@ tic4x_sect (int x ATTRIBUTE_UNUSED) else num = 0; +#ifdef OBJ_COFF + obj_coff_section_change_hook (); +#endif seg = subseg_new (name, num); if (line_label != NULL) { diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 5d7772d62d3..6beb30a0171 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -6700,7 +6700,7 @@ undefined. This is one of the ELF section stack manipulation directives. The others are @code{.section} (@pxref{Section}), @code{.subsection} (@pxref{SubSection}), @code{.pushsection} (@pxref{PushSection}), and @code{.previous} -(@pxref{Previous}). +(@pxref{Previous}). It is also implemented on COFF targets. This directive replaces the current section (and subsection) with the top section (and subsection) on the section stack. This section is popped off the @@ -6716,7 +6716,7 @@ stack. This is one of the ELF section stack manipulation directives. The others are @code{.section} (@pxref{Section}), @code{.subsection} (@pxref{SubSection}), @code{.pushsection} (@pxref{PushSection}), and @code{.popsection} -(@pxref{PopSection}). +(@pxref{PopSection}). It is also implemented on COFF targets. This directive swaps the current section (and subsection) with most recently referenced section/subsection pair prior to this one. Multiple @@ -6820,7 +6820,7 @@ expanded. @xref{Macro}. This is one of the ELF section stack manipulation directives. The others are @code{.section} (@pxref{Section}), @code{.subsection} (@pxref{SubSection}), @code{.popsection} (@pxref{PopSection}), and @code{.previous} -(@pxref{Previous}). +(@pxref{Previous}). It is also implemented on COFF targets. This directive pushes the current section (and subsection) onto the top of the section stack, and then replaces the current section and @@ -6996,6 +6996,11 @@ will be as if no flags had been specified at all. If the optional argument to the @code{.section} directive is not quoted, it is taken as a subsection number (@pxref{Sub-Sections}). + +For COFF targets, the @code{.pushsection} (@pxref{PushSection}), +@code{.popsection} (@pxref{PopSection}), and @code{.previous} +(@pxref{Previous}) directives are also implemented. + @end ifset @ifset ELF diff --git a/gas/read.c b/gas/read.c index ae481007c32..76c8fa84d53 100644 --- a/gas/read.c +++ b/gas/read.c @@ -3952,6 +3952,9 @@ s_struct (int ignore ATTRIBUTE_UNUSED) that .previous works correctly. */ if (IS_ELF) obj_elf_section_change_hook (); +#endif +#if defined (OBJ_COFF) + obj_coff_section_change_hook (); #endif subseg_set (absolute_section, 0); demand_empty_rest_of_line (); diff --git a/gas/testsuite/gas/coff/coff.exp b/gas/testsuite/gas/coff/coff.exp index 3732a226e3b..323c59c21ce 100644 --- a/gas/testsuite/gas/coff/coff.exp +++ b/gas/testsuite/gas/coff/coff.exp @@ -38,3 +38,6 @@ if { ![istarget *c4x*-*-*] && ![istarget *c54x*-*-*] } { run_dump_test func3 run_dump_test func4 } + +run_dump_test pushpop +run_dump_test previous diff --git a/gas/testsuite/gas/coff/previous.d b/gas/testsuite/gas/coff/previous.d new file mode 100644 index 00000000000..495fb245cab --- /dev/null +++ b/gas/testsuite/gas/coff/previous.d @@ -0,0 +1,9 @@ +#objdump: -s +#name: .previous support + +.*: file format .* + +Contents of section a: + 0000.*01[0 ]*03.* +Contents of section b: + 0000.*02[0 ]*04.* diff --git a/gas/testsuite/gas/coff/previous.s b/gas/testsuite/gas/coff/previous.s new file mode 100644 index 00000000000..aea07428368 --- /dev/null +++ b/gas/testsuite/gas/coff/previous.s @@ -0,0 +1,8 @@ + .section a + .byte 1 + .section b + .byte 2 + .previous + .byte 3 + .previous + .byte 4 diff --git a/gas/testsuite/gas/coff/pushpop.d b/gas/testsuite/gas/coff/pushpop.d new file mode 100644 index 00000000000..7d3ce21a273 --- /dev/null +++ b/gas/testsuite/gas/coff/pushpop.d @@ -0,0 +1,9 @@ +#objdump: -s +#name: .pushsection and .popsection support + +.*: file format .* + +Contents of section a: + 0000.*01[0 ]*03.* +Contents of section b: + 0000.*02.* diff --git a/gas/testsuite/gas/coff/pushpop.s b/gas/testsuite/gas/coff/pushpop.s new file mode 100644 index 00000000000..ec05bade0dc --- /dev/null +++ b/gas/testsuite/gas/coff/pushpop.s @@ -0,0 +1,6 @@ + .section a + .byte 1 + .pushsection b + .byte 2 + .popsection + .byte 3 diff --git a/gas/testsuite/gas/ppc/aix.exp b/gas/testsuite/gas/ppc/aix.exp index 613c71b81ff..6f195289220 100644 --- a/gas/testsuite/gas/ppc/aix.exp +++ b/gas/testsuite/gas/ppc/aix.exp @@ -79,6 +79,8 @@ if { [istarget "powerpc*-*-aix*"] || [istarget "rs6000-*-aix*"] } then { run_dump_test "xcoff-function-1-32" run_dump_test "xcoff-function-1-64" + run_dump_test "xcoff-previous" + run_dump_test "xcoff-tls-32" run_dump_test "xcoff-tls-64" diff --git a/gas/testsuite/gas/ppc/xcoff-previous.d b/gas/testsuite/gas/ppc/xcoff-previous.d new file mode 100644 index 00000000000..838475b0b8a --- /dev/null +++ b/gas/testsuite/gas/ppc/xcoff-previous.d @@ -0,0 +1,9 @@ +#objdump: -s +#name: .previous support for xcoff + +.*: file format .* + +Contents of section .text: + 0000.*01[0 ]*03.* +Contents of section .data: + 0008.*02[0 ]*04.* diff --git a/gas/testsuite/gas/ppc/xcoff-previous.s b/gas/testsuite/gas/ppc/xcoff-previous.s new file mode 100644 index 00000000000..f57ded56e84 --- /dev/null +++ b/gas/testsuite/gas/ppc/xcoff-previous.s @@ -0,0 +1,10 @@ + .globl .a + .globl .b + .section .text + .byte 1 + .section .data + .byte 2 + .previous + .byte 3 + .previous + .byte 4 -- 2.55.0