From 2555e36799fb8fdd415ad89f35c515885827e910 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sun, 16 Oct 2005 08:45:11 +0000 Subject: [PATCH] * gas-bison.y: Implement .type and .size directives. * elf-objfmt.c (elf_objfmt_directive): Implement type/size/weak for ELF output. * elf.h (elf_sym_set_type, elf_sym_set_size): Supporting functions. * elf.c (elf_sym_set_type, elf_sym_set_size): Implement. svn path=/trunk/yasm/; revision=1285 --- modules/objfmts/elf/elf-objfmt.c | 76 +++++++++++++++++++++++++++++--- modules/objfmts/elf/elf.c | 16 +++++++ modules/objfmts/elf/elf.h | 2 + modules/parsers/gas/gas-bison.y | 28 +++++++++++- 4 files changed, 115 insertions(+), 7 deletions(-) diff --git a/modules/objfmts/elf/elf-objfmt.c b/modules/objfmts/elf/elf-objfmt.c index 613f58ef..bb42a32c 100644 --- a/modules/objfmts/elf/elf-objfmt.c +++ b/modules/objfmts/elf/elf-objfmt.c @@ -988,14 +988,80 @@ elf_objfmt_common_declare(yasm_objfmt *objfmt, const char *name, } static int -elf_objfmt_directive(/*@unused@*/ yasm_objfmt *objfmt, - /*@unused@*/ const char *name, - /*@unused@*/ yasm_valparamhead *valparams, +elf_objfmt_directive(yasm_objfmt *objfmt, const char *name, + yasm_valparamhead *valparams, /*@unused@*/ /*@null@*/ yasm_valparamhead *objext_valparams, - /*@unused@*/ unsigned long line) + unsigned long line) { - return 1; /* no objfmt directives */ + yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt; + yasm_symrec *sym; + yasm_valparam *vp = yasm_vps_first(valparams); + char *symname = vp->val; + elf_symtab_entry *entry; + + if (!symname) { + yasm__error(line, N_("Symbol name not specified")); + return 0; + } + + if (yasm__strcasecmp(name, "type") == 0) { + /* Get symbol elf data */ + sym = yasm_symtab_use(objfmt_elf->symtab, symname, line); + entry = yasm_symrec_get_data(sym, &elf_symrec_data); + + /* Create entry if necessary */ + if (!entry) { + entry = elf_symtab_entry_create( + elf_strtab_append_str(objfmt_elf->strtab, symname), sym); + elf_symtab_append_entry(objfmt_elf->elf_symtab, entry); + yasm_symrec_add_data(sym, &elf_symrec_data, entry); + } + + /* Pull new type from val */ + vp = yasm_vps_next(vp); + if (vp->val) { + if (yasm__strcasecmp(vp->val, "function") == 0) + elf_sym_set_type(entry, STT_FUNC); + else if (yasm__strcasecmp(vp->val, "object") == 0) + elf_sym_set_type(entry, STT_OBJECT); + else + yasm__warning(YASM_WARN_GENERAL, line, + N_("unrecognized symbol type `%s'"), vp->val); + } else + yasm__error(line, N_("no type specified")); + } else if (yasm__strcasecmp(name, "size") == 0) { + /* Get symbol elf data */ + sym = yasm_symtab_use(objfmt_elf->symtab, symname, line); + entry = yasm_symrec_get_data(sym, &elf_symrec_data); + + /* Create entry if necessary */ + if (!entry) { + entry = elf_symtab_entry_create( + elf_strtab_append_str(objfmt_elf->strtab, symname), sym); + elf_symtab_append_entry(objfmt_elf->elf_symtab, entry); + yasm_symrec_add_data(sym, &elf_symrec_data, entry); + } + + /* Pull new size from either param (expr) or val */ + vp = yasm_vps_next(vp); + if (vp->param) { + elf_sym_set_size(entry, vp->param); + vp->param = NULL; + } else if (vp->val) + elf_sym_set_size(entry, yasm_expr_create_ident(yasm_expr_sym( + yasm_symtab_use(objfmt_elf->symtab, vp->val, line)), line)); + else + yasm__error(line, N_("no size specified")); + } else if (yasm__strcasecmp(name, "weak") == 0) { + sym = yasm_symtab_declare(objfmt_elf->symtab, symname, YASM_SYM_GLOBAL, + line); + elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK, + STT_NOTYPE, STV_DEFAULT, NULL, 0); + } else + return 1; /* unrecognized */ + + return 0; } diff --git a/modules/objfmts/elf/elf.c b/modules/objfmts/elf/elf.c index 4081f70a..a19ccbed 100644 --- a/modules/objfmts/elf/elf.c +++ b/modules/objfmts/elf/elf.c @@ -499,6 +499,22 @@ elf_sym_set_visibility(elf_symtab_entry *entry, entry->vis = ELF_ST_VISIBILITY(vis); } +void +elf_sym_set_type(elf_symtab_entry *entry, + elf_symbol_type type) +{ + entry->type = type; +} + +void +elf_sym_set_size(elf_symtab_entry *entry, + struct yasm_expr *size) +{ + if (entry->xsize) + yasm_expr_destroy(entry->xsize); + entry->xsize = size; +} + elf_secthead * elf_secthead_create(elf_strtab_entry *name, elf_section_type type, diff --git a/modules/objfmts/elf/elf.h b/modules/objfmts/elf/elf.h index c32ff808..a78d345f 100644 --- a/modules/objfmts/elf/elf.h +++ b/modules/objfmts/elf/elf.h @@ -442,6 +442,8 @@ void elf_symtab_set_nonzero(elf_symtab_entry *entry, elf_address value); void elf_sym_set_visibility(elf_symtab_entry *entry, elf_symbol_vis vis); +void elf_sym_set_type(elf_symtab_entry *entry, elf_symbol_type type); +void elf_sym_set_size(elf_symtab_entry *entry, struct yasm_expr *size); /* section header functions */ elf_secthead *elf_secthead_create(elf_strtab_entry *name, diff --git a/modules/parsers/gas/gas-bison.y b/modules/parsers/gas/gas-bison.y index 0148090f..8885fea7 100644 --- a/modules/parsers/gas/gas-bison.y +++ b/modules/parsers/gas/gas-bison.y @@ -367,11 +367,35 @@ lineexp: instr $$ = NULL; } | DIR_TYPE label_id ',' '@' label_id { - /* TODO */ + yasm_valparamhead vps; + yasm_valparam *vp; + + yasm_vps_initialize(&vps); + vp = yasm_vp_create($2, NULL); + yasm_vps_append(&vps, vp); + vp = yasm_vp_create($5, NULL); + yasm_vps_append(&vps, vp); + + yasm_objfmt_directive(parser_gas->objfmt, "type", &vps, NULL, + cur_line); + + yasm_vps_delete(&vps); $$ = NULL; } | DIR_SIZE label_id ',' expr { - /* TODO */ + yasm_valparamhead vps; + yasm_valparam *vp; + + yasm_vps_initialize(&vps); + vp = yasm_vp_create($2, NULL); + yasm_vps_append(&vps, vp); + vp = yasm_vp_create(NULL, $4); + yasm_vps_append(&vps, vp); + + yasm_objfmt_directive(parser_gas->objfmt, "size", &vps, NULL, + cur_line); + + yasm_vps_delete(&vps); $$ = NULL; } | DIR_ID datavals { -- 2.40.0