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 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;