summaryrefslogtreecommitdiff
blob: d4f1948b5d065ba258e2639922681c9e210300ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
Add support for declaring elf visibility attributes.  Used to
help cleanup TEXTRELs in misc libraries (like libsdl).

Syntax to declare function foo hidden:
GLOBAL foo:function hidden

Patch by Mike Frysinger <vapier@gentoo.org>

http://sourceforge.net/mailarchive/forum.php?thread_id=9230919&forum_id=4978

--- nasm/output/outelf.c
+++ nasm/output/outelf.c
@@ -50,6 +50,7 @@ struct Symbol {
     long strpos;                /* string table position of name */
     long section;               /* section ID of the symbol */
     int type;                   /* symbol type */
+    int other;                  /* symbol visibility */
     long value;                 /* address, or COMMON variable align */
     long size;                  /* size of symbol */
     long globnum;               /* symbol table offset if global */
@@ -113,9 +114,15 @@ extern struct ofmt of_elf;
 
 #define SYM_SECTION 0x04
 #define SYM_GLOBAL 0x10
+#define SYM_NOTYPE 0x00
 #define SYM_DATA 0x01
 #define SYM_FUNCTION 0x02
 
+#define STV_DEFAULT 0
+#define STV_INTERNAL 1
+#define STV_HIDDEN 2
+#define STV_PROTECTED 3
+
 #define GLOBAL_TEMP_BASE 16     /* bigger than any constant sym id */
 
 #define SEG_ALIGN 16            /* alignment of sections in file */
@@ -493,6 +500,7 @@ static void elf_deflabel(char *name, lon
 
     sym->strpos = pos;
     sym->type = is_global ? SYM_GLOBAL : 0;
+    sym->other = STV_DEFAULT;
     sym->size = 0;
     if (segment == NO_SEG)
         sym->section = SHN_ABS;
@@ -570,18 +578,39 @@ static void elf_deflabel(char *name, lon
             sym->next = sects[sym->section - 1]->gsyms;
             sects[sym->section - 1]->gsyms = sym;
 
+            /* ELF syntax: GLOBAL name[:type [visibility]] */
             if (special) {
-                int n = strcspn(special, " ");
-
+                int n = strcspn(special, " \t");
                 if (!nasm_strnicmp(special, "function", n))
                     sym->type |= SYM_FUNCTION;
                 else if (!nasm_strnicmp(special, "data", n) ||
                          !nasm_strnicmp(special, "object", n))
                     sym->type |= SYM_DATA;
+                else if (!nasm_strnicmp(special, "notype", n))
+                    sym->type |= SYM_NOTYPE;
                 else
                     error(ERR_NONFATAL, "unrecognised symbol type `%.*s'",
                           n, special);
+                special += n;
+
+                while (isspace(*special))
+                    ++special;
+                if (*special) {
+                    n = strcspn(special, " \t");
+                    if (!nasm_strnicmp(special, "default", n))
+                        sym->other = STV_DEFAULT;
+                    else if (!nasm_strnicmp(special, "internal", n))
+                        sym->other = STV_INTERNAL;
+                    else if (!nasm_strnicmp(special, "hidden", n))
+                        sym->other = STV_HIDDEN;
+                    else if (!nasm_strnicmp(special, "protected", n))
+                        sym->other = STV_PROTECTED;
+                    else
+                        n = 0;
+                    special += n;
+                }
+
-                if (special[n]) {
+                if (*special) {
                     struct tokenval tokval;
                     expr *e;
                     int fwd = FALSE;
@@ -1120,7 +1149,8 @@ static struct SAA *elf_build_symtab(long
         WRITELONG(p, sym->strpos);
         WRITELONG(p, sym->value);
         WRITELONG(p, sym->size);
-        WRITESHORT(p, sym->type);       /* local non-typed thing */
+        WRITECHAR(p, sym->type);       /* local non-typed thing */
+        WRITECHAR(p, sym->other);
         WRITESHORT(p, sym->section);
         saa_wbytes(s, entry, 16L);
         *len += 16;
@@ -1138,7 +1168,8 @@ static struct SAA *elf_build_symtab(long
         WRITELONG(p, sym->strpos);
         WRITELONG(p, sym->value);
         WRITELONG(p, sym->size);
-        WRITESHORT(p, sym->type);       /* global non-typed thing */
+        WRITECHAR(p, sym->type);       /* global non-typed thing */
+        WRITECHAR(p, sym->other);
         WRITESHORT(p, sym->section);
         saa_wbytes(s, entry, 16L);
         *len += 16;