]> granicus.if.org Git - yasm/commitdiff
Add `hidden' `internal' and `protected' symbol visibility types to
authorMichael Urman <mu@tortall.net>
Sat, 12 Mar 2005 05:06:50 +0000 (05:06 -0000)
committerMichael Urman <mu@tortall.net>
Sat, 12 Mar 2005 05:06:50 +0000 (05:06 -0000)
global symbols in ELF. Search for STV_HIDDEN for explanations; these
don't seem to appear in the base ELF documentation.

Sample syntax:
    global foo:hidden

Inspiration and base patch provided by Oskari Saarenmaa under our BSD
license. This checkin tweaks and extends Oskari's patch and adds tests.

svn path=/trunk/yasm/; revision=1202

modules/objfmts/elf/elf-objfmt.c
modules/objfmts/elf/elf-x86-amd64.c
modules/objfmts/elf/elf-x86-x86.c
modules/objfmts/elf/elf.c
modules/objfmts/elf/elf.h
modules/objfmts/elf/tests/Makefile.inc
modules/objfmts/elf/tests/elfvisibility.asm [new file with mode: 0644]
modules/objfmts/elf/tests/elfvisibility.errwarn [new file with mode: 0644]
modules/objfmts/elf/tests/elfvisibility.hex [new file with mode: 0644]

index 8b5c84aed9fcb190cb829a55926860bdc30df15e..59bff2f3531f08a2dca88006d02ce2534419d55f 100644 (file)
@@ -86,8 +86,8 @@ yasm_objfmt_module yasm_elf_LTX_objfmt;
 static elf_symtab_entry *
 elf_objfmt_symtab_append(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym,
                         elf_section_index sectidx, elf_symbol_binding bind,
-                        elf_symbol_type type, yasm_expr *size,
-                        elf_address value)
+                        elf_symbol_type type, elf_symbol_vis vis,
+                         yasm_expr *size, elf_address value)
 {
     elf_strtab_entry *name = elf_strtab_append_str(objfmt_elf->strtab,
                                                   yasm_symrec_get_name(sym));
@@ -95,6 +95,7 @@ elf_objfmt_symtab_append(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym,
     elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
 
     elf_symtab_set_nonzero(entry, NULL, sectidx, bind, type, size, value);
+    elf_sym_set_visibility(entry, vis);
     yasm_symrec_add_data(sym, &elf_symrec_data, entry);
 
     return entry;
@@ -822,8 +823,16 @@ elf_objfmt_extern_declare(yasm_objfmt *objfmt, const char *name, /*@unused@*/
 
     sym = yasm_symtab_declare(objfmt_elf->symtab, name, YASM_SYM_EXTERN, line);
     elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL,
-                            STT_NOTYPE, NULL, 0);
+                             STT_NOTYPE, STV_DEFAULT, NULL, 0);
 
+    if (objext_valparams) {
+       yasm_valparam *vp = yasm_vps_first(objext_valparams);
+       for (; vp; vp = yasm_vps_next(vp))
+        {
+            if (vp->val)
+                yasm__error(line, N_("unrecognized symbol type `%s'"), vp->val);
+        }
+    }
     return sym;
 }
 
@@ -836,30 +845,50 @@ elf_objfmt_global_declare(yasm_objfmt *objfmt, const char *name,
     yasm_symrec *sym;
     elf_symbol_type type = STT_NOTYPE;
     yasm_expr *size = NULL;
+    elf_symbol_vis vis = STV_DEFAULT;
+    unsigned int vis_overrides = 0;
 
     sym = yasm_symtab_declare(objfmt_elf->symtab, name, YASM_SYM_GLOBAL, line);
 
     if (objext_valparams) {
        yasm_valparam *vp = yasm_vps_first(objext_valparams);
-       if (vp && vp->val) {
-           if (yasm__strcasecmp(vp->val, "function") == 0)
-               type = STT_FUNC;
-           else if (yasm__strcasecmp(vp->val, "data") == 0 ||
-                    yasm__strcasecmp(vp->val, "object") == 0)
-               type = STT_OBJECT;
-           else
-               yasm__error(line, N_("unrecognized symbol type `%s'"),
-                           vp->val);
-           vp = yasm_vps_next(vp);
-       }
-       if (vp && !vp->val && vp->param) {
-           size = vp->param;
-           vp->param = NULL;   /* to avoid deleting the expr */
+       for (; vp; vp = yasm_vps_next(vp))
+        {
+            if (vp->val) {
+                if (yasm__strcasecmp(vp->val, "function") == 0)
+                    type = STT_FUNC;
+                else if (yasm__strcasecmp(vp->val, "data") == 0 ||
+                         yasm__strcasecmp(vp->val, "object") == 0)
+                    type = STT_OBJECT;
+                else if (yasm__strcasecmp(vp->val, "internal") == 0) {
+                    vis = STV_INTERNAL;
+                    vis_overrides++;
+                }
+                else if (yasm__strcasecmp(vp->val, "hidden") == 0) {
+                    vis = STV_HIDDEN;
+                    vis_overrides++;
+                }
+                else if (yasm__strcasecmp(vp->val, "protected") == 0) {
+                    vis = STV_PROTECTED;
+                    vis_overrides++;
+                }
+                else
+                    yasm__error(line, N_("unrecognized symbol type `%s'"),
+                                vp->val);
+            }
+            else if (vp->param && !size) {
+                size = vp->param;
+                vp->param = NULL;      /* to avoid deleting the expr */
+            }
        }
+        if (vis_overrides > 1) {
+            yasm__warning(YASM_WARN_GENERAL, line,
+                N_("More than one symbol visibility provided; using last"));
+        }
     }
 
     elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL,
-                            type, size, 0);
+                             type, vis, size, 0);
 
     return sym;
 }
@@ -878,30 +907,32 @@ elf_objfmt_common_declare(yasm_objfmt *objfmt, const char *name,
 
     if (objext_valparams) {
        yasm_valparam *vp = yasm_vps_first(objext_valparams);
-       if (vp && !vp->val && vp->param) {
-            /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr;
-
-            align_expr = yasm_expr_get_intnum(&vp->param, NULL);
-            if (!align_expr) {
-                yasm__error(line,
-                            N_("alignment constraint is not a power of two"));
-                return sym;
-            }
-            addralign = yasm_intnum_get_uint(align_expr);
-
-            /* Alignments must be a power of two. */
-            if ((addralign & (addralign - 1)) != 0) {
-                yasm__error(line,
-                            N_("alignment constraint is not a power of two"));
-                return sym;
-            }
-       } else if (vp && vp->val)
-           yasm__warning(YASM_WARN_GENERAL, line,
-                         N_("Unrecognized qualifier `%s'"), vp->val);
+        for (; vp; vp = yasm_vps_next(vp)) {
+            if (!vp->val && vp->param) {
+                /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr;
+
+                align_expr = yasm_expr_get_intnum(&vp->param, NULL);
+                if (!align_expr) {
+                    yasm__error(line,
+                                N_("alignment constraint is not a power of two"));
+                    return sym;
+                }
+                addralign = yasm_intnum_get_uint(align_expr);
+
+                /* Alignments must be a power of two. */
+                if ((addralign & (addralign - 1)) != 0) {
+                    yasm__error(line,
+                                N_("alignment constraint is not a power of two"));
+                    return sym;
+                }
+            } else if (vp->val)
+                yasm__warning(YASM_WARN_GENERAL, line,
+                              N_("Unrecognized qualifier `%s'"), vp->val);
+        }
     }
 
     elf_objfmt_symtab_append(objfmt_elf, sym, SHN_COMMON, STB_GLOBAL,
-                            STT_NOTYPE, size, addralign);
+                             STT_NOTYPE, STV_DEFAULT, size, addralign);
 
     return sym;
 }
index 29542f92798c7717dac8e0266f4e165a55b492ee..27bfb1c3b02d1f10edbf62f050b91fc4cfb9cab5 100644 (file)
@@ -63,7 +63,7 @@ elf_x86_amd64_write_symtab_entry(unsigned char *bufp,
 {
     YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0);
     YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type));
-    YASM_WRITE_8(bufp, 0);
+    YASM_WRITE_8(bufp, ELF64_ST_OTHER(entry->vis));
     if (entry->sect) {
         if (yasm_section_is_absolute(entry->sect)) {
             YASM_WRITE_16_L(bufp, SHN_ABS);
index e20150ea76f3f373cb0bff0225a9a48572e7b965..d585a398c9bd4ad7a962b1d8eafdf2af3dbb9fa5 100644 (file)
@@ -68,7 +68,7 @@ elf_x86_x86_write_symtab_entry(unsigned char *bufp,
     YASM_WRITE_32I_L(bufp, size_intn);
 
     YASM_WRITE_8(bufp, ELF32_ST_INFO(entry->bind, entry->type));
-    YASM_WRITE_8(bufp, 0);
+    YASM_WRITE_8(bufp, ELF32_ST_OTHER(entry->vis));
     if (entry->sect) {
         if (yasm_section_is_absolute(entry->sect)) {
             YASM_WRITE_16_L(bufp, SHN_ABS);
index 1af535976036549933448ae45d1ba74dc4689e86..3cfa772d7645c510c002cd8d780e50ee0bd4fd62 100644 (file)
@@ -252,6 +252,7 @@ elf_symtab_entry_create(elf_strtab_entry *name,
     entry->index = 0;
     entry->bind = 0;
     entry->type = STT_NOTYPE;
+    entry->vis = STV_DEFAULT;
 
     return entry;
 }
@@ -324,6 +325,7 @@ elf_symtab_create()
     entry->index = SHN_UNDEF;
     entry->bind = 0;
     entry->type = 0;
+    entry->vis = STV_DEFAULT;
     entry->symindex = 0;
     STAILQ_INSERT_TAIL(symtab, entry, qlink);
     return symtab;
@@ -489,6 +491,12 @@ void elf_symtab_set_nonzero(elf_symtab_entry *entry,
     if (value) entry->value = value;
 }
 
+void
+elf_sym_set_visibility(elf_symtab_entry *entry,
+                       elf_symbol_vis    vis)
+{
+    entry->vis = ELF_ST_VISIBILITY(vis);
+}                            
 
 elf_secthead *
 elf_secthead_create(elf_strtab_entry   *name,
index 10208c5c02e05f1e038b4862d9b47b3420be865a..5c5791388ab36866aaff4a153a29bb0aa38e2e76 100644 (file)
@@ -196,15 +196,28 @@ typedef enum {
     STN_UNDEF = 0
 } elf_symbol_index;
 
+/* elf symbol visibility - lower two bits of OTHER field */
+typedef enum {
+    STV_DEFAULT = 0,           /* Default symbol visibility rules */
+    STV_INTERNAL = 1,          /* Processor specific hidden class */
+    STV_HIDDEN = 2,            /* Sym unavailable in other modules */
+    STV_PROTECTED = 3          /* Not preemptable, not exported */
+} elf_symbol_vis;
+
 
 /* internal only object definitions */
 #ifdef YASM_OBJFMT_ELF_INTERNAL
 
+#define ELF_VISIBILITY_MASK            0x03
+#define ELF_ST_VISIBILITY(v)            ((v) & ELF_VISIBILITY_MASK)
+
 #define ELF32_ST_INFO(bind, type)      (((bind) << 4) + ((type) & 0xf))
 #define ELF32_R_INFO(s,t)              (((s)<<8)+(unsigned char)(t))
+#define ELF32_ST_OTHER(vis)             ELF_ST_VISIBILITY(vis)
 
 #define ELF64_ST_INFO(bind, type)      (((bind) << 4) + ((type) & 0xf))
 #define ELF64_R_INFO(s,t)              (((s)<<32) + ((t) & 0xffffffffL))
+#define ELF64_ST_OTHER(vis)             ELF_ST_VISIBILITY(vis)
 
 #define EHDR32_SIZE 52
 #define EHDR64_SIZE 64
@@ -376,6 +389,7 @@ struct elf_symtab_entry {
     elf_section_index   index;
     elf_symbol_binding  bind;
     elf_symbol_type     type;
+    elf_symbol_vis       vis;
     elf_symbol_index    symindex;
 };
 
@@ -422,7 +436,8 @@ void elf_symtab_set_nonzero(elf_symtab_entry        *entry,
                            elf_symbol_type      type,
                            struct yasm_expr    *size,
                            elf_address          value);
-
+void elf_sym_set_visibility(elf_symtab_entry    *entry,
+                            elf_symbol_vis       vis);
 
 /* section header functions */
 elf_secthead *elf_secthead_create(elf_strtab_entry     *name,
index dee1cb8a6c2d4a536fc9883a506ded1da4755353..51d51b0660b211220feb07382d970aaf648088b5 100644 (file)
@@ -34,6 +34,9 @@ EXTRA_DIST += modules/objfmts/elf/tests/elfreloc-ext.hex
 EXTRA_DIST += modules/objfmts/elf/tests/elfabssect.asm
 EXTRA_DIST += modules/objfmts/elf/tests/elfabssect.errwarn
 EXTRA_DIST += modules/objfmts/elf/tests/elfabssect.hex
+EXTRA_DIST += modules/objfmts/elf/tests/elfvisibility.asm
+EXTRA_DIST += modules/objfmts/elf/tests/elfvisibility.errwarn
+EXTRA_DIST += modules/objfmts/elf/tests/elfvisibility.hex
 
 EXTRA_DIST += modules/objfmts/elf/tests/amd64/Makefile.inc
 
diff --git a/modules/objfmts/elf/tests/elfvisibility.asm b/modules/objfmts/elf/tests/elfvisibility.asm
new file mode 100644 (file)
index 0000000..1320310
--- /dev/null
@@ -0,0 +1,6 @@
+[section .text]
+
+global ghidden:hidden
+global ginternal:internal
+global gprotected:protected
+global gtoomany:hidden internal
diff --git a/modules/objfmts/elf/tests/elfvisibility.errwarn b/modules/objfmts/elf/tests/elfvisibility.errwarn
new file mode 100644 (file)
index 0000000..968dc9b
--- /dev/null
@@ -0,0 +1 @@
+-:6: warning: More than one symbol visibility provided; using last
diff --git a/modules/objfmts/elf/tests/elfvisibility.hex b/modules/objfmts/elf/tests/elfvisibility.hex
new file mode 100644 (file)
index 0000000..8b2d2cb
--- /dev/null
@@ -0,0 +1,456 @@
+7f 
+45 
+4c 
+46 
+01 
+01 
+01 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+01 
+00 
+03 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+00 
+34 
+00 
+00 
+00 
+00 
+00 
+28 
+00 
+05 
+00 
+01 
+00 
+00 
+2e 
+74 
+65 
+78 
+74 
+00 
+2e 
+73 
+74 
+72 
+74 
+61 
+62 
+00 
+2e 
+73 
+79 
+6d 
+74 
+61 
+62 
+00 
+2e 
+73 
+68 
+73 
+74 
+72 
+74 
+61 
+62 
+00 
+00 
+00 
+00 
+00 
+2d 
+00 
+67 
+68 
+69 
+64 
+64 
+65 
+6e 
+00 
+67 
+69 
+6e 
+74 
+65 
+72 
+6e 
+61 
+6c 
+00 
+67 
+70 
+72 
+6f 
+74 
+65 
+63 
+74 
+65 
+64 
+00 
+67 
+74 
+6f 
+6f 
+6d 
+61 
+6e 
+79 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+04 
+00 
+f1 
+ff 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+10 
+02 
+00 
+00 
+0b 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+10 
+01 
+00 
+00 
+15 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+10 
+03 
+00 
+00 
+20 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+10 
+01 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+17 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+34 
+00 
+00 
+00 
+21 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+07 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+58 
+00 
+00 
+00 
+29 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+0f 
+00 
+00 
+00 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+84 
+00 
+00 
+00 
+70 
+00 
+00 
+00 
+02 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+04 
+00 
+00 
+00 
+10 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+06 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+10 
+00 
+00 
+00 
+00 
+00 
+00 
+00