From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4877 invoked by alias); 9 Jan 2012 13:00:39 -0000 Received: (qmail 4844 invoked by uid 22791); 9 Jan 2012 13:00:35 -0000 X-SWARE-Spam-Status: No, hits=0.3 required=5.0 tests=AWL,BAYES_50,KAM_STOCKGEN,RCVD_IN_DNSWL_NONE X-Spam-Check-By: sourceware.org Received: from c2beaomr06.btconnect.com (HELO mail.btconnect.com) (213.123.26.184) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 09 Jan 2012 13:00:18 +0000 Received: from host81-138-1-83.in-addr.btopenworld.com (EHLO thor.office) ([81.138.1.83]) by c2beaomr06.btconnect.com with ESMTP id FZN10742; Mon, 09 Jan 2012 13:00:15 +0000 (GMT) Message-Id: <56BB999A-CDA7-4F2C-B58A-B4788E9B7034@sandoe-acoustics.co.uk> From: Iain Sandoe To: binutils Development Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (Apple Message framework v936) Subject: [Patch macho/bfd/gas] .indirect_symbol, take 2. Date: Mon, 09 Jan 2012 13:00:00 -0000 Cc: Tristan Gingold X-Mirapoint-IP-Reputation: reputation=Fair-1, source=Queried, refid=tid=0001.0A0B0302.4F0AE4DE.008F, actions=TAG X-Junkmail-Premium-Raw: score=7/50, refid=2.7.2:2012.1.9.115718:17:7.586, ip=81.138.1.83, rules=__HAS_MSGID, __SANE_MSGID, __MSGID_APPLEMAIL, __TO_MALFORMED_2, __CT, __CT_TEXT_PLAIN, __CTE, __MIME_VERSION, __MIME_VERSION_APPLEMAIL, __HAS_X_MAILER, __X_MAILER_APPLEMAIL, __CP_MEDIA_BODY, BODY_SIZE_10000_PLUS, __MIME_TEXT_ONLY, RDNS_GENERIC_POOLED, RDNS_SUSP_GENERIC, __USER_AGENT_APPLEMAIL, RDNS_SUSP, NO_URI_FOUND X-Junkmail-Signature-Raw: score=unknown, refid=str=0001.0A0B0201.4F0AE4DF.01D8,ss=1,re=0.000,fgs=0, ip=0.0.0.0, so=2011-07-25 19:15:43, dmn=2011-05-27 18:58:46, mode=multiengine X-IsSubscribed: yes Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2012-01/txt/msg00127.txt.bz2 Here is a different implementation of the .indirect_symbol patch. In this we keep indirect_symbols in a linked list in the section to which they belong. As of now, I can't see a reason to keep them in GAS as well. If this is OK, then a TODO would be to populate the list when a mach-o file is read in - - this is nicely symmetrical - - and means that sections can be reordered/removed without having to cross-check the dysymtab. The only thing that is less satisfactory, is that there is no way (AFAICS) to mark a symbol as 'referenced by an indirect' which means if one deletes (or wishes to delete) symbols - then one should cross- check the usage from the indirect tables. tests follow as separate patch (they've all be posted before anyway). OK? Iain bfd: * mach-o.c (bfd_mach_o_count_indirect_symbols): New. (bfd_mach_o_build_dysymtab_command): Populate indirect table. * mach-o.h (bfd_mach_o_section): Add fields for indirect symbol lists. gas: * config/obj-macho.c (obj_mach_o_set_symbol_qualifier): Switch off lazy for extern/private extern. (obj_mach_o_indirect_symbol): New. (obj_mach_o_placeholder): Remove. (mach_o_pseudo_table): Use obj_mach_o_indirect_symbol. (obj_macho_frob_label): Take care not to force local symbols into the regular table. (obj_macho_frob_symbol): Likewise. Ensure undefined and comm syms have their fields set. (obj_mach_o_frob_section): New. * config/obj-macho.h (obj_frob_section): Define. (obj_mach_o_frob_section): Declare. bfd/mach-o.c | 63 +++++++++++++- bfd/mach-o.h | 16 ++++ gas/config/obj-macho.c | 214 +++++++++++++++++++++++++++++++++++++++ ++------- gas/config/obj-macho.h | 3 + 4 files changed, 262 insertions(+), 34 deletions(-) diff --git a/bfd/mach-o.c b/bfd/mach-o.c index a1f6596..493116a 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -2067,6 +2067,33 @@ bfd_mach_o_build_seg_command (const char *segment, return TRUE; } +/* Count the number of indirect symbols in the image. + Requires that the sections are in their final order. */ + +static unsigned int +bfd_mach_o_count_indirect_symbols (bfd *abfd, bfd_mach_o_data_struct *mdata) +{ + unsigned int i; + unsigned int nisyms = 0; + + for (i = 0; i < mdata->nsects; ++i) + { + bfd_mach_o_section *sec = mdata->sections[i]; + + switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK) + { + case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS: + case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS: + case BFD_MACH_O_S_SYMBOL_STUBS: + nisyms += bfd_mach_o_section_get_nbr_indirect (abfd, sec); + break; + default: + break; + } + } + return nisyms; +} + static bfd_boolean bfd_mach_o_build_dysymtab_command (bfd *abfd, bfd_mach_o_data_struct *mdata, @@ -2123,9 +2150,11 @@ bfd_mach_o_build_dysymtab_command (bfd *abfd, dsym->nundefsym = 0; } + dsym->nindirectsyms = bfd_mach_o_count_indirect_symbols (abfd, mdata); if (dsym->nindirectsyms > 0) { unsigned i; + unsigned n; mdata->filelen = FILE_ALIGN (mdata->filelen, 2); dsym->indirectsymoff = mdata->filelen; @@ -2134,11 +2163,37 @@ bfd_mach_o_build_dysymtab_command (bfd *abfd, dsym->indirect_syms = bfd_zalloc (abfd, dsym->nindirectsyms * 4); if (dsym->indirect_syms == NULL) return FALSE; - - /* So fill in the indices. */ - for (i = 0; i < dsym->nindirectsyms; ++i) + + n = 0; + for (i = 0; i < mdata->nsects; ++i) { - /* TODO: fill in the table. */ + bfd_mach_o_section *sec = mdata->sections[i]; + + switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK) + { + case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS: + case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS: + case BFD_MACH_O_S_SYMBOL_STUBS: + { + bfd_mach_o_indirect_sym *isym = sec->indirectsyms; + if (isym == NULL) + break; + /* Record the starting index in the reserved1 field. */ + sec->reserved1 = n; + do + { + dsym->indirect_syms[n] = isym->sym->symbol.udata.i; + n++; + /* Final safety net. */ + if (n > dsym->nindirectsyms) + abort (); + } + while ((isym = isym->next) != NULL); + } + break; + default: + break; + } } } diff --git a/bfd/mach-o.h b/bfd/mach-o.h index ca810a0..31a4095 100644 --- a/bfd/mach-o.h +++ b/bfd/mach-o.h @@ -63,6 +63,12 @@ typedef struct bfd_mach_o_section /* Corresponding bfd section. */ asection *bfdsection; + + /* Linked list of indirect symbols for this section (only applies to + stub and reference sections). */ + struct bfd_mach_o_indirect_sym *indirectsyms; + /* Pointer to the last indirect, to save reversing the list. */ + struct bfd_mach_o_indirect_sym *lastindirectsym; /* Simply linked list. */ struct bfd_mach_o_section *next; @@ -117,6 +123,16 @@ typedef struct bfd_mach_o_asymbol } bfd_mach_o_asymbol; +/* An element in a list of indirect symbols the root of which + is "indirectsyms" in the section to which they apply. */ + +typedef struct bfd_mach_o_indirect_sym +{ + struct bfd_mach_o_indirect_sym *next; + struct bfd_mach_o_asymbol *sym; +} +bfd_mach_o_indirect_sym; + /* The symbol table is sorted like this: (1) local. (otherwise in order of generation) diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c index 43f4fba..5d82977 100644 --- a/gas/config/obj-macho.c +++ b/gas/config/obj-macho.c @@ -39,6 +39,7 @@ #include "as.h" #include "subsegs.h" +#include "struc-symbol.h" /* For local symbol stuff in frob_label/ symbol. */ #include "symbols.h" #include "write.h" #include "mach-o.h" @@ -1032,6 +1033,7 @@ obj_mach_o_set_symbol_qualifier (symbolS *sym, int type) case OBJ_MACH_O_SYM_PRIV_EXT: s->n_type |= BFD_MACH_O_N_PEXT ; + s->n_desc &= ~LAZY; /* The native tool swithes this off too. */ /* We follow the system tools in marking PEXT as also global. */ /* Fall through. */ @@ -1131,13 +1133,74 @@ obj_mach_o_sym_qual (int ntype) demand_empty_rest_of_line (); } -/* Dummy function to allow test-code to work while we are working - on things. */ - static void -obj_mach_o_placeholder (int arg ATTRIBUTE_UNUSED) +obj_mach_o_indirect_symbol (int arg ATTRIBUTE_UNUSED) { - ignore_rest_of_line (); + bfd_mach_o_section *sec = bfd_mach_o_get_mach_o_section (now_seg); + unsigned lazy = 0; + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK) + { + case BFD_MACH_O_S_SYMBOL_STUBS: + case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS: + lazy = LAZY; + /* Fall through. */ + case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS: + { + bfd_mach_o_indirect_sym *isym; + char *name = input_line_pointer; + char c = get_symbol_end (); + symbolS *sym = symbol_find_or_make (name); + unsigned int elsize = + bfd_mach_o_section_get_entry_size (stdoutput, sec); + + if (elsize == 0) + { + as_bad (_("attempt to add an indirect_symbol to a stub or" + " reference section with a zero-sized element at %s"), + name); + *input_line_pointer = c; + ignore_rest_of_line (); + return; + } + + *input_line_pointer = c; + + /* This should be allocated in bfd, since it is owned there. */ + isym = (bfd_mach_o_indirect_sym *) + bfd_zalloc (stdoutput, sizeof (bfd_mach_o_indirect_sym)); + if (isym == NULL) + abort (); + + isym->sym = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sym); + if (sec->indirectsyms == NULL) + sec->indirectsyms = isym; + else + sec->lastindirectsym->next = isym; + sec->lastindirectsym = isym; + + /* We put in the lazy flag, it will get reset if the symbols is later + defined, or if the symbol becomes private_extern. */ + if (isym->sym->symbol.section == bfd_und_section_ptr + && ! (isym->sym->n_type & BFD_MACH_O_N_PEXT)) + { + isym->sym->n_desc = lazy; + isym->sym->symbol.udata.i = SYM_MACHO_FIELDS_NOT_VALIDATED; + } + } + break; + + default: + as_bad (_("an .indirect_symbol must be in a symbol pointer" + " or stub section.")); + ignore_rest_of_line (); + return; + } + demand_empty_rest_of_line (); } const pseudo_typeS mach_o_pseudo_table[] = @@ -1231,7 +1294,7 @@ const pseudo_typeS mach_o_pseudo_table[] = {"no_dead_strip", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_NO_DEAD_STRIP}, {"weak", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_WEAK}, /* ext */ - {"indirect_symbol", obj_mach_o_placeholder, 0}, + {"indirect_symbol", obj_mach_o_indirect_symbol, 0}, /* File flags. */ { "subsections_via_symbols", obj_mach_o_fileprop, @@ -1270,15 +1333,33 @@ obj_mach_o_type_for_symbol (bfd_mach_o_asymbol *s) void obj_macho_frob_label (struct symbol *sp) { - bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sp); - /* This is the base symbol type, that we mask in. */ - unsigned base_type = obj_mach_o_type_for_symbol (s); - bfd_mach_o_section *sec = bfd_mach_o_get_mach_o_section (s- >symbol.section); + bfd_mach_o_asymbol *s; + unsigned base_type; + bfd_mach_o_section *sec; int sectype = -1; + /* Leave local symbols alone (unless they've already been made into a real + one). */ + + if (0 && sp->bsym == NULL) + { + if (((struct local_symbol *) sp)->lsy_section != reg_section) + return; + else + /* We have a local which has been added to the symbol table, so carry + on with the checking. */ + sp = ((struct local_symbol *) sp)->u.lsy_sym; + } + + s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sp); + /* Leave debug symbols alone. */ if ((s->n_type & BFD_MACH_O_N_STAB) != 0) - return; /* Leave alone. */ - + return; + + /* This is the base symbol type, that we mask in. */ + base_type = obj_mach_o_type_for_symbol (s); + + sec = bfd_mach_o_get_mach_o_section (s->symbol.section); if (sec != NULL) sectype = sec->flags & BFD_MACH_O_SECTION_TYPE_MASK; @@ -1307,34 +1388,50 @@ void obj_macho_frob_label (struct symbol *sp) int obj_macho_frob_symbol (struct symbol *sp) { - bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sp); - unsigned base_type = obj_mach_o_type_for_symbol (s); - bfd_mach_o_section *sec = bfd_mach_o_get_mach_o_section (s- >symbol.section); + bfd_mach_o_asymbol *s; + unsigned base_type; + bfd_mach_o_section *sec; int sectype = -1; - + + /* Leave local symbols alone (unless they've already been made into a real + one). */ + + if (0 && sp->bsym == NULL) + { + if (((struct local_symbol *) sp)->lsy_section != reg_section) + return 0; + else + /* We have a local which has been added to the symbol table, so carry + on with the checking. */ + sp = ((struct local_symbol *) sp)->u.lsy_sym; + } + + s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sp); + /* Leave debug symbols alone. */ + if ((s->n_type & BFD_MACH_O_N_STAB) != 0) + return 0; + + base_type = obj_mach_o_type_for_symbol (s); + sec = bfd_mach_o_get_mach_o_section (s->symbol.section); if (sec != NULL) sectype = sec->flags & BFD_MACH_O_SECTION_TYPE_MASK; - if ((s->n_type & BFD_MACH_O_N_STAB) != 0) - return 0; /* Leave alone. */ - else if (s->symbol.section == bfd_und_section_ptr) + if (s->symbol.section == bfd_und_section_ptr) { /* ??? Do we really gain much from implementing this as well as the mach-o specific ones? */ if (s->symbol.flags & BSF_WEAK) s->n_desc |= BFD_MACH_O_N_WEAK_REF; - /* Undefined references, become extern. */ - if (s->n_desc & REFE) - { - s->n_desc &= ~REFE; - s->n_type |= BFD_MACH_O_N_EXT; - } - - /* So do undefined 'no_dead_strip's. */ - if (s->n_desc & BFD_MACH_O_N_NO_DEAD_STRIP) - s->n_type |= BFD_MACH_O_N_EXT; - + /* Undefined syms, become extern. */ + s->n_type |= BFD_MACH_O_N_EXT; + S_SET_EXTERNAL (sp); + } + else if (s->symbol.section == bfd_com_section_ptr) + { + /* ... so to comm. */ + s->n_type |= BFD_MACH_O_N_EXT; + S_SET_EXTERNAL (sp); } else { @@ -1353,6 +1450,7 @@ obj_macho_frob_symbol (struct symbol *sp) { /* Anything here that should be added that is non-standard. */ s->n_desc &= ~BFD_MACH_O_REFERENCE_MASK; + s->symbol.udata.i = SYM_MACHO_FIELDS_NOT_VALIDATED; } else if (s->symbol.udata.i == SYM_MACHO_FIELDS_NOT_VALIDATED) { @@ -1388,6 +1486,62 @@ obj_macho_frob_symbol (struct symbol *sp) return 0; } +void +obj_mach_o_frob_section (asection *sec) +{ + bfd_vma sect_size = bfd_section_size (stdoutput, sec); + bfd_mach_o_section *ms = bfd_mach_o_get_mach_o_section (sec); + + /* Process indirect symbols to determine if we have errors there. */ + + switch (ms->flags & BFD_MACH_O_SECTION_TYPE_MASK) + { + case BFD_MACH_O_S_SYMBOL_STUBS: + case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS: + case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS: + { + unsigned int nactual; + unsigned int ncalc; + bfd_mach_o_indirect_sym *isym = ms->indirectsyms; + unsigned long eltsiz = + bfd_mach_o_section_get_entry_size (stdoutput, ms); + + /* If we somehow added indirect symbols to a section with a zero + entry size, we're dead ... */ + if (eltsiz == 0 && isym != NULL) + abort (); + + ncalc = (unsigned int) (sect_size / eltsiz); + + nactual = 0; + if (isym != NULL) + do + { + /* Count it. */ + nactual++; + if (isym->sym->symbol.section == bfd_und_section_ptr) + { + /* If the referenced symbol is undefined, make + it extern. */ + isym->sym->n_type |= BFD_MACH_O_N_EXT; + isym->sym->symbol.flags |= BSF_GLOBAL; + } + } + while ((isym = isym->next) != NULL); + + if (nactual != ncalc) + as_bad (_("there %s %d indirect_symbol%sin section %s but" + " %d %s expected"), (nactual == 1)?"is":"are", nactual, + (nactual == 1)?" ":"s ", sec->name, ncalc, + (ncalc == 1)?"is":"are"); + } + break; + + default: + break; + } +} + /* Support stabs for mach-o. */ void diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h index cbc3a4f..ceb1097 100644 --- a/gas/config/obj-macho.h +++ b/gas/config/obj-macho.h @@ -62,6 +62,9 @@ extern void obj_macho_frob_label (struct symbol *); #define obj_frob_symbol(s, punt) punt = obj_macho_frob_symbol(s) extern int obj_macho_frob_symbol (struct symbol *); +#define obj_frob_section(s) obj_mach_o_frob_section(s) +void obj_mach_o_frob_section (asection *); + #define EMIT_SECTION_SYMBOLS 0 #define OBJ_PROCESS_STAB(SEG,W,S,T,O,D) obj_mach_o_process_stab(W,S,T,O,D)