From: Peter Johnson Date: Wed, 19 Oct 2005 07:44:59 +0000 (-0000) Subject: * gas-bison.y: Add support for .value alias for .2byte (GAS-x86/amd64). X-Git-Tag: v0.5.0rc1~89 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c67a80021b9df481d050d0c207d4e92aed2e4eff;p=yasm * gas-bison.y: Add support for .value alias for .2byte (GAS-x86/amd64). This is generated by GCC in debug sections. * gas-token.re: Likewise. * gas-bison.y: Add support for 4th parameter on .section directive, for use with M (SHF_MERGE) ELF section flag. * elf-objfmt.c: Add support for M, S (SHF_STRINGS), G (SHF_GROUP), and T (SHF_TLS) section flags. * elf.h: Declare additional SHF_* flags. With these changes, debug information generated by GCC in GAS format is passed through successfully. Should just need line number generation to have full debugging for ELF-DWARF2 coming from GCC. Only remaining thing to handle that I see at the moment for full GCC output support is multiple instructions on one line (separated by semicolons). svn path=/trunk/yasm/; revision=1289 --- diff --git a/modules/objfmts/elf/elf-objfmt.c b/modules/objfmts/elf/elf-objfmt.c index bb42a32c..f082d477 100644 --- a/modules/objfmts/elf/elf-objfmt.c +++ b/modules/objfmts/elf/elf-objfmt.c @@ -715,8 +715,7 @@ elf_objfmt_destroy(yasm_objfmt *objfmt) static /*@observer@*/ /*@null@*/ yasm_section * elf_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams, - /*@unused@*/ /*@null@*/ - yasm_valparamhead *objext_valparams, + /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line) { yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt; @@ -800,6 +799,22 @@ elf_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams, case 'x': flags |= SHF_EXECINSTR; break; + case 'M': + flags |= SHF_MERGE; + break; + case 'S': + flags |= SHF_STRINGS; + break; + case 'G': + flags |= SHF_GROUP; + break; + case 'T': + flags |= SHF_TLS; + break; + default: + yasm__warning(YASM_WARN_GENERAL, line, + N_("unrecognized section attribute: `%c'"), + vp->val[i]); } } } else if (yasm__strcasecmp(vp->val, "progbits") == 0) { @@ -857,6 +872,26 @@ elf_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams, yasm_section_bcs_first(retval), 1, line); elf_secthead_set_sym(esd, sym); + + /* Handle merge entity size */ + if (flags & SHF_MERGE) { + if (objext_valparams && (vp = yasm_vps_first(objext_valparams)) + && vp->param) { + /*@dependent@*/ /*@null@*/ const yasm_intnum *merge_intn; + + merge_intn = yasm_expr_get_intnum(&vp->param, NULL); + if (merge_intn) + elf_secthead_set_entsize(esd, + yasm_intnum_get_uint(merge_intn)); + else + yasm__warning(YASM_WARN_GENERAL, line, + N_("invalid merge entity size")); + } else { + yasm__warning(YASM_WARN_GENERAL, line, + N_("entity size for SHF_MERGE not specified")); + flags &= ~SHF_MERGE; + } + } } else if (flags_override) yasm__warning(YASM_WARN_GENERAL, line, N_("section flags ignored on section redeclaration")); diff --git a/modules/objfmts/elf/elf.h b/modules/objfmts/elf/elf.h index a78d345f..5a7fb159 100644 --- a/modules/objfmts/elf/elf.h +++ b/modules/objfmts/elf/elf.h @@ -151,6 +151,10 @@ typedef enum { SHF_WRITE = 0x1, /* data should be writable at runtime */ SHF_ALLOC = 0x2, /* occupies memory at runtime */ SHF_EXECINSTR = 0x4, /* contains machine instructions */ + SHF_MERGE = 0x10, /* data can be merged */ + SHF_STRINGS = 0x20, /* contains 0-terminated strings */ + SHF_GROUP = 0x200, /* member of a section group */ + SHF_TLS = 0x400, /* thread local storage */ SHF_MASKOS = 0x0f000000/*,*//* environment specific use */ /*SHF_MASKPROC = 0xf0000000*/ /* bits reserved for processor specific needs */ } elf_section_flags; diff --git a/modules/parsers/gas/gas-bison.y b/modules/parsers/gas/gas-bison.y index af6a8dd1..3a883335 100644 --- a/modules/parsers/gas/gas-bison.y +++ b/modules/parsers/gas/gas-bison.y @@ -43,11 +43,12 @@ RCSID("$Id$"); #include "modules/parsers/gas/gas-defs.h" static void define_label(yasm_parser_gas *parser_gas, char *name, int local); -static yasm_section *gas_get_section(yasm_parser_gas *parser_gas, char *name, - /*@null@*/ char *flags, - /*@null@*/ char *type); +static yasm_section *gas_get_section + (yasm_parser_gas *parser_gas, char *name, /*@null@*/ char *flags, + /*@null@*/ char *type, /*@null@*/ yasm_valparamhead *objext_valparams); static void gas_switch_section(yasm_parser_gas *parser_gas, char *name, - /*@null@*/ char *flags, /*@null@*/ char *type); + /*@null@*/ char *flags, /*@null@*/ char *type, + /*@null@*/ yasm_valparamhead *objext_valparams); static yasm_bytecode *gas_parser_align(yasm_parser_gas *parser_gas, yasm_valparamhead *valparams, int power2); @@ -107,8 +108,8 @@ static void gas_parser_directive %token DIR_BSS DIR_BYTE DIR_COMM DIR_DATA DIR_DOUBLE DIR_ENDR DIR_EXTERN %token DIR_EQU DIR_FILE DIR_FLOAT DIR_GLOBAL DIR_IDENT DIR_INT DIR_LOC %token DIR_LCOMM DIR_OCTA DIR_ORG DIR_P2ALIGN DIR_REPT DIR_SECTION -%token DIR_SHORT DIR_SIZE DIR_SKIP DIR_SLEB128 DIR_STRING -%token DIR_TEXT DIR_TFLOAT DIR_TYPE DIR_QUAD DIR_ULEB128 DIR_WEAK DIR_WORD +%token DIR_SHORT DIR_SIZE DIR_SKIP DIR_SLEB128 DIR_STRING DIR_TEXT +%token DIR_TFLOAT DIR_TYPE DIR_QUAD DIR_ULEB128 DIR_VALUE DIR_WEAK DIR_WORD %token DIR_ZERO %type line lineexp instr @@ -226,7 +227,8 @@ lineexp: instr | DIR_LCOMM label_id ',' expr { /* Put into .bss section. */ /*@dependent@*/ yasm_section *bss = - gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL); + gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL, + NULL); /* TODO: default alignment */ yasm_symtab_define_label(p_symtab, $2, yasm_section_bcs_last(bss), 1, cur_line); @@ -237,7 +239,8 @@ lineexp: instr | DIR_LCOMM label_id ',' expr ',' expr { /* Put into .bss section. */ /*@dependent@*/ yasm_section *bss = - gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL); + gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL, + NULL); /* TODO: force alignment */ yasm_symtab_define_label(p_symtab, $2, yasm_section_bcs_last(bss), 1, cur_line); @@ -273,6 +276,11 @@ lineexp: instr $$ = gas_define_data(parser_gas, &$2, 4); yasm_vps_delete(&$2); } + | DIR_VALUE datavals { + /* XXX: At least on x86, this is two bytes */ + $$ = gas_define_data(parser_gas, &$2, 2); + yasm_vps_delete(&$2); + } | DIR_2BYTE datavals { $$ = gas_define_data(parser_gas, &$2, 2); yasm_vps_delete(&$2); @@ -335,34 +343,41 @@ lineexp: instr } /* Section directives */ | DIR_TEXT { - gas_switch_section(parser_gas, yasm__xstrdup(".text"), NULL, NULL); + gas_switch_section(parser_gas, yasm__xstrdup(".text"), NULL, NULL, + NULL); $$ = NULL; } | DIR_DATA { - gas_switch_section(parser_gas, yasm__xstrdup(".data"), NULL, NULL); + gas_switch_section(parser_gas, yasm__xstrdup(".data"), NULL, NULL, + NULL); $$ = NULL; } | DIR_BSS { - gas_switch_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL); + gas_switch_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL, NULL); $$ = NULL; } | DIR_SECTION label_id { - gas_switch_section(parser_gas, $2, NULL, NULL); + gas_switch_section(parser_gas, $2, NULL, NULL, NULL); $$ = NULL; } | DIR_SECTION label_id ',' STRING { - gas_switch_section(parser_gas, $2, $4, NULL); + gas_switch_section(parser_gas, $2, $4, NULL, NULL); $$ = NULL; } | DIR_SECTION label_id ',' STRING ',' '@' label_id { - gas_switch_section(parser_gas, $2, $4, $7); + gas_switch_section(parser_gas, $2, $4, $7, NULL); + $$ = NULL; + } + | DIR_SECTION label_id ',' STRING ',' '@' label_id ',' datavals { + gas_switch_section(parser_gas, $2, $4, $7, &$9); $$ = NULL; } /* Other directives */ | DIR_IDENT strvals { /* Put text into .comment section. */ /*@dependent@*/ yasm_section *comment = - gas_get_section(parser_gas, yasm__xstrdup(".comment"), NULL, NULL); + gas_get_section(parser_gas, yasm__xstrdup(".comment"), NULL, NULL, + NULL); /* To match GAS output, if the comment section is empty, put an * initial 0 byte in the section. */ @@ -688,7 +703,8 @@ define_label(yasm_parser_gas *parser_gas, char *name, int local) static yasm_section * gas_get_section(yasm_parser_gas *parser_gas, char *name, - /*@null@*/ char *flags, /*@null@*/ char *type) + /*@null@*/ char *flags, /*@null@*/ char *type, + /*@null@*/ yasm_valparamhead *objext_valparams) { yasm_valparamhead vps; yasm_valparam *vp; @@ -713,8 +729,8 @@ gas_get_section(yasm_parser_gas *parser_gas, char *name, yasm_vps_append(&vps, vp); } - new_section = yasm_objfmt_section_switch(parser_gas->objfmt, &vps, NULL, - cur_line); + new_section = yasm_objfmt_section_switch(parser_gas->objfmt, &vps, + objext_valparams, cur_line); yasm_vps_delete(&vps); return new_section; @@ -722,11 +738,13 @@ gas_get_section(yasm_parser_gas *parser_gas, char *name, static void gas_switch_section(yasm_parser_gas *parser_gas, char *name, - /*@null@*/ char *flags, /*@null@*/ char *type) + /*@null@*/ char *flags, /*@null@*/ char *type, + /*@null@*/ yasm_valparamhead *objext_valparams) { yasm_section *new_section; - new_section = gas_get_section(parser_gas, name, flags, type); + new_section = gas_get_section(parser_gas, name, flags, type, + objext_valparams); if (new_section) { parser_gas->cur_section = new_section; parser_gas->prev_bc = yasm_section_bcs_last(new_section); diff --git a/modules/parsers/gas/gas-token.re b/modules/parsers/gas/gas-token.re index 61edb0ed..2f5974f0 100644 --- a/modules/parsers/gas/gas-token.re +++ b/modules/parsers/gas/gas-token.re @@ -299,6 +299,7 @@ scan: '.type' { RETURN(DIR_TYPE); } '.quad' { RETURN(DIR_QUAD); } '.uleb128' { RETURN(DIR_ULEB128); } + '.value' { RETURN(DIR_VALUE); } '.weak' { RETURN(DIR_WEAK); } '.word' { RETURN(DIR_WORD); } '.zero' { RETURN(DIR_ZERO); }