Mercurial > hg > qcc
changeset 469:bb13836ab658
Patch from Vincent Pit to fix visibility problems in the linker (resulting
in error "/usr/lib/libc_nonshared.a: '__i686.get_pc_thunk.bx' defined twice").
Unfortunately, this patch results in strip complaining
"no group info for section .text.__i686.get_pc_thunk.bx", but it's progress.
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 04 Sep 2007 23:51:37 -0500 |
parents | d3c99a19c0ce |
children | 44036032a50a |
files | tccelf.c |
diffstat | 1 files changed, 19 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/tccelf.c Tue Sep 04 23:34:33 2007 -0500 +++ b/tccelf.c Tue Sep 04 23:51:37 2007 -0500 @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <limits.h> + static int put_elf_str(Section *s, const char *sym) { int offset, len; @@ -182,9 +184,11 @@ { Elf32_Sym *esym; int sym_bind, sym_index, sym_type, esym_bind; + unsigned char sym_vis, esym_vis, new_vis; sym_bind = ELF32_ST_BIND(info); sym_type = ELF32_ST_TYPE(info); + sym_vis = ELF32_ST_VISIBILITY(other); if (sym_bind != STB_LOCAL) { /* we search global or weak symbols */ @@ -194,6 +198,19 @@ esym = &((Elf32_Sym *)s->data)[sym_index]; if (esym->st_shndx != SHN_UNDEF) { esym_bind = ELF32_ST_BIND(esym->st_info); + /* propagate the most constraining visibility */ + /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */ + esym_vis = ELF32_ST_VISIBILITY(esym->st_other); + if (esym_vis == STV_DEFAULT) { + new_vis = sym_vis; + } else if (sym_vis == STV_DEFAULT) { + new_vis = esym_vis; + } else { + new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis; + } + esym->st_other = (esym->st_other & ~ELF32_ST_VISIBILITY(UCHAR_MAX)) + | new_vis; + other = esym->st_other; /* in case we have to patch esym */ if (sh_num == SHN_UNDEF) { /* ignore adding of undefined symbol if the corresponding symbol is already defined */ @@ -202,6 +219,8 @@ goto do_patch; } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) { /* weak is ignored if already global */ + } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) { + /* ignore hidden symbols after */ } else { #if 0 printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",