summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Kotler <fbkotler@users.sourceforge.net>2007-08-26 05:10:24 +0000
committerFrank Kotler <fbkotler@users.sourceforge.net>2007-08-26 05:10:24 +0000
commit155eef6a3d309fdfef45f4476590234007fdbf9b (patch)
tree604b879f51adee60f5f70a100472a0b29283d0ff
parent85f5f148bb6536f326c3d3c0ba9c516998f2e798 (diff)
downloadnasm-155eef6a3d309fdfef45f4476590234007fdbf9b.tar.gz
finally commit Mike Frysinger's "elf-visibility" patch
-rw-r--r--doc/nasmdoc.src7
-rw-r--r--output/outelf32.c39
-rw-r--r--output/outelf64.c39
3 files changed, 77 insertions, 8 deletions
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index 48c5bdf0..ee8c0f62 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -4408,6 +4408,13 @@ object by suffixing the name with a colon and the word
exports the global symbol \c{hashlookup} as a function and
\c{hashtable} as a data object.
+Optionally, you can control the ELF visibility of the symbol. Just
+add one of the visibility keywords: \i\c{default}, \i\c{internal},
+\i\c{hidden}, or \i\c{protected}. The default is \i\c{default} of
+course. For example, to make \c{hashlookup} hidden:
+
+\c global hashlookup:function hidden
+
You can also specify the size of the data associated with the
symbol, as a numeric expression (which may involve labels, and even
forward references) after the type specifier. Like this:
diff --git a/output/outelf32.c b/output/outelf32.c
index 739417da..6c16645a 100644
--- a/output/outelf32.c
+++ b/output/outelf32.c
@@ -51,6 +51,7 @@ struct Symbol {
int32_t strpos; /* string table position of name */
int32_t section; /* section ID of the symbol */
int type; /* symbol type */
+ int other; /* symbol visibility */
int32_t value; /* address, or COMMON variable align */
int32_t size; /* size of symbol */
int32_t globnum; /* symbol table offset if global */
@@ -115,9 +116,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 */
@@ -495,6 +502,7 @@ static void elf_deflabel(char *name, int32_t segment, int32_t offset,
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;
@@ -566,17 +574,38 @@ static void elf_deflabel(char *name, int32_t segment, int32_t offset,
sects[sym->section - 1]->gsyms = sym;
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);
- if (special[n]) {
+ 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) {
struct tokenval tokval;
expr *e;
int fwd = FALSE;
@@ -1115,7 +1144,8 @@ static struct SAA *elf_build_symtab(int32_t *len, int32_t *local)
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;
@@ -1133,7 +1163,8 @@ static struct SAA *elf_build_symtab(int32_t *len, int32_t *local)
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;
diff --git a/output/outelf64.c b/output/outelf64.c
index f53a022e..b83bab77 100644
--- a/output/outelf64.c
+++ b/output/outelf64.c
@@ -71,6 +71,7 @@ struct Symbol {
int32_t strpos; /* string table position of name */
int32_t section; /* section ID of the symbol */
int type; /* symbol type */
+ int other; /* symbol visibility */
int32_t value; /* address, or COMMON variable align */
int32_t size; /* size of symbol */
int32_t globnum; /* symbol table offset if global */
@@ -126,9 +127,15 @@ extern struct ofmt of_elf64;
#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 */
@@ -507,6 +514,7 @@ static void elf_deflabel(char *name, int32_t segment, int32_t offset,
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;
@@ -578,17 +586,38 @@ static void elf_deflabel(char *name, int32_t segment, int32_t offset,
sects[sym->section - 1]->gsyms = sym;
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);
- if (special[n]) {
+ 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) {
struct tokenval tokval;
expr *e;
int fwd = FALSE;
@@ -1127,7 +1156,8 @@ static struct SAA *elf_build_symtab(int32_t *len, int32_t *local)
continue;
p = entry;
WRITELONG(p, sym->strpos);
- WRITESHORT(p, sym->type); /* local non-typed thing */
+ WRITECHAR(p, sym->type); /* local non-typed thing */
+ WRITECHAR(p, sym->other);
WRITESHORT(p, sym->section);
WRITEDLONG(p, (int64_t)sym->value);
WRITEDLONG(p, (int64_t)sym->size);
@@ -1145,7 +1175,8 @@ static struct SAA *elf_build_symtab(int32_t *len, int32_t *local)
continue;
p = entry;
WRITELONG(p, sym->strpos);
- WRITESHORT(p, sym->type); /* global non-typed thing */
+ WRITECHAR(p, sym->type); /* global non-typed thing */
+ WRITECHAR(p, sym->other);
WRITESHORT(p, sym->section);
WRITEDLONG(p, (int64_t)sym->value);
WRITEDLONG(p, (int64_t)sym->size);