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",