From 54cfded08ec4835361d381d602fe3f845a45c118 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 20 May 2003 07:58:07 +0000 Subject: [PATCH] * dw2gencfi.c, dw2gencfi.h: New files. * config/tc-i386.c (tc_x86_cfi_init): New function. * config/tc-i386.h (TARGET_USE_CFIPOP, tc_cfi_init): New defines. * as.c (parse_args): Set verbose flag on --verbose. (main): Call tc_cfi_init()/cfi_finish(). * as.h (verbose): New external variable. * read.c (pobegin): Insert CFI pops to the list. * symbols.c (local_symbol_make): Make symbol external. * symbols.h (local_symbol_make): New prototype. * Makefile.am: Add dw2gencfi.[ch] files. Run "make dep-am". * Makefile.in: Regenerate. * doc/as.texinfo: Added node "CFI directives" with description of all implemented .cfi_* directives. * doc/Makefile.in: Regenerate. * po/POTFILES.in: Regenerate. --- gas/ChangeLog | 100 +++--- gas/Makefile.am | 30 +- gas/Makefile.in | 50 +-- gas/as.c | 13 + gas/as.h | 3 + gas/config/tc-i386.c | 83 +++++ gas/config/tc-i386.h | 15 + gas/doc/Makefile.in | 4 +- gas/doc/as.texinfo | 52 ++++ gas/dw2gencfi.c | 721 +++++++++++++++++++++++++++++++++++++++++++ gas/dw2gencfi.h | 100 ++++++ gas/po/POTFILES.in | 5 + gas/read.c | 11 + gas/symbols.c | 4 +- gas/symbols.h | 2 + 15 files changed, 1113 insertions(+), 80 deletions(-) create mode 100644 gas/dw2gencfi.c create mode 100644 gas/dw2gencfi.h diff --git a/gas/ChangeLog b/gas/ChangeLog index a15d38133ac..e4293522cf8 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,6 +1,25 @@ +2003-05-20 Michal Ludvig + + * dw2gencfi.c, dw2gencfi.h: New files. + * config/tc-i386.c (tc_x86_cfi_init): New function. + * config/tc-i386.h (TARGET_USE_CFIPOP, tc_cfi_init): New defines. + * as.c (parse_args): Set verbose flag on --verbose. + (main): Call tc_cfi_init()/cfi_finish(). + * as.h (verbose): New external variable. + * read.c (pobegin): Insert CFI pops to the list. + * symbols.c (local_symbol_make): Make symbol external. + * symbols.h (local_symbol_make): New prototype. + * Makefile.am: Add dw2gencfi.[ch] files. Run "make dep-am". + * Makefile.in: Regenerate. + * doc/as.texinfo: Added node "CFI directives" with description of + all implemented .cfi_* directives. + * doc/Makefile.in: Regenerate. + * po/POTFILES.in: Regenerate. + 2003-05-19 Svein E. Seldal - * config/tc-tic4x.c (md_assemble): Added support for one-line parallel insns. + * config/tc-tic4x.c (md_assemble): Added support for one-line parallel + insns. * config/tc-tic4x.h: Added DOUBLEBAR_PARALLEL definition 2003-05-18 Jason Eckhardt @@ -20,7 +39,7 @@ 2003-05-13 Hans-Peter Nilsson * read.c (old_buffer, old_input, old_limit): Remove variables. - (read_a_source_file): Delete label contin. + (read_a_source_file): Delete label contin. : Use an "sb" to push #APP expansion into input as with macros, instead of in separate old_* variables. Zero-terminate string being scrubbed. @@ -113,7 +132,7 @@ 2003-05-02 Michael Snyder - * write.h (FAKE_LABEL_NAME): Allow override + * write.h (FAKE_LABEL_NAME): Allow override (for targets that like eg. a leading dot in a local label). 2003-05-02 Nick Clifton @@ -150,7 +169,7 @@ 2003-05-01 Christian Groessler * expr.h: Fix comments in operatorT typedef. - * config/tc-z8k.c: Add 2003 to copyright message. + * config/tc-z8k.c: Add 2003 to copyright message. Fold s_segm() and s_unseg() into one function s_segm(parm) which decides by the parameter. (md_begin): Don't set linkrelax. Only set Z8002 default if no @@ -282,8 +301,8 @@ 2003-04-21 Richard Henderson - * dwarf2dbg.c (get_filenum): Skip as-yet unassigned file numbers. - (out_file_list): Assign non-null filename after generating error. + * dwarf2dbg.c (get_filenum): Skip as-yet unassigned file numbers. + (out_file_list): Assign non-null filename after generating error. 2003-04-18 Jakub Jelinek @@ -418,32 +437,31 @@ 2003-04-01 Bob Wilson - * Makefile.am (CPU_TYPES): Add xtensa. - (TARGET_CPU_CFILES): Add config/tc-xtensa.c. - (TARGET_CPU_HFILES): Add config/tc-xtensa.h. - (xtensa-relax.o): New target. - Run "make dep-am". - * Makefile.in: Regenerate. - * configure.in: Handle xtensa-*-*. Add xtensa-relax.o to - extra_objects for xtensa targets. - * configure: Regenerate. - * write.c (write_object_file): Add new md_post_relax_hook. - * config/tc-xtensa.c: New file. - * config/tc-xtensa.h: Likewise. - * config/xtensa-istack.h: Likewise. - * config/xtensa-relax.c: Likewise. - * config/xtensa-relax.h: Likewise. - * doc/Makefile.am (CPU_DOCS): Add c-xtensa.texi. - * doc/Makefile.in: Regenerate. - * doc/all.texi: Set new XTENSA variable. - * doc/as.texinfo: Set new Xtensa variable. Describe - Xtensa-specific options. Define line comment character for - Xtensa. Add Xtensa processors to list of ELF targets where - alignment is specified in bytes. Add new Xtensa-Dependent node. - Add acknowledgements for those contributing to the Xtensa port. - * doc/internals.texi: Describe new md_post_relax_hook. - * doc/c-xtensa.texi: New file. - + * Makefile.am (CPU_TYPES): Add xtensa. + (TARGET_CPU_CFILES): Add config/tc-xtensa.c. + (TARGET_CPU_HFILES): Add config/tc-xtensa.h. + (xtensa-relax.o): New target. + Run "make dep-am". + * Makefile.in: Regenerate. + * configure.in: Handle xtensa-*-*. Add xtensa-relax.o to + extra_objects for xtensa targets. + * configure: Regenerate. + * write.c (write_object_file): Add new md_post_relax_hook. + * config/tc-xtensa.c: New file. + * config/tc-xtensa.h: Likewise. + * config/xtensa-istack.h: Likewise. + * config/xtensa-relax.c: Likewise. + * config/xtensa-relax.h: Likewise. + * doc/Makefile.am (CPU_DOCS): Add c-xtensa.texi. + * doc/Makefile.in: Regenerate. + * doc/all.texi: Set new XTENSA variable. + * doc/as.texinfo: Set new Xtensa variable. Describe + Xtensa-specific options. Define line comment character for + Xtensa. Add Xtensa processors to list of ELF targets where + alignment is specified in bytes. Add new Xtensa-Dependent node. + Add acknowledgements for those contributing to the Xtensa port. + * doc/internals.texi: Describe new md_post_relax_hook. + * doc/c-xtensa.texi: New file. 2003-04-01 Nick Clifton Richard Earnshaw @@ -457,8 +475,7 @@ 2003-03-26 Eric Christopher - * config/tc-mips.c (nopic_need_relax): Check for - S_IS_EXTERN. + * config/tc-mips.c (nopic_need_relax): Check for S_IS_EXTERN. 2003-03-25 Stan Cox Nick Clifton @@ -763,15 +780,12 @@ 2003-01-23 Nick Clifton - NEWS: Announce sh2e support. - - * Add sh2e support: + * NEWS: Announce sh2e support. + Add sh2e support: 2002-04-02 Alexandre Oliva - - * config/tc-sh.c (md_show_usage): Added sh2e next to - sh3e. - (sh_elf_final_processing): Handle arch_sh2e. + * config/tc-sh.c (md_show_usage): Added sh2e next to sh3e. + (sh_elf_final_processing): Handle arch_sh2e. 2003-01-23 Alan Modra @@ -945,8 +959,8 @@ 2003-01-01 John David Anglin - * config/obj-elf.c (special_sections): Work around HP's incorrect usage - of .init and .fini sections for array initializers and finalizers. + * config/obj-elf.c (special_sections): Work around HP's incorrect usage + of .init and .fini sections for array initializers and finalizers. 2002-12-31 Chris Demetriou diff --git a/gas/Makefile.am b/gas/Makefile.am index 24d7dd2796e..264b7344b22 100644 --- a/gas/Makefile.am +++ b/gas/Makefile.am @@ -176,6 +176,7 @@ GAS_CFILES = \ cond.c \ depend.c \ dwarf2dbg.c \ + dw2gencfi.c \ ecoff.c \ ehopt.c \ expr.c \ @@ -207,6 +208,7 @@ HFILES = \ bit_fix.h \ cgen.h \ dwarf2dbg.h \ + dw2gencfi.h \ ecoff.h \ emul-target.h \ emul.h \ @@ -422,6 +424,7 @@ GENERIC_OBJS = \ cond.o \ depend.o \ dwarf2dbg.o \ + dw2gencfi.o \ ehopt.o \ expr.o \ flonum-konst.o \ @@ -1098,14 +1101,13 @@ DEPTC_frv_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ DEPTC_h8300_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-h8300.h $(INCDIR)/coff/internal.h \ $(INCDIR)/coff/h8300.h $(INCDIR)/coff/external.h $(BFDDIR)/libcoff.h \ - $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h \ - $(INCDIR)/safe-ctype.h dwarf2dbg.h + $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h dwarf2dbg.h \ + $(INCDIR)/opcode/h8300.h $(INCDIR)/safe-ctype.h DEPTC_h8300_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h \ - subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h \ - $(INCDIR)/safe-ctype.h $(INCDIR)/elf/h8.h $(INCDIR)/elf/reloc-macros.h \ - dwarf2dbg.h + subsegs.h $(INCDIR)/obstack.h dwarf2dbg.h $(INCDIR)/opcode/h8300.h \ + $(INCDIR)/safe-ctype.h $(INCDIR)/elf/h8.h $(INCDIR)/elf/reloc-macros.h DEPTC_h8500_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-h8500.h $(INCDIR)/coff/internal.h \ $(INCDIR)/coff/h8500.h $(INCDIR)/coff/external.h $(BFDDIR)/libcoff.h \ @@ -1150,17 +1152,18 @@ DEPTC_i370_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ DEPTC_i386_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \ $(srcdir)/config/tc-i386.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \ $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \ - dwarf2dbg.h $(INCDIR)/opcode/i386.h + dwarf2dbg.h dw2gencfi.h $(INCDIR)/elf/dwarf2.h $(INCDIR)/opcode/i386.h DEPTC_i386_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-i386.h $(INCDIR)/coff/internal.h \ $(INCDIR)/coff/i386.h $(INCDIR)/coff/external.h $(BFDDIR)/libcoff.h \ $(INCDIR)/bfdlink.h $(INCDIR)/safe-ctype.h subsegs.h \ - $(INCDIR)/obstack.h dwarf2dbg.h $(INCDIR)/opcode/i386.h + $(INCDIR)/obstack.h dwarf2dbg.h dw2gencfi.h $(INCDIR)/elf/dwarf2.h \ + $(INCDIR)/opcode/i386.h DEPTC_i386_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i386.h \ $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \ - dwarf2dbg.h $(INCDIR)/opcode/i386.h + dwarf2dbg.h dw2gencfi.h $(INCDIR)/elf/dwarf2.h $(INCDIR)/opcode/i386.h DEPTC_i860_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i860.h \ @@ -2403,13 +2406,17 @@ BMKDEP = #DO NOT PUT ANYTHING BETWEEN THIS LINE AND THE MATCHING WARNING ABOVE. #MKDEP DO NOT PUT ANYTHING BETWEEN THIS LINE AND THE MATCHING WARNING BELOW. app.o: app.c $(INCDIR)/symcat.h as.o: as.c $(INCDIR)/symcat.h subsegs.h $(INCDIR)/obstack.h \ - output-file.h sb.h macro.h dwarf2dbg.h $(BFDVER_H) + output-file.h sb.h macro.h dwarf2dbg.h dw2gencfi.h \ + $(INCDIR)/elf/dwarf2.h $(BFDVER_H) atof-generic.o: atof-generic.c $(INCDIR)/symcat.h $(INCDIR)/safe-ctype.h bignum-copy.o: bignum-copy.c $(INCDIR)/symcat.h cond.o: cond.c $(INCDIR)/symcat.h macro.h sb.h $(INCDIR)/obstack.h depend.o: depend.c $(INCDIR)/symcat.h dwarf2dbg.o: dwarf2dbg.c $(INCDIR)/symcat.h dwarf2dbg.h \ - subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h + $(INCDIR)/filenames.h subsegs.h $(INCDIR)/obstack.h \ + $(INCDIR)/elf/dwarf2.h +dw2gencfi.o: dw2gencfi.c $(INCDIR)/symcat.h dw2gencfi.h \ + $(INCDIR)/elf/dwarf2.h ecoff.o: ecoff.c $(INCDIR)/symcat.h ecoff.h ehopt.o: ehopt.c $(INCDIR)/symcat.h subsegs.h $(INCDIR)/obstack.h \ $(INCDIR)/elf/dwarf2.h @@ -2432,7 +2439,8 @@ macro.o: macro.c $(INCDIR)/safe-ctype.h sb.h macro.h messages.o: messages.c $(INCDIR)/symcat.h output-file.o: output-file.c $(INCDIR)/symcat.h output-file.h read.o: read.c $(INCDIR)/symcat.h $(INCDIR)/safe-ctype.h \ - subsegs.h $(INCDIR)/obstack.h sb.h macro.h ecoff.h + subsegs.h $(INCDIR)/obstack.h sb.h macro.h ecoff.h \ + dw2gencfi.h $(INCDIR)/elf/dwarf2.h sb.o: sb.c sb.h stabs.o: stabs.c $(INCDIR)/symcat.h $(INCDIR)/obstack.h \ subsegs.h ecoff.h $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def diff --git a/gas/Makefile.in b/gas/Makefile.in index bb645a52233..de3437de2aa 100644 --- a/gas/Makefile.in +++ b/gas/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation @@ -291,6 +291,7 @@ GAS_CFILES = \ cond.c \ depend.c \ dwarf2dbg.c \ + dw2gencfi.c \ ecoff.c \ ehopt.c \ expr.c \ @@ -323,6 +324,7 @@ HFILES = \ bit_fix.h \ cgen.h \ dwarf2dbg.h \ + dw2gencfi.h \ ecoff.h \ emul-target.h \ emul.h \ @@ -546,6 +548,7 @@ GENERIC_OBJS = \ cond.o \ depend.o \ dwarf2dbg.o \ + dw2gencfi.o \ ehopt.o \ expr.o \ flonum-konst.o \ @@ -824,15 +827,14 @@ DEPTC_frv_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ DEPTC_h8300_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-h8300.h $(INCDIR)/coff/internal.h \ $(INCDIR)/coff/h8300.h $(INCDIR)/coff/external.h $(BFDDIR)/libcoff.h \ - $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h \ - $(INCDIR)/safe-ctype.h dwarf2dbg.h + $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h dwarf2dbg.h \ + $(INCDIR)/opcode/h8300.h $(INCDIR)/safe-ctype.h DEPTC_h8300_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h \ - subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h \ - $(INCDIR)/safe-ctype.h $(INCDIR)/elf/h8.h $(INCDIR)/elf/reloc-macros.h \ - dwarf2dbg.h + subsegs.h $(INCDIR)/obstack.h dwarf2dbg.h $(INCDIR)/opcode/h8300.h \ + $(INCDIR)/safe-ctype.h $(INCDIR)/elf/h8.h $(INCDIR)/elf/reloc-macros.h DEPTC_h8500_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-h8500.h $(INCDIR)/coff/internal.h \ @@ -886,19 +888,20 @@ DEPTC_i370_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ DEPTC_i386_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \ $(srcdir)/config/tc-i386.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \ $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \ - dwarf2dbg.h $(INCDIR)/opcode/i386.h + dwarf2dbg.h dw2gencfi.h $(INCDIR)/elf/dwarf2.h $(INCDIR)/opcode/i386.h DEPTC_i386_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \ $(srcdir)/config/tc-i386.h $(INCDIR)/coff/internal.h \ $(INCDIR)/coff/i386.h $(INCDIR)/coff/external.h $(BFDDIR)/libcoff.h \ $(INCDIR)/bfdlink.h $(INCDIR)/safe-ctype.h subsegs.h \ - $(INCDIR)/obstack.h dwarf2dbg.h $(INCDIR)/opcode/i386.h + $(INCDIR)/obstack.h dwarf2dbg.h dw2gencfi.h $(INCDIR)/elf/dwarf2.h \ + $(INCDIR)/opcode/i386.h DEPTC_i386_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i386.h \ $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \ - dwarf2dbg.h $(INCDIR)/opcode/i386.h + dwarf2dbg.h dw2gencfi.h $(INCDIR)/elf/dwarf2.h $(INCDIR)/opcode/i386.h DEPTC_i860_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ @@ -2469,13 +2472,13 @@ itbl_test_DEPENDENCIES = itbl-tops.o itbl-test.o \ itbl_test_LDFLAGS = as_new_OBJECTS = app.$(OBJEXT) as.$(OBJEXT) atof-generic.$(OBJEXT) \ bignum-copy.$(OBJEXT) cond.$(OBJEXT) depend.$(OBJEXT) \ -dwarf2dbg.$(OBJEXT) ecoff.$(OBJEXT) ehopt.$(OBJEXT) expr.$(OBJEXT) \ -flonum-copy.$(OBJEXT) flonum-konst.$(OBJEXT) flonum-mult.$(OBJEXT) \ -frags.$(OBJEXT) hash.$(OBJEXT) input-file.$(OBJEXT) \ -input-scrub.$(OBJEXT) listing.$(OBJEXT) literal.$(OBJEXT) \ -macro.$(OBJEXT) messages.$(OBJEXT) output-file.$(OBJEXT) read.$(OBJEXT) \ -sb.$(OBJEXT) stabs.$(OBJEXT) subsegs.$(OBJEXT) symbols.$(OBJEXT) \ -write.$(OBJEXT) +dwarf2dbg.$(OBJEXT) dw2gencfi.$(OBJEXT) ecoff.$(OBJEXT) ehopt.$(OBJEXT) \ +expr.$(OBJEXT) flonum-copy.$(OBJEXT) flonum-konst.$(OBJEXT) \ +flonum-mult.$(OBJEXT) frags.$(OBJEXT) hash.$(OBJEXT) \ +input-file.$(OBJEXT) input-scrub.$(OBJEXT) listing.$(OBJEXT) \ +literal.$(OBJEXT) macro.$(OBJEXT) messages.$(OBJEXT) \ +output-file.$(OBJEXT) read.$(OBJEXT) sb.$(OBJEXT) stabs.$(OBJEXT) \ +subsegs.$(OBJEXT) symbols.$(OBJEXT) write.$(OBJEXT) as_new_LDFLAGS = SCRIPTS = $(noinst_SCRIPTS) @@ -2494,7 +2497,7 @@ configure configure.in gdbinit.in itbl-lex.c itbl-parse.c DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = gtar +TAR = tar GZIP_ENV = --best SOURCES = $(itbl_test_SOURCES) $(as_new_SOURCES) $(EXTRA_as_new_SOURCES) OBJECTS = $(itbl_test_OBJECTS) $(as_new_OBJECTS) @@ -2830,7 +2833,7 @@ distclean-generic: -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: - -test -z "itbl-lexlconfig/m68k-parsehconfig/m68k-parsecitbl-parsehitbl-parsec" || rm -f itbl-lexl config/m68k-parseh config/m68k-parsec itbl-parseh itbl-parsec + -test -z "itbl-lex.cconfig/m68k-parse.hconfig/m68k-parse.citbl-parse.hitbl-parse.c" || rm -f itbl-lex.c config/m68k-parse.h config/m68k-parse.c itbl-parse.h itbl-parse.c mostlyclean-am: mostlyclean-hdr mostlyclean-noinstPROGRAMS \ mostlyclean-compile mostlyclean-libtool \ mostlyclean-tags mostlyclean-generic @@ -3315,13 +3318,17 @@ dep-am: DEP #MKDEP DO NOT PUT ANYTHING BETWEEN THIS LINE AND THE MATCHING WARNING BELOW. app.o: app.c $(INCDIR)/symcat.h as.o: as.c $(INCDIR)/symcat.h subsegs.h $(INCDIR)/obstack.h \ - output-file.h sb.h macro.h dwarf2dbg.h $(BFDVER_H) + output-file.h sb.h macro.h dwarf2dbg.h dw2gencfi.h \ + $(INCDIR)/elf/dwarf2.h $(BFDVER_H) atof-generic.o: atof-generic.c $(INCDIR)/symcat.h $(INCDIR)/safe-ctype.h bignum-copy.o: bignum-copy.c $(INCDIR)/symcat.h cond.o: cond.c $(INCDIR)/symcat.h macro.h sb.h $(INCDIR)/obstack.h depend.o: depend.c $(INCDIR)/symcat.h dwarf2dbg.o: dwarf2dbg.c $(INCDIR)/symcat.h dwarf2dbg.h \ - subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h + $(INCDIR)/filenames.h subsegs.h $(INCDIR)/obstack.h \ + $(INCDIR)/elf/dwarf2.h +dw2gencfi.o: dw2gencfi.c $(INCDIR)/symcat.h dw2gencfi.h \ + $(INCDIR)/elf/dwarf2.h ecoff.o: ecoff.c $(INCDIR)/symcat.h ecoff.h ehopt.o: ehopt.c $(INCDIR)/symcat.h subsegs.h $(INCDIR)/obstack.h \ $(INCDIR)/elf/dwarf2.h @@ -3344,7 +3351,8 @@ macro.o: macro.c $(INCDIR)/safe-ctype.h sb.h macro.h messages.o: messages.c $(INCDIR)/symcat.h output-file.o: output-file.c $(INCDIR)/symcat.h output-file.h read.o: read.c $(INCDIR)/symcat.h $(INCDIR)/safe-ctype.h \ - subsegs.h $(INCDIR)/obstack.h sb.h macro.h ecoff.h + subsegs.h $(INCDIR)/obstack.h sb.h macro.h ecoff.h \ + dw2gencfi.h $(INCDIR)/elf/dwarf2.h sb.o: sb.c sb.h stabs.o: stabs.c $(INCDIR)/symcat.h $(INCDIR)/obstack.h \ subsegs.h ecoff.h $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def diff --git a/gas/as.c b/gas/as.c index 23ed9f7825a..da2e0554ea0 100644 --- a/gas/as.c +++ b/gas/as.c @@ -42,6 +42,7 @@ #include "sb.h" #include "macro.h" #include "dwarf2dbg.h" +#include "dw2gencfi.h" #ifdef BFD_ASSEMBLER #include "bfdver.h" @@ -98,6 +99,9 @@ int chunksize = 0; Then the chunk sizes for gas and bfd will be reduced. */ int debug_memory = 0; +/* Enable verbose mode. */ +int verbose = 0; + /* We build a list of defsyms as we read the options, and then define them after we have initialized everything. */ @@ -497,6 +501,7 @@ parse_args (pargc, pargv) #endif case OPTION_VERBOSE: print_version_id (); + verbose = 1; break; } /* Fall through. */ @@ -832,6 +837,10 @@ main (argc, argv) bfd_set_error_program_name (myname); #endif +#ifdef TARGET_USE_CFIPOP + tc_cfi_init (); +#endif + #ifdef USE_EMULATIONS select_emulation_mode (argc, argv); #endif @@ -906,6 +915,10 @@ main (argc, argv) assembly debugging or on behalf of the compiler, emit it now. */ dwarf2_finish (); +#ifdef TARGET_USE_CFIPOP + cfi_finish (); +#endif + if (seen_at_least_1_file () && (flag_always_generate_output || had_errors () == 0)) keep_it = 1; diff --git a/gas/as.h b/gas/as.h index cdb267adbf0..2c5a22ccde4 100644 --- a/gas/as.h +++ b/gas/as.h @@ -474,6 +474,9 @@ extern enum debug_info_type debug_type; /* Maximum level of macro nesting. */ extern int max_macro_nest; +/* Verbosity level. */ +extern int verbose; + /* Obstack chunk size. Keep large for efficient space use, make small to increase malloc calls for monitoring memory allocation. */ extern int chunksize; diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 92540ad625d..9a3bbbbd360 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -30,6 +30,7 @@ #include "safe-ctype.h" #include "subsegs.h" #include "dwarf2dbg.h" +#include "dw2gencfi.h" #include "opcode/i386.h" #ifndef REGISTER_WARNINGS @@ -6299,3 +6300,85 @@ intel_putback_token () prev_token.reg = NULL; prev_token.str = NULL; } + +void +tc_x86_cfi_init (void) +{ + struct cfi_config cfi_config; + + if (flag_code == CODE_64BIT) + { + cfi_config.addr_length = 8; + cfi_config.eh_align = 8; + cfi_config.code_align = 1; + cfi_config.data_align = -8; + cfi_config.ra_column = 0x10; + cfi_config.reloc_type = BFD_RELOC_64; + } + else + { + cfi_config.addr_length = 4; + cfi_config.eh_align = 4; + cfi_config.code_align = 1; + cfi_config.data_align = -4; + cfi_config.ra_column = 0x08; + cfi_config.reloc_type = BFD_RELOC_32; + } + + cfi_set_config (&cfi_config); +} + +unsigned long +tc_x86_regname_to_dw2regnum (const char *regname) +{ + unsigned int regnum; + unsigned int regnames_count; + char *regnames_32[] = + { + "eax", "ebx", "ecx", "edx", + "edi", "esi", "ebp", "esp", + "eip" + }; + char *regnames_64[] = + { + "rax", "rbx", "rcx", "rdx", + "rdi", "rsi", "rbp", "rsp", + "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15", + "rip" + }; + char **regnames; + + if (flag_code == CODE_64BIT) + { + regnames = regnames_64; + regnames_count = sizeof (regnames_64); + } + else + { + regnames = regnames_32; + regnames_count = sizeof (regnames_32); + } + + for (regnum = 0; regnum < regnames_count; regnum++) + if (strcmp (regname, regnames[regnum]) == 0) + return regnum; + + as_bad (_("unknown register name '%s'"), regname); + return -1; +} + +void +tc_x86_frame_initial_instructions (void) +{ + if (flag_code == CODE_64BIT) + { + cfi_add_insn (CFA_def_cfa, tc_x86_regname_to_dw2regnum ("rsp"), 8); + cfi_add_insn (CFA_offset, tc_x86_regname_to_dw2regnum ("rip"), -8); + } + else + { + cfi_add_insn (CFA_def_cfa, tc_x86_regname_to_dw2regnum ("esp"), 4); + cfi_add_insn (CFA_offset, tc_x86_regname_to_dw2regnum ("eip"), -4); + } +} diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index 45c3acf626d..aa131ba5060 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -545,4 +545,19 @@ void i386_print_statistics PARAMS ((FILE *)); extern void sco_id PARAMS ((void)); #endif +/* We want .cfi_* pseudo-ops for generating unwind info. */ +#define TARGET_USE_CFIPOP +#ifdef TARGET_USE_CFIPOP + +#define tc_cfi_init() tc_x86_cfi_init () +extern void tc_x86_cfi_init PARAMS ((void)); + +#define tc_regname_to_dw2regnum tc_x86_regname_to_dw2regnum +extern unsigned long tc_x86_regname_to_dw2regnum PARAMS ((const char *regname)); + +#define tc_cfi_frame_initial_instructions tc_x86_frame_initial_instructions +extern void tc_x86_frame_initial_instructions PARAMS ((void)); + +#endif /* TARGET_USE_CFIPOP */ + #endif /* TC_I386 */ diff --git a/gas/doc/Makefile.in b/gas/doc/Makefile.in index 6b8a4e4da9b..0a1b7a3d708 100644 --- a/gas/doc/Makefile.in +++ b/gas/doc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation @@ -195,7 +195,7 @@ DIST_COMMON = Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = gtar +TAR = tar GZIP_ENV = --best all: all-redirect .SUFFIXES: diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index dd78d68cb0b..720c05491e8 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -3690,6 +3690,16 @@ Some machine configurations provide additional directives. * Balign:: @code{.balign @var{abs-expr} , @var{abs-expr}} * Byte:: @code{.byte @var{expressions}} * Comm:: @code{.comm @var{symbol} , @var{length} } + +* CFI directives:: @code{.cfi_startproc} + @code{.cfi_endproc} + @code{.cfi_def_cfa @var{register}, @var{offset}} + @code{.cfi_def_cfa_register @var{register}} + @code{.cfi_def_cfa_offset @var{offset}} + @code{.cfi_adjust_cfa_offset @var{offset}} + @code{.cfi_offset @var{register}, @var{offset}} + @code{.cfi_verbose [1|0]} + * Data:: @code{.data @var{subsection}} @ifset COFF * Def:: @code{.def @var{name}} @@ -3966,6 +3976,48 @@ undefined. @code{.byte} expects zero or more expressions, separated by commas. Each expression is assembled into the next byte. +@node CFI directives +@section @code{.cfi_startproc} +@cindex @code{cfi_startproc} directive +@code{.cfi_startproc} is used at the beginning of each function that +should have an entry in @code{.eh_frame}. It initializes some internal +data structures and emits architecture dependent initial CFI instructions. +Don't forget to close the function by +@code{.cfi_endproc}. + +@section @code{.cfi_endproc} +@cindex @code{cfi_endproc} directive +@code{.cfi_endproc} is used at the end of a function where it closes its +unwind entry previously opened by +@code{.cfi_startproc}. and emits it to @code{.eh_frame}. + +@section @code{.cfi_def_cfa @var{register}, @var{offset}} +@code{.cfi_def_cfa} defines a rule for computing CFA as: @i{take +address from @var{register} and add @var{offset} to it}. + +@section @code{.cfi_def_cfa_register @var{register}} +@code{.cfi_def_cfa_register} modifies a rule for computing CFA. From +now on @var{register} will be used instead of the old one. Offset +remains the same. + +@section @code{.cfi_def_cfa_offset @var{offset}} +@code{.cfi_def_cfa_offset} modifies a rule for computing CFA. Register +remains the same, but @var{offset} is new. Note that it is the +absolute offset that will be added to a defined register to compute +CFA address. + +@section @code{.cfi_adjust_cfa_offset @var{offset}} +Same as @code{.cfi_def_cfa_offset} but @var{offset} is a relative +value that is added/substracted from the previous offset. + +@section @code{.cfi_offset @var{register}, @var{offset}} +Previous value of @var{register} is saved at offset @var{offset} from +CFA. + +@section @code{.cfi_verbose [1|0]} +Switch on/off verbosity of the CFI machinery. @value{AS} will print +lots of useful messages to standard output if you use this directive. + @node Comm @section @code{.comm @var{symbol} , @var{length} } diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c new file mode 100644 index 00000000000..f83610b3765 --- /dev/null +++ b/gas/dw2gencfi.c @@ -0,0 +1,721 @@ +/* dw2gencfi.c - Support for generating Dwarf2 CFI information. + Copyright 2003 Free Software Foundation, Inc. + Contributed by Michal Ludvig + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include +#include "as.h" +#include "dw2gencfi.h" + +/* Current target config. */ +static struct cfi_config current_config; + +/* This is the main entry point to the CFI machinery. */ +static void dot_cfi (int arg); + +const pseudo_typeS cfi_pseudo_table[] = + { + { "cfi_verbose", dot_cfi, CFI_verbose }, + { "cfi_startproc", dot_cfi, CFI_startproc }, + { "cfi_endproc", dot_cfi, CFI_endproc }, + { "cfi_def_cfa", dot_cfi, CFA_def_cfa }, + { "cfi_def_cfa_register", dot_cfi, CFA_def_cfa_register }, + { "cfi_def_cfa_offset", dot_cfi, CFA_def_cfa_offset }, + { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset }, + { "cfi_offset", dot_cfi, CFA_offset }, + { NULL, NULL, 0 } + }; + +static const char * +cfi_insn_str (enum cfi_insn insn) +{ + switch (insn) + { + case CFA_nop: + return "CFA_nop"; + case CFA_set_loc: + return "CFA_set_loc"; + case CFA_advance_loc1: + return "CFA_advance_loc1"; + case CFA_advance_loc2: + return "CFA_advance_loc2"; + case CFA_advance_loc4: + return "CFA_advance_loc4"; + case CFA_offset_extended: + return "CFA_offset_extended"; + case CFA_resotre_extended: + return "CFA_resotre_extended"; + case CFA_undefined: + return "CFA_undefined"; + case CFA_same_value: + return "CFA_same_value"; + case CFA_register: + return "CFA_register"; + case CFA_remember_state: + return "CFA_remember_state"; + case CFA_restore_state: + return "CFA_restore_state"; + case CFA_def_cfa: + return "CFA_def_cfa"; + case CFA_def_cfa_register: + return "CFA_def_cfa_register"; + case CFA_def_cfa_offset: + return "CFA_def_cfa_offset"; + case CFA_advance_loc: + return "CFA_advance_loc"; + case CFA_offset: + return "CFA_offset"; + case CFA_restore: + return "CFA_restore"; + default: + break; + } + + return "CFA_unknown"; +} + +struct cfi_data +{ + enum cfi_insn insn; + long param[2]; + struct cfi_data *next; +}; + +struct cfi_info +{ + addressT start_address; + addressT end_address; + addressT last_address; + const char *labelname; + struct cfi_data *data; + struct cfi_info *next; +}; + +static struct cfi_info *cfi_info; + +static struct cfi_data * +alloc_cfi_data (void) +{ + return (struct cfi_data *) xcalloc (sizeof (struct cfi_info), 1); +} + +static struct cfi_info * +alloc_cfi_info (void) +{ + return (struct cfi_info *) xcalloc (sizeof (struct cfi_info), 1); +} + +/* Parse arguments. */ +static int +cfi_parse_arg (long *param, int resolvereg) +{ + char *name, c, *p; + long value; + int retval = -1; + int nchars; + + assert (param != NULL); + SKIP_WHITESPACE (); + + if (sscanf (input_line_pointer, "%li%n", &value, &nchars) >= 1) + { + input_line_pointer += nchars; + retval = 1; + } + else if (resolvereg && (is_name_beginner (*input_line_pointer))) + { + name = input_line_pointer; + c = get_symbol_end (); + p = input_line_pointer; + + if ((value = tc_regname_to_dw2regnum (name)) >= 0) + retval = 1; + + *p = c; + } + else + as_bad (resolvereg ? + _("can't convert argument to a register number") : + _("can't convert argument to an integer")); + + if (retval > 0) + *param = value; + + SKIP_WHITESPACE (); + if (*input_line_pointer == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + } + + return retval; +} + +static int +cfi_parse_reg (long *param) +{ + return cfi_parse_arg (param, 1); +} + +static int +cfi_parse_const (long *param) +{ + return cfi_parse_arg (param, 0); +} + +void +cfi_add_insn (enum cfi_insn insn, long param0, long param1) +{ + struct cfi_data *data_ptr; + + if (!cfi_info->data) + { + cfi_info->data = alloc_cfi_data (); + data_ptr = cfi_info->data; + } + else + { + data_ptr = cfi_info->data; + + while (data_ptr && data_ptr->next) + data_ptr = data_ptr->next; + + data_ptr->next = alloc_cfi_data (); + + data_ptr = data_ptr->next; + } + + data_ptr->insn = insn; + data_ptr->param[0] = param0; + data_ptr->param[1] = param1; +} + +static void +cfi_advance_loc (void) +{ + addressT curr_address = frag_now_fix (); + if (cfi_info->last_address == curr_address) + return; + cfi_add_insn (CFA_advance_loc, + (long) (curr_address - cfi_info->last_address), 0); + cfi_info->last_address = curr_address; +} + +static long +get_current_offset (struct cfi_info *info) +{ + long current_offset = 0; + struct cfi_data *data = info->data; + + current_offset = 0; + while (data) + { + if (data->insn == CFA_def_cfa) + current_offset = data->param[1]; + else if (data->insn == CFA_def_cfa_offset) + current_offset = data->param[0]; + data = data->next; + } + + return current_offset; +} + +static void +cfi_make_insn (int arg) +{ + long param[2] = { 0, 0 }; + + if (!cfi_info) + { + as_bad (_("CFI instruction used without previous .cfi_startproc")); + return; + } + + cfi_advance_loc (); + + switch (arg) + { + /* Instructions that take two arguments (register, integer). */ + case CFA_offset: + case CFA_def_cfa: + if (cfi_parse_reg (¶m[0]) < 0) + { + as_bad (_("first argument to %s is not a register"), + cfi_insn_str (arg)); + return; + } + if (cfi_parse_const (¶m[1]) < 0) + { + as_bad (_("second argument to %s is not a number"), + cfi_insn_str (arg)); + return; + } + break; + + /* Instructions that take one register argument. */ + case CFA_def_cfa_register: + if (cfi_parse_reg (¶m[0]) < 0) + { + as_bad (_("argument to %s is not a register"), cfi_insn_str (arg)); + return; + } + break; + + /* Instructions that take one integer argument. */ + case CFA_def_cfa_offset: + if (cfi_parse_const (¶m[0]) < 0) + { + as_bad (_("argument to %s is not a number"), cfi_insn_str (arg)); + return; + } + break; + + /* Special handling for pseudo-instruction. */ + case CFI_adjust_cfa_offset: + if (cfi_parse_const (¶m[0]) < 0) + { + as_bad (_("argument to %s is not a number"), + ".cfi_adjust_cfa_offset"); + return; + } + param[0] += get_current_offset (cfi_info); + arg = CFA_def_cfa_offset; + break; + + default: + as_bad (_("unknown CFI instruction %d (%s)"), arg, cfi_insn_str (arg)); + return; + } + cfi_add_insn (arg, param[0], param[1]); +} + +static symbolS * +cfi_get_label (void) +{ + char symname[40], *symbase=".Llbl_cfi"; + symbolS *symbolP; + unsigned int i = 0; + + snprintf (symname, sizeof (symname), "%s_0x%lx", + symbase, (long) frag_now_fix ()); + while ((symbolP = symbol_find (symname))) + { + if ((S_GET_VALUE (symbolP) == frag_now_fix ()) + && (S_GET_SEGMENT (symbolP) == now_seg)) + { + return symbolP; + } + snprintf (symname, sizeof (symname), "%s_0x%lx_%u", + symbase, (long) frag_now_fix (), i++); + } + symbolP = (symbolS *) local_symbol_make (symname, now_seg, + (valueT) frag_now_fix (), + frag_now); + return symbolP; +} + +static void +dot_cfi_startproc (void) +{ + if (cfi_info) + { + as_bad (_("previous CFI entry not closed (missing .cfi_endproc)")); + return; + } + + cfi_info = alloc_cfi_info (); + + cfi_info->start_address = frag_now_fix (); + cfi_info->last_address = cfi_info->start_address; + cfi_info->labelname = S_GET_NAME (cfi_get_label ()); + +#ifdef tc_cfi_frame_initial_instructions + tc_cfi_frame_initial_instructions (); +#endif +} + +#define cfi_is_advance_insn(insn) \ + ((insn >= CFA_set_loc && insn <= CFA_advance_loc4) \ + || insn == CFA_advance_loc) + +enum data_types + { + t_ascii = 0, + t_byte = 1, + t_half = 2, + t_long = 4, + t_quad = 8, + t_uleb128 = 0x10, + t_sleb128 = 0x11 + }; + +/* Output CFI instructions to the file. */ + +static int +output_data (char **p, unsigned long *size, enum data_types type, long value) +{ + char *ptr = *p; + unsigned int ret_size; + + switch (type) + { + case t_byte: + ret_size = 1; + break; + case t_half: + ret_size = 2; + break; + case t_long: + ret_size = 4; + break; + case t_quad: + case t_uleb128: + case t_sleb128: + ret_size = 8; + break; + default: + as_warn (_("unknown type %d"), type); + return 0; + } + + if (*size < ret_size) + { + as_bad (_("output_data buffer is too small")); + return 0; + } + + switch (type) + { + case t_byte: + *ptr = (char) value; + if (verbose) + printf ("\t.byte\t0x%x\n", (unsigned char) *ptr); + break; + case t_half: + *(short *) ptr = (short) value & 0xFFFF; + if (verbose) + printf ("\t.half\t0x%x\n", (unsigned short) *ptr); + break; + case t_long: + *(int *) ptr = (int) value & 0xFFFFFFFF; + if (verbose) + printf ("\t.long\t0x%x\n", (unsigned int) *ptr); + break; + case t_quad: + *(long long *) ptr = (long long) value & 0xFFFFFFFF; + if (verbose) + printf ("\t.quad\t0x%x\n", (unsigned int) *ptr); + break; + case t_uleb128: + case t_sleb128: + ret_size = output_leb128 (ptr, value, type == t_sleb128); + if (verbose) + printf ("\t.%s\t0x%lx\n", + type == t_sleb128 ? "sleb128" : "uleb128", + value); + break; + default: + as_warn ("unknown type %d", type); + return 0; + } + + *size -= ret_size; + *p += ret_size; + + return ret_size; +} + +static int +cfi_output_insn (struct cfi_data *data, char **buf, unsigned long *buf_size) +{ + char **pbuf = buf, *orig_buf = *buf; + unsigned long size; + + if (!data || !buf) + as_fatal (_("cfi_output_insn called with NULL pointer")); + + switch (data->insn) + { + case CFA_advance_loc: + if (verbose) + printf ("\t# %s(%ld)\n", cfi_insn_str (data->insn), + data->param[0]); + if (data->param[0] <= 0x3F) + { + output_data (pbuf, buf_size, t_byte, CFA_advance_loc + + (data->param[0] / current_config.code_align)); + } + else if (data->param[0] <= 0xFF) + { + output_data (pbuf, buf_size, t_byte, CFA_advance_loc1); + output_data (pbuf, buf_size, t_byte, + data->param[0] / current_config.code_align); + } + else if (data->param[0] <= 0xFFFF) + { + output_data (pbuf, buf_size, t_byte, CFA_advance_loc2); + output_data (pbuf, buf_size, t_half, + data->param[0] / current_config.code_align); + } + else + { + output_data (pbuf, buf_size, t_byte, CFA_advance_loc4); + output_data (pbuf, buf_size, t_long, + data->param[0] / current_config.code_align); + } + break; + + case CFA_def_cfa: + if (verbose) + printf ("\t# CFA_def_cfa(%ld,%ld)\n", data->param[0], data->param[1]); + output_data (pbuf, buf_size, t_byte, CFA_def_cfa); + output_data (pbuf, buf_size, t_uleb128, data->param[0]); + output_data (pbuf, buf_size, t_uleb128, data->param[1]); + break; + + case CFA_def_cfa_register: + case CFA_def_cfa_offset: + if (verbose) + printf ("\t# %s(%ld)\n", cfi_insn_str (data->insn), + data->param[0]); + output_data (pbuf, buf_size, t_byte, data->insn); + output_data (pbuf, buf_size, t_uleb128, data->param[0]); + break; + + case CFA_offset: + if (verbose) + printf ("\t# %s(%ld,%ld)\n", cfi_insn_str (data->insn), + data->param[0], data->param[1]); + + /* Check whether to use CFA_offset or CFA_offset_extended. */ + if (data->param[0] <= 0x3F) + output_data (pbuf, buf_size, t_byte, CFA_offset + data->param[0]); + else + { + output_data (pbuf, buf_size, t_byte, CFA_offset_extended); + output_data (pbuf, buf_size, t_uleb128, data->param[0]); + } + output_data (pbuf, buf_size, t_uleb128, + data->param[1] / current_config.data_align); + break; + + case CFA_nop: + if (verbose) + printf ("\t# CFA_nop\n"); + output_data (pbuf, buf_size, t_byte, CFA_nop); + break; + + default: + as_warn ("CFA_unknown[%d](%ld,%ld)", data->insn, + data->param[0], data->param[1]); + } + size = *pbuf - orig_buf; + *buf = *pbuf; + *buf_size -= size; + return size; +} + +static void +dot_cfi_endproc (void) +{ + struct cfi_data *data_ptr; + char *cie_buf, *fde_buf, *pbuf, *where; + unsigned long buf_size, cie_size, fde_size, last_cie_offset; + unsigned long fde_initloc_offset, fde_len_offset; + void *saved_seg, *cfi_seg; + + if (! cfi_info) + { + as_bad (_(".cfi_endproc without corresponding .cfi_startproc")); + return; + } + cfi_info->end_address = frag_now_fix (); + + /* Open .eh_frame section. */ + saved_seg = now_seg; + cfi_seg = subseg_new (".eh_frame", 0); + bfd_set_section_flags (stdoutput, cfi_seg, + SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA); + subseg_set (cfi_seg, 0); + + /* Build CIE. */ + cie_buf = xcalloc (1024, 1); + /* Skip space for CIE length. */ + pbuf = cie_buf + 4; + buf_size = 1020; + + if (verbose) + printf ("# CIE *****\n"); + + /* CIE id. */ + output_data (&pbuf, &buf_size, t_long, 0x0); + /* Version. */ + output_data (&pbuf, &buf_size, t_byte, 1); + /* Augmentation. */ + output_data (&pbuf, &buf_size, t_byte, 0); + /* Code alignment. */ + output_data (&pbuf, &buf_size, t_uleb128, current_config.code_align); + /* Data alignment. */ + output_data (&pbuf, &buf_size, t_sleb128, current_config.data_align); + /* Return address column. */ + output_data (&pbuf, &buf_size, t_byte, current_config.ra_column); + + /* Build CFI instructions. */ + data_ptr = cfi_info->data; + while (data_ptr && !cfi_is_advance_insn (data_ptr->insn)) + { + cfi_output_insn (data_ptr, &pbuf, &buf_size); + data_ptr = data_ptr->next; + } + + /* Align the whole data to current_config.eh_align. */ + cie_size = pbuf - cie_buf; + cie_size += current_config.eh_align - cie_size % current_config.eh_align; + + /* CIE length. */ + pbuf = cie_buf; + output_data (&pbuf, &buf_size, t_long, cie_size - 4); + + /* OK, we built the CIE. Let's write it to the file... */ + last_cie_offset = frag_now_fix (); + where = (unsigned char *) frag_more (cie_size); + memcpy (where, cie_buf, cie_size); + + /* Clean up. */ + free (cie_buf); + + /* Build the FDE... */ + fde_buf = xcalloc (1024, 1); + pbuf = fde_buf; + buf_size = 1024; + + if (verbose) + { + printf ("# FDE: start=0x%lx, end=0x%lx, delta=%d\n", + (long) cfi_info->start_address, + (long) cfi_info->end_address, + (int) (cfi_info->end_address - cfi_info->start_address)); + } + + /* FDE length (t_long, 4 bytes) - will be set later. */ + fde_len_offset = pbuf - fde_buf; + pbuf += 4; + buf_size -= 4; + + /* CIE pointer - offset from here. */ + output_data (&pbuf, &buf_size, t_long, cie_size + 4); + + /* FDE initial location - this must be set relocatable! */ + fde_initloc_offset = pbuf - fde_buf; + output_data (&pbuf, &buf_size, current_config.addr_length, + cfi_info->start_address); + + /* FDE address range. */ + output_data (&pbuf, &buf_size, current_config.addr_length, + cfi_info->end_address - cfi_info->start_address); + + while (data_ptr) + { + cfi_output_insn (data_ptr, &pbuf, &buf_size); + data_ptr = data_ptr->next; + } + + fde_size = pbuf - fde_buf; + fde_size += current_config.eh_align - fde_size % current_config.eh_align; + + /* Now we can set FDE length. */ + pbuf = fde_buf + fde_len_offset; + buf_size = 4; + output_data (&pbuf, &buf_size, t_long, fde_size - 4); + + /* Adjust initloc offset. */ + fde_initloc_offset += frag_now_fix (); + + /* Copy FDE to objfile. */ + where = (unsigned char *) frag_more (fde_size); + memcpy (where, fde_buf, fde_size); + + /* Set relocation for initial address. */ + buf_size = current_config.addr_length; + expressionS exp; + memset (&exp, 0, sizeof (exp)); + exp.X_op = O_symbol; + exp.X_add_symbol = symbol_find (cfi_info->labelname); + fix_new_exp (frag_now, fde_initloc_offset, + current_config.addr_length, + &exp, 0, current_config.reloc_type); + + /* Clean up. */ + free (fde_buf); + + free (cfi_info); + cfi_info = NULL; + + /* Restore previous segment. */ + subseg_set (saved_seg, 0); +} + +void +dot_cfi (int arg) +{ + long param; + + switch (arg) + { + case CFI_startproc: + dot_cfi_startproc (); + break; + case CFI_endproc: + dot_cfi_endproc (); + break; + case CFA_def_cfa: + case CFA_def_cfa_register: + case CFA_def_cfa_offset: + case CFA_offset: + case CFI_adjust_cfa_offset: + cfi_make_insn (arg); + break; + case CFI_verbose: + if (cfi_parse_const (¶m) >= 0) + verbose = (int) param; + else + verbose = 1; + break; + default: + as_bad (_("unknown CFI code 0x%x (%s)"), arg, cfi_insn_str (arg)); + break; + } + ignore_rest_of_line (); +} + +void +cfi_set_config (struct cfi_config *cfg) +{ + assert (cfg != NULL); + assert (cfg->addr_length > 0); + + current_config = *cfg; +} + +void +cfi_finish (void) +{ + if (cfi_info) + as_bad (_("open CFI at the end of file; missing .cfi_endproc directive")); +} diff --git a/gas/dw2gencfi.h b/gas/dw2gencfi.h new file mode 100644 index 00000000000..1c724540e6c --- /dev/null +++ b/gas/dw2gencfi.h @@ -0,0 +1,100 @@ +/* dw2gencfi.h - Support for generating Dwarf2 CFI information. + Copyright 2003 Free Software Foundation, Inc. + Contributed by Michal Ludvig + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef DW2GENCFI_H +#define DW2GENCFI_H + +#include "elf/dwarf2.h" + +struct cfi_config { + /* Target address length in bytes. (usually 4 or 8). + Round it up for archs like S/390 with 31b addresses. */ + unsigned int addr_length; + + /* Alignment of .eh_frame blocks in bytes (usually 1, 4 or 8). */ + unsigned int eh_align; + + /* Code alignment (1 for x86/amd64 machines, 4 or 8 for + RISC machines). Consult Dwarf2 standard for details. */ + int code_align; + + /* Data (stack) alignment (-4 on x86, -8 on amd64, something + positive on archs where stack grows up). Consult Dwarf2 + standard for details. */ + int data_align; + + /* Return address column (0x8 on x86, 0x10 on amd64). Consult + Dwarf2 standard for details. */ + int ra_column; + + /* Relocation type for init_addr FDE record. (BFD_RELOC_64 + on amd64). */ + int reloc_type; +}; + +/* Codes of CFI instructions taken from Dwarf2 standard. */ +enum cfi_insn { + CFA_nop = DW_CFA_nop, + CFA_set_loc = DW_CFA_set_loc, + CFA_advance_loc1 = DW_CFA_advance_loc1, + CFA_advance_loc2 = DW_CFA_advance_loc2, + CFA_advance_loc4 = DW_CFA_advance_loc4, + CFA_offset_extended = DW_CFA_offset_extended, + CFA_resotre_extended = DW_CFA_restore_extended, + CFA_undefined = DW_CFA_undefined, + CFA_same_value = DW_CFA_same_value, + CFA_register = DW_CFA_register, + CFA_remember_state = DW_CFA_remember_state, + CFA_restore_state = DW_CFA_restore_state, + CFA_def_cfa = DW_CFA_def_cfa, + CFA_def_cfa_register = DW_CFA_def_cfa_register, + CFA_def_cfa_offset = DW_CFA_def_cfa_offset, + CFA_advance_loc = DW_CFA_advance_loc, + CFA_offset = DW_CFA_offset, + CFA_restore = DW_CFA_restore, + + /* These don't belong to the standard. */ + CFI_startproc = 0xff00, + CFI_endproc = 0xff01, + CFI_adjust_cfa_offset = 0xff10, + CFI_verbose = 0xffff +}; + +extern const pseudo_typeS cfi_pseudo_table[]; + +/* Insert .cfi_* directives to the list of pseudo-ops. */ +void cfi_pop_insert PARAMS ((void)); + +/* Set/change setup of the CFI machinery. This change won't + affect already generated CIEs/FDEs. */ +void cfi_set_config PARAMS ((struct cfi_config *cfg)); + +/* cfi_finish() is called at the end of file. It will complain if + the last CFI wasn't properly closed by .cfi_endproc. */ +void cfi_finish PARAMS ((void)); + +/* Add CFI instruction to the list of instructions + of the current frame. cfi_add_insn() could be used + in tc_cfi_frame_initial_instructions() to add instructions + needed for every frame (ie. those that usually go to CIE). */ +void cfi_add_insn (enum cfi_insn insn, long param0, long param1); + +#endif /* DW2GENCFI_H */ diff --git a/gas/po/POTFILES.in b/gas/po/POTFILES.in index 2a25db2b78f..f80d3017f85 100644 --- a/gas/po/POTFILES.in +++ b/gas/po/POTFILES.in @@ -136,10 +136,15 @@ config/tc-w65.c config/tc-w65.h config/tc-xstormy16.c config/tc-xstormy16.h +config/tc-xtensa.c +config/tc-xtensa.h config/tc-z8k.c config/tc-z8k.h depend.c depend.c +dw2gencfi.c +dw2gencfi.c +dw2gencfi.h dwarf2dbg.c dwarf2dbg.c dwarf2dbg.h diff --git a/gas/read.c b/gas/read.c index 07f8238d073..d75083e546b 100644 --- a/gas/read.c +++ b/gas/read.c @@ -43,6 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "obstack.h" #include "listing.h" #include "ecoff.h" +#include "dw2gencfi.h" #ifndef TC_START_LABEL #define TC_START_LABEL(x,y) (x == ':') @@ -451,6 +452,10 @@ pop_insert (table) #define obj_pop_insert() pop_insert(obj_pseudo_table) #endif +#ifndef cfi_pop_insert +#define cfi_pop_insert() pop_insert(cfi_pseudo_table) +#endif + static void pobegin () { @@ -468,6 +473,12 @@ pobegin () /* Now portable ones. Skip any that we've seen already. */ pop_table_name = "standard"; pop_insert (potable); + +#ifdef TARGET_USE_CFIPOP + pop_table_name = "cfi"; + pop_override_ok = 1; + cfi_pop_insert (); +#endif } #define HANDLE_CONDITIONAL_ASSEMBLY() \ diff --git a/gas/symbols.c b/gas/symbols.c index 59658dff0d0..416ff1a8c43 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -182,8 +182,6 @@ symbol_create (name, segment, valu, frag) /* Local symbol support. If we can get away with it, we keep only a small amount of information for local symbols. */ -static struct local_symbol *local_symbol_make PARAMS ((const char *, segT, - valueT, fragS *)); static symbolS *local_symbol_convert PARAMS ((struct local_symbol *)); /* Used for statistics. */ @@ -205,7 +203,7 @@ static unsigned long local_symbol_conversion_count; /* Create a local symbol and insert it into the local hash table. */ -static struct local_symbol * +struct local_symbol * local_symbol_make (name, section, value, frag) const char *name; segT section; diff --git a/gas/symbols.h b/gas/symbols.h index 65fb8492fd7..d3b9dd3734a 100644 --- a/gas/symbols.h +++ b/gas/symbols.h @@ -57,6 +57,8 @@ symbolS *symbol_new PARAMS ((const char *name, segT segment, valueT value, fragS * frag)); symbolS *symbol_create PARAMS ((const char *name, segT segment, valueT value, fragS * frag)); +struct local_symbol *local_symbol_make PARAMS ((const char *name, segT section, + valueT value, fragS * frag)); symbolS *colon PARAMS ((const char *sym_name)); void local_colon PARAMS ((int n)); void symbol_begin PARAMS ((void)); -- 2.30.2