From 3e7a7d11f1106a451c26b49fcb8fafb5059fd684 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 23 Jul 2009 13:00:30 +0000 Subject: [PATCH] * config/obj-elf.c (obj_elf_type): Add code to support a type of gnu_unique_object. * doc/as.texinfo: Document new feature of .type directive. * NEWS: Mention support for gnu_unique_object symbol type. * common.h (STB_GNU_UNIQUE): Define. * NEWS: Mention the linker's support for symbols with a binding of STB_GNU_UNIQUE. * gas/elf/type.s: Add unique global symbol definition. * gas/elf/type.e: Add expected readelf output for global unique symbol. * elfcpp.h (enum STB): Add STB_GNU_UNIQUE. * readelf.c (get_symbol_binding): For Linux targeted files return UNIQUE for symbols with the STB_GNU_UNIQUE binding. * doc/binutils.texi: Document the meaning of the 'u' symbol binding in the output of nm and objdump --syms. * elf-bfd.h (struct elf_link_hash_entry): Add unique_global field. * elf.c (swap_out_syms): Set binding to STB_GNU_UNIQUE for symbols with the BSF_GNU_UNIQUE flag bit set. * elfcode.h (elf_slurp_symbol_table): Set the BSF_GNU_UNIQUE flag for symbols with STB_GNU_UNIQUE binding. * elflink.c (_bfd_elf_merge_symbol): Set unique_global for symbols with the STB_GNU_UNIQUE binding. (elf_link_add_object_symbols): Set the BSF_GNU_UNIQUE flag for symbols with STB_GNU_UNIQUE binding. Set STB_GNU_UNIQUE for symbols with the unique_global field set. (elf_link_output_extsym): Set unique_global field for symbols with the STB_GNU_UNIQUE binding. * syms.c (struct bfd_symbol): Define BSF_GNU_UNIQUE flag bit. (bfd_print_symbol_vandf): Print a 'u' character for BSF_GNU_UNIQUE symbols. (bfd_decode_symclass): Return a 'u' character for BSF_GNU_UNIQUE symbols. * bfd-in2.h: Regenerate. --- bfd/ChangeLog | 21 +++++++++++++++++++++ bfd/bfd-in2.h | 4 ++++ bfd/elf-bfd.h | 2 ++ bfd/elf.c | 2 ++ bfd/elfcode.h | 5 ++++- bfd/elflink.c | 32 +++++++++++++++++++++++--------- bfd/syms.c | 9 ++++++++- binutils/ChangeLog | 7 +++++++ binutils/doc/binutils.texi | 23 ++++++++++++++++++++--- binutils/readelf.c | 9 ++++++++- elfcpp/ChangeLog | 4 ++++ elfcpp/elfcpp.h | 1 + gas/ChangeLog | 7 +++++++ gas/NEWS | 4 ++++ gas/config/obj-elf.c | 16 ++++++++++++++-- gas/doc/as.texinfo | 5 +++++ gas/testsuite/ChangeLog | 6 ++++++ gas/testsuite/gas/elf/type.e | 1 + gas/testsuite/gas/elf/type.s | 11 +++++++++++ include/elf/ChangeLog | 4 ++++ include/elf/common.h | 3 ++- ld/ChangeLog | 5 +++++ ld/NEWS | 4 ++++ 23 files changed, 167 insertions(+), 18 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7987bbc927b..42dd8e3ce33 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,24 @@ +2009-07-23 Ulrich Drepper + + * elf-bfd.h (struct elf_link_hash_entry): Add unique_global field. + * elf.c (swap_out_syms): Set binding to STB_GNU_UNIQUE for symbols + with the BSF_GNU_UNIQUE flag bit set. + * elfcode.h (elf_slurp_symbol_table): Set the BSF_GNU_UNIQUE flag + for symbols with STB_GNU_UNIQUE binding. + * elflink.c (_bfd_elf_merge_symbol): Set unique_global for symbols + with the STB_GNU_UNIQUE binding. + (elf_link_add_object_symbols): Set the BSF_GNU_UNIQUE flag for + symbols with STB_GNU_UNIQUE binding. Set STB_GNU_UNIQUE for + symbols with the unique_global field set. + (elf_link_output_extsym): Set unique_global field for symbols with + the STB_GNU_UNIQUE binding. + * syms.c (struct bfd_symbol): Define BSF_GNU_UNIQUE flag bit. + (bfd_print_symbol_vandf): Print a 'u' character for BSF_GNU_UNIQUE + symbols. + (bfd_decode_symclass): Return a 'u' character for BSF_GNU_UNIQUE + symbols. + * bfd-in2.h: Regenerate. + 2009-07-22 H.J. Lu * elflink.c (elf_link_output_extsym): Revert the last change. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 5244b9ae1e0..562f8338b69 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -4639,6 +4639,10 @@ typedef struct bfd_symbol 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 just one symbol + with this name and type in use. BSF_OBJECT must also be set. */ +#define BSF_GNU_UNIQUE (1 << 23) flagword flags; diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 1690def1c8d..8f70d7923a0 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -178,6 +178,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 --git a/bfd/elf.c b/bfd/elf.c index 19f26842046..f27c607ab2b 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -6446,6 +6446,8 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"), 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 --git a/bfd/elfcode.h b/bfd/elfcode.h index 024ead4930a..10aa13140e7 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1,6 +1,6 @@ /* ELF executable support for BFD. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published @@ -1282,6 +1282,9 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) 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 --git a/bfd/elflink.c b/bfd/elflink.c index f9b577c7738..a11706383f7 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1248,6 +1248,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 @@ -3871,24 +3874,31 @@ error_free_dyn: common = bed->common_definition (isym); bind = ELF_ST_BIND (isym->st_info); - if (bind == STB_LOCAL) + switch (bind) { + case STB_LOCAL: /* This should be impossible, since ELF requires that all global symbols follow all local symbols, and that sh_info point to the first global symbol. Unfortunately, Irix 5 screws this up. */ continue; - } - else if (bind == STB_GLOBAL) - { + + case STB_GLOBAL: if (isym->st_shndx != SHN_UNDEF && !common) flags = BSF_GLOBAL; - } - else if (bind == STB_WEAK) - flags = BSF_WEAK; - else - { + break; + + case STB_WEAK: + flags = BSF_WEAK; + break; + + case STB_GNU_UNIQUE: + flags = BSF_GNU_UNIQUE; + break; + + default: /* Leave it up to the processor backend. */ + break; } if (isym->st_shndx == SHN_UNDEF) @@ -4140,7 +4150,9 @@ error_free_dyn: while (h->root.type == bfd_link_hash_indirect || 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 @@ -8571,6 +8583,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) 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 --git a/bfd/syms.c b/bfd/syms.c index 6abb9294704..e4258b556a4 100644 --- a/bfd/syms.c +++ b/bfd/syms.c @@ -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 just 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 *arg, asymbol *symbol) 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 --git a/binutils/ChangeLog b/binutils/ChangeLog index 89b1a668f89..28caa230ea3 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2009-07-23 Ulrich Drepper + + * readelf.c (get_symbol_binding): For Linux targeted files return + UNIQUE for symbols with the STB_GNU_UNIQUE binding. + * doc/binutils.texi: Document the meaning of the 'u' symbol + binding in the output of nm and objdump --syms. + 2009-07-20 H.J. Lu * NEWS: Mention --insn-width. diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 98438f2af4e..a5856b2b12a 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -745,7 +745,13 @@ object file formats permit more efficient access to small data objects, such as a global int variable as opposed to a large global array. @item i -The symbol is in a section specific to the implementation of DLLs. +For PE format files this indicates that the symbol is in a section +specific to the implementation of DLLs. For ELF format files this +indicates that the symbol is an indirect function. This is a GNU +extension to the standard set of ELF symbol types. It indicates a +symbol which if referenced by a relocation does not evaluate to its +address, but instead must be invoked at runtime. The runtime +execution will then return the value to be used in the relocation. @item N The symbol is a debugging symbol. @@ -768,6 +774,12 @@ The symbol is in the text (code) section. @item U The symbol is undefined. +@item u +The symbol is a unique global symbol. This is a GNU extension to the +standard set of ELF symbol bindings. For such a symbol the dynamic linker +will make sure that in the entire process there is just one symbol with +this name and type in use. + @item V @itemx v The symbol is a weak object. When a weak defined symbol is linked with @@ -2142,11 +2154,16 @@ The flag characters are divided into 7 groups as follows: @table @code @item l @itemx g +@itemx u @itemx ! -The symbol is local (l), global (g), neither (a space) or both (!). A +The symbol is a local (l), global (g), unique global (u), neither +global nor local (a space) or both global and local (!). A symbol can be neither local or global for a variety of reasons, e.g., because it is used for debugging, but it is probably an indication of -a bug if it is ever both local and global. +a bug if it is ever both local and global. Unique global symbols are +a GNU extension to the standard set of ELF symbol bindings. For such +a symbol the dynamic linker will make sure that in the entire process +there is just one symbol with this name and type in use. @item w The symbol is weak (w) or strong (a space). diff --git a/binutils/readelf.c b/binutils/readelf.c index ce739e68449..f56e6c2f267 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -6902,7 +6902,14 @@ get_symbol_binding (unsigned int binding) snprintf (buff, sizeof (buff), _(": %d"), binding); else if (binding >= STB_LOOS && binding <= STB_HIOS) - snprintf (buff, sizeof (buff), _(": %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), _(": %d"), binding); + } else snprintf (buff, sizeof (buff), _(": %d"), binding); return buff; diff --git a/elfcpp/ChangeLog b/elfcpp/ChangeLog index 2a8204f8ae7..2a668a67444 100644 --- a/elfcpp/ChangeLog +++ b/elfcpp/ChangeLog @@ -1,3 +1,7 @@ +2009-07-23 Ulrich Drepper + + * elfcpp.h (enum STB): Add STB_GNU_UNIQUE. + 2009-06-21 Ian Lance Taylor * elfcpp.h (SHN_X86_64_LCOMMON): Define enum constant. diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index 1b1a875c3d7..683cd9dceb0 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -485,6 +485,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 --git a/gas/ChangeLog b/gas/ChangeLog index 8f150fc5ade..de98024c00b 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2009-07-23 Ulrich Drepper + + * config/obj-elf.c (obj_elf_type): Add code to support a type of + gnu_unique_object. + * doc/as.texinfo: Document new feature of .type directive. + * NEWS: Mention support for gnu_unique_object symbol type. + 2009-07-23 Nick Clifton PR binutils/10379 diff --git a/gas/NEWS b/gas/NEWS index 529f4ab5ea8..c2eea84616b 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -1,4 +1,8 @@ -*- text -*- +* GNU/Linux targets now supports "gnu_unique_object" as a value in the .type + pseudo op. It marks the symbol as being globally unique in the entire + process. + * ARM assembler now supports .inst[.nw] pseudo-ops to insert opcodes specified in binary rather than text. diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 3c723266156..c9c7a9c7ee2 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -1665,8 +1665,8 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED) } } else if (strcmp (typename, "gnu_indirect_function") == 0 - || strcmp (typename, "10") == 0 - || strcmp (typename, "STT_GNU_IFUNC") == 0) + || strcmp (typename, "10") == 0 + || strcmp (typename, "STT_GNU_IFUNC") == 0) { const struct elf_backend_data *bed; @@ -1678,6 +1678,18 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED) 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 --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index d1240bf5621..3af86f8e2e2 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -6360,6 +6360,11 @@ Mark the symbol as being a common data object. @itemx notype Does not mark the symbol in any way. It is supported just for completeness. +@item gnu_unique_object +Marks the symbol as being a globally unique data object. The dynamic linker +will make sure that in the entire process there is just one symbol with this +name and type in use. (This is only supported on Linux targeted assemblers). + @end table Note: Some targets support extra types in addition to those listed above. diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index a5d0bdb91f2..a30164baa3d 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-07-23 Ulrich Drepper + + * gas/elf/type.s: Add unique global symbol definition. + * gas/elf/type.e: Add expected readelf output for global unique + symbol. + 2009-07-21 H.J. Lu PR gas/10420 diff --git a/gas/testsuite/gas/elf/type.e b/gas/testsuite/gas/elf/type.e index 95d846aff45..2d26af89ce6 100644 --- a/gas/testsuite/gas/elf/type.e +++ b/gas/testsuite/gas/elf/type.e @@ -3,4 +3,5 @@ .: 0+0 1 OBJECT LOCAL DEFAULT . object .: 0+1 1 TLS LOCAL DEFAULT . tls_object ..: 0+2 1 NOTYPE LOCAL DEFAULT . notype + ..: 0+3 1 OBJECT UNIQUE DEFAULT . unique_global ..: 0+1 1 (COMMON|OBJECT) GLOBAL DEFAULT COM common diff --git a/gas/testsuite/gas/elf/type.s b/gas/testsuite/gas/elf/type.s index 8620cc2bc1d..159bf6d0387 100644 --- a/gas/testsuite/gas/elf/type.s +++ b/gas/testsuite/gas/elf/type.s @@ -1,24 +1,35 @@ .text + .size function,1 .type function,%function function: .byte 0x0 + .size indirect_function,1 .type indirect_function,%gnu_indirect_function indirect_function: .byte 0x0 + .data + .type object,%object .size object,1 object: .byte 0x0 .type tls_object,%tls_object + .size tls_object,1 tls_object: .byte 0x0 .type notype,%notype + .size notype,1 notype: .byte 0x0 .comm common, 1 .type common,STT_COMMON + + .type unique_global,%gnu_unique_object +unique_global: + .byte 0x0 + .size unique_global,1 diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index 89235d1a98f..600342c8a35 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,7 @@ +2009-07-23 Ulrich Drepper + + * common.h (STB_GNU_UNIQUE): Define. + 2009-07-10 Tom Tromey * dwarf2.h: Move to `..'. diff --git a/include/elf/common.h b/include/elf/common.h index 75f4eb82dbc..72afa918e22 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -1,6 +1,6 @@ /* ELF support for BFD. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published @@ -555,6 +555,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 */ diff --git a/ld/ChangeLog b/ld/ChangeLog index 87ab48b5d5b..10160ebc40f 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2009-07-23 Ulrich Drepper + + * NEWS: Mention the linker's support for symbols with a binding of + STB_GNU_UNIQUE. + 2009-07-22 H.J. Lu PR ld/10429 diff --git a/ld/NEWS b/ld/NEWS index 6f05361f573..821915e804a 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,4 +1,8 @@ -*- text -*- +* GNU/Linux targets now support the STB_GNU_UNIQUE symbol binding. This is a + GNU extension to the standard set of ELF symbol bindings. The binding will + be passed on to the dynamic linker which will make sure that in the entire + process there is just one symbol with the given name and type in use. * PE targets now support a GNU extension to allow the alignment of common common symbols to be specified. This support uses custom options in -- 2.30.2