This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
The C++ ABI demands that certain data objects are unique in the entire process. This is the case static class members or static variables in inline functions. Jason can provide the necessary details, if needed. I attach a patch which implements a new symbol binding, STB_GNU_UNIQUE. The compile will use this binding, instead of defining the variable as a global variable. Jason already has a patch for gcc which is using the extension of the patch below. There is one detail of the patch which is non-obvious. The interface to get to such an object is not implemented by providing a pseudo-op similar to .global. Instead, I've defined a new symbol type, to be used with the .type pseudo-op. The reason for this is that it is wrong to apply the new symbol binding to anything but data object (no functions in particular). It makes no sense. So, instead of opening the door for misuse the compiler will emit .type name,%gnu_unique_object .global instead of .type name,%object .global At the assembler source level this isn't confusing at all. It's only the translation to what it means at the ELF level that might be a bit confusing. But not many people have to actually deal with this so I don't consider it a problem. The patch below applies on top of the RH binutils RPM. It should also apply with little fuzz to the normal sources. -- â Ulrich Drepper â Red Hat, Inc. â 444 Castro St â Mountain View, CA â
diff -up binutils-2.19.51.0.7/bfd/bfd-in2.h.uobject binutils-2.19.51.0.7/bfd/bfd-in2.h --- binutils-2.19.51.0.7/bfd/bfd-in2.h.uobject 2009-06-01 09:44:22.000000000 -0700 +++ binutils-2.19.51.0.7/bfd/bfd-in2.h 2009-06-01 12:50:59.130760158 -0700 @@ -4627,6 +4627,11 @@ typedef struct bfd_symbol also be also set. */ #define BSF_GNU_INDIRECT_FUNCTION (1 << 22) + /* This symbol is a globally unique data object. The dynamic linker + will make sure that in the entire process there is one symbol with + this name and type in use. BSF_OBJECT must also be set. */ +#define BSF_GNU_UNIQUE (1 << 23) + flagword flags; /* A pointer to the section to which this symbol is diff -up binutils-2.19.51.0.7/bfd/elf-bfd.h.uobject binutils-2.19.51.0.7/bfd/elf-bfd.h --- binutils-2.19.51.0.7/bfd/elf-bfd.h.uobject 2009-06-01 09:44:22.000000000 -0700 +++ binutils-2.19.51.0.7/bfd/elf-bfd.h 2009-06-01 12:50:59.133989942 -0700 @@ -176,6 +176,8 @@ struct elf_link_hash_entry /* Symbol is referenced with a relocation where C/C++ pointer equality matters. */ unsigned int pointer_equality_needed : 1; + /* Symbol is a unique global symbol. */ + unsigned int unique_global : 1; /* String table index in .dynstr if this is a dynamic symbol. */ unsigned long dynstr_index; diff -up binutils-2.19.51.0.7/bfd/elfcode.h.uobject binutils-2.19.51.0.7/bfd/elfcode.h --- binutils-2.19.51.0.7/bfd/elfcode.h.uobject 2009-06-01 12:49:28.425987917 -0700 +++ binutils-2.19.51.0.7/bfd/elfcode.h 2009-06-01 12:50:59.136990644 -0700 @@ -1342,6 +1342,9 @@ elf_slurp_symbol_table (bfd *abfd, asymb case STB_WEAK: sym->symbol.flags |= BSF_WEAK; break; + case STB_GNU_UNIQUE: + sym->symbol.flags |= BSF_GNU_UNIQUE; + break; } switch (ELF_ST_TYPE (isym->st_info)) diff -up binutils-2.19.51.0.7/bfd/elf.c.uobject binutils-2.19.51.0.7/bfd/elf.c --- binutils-2.19.51.0.7/bfd/elf.c.uobject 2009-06-01 09:44:22.000000000 -0700 +++ binutils-2.19.51.0.7/bfd/elf.c 2009-06-01 12:50:59.143989883 -0700 @@ -6566,6 +6566,8 @@ Unable to find equivalent output section if (flags & BSF_LOCAL) bind = STB_LOCAL; + else if (flags & BSF_GNU_UNIQUE) + bind = STB_GNU_UNIQUE; else if (flags & BSF_WEAK) bind = STB_WEAK; else if (flags & BSF_GLOBAL) diff -up binutils-2.19.51.0.7/bfd/elflink.c.uobject binutils-2.19.51.0.7/bfd/elflink.c --- binutils-2.19.51.0.7/bfd/elflink.c.uobject 2009-06-01 09:44:22.000000000 -0700 +++ binutils-2.19.51.0.7/bfd/elflink.c 2009-06-01 12:50:59.153989614 -0700 @@ -1285,6 +1285,9 @@ _bfd_elf_merge_symbol (bfd *abfd, oldweak = (h->root.type == bfd_link_hash_defweak || h->root.type == bfd_link_hash_undefweak); + if (bind == STB_GNU_UNIQUE) + h->unique_global = 1; + /* If a new weak symbol definition comes from a regular file and the old symbol comes from a dynamic library, we treat the new one as strong. Similarly, an old weak symbol definition from a regular @@ -3925,6 +3928,8 @@ elf_link_add_object_symbols (bfd *abfd, } else if (bind == STB_WEAK) flags = BSF_WEAK; + else if (bind == STB_GNU_UNIQUE) + flags = BSF_GNU_UNIQUE; else { /* Leave it up to the processor backend. */ @@ -4183,6 +4188,7 @@ elf_link_add_object_symbols (bfd *abfd, || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; *sym_hash = h; + h->unique_global = (flags & BSF_GNU_UNIQUE) != 0; new_weakdef = FALSE; if (dynamic @@ -8633,6 +8639,8 @@ elf_link_output_extsym (struct elf_link_ sym.st_other = h->other; if (h->forced_local) sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type); + else if (h->unique_global) + sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type); else if (h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_defweak) sym.st_info = ELF_ST_INFO (STB_WEAK, h->type); diff -up binutils-2.19.51.0.7/bfd/syms.c.uobject binutils-2.19.51.0.7/bfd/syms.c --- binutils-2.19.51.0.7/bfd/syms.c.uobject 2009-05-25 07:02:20.000000000 -0700 +++ binutils-2.19.51.0.7/bfd/syms.c 2009-06-01 12:50:59.163990113 -0700 @@ -302,6 +302,10 @@ CODE_FRAGMENT . calling the function that it points to. BSF_FUNCTION must . also be also set. *} .#define BSF_GNU_INDIRECT_FUNCTION (1 << 22) +. {* This symbol is a globally unique data object. The dynamic linker +. will make sure that in the entire process there is one symbol with +. this name and type in use. BSF_OBJECT must also be set. *} +.#define BSF_GNU_UNIQUE (1 << 23) . . flagword flags; . @@ -485,7 +489,8 @@ bfd_print_symbol_vandf (bfd *abfd, void fprintf (file, " %c%c%c%c%c%c%c", ((type & BSF_LOCAL) ? (type & BSF_GLOBAL) ? '!' : 'l' - : (type & BSF_GLOBAL) ? 'g' : ' '), + : (type & BSF_GLOBAL) ? 'g' + : (type & BSF_GNU_UNIQUE) ? 'u' : ' '), (type & BSF_WEAK) ? 'w' : ' ', (type & BSF_CONSTRUCTOR) ? 'C' : ' ', (type & BSF_WARNING) ? 'W' : ' ', @@ -686,6 +691,8 @@ bfd_decode_symclass (asymbol *symbol) else return 'W'; } + if (symbol->flags & BSF_GNU_UNIQUE) + return 'u'; if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL))) return '?'; diff -up binutils-2.19.51.0.7/binutils/readelf.c.uobject binutils-2.19.51.0.7/binutils/readelf.c --- binutils-2.19.51.0.7/binutils/readelf.c.uobject 2009-06-01 09:44:22.000000000 -0700 +++ binutils-2.19.51.0.7/binutils/readelf.c 2009-06-01 12:50:59.166987532 -0700 @@ -7035,7 +7035,14 @@ get_symbol_binding (unsigned int binding snprintf (buff, sizeof (buff), _("<processor specific>: %d"), binding); else if (binding >= STB_LOOS && binding <= STB_HIOS) - snprintf (buff, sizeof (buff), _("<OS specific>: %d"), binding); + { + if (binding == STB_GNU_UNIQUE + && (elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX + /* GNU/Linux is still using the default value 0. */ + || elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE)) + return "UNIQUE"; + snprintf (buff, sizeof (buff), _("<OS specific>: %d"), binding); + } else snprintf (buff, sizeof (buff), _("<unknown>: %d"), binding); return buff; diff -up binutils-2.19.51.0.7/elfcpp/elfcpp.h.uobject binutils-2.19.51.0.7/elfcpp/elfcpp.h --- binutils-2.19.51.0.7/elfcpp/elfcpp.h.uobject 2009-05-29 14:08:38.000000000 -0700 +++ binutils-2.19.51.0.7/elfcpp/elfcpp.h 2009-06-01 12:50:59.167985368 -0700 @@ -476,6 +476,7 @@ enum STB STB_GLOBAL = 1, STB_WEAK = 2, STB_LOOS = 10, + STB_GNU_UNIQUE = 10, STB_HIOS = 12, STB_LOPROC = 13, STB_HIPROC = 15 diff -up binutils-2.19.51.0.7/gas/config/obj-elf.c.uobject binutils-2.19.51.0.7/gas/config/obj-elf.c --- binutils-2.19.51.0.7/gas/config/obj-elf.c.uobject 2009-06-01 09:44:21.000000000 -0700 +++ binutils-2.19.51.0.7/gas/config/obj-elf.c 2009-06-01 12:50:59.168987604 -0700 @@ -1720,6 +1720,18 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSE typename); type = BSF_FUNCTION | BSF_GNU_INDIRECT_FUNCTION; } + else if (strcmp (typename, "gnu_unique_object") == 0) + { + const struct elf_backend_data *bed; + + bed = get_elf_backend_data (stdoutput); + if (!(bed->elf_osabi == ELFOSABI_LINUX + /* GNU/Linux is still using the default value 0. */ + || bed->elf_osabi == ELFOSABI_NONE)) + as_bad (_("symbol type \"%s\" is supported only by GNU targets"), + typename); + type = BSF_OBJECT | BSF_GNU_UNIQUE; + } #ifdef md_elf_symbol_type else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1) ; diff -up binutils-2.19.51.0.7/include/elf/common.h.uobject binutils-2.19.51.0.7/include/elf/common.h --- binutils-2.19.51.0.7/include/elf/common.h.uobject 2009-06-01 09:44:21.000000000 -0700 +++ binutils-2.19.51.0.7/include/elf/common.h 2009-06-01 12:50:59.169985510 -0700 @@ -558,6 +558,7 @@ #define STB_GLOBAL 1 /* Symbol visible outside obj */ #define STB_WEAK 2 /* Like globals, lower precedence */ #define STB_LOOS 10 /* OS-specific semantics */ +#define STB_GNU_UNIQUE 10 /* Symbol is unique in namespace */ #define STB_HIOS 12 /* OS-specific semantics */ #define STB_LOPROC 13 /* Processor-specific semantics */ #define STB_HIPROC 15 /* Processor-specific semantics */
Attachment:
signature.asc
Description: OpenPGP digital signature
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |