--- /dev/null
+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;