From: Michael Urman <mu@tortall.net> Date: Sat, 12 Mar 2005 05:06:50 +0000 (-0000) Subject: Add `hidden' `internal' and `protected' symbol visibility types to X-Git-Tag: v0.5.0rc1~172 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3cc450d3ea88c4e22cd16b2459bef8c7b3f124ef;p=yasm Add `hidden' `internal' and `protected' symbol visibility types to 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 --- diff --git a/modules/objfmts/elf/elf-objfmt.c b/modules/objfmts/elf/elf-objfmt.c index 8b5c84ae..59bff2f3 100644 --- a/modules/objfmts/elf/elf-objfmt.c +++ b/modules/objfmts/elf/elf-objfmt.c @@ -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; } diff --git a/modules/objfmts/elf/elf-x86-amd64.c b/modules/objfmts/elf/elf-x86-amd64.c index 29542f92..27bfb1c3 100644 --- a/modules/objfmts/elf/elf-x86-amd64.c +++ b/modules/objfmts/elf/elf-x86-amd64.c @@ -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); diff --git a/modules/objfmts/elf/elf-x86-x86.c b/modules/objfmts/elf/elf-x86-x86.c index e20150ea..d585a398 100644 --- a/modules/objfmts/elf/elf-x86-x86.c +++ b/modules/objfmts/elf/elf-x86-x86.c @@ -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); diff --git a/modules/objfmts/elf/elf.c b/modules/objfmts/elf/elf.c index 1af53597..3cfa772d 100644 --- a/modules/objfmts/elf/elf.c +++ b/modules/objfmts/elf/elf.c @@ -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, diff --git a/modules/objfmts/elf/elf.h b/modules/objfmts/elf/elf.h index 10208c5c..5c579138 100644 --- a/modules/objfmts/elf/elf.h +++ b/modules/objfmts/elf/elf.h @@ -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, diff --git a/modules/objfmts/elf/tests/Makefile.inc b/modules/objfmts/elf/tests/Makefile.inc index dee1cb8a..51d51b06 100644 --- a/modules/objfmts/elf/tests/Makefile.inc +++ b/modules/objfmts/elf/tests/Makefile.inc @@ -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 index 00000000..13203106 --- /dev/null +++ b/modules/objfmts/elf/tests/elfvisibility.asm @@ -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 index 00000000..968dc9bb --- /dev/null +++ b/modules/objfmts/elf/tests/elfvisibility.errwarn @@ -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 index 00000000..8b2d2cb0 --- /dev/null +++ b/modules/objfmts/elf/tests/elfvisibility.hex @@ -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