]> granicus.if.org Git - yasm/commitdiff
* gas-bison.y: Implement .type and .size directives.
authorPeter Johnson <peter@tortall.net>
Sun, 16 Oct 2005 08:45:11 +0000 (08:45 -0000)
committerPeter Johnson <peter@tortall.net>
Sun, 16 Oct 2005 08:45:11 +0000 (08:45 -0000)
* 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
modules/objfmts/elf/elf.c
modules/objfmts/elf/elf.h
modules/parsers/gas/gas-bison.y

index 613f58efd0f72d66cf43f0268594cdc1c09e7fc9..bb42a32c0b2fd2292bd3f9a3f9f11342b7b11866 100644 (file)
@@ -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;
 }
 
 
index 4081f70afd2471ab9065d6eaf3c282a186d4f2dc..a19ccbede94db7af52757d194a1192484068e1ea 100644 (file)
@@ -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,
index c32ff80898963adc0360f55fbca151b7edac6329..a78d345f9df5deab7d69cb01dbb4eb8c09e56f5f 100644 (file)
@@ -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,
index 0148090f2f9f23ce5ca7467f193d1e1b7d6a5a6e..8885fea7631d5437865d744cd9614e3764021bee 100644 (file)
@@ -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  {