* [Patch macho/bfd/gas] .indirect_symbol, take 2. @ 2012-01-09 13:00 Iain Sandoe 2012-01-10 13:03 ` Tristan Gingold 0 siblings, 1 reply; 5+ messages in thread From: Iain Sandoe @ 2012-01-09 13:00 UTC (permalink / raw) To: binutils Development; +Cc: Tristan Gingold 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) ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Patch macho/bfd/gas] .indirect_symbol, take 2. 2012-01-09 13:00 [Patch macho/bfd/gas] .indirect_symbol, take 2 Iain Sandoe @ 2012-01-10 13:03 ` Tristan Gingold 2012-01-12 8:37 ` [Patch macho/bfd/gas] .indirect_symbol, take 3 Iain Sandoe 0 siblings, 1 reply; 5+ messages in thread From: Tristan Gingold @ 2012-01-10 13:03 UTC (permalink / raw) To: Iain Sandoe; +Cc: binutils Development On Jan 9, 2012, at 2:00 PM, Iain Sandoe wrote: > 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. I don't think that linked list is the best choice. The overhead is large (at least 2x), and the list structure is useful only for creating it (i.e. for gas). I would prefer to have an array in BFD, and the linked list in GAS. > 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. Yes, this is an issue. I need to investigate how to address that. > tests follow as separate patch (they've all be posted before anyway). Thanks! > OK? See some additional comments. Tristan. > 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; > +} > + ok. > 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 (); Use bfd_assert instead. Note that we should take care of local and absolute symbols. > + } > + 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. */ Unrelated chunk ? > > @@ -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; > + } Don't let 'if (0)' code. Please, use macro accessor instead of '((struct local_symbol *) sp)->lsy_section != reg_section'. > + > + 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; > + } Likewise. > + > + 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 (); gas_assert. > + > + 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, "is":"are" don't make sense with other languages ! > + (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) Tristan. ^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch macho/bfd/gas] .indirect_symbol, take 3. 2012-01-10 13:03 ` Tristan Gingold @ 2012-01-12 8:37 ` Iain Sandoe 2012-01-12 8:49 ` Tristan Gingold 0 siblings, 1 reply; 5+ messages in thread From: Iain Sandoe @ 2012-01-12 8:37 UTC (permalink / raw) To: Tristan Gingold; +Cc: binutils Development On 10 Jan 2012, at 13:03, Tristan Gingold wrote: >> Here is a different implementation of the .indirect_symbol patch. V3 ;-) >> In this we keep indirect_symbols in a linked list in the section to >> which they belong. > > I don't think that linked list is the best choice. The overhead is > large (at least 2x), and the list structure is useful only for > creating it (i.e. for gas). I would prefer to have an array in BFD, > and the linked list in GAS. well, it's a bit like a balloon - push in one place and it pops out in another - this version is lighter in BFD, but heavier in GAS. >> 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. > > Yes, this is an issue. I need to investigate how to address that. I guess we could request a bit in the symbol flags... > > Use bfd_assert instead. > > Note that we should take care of local and absolute symbols. I think locals are now done.. I will investigate ABS as a follow-on... >> >> 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. */ > > Unrelated chunk ? no, symbol stubs and lazy pointer section symbols are, by default, lazy but this gets cancelled if they are defined (or local). >> >> + if (nactual != ncalc) >> + as_bad (_("there %s %d indirect_symbol%sin section %s but" >> + " %d %s expected"), (nactual == 1)?"is":"are", nactual, > > "is":"are" don't make sense with other languages ! ... and in some languages plurals are indicated by additional words ... Does this not get handled by the translation process? I don't especially like grammatically incorrect error/warning messages.. If it is un-handled, what is the usual solution? ==== Naturally, the changelog needs some tweaking, but I trust that we can do this once we're agreed on the basic patch... OK for this version? Iain bfd/mach-o.c | 64 +++++++++++- bfd/mach-o.h | 34 ++++--- gas/config/obj-macho.c | 257 +++++++++++++++++++++++++++++++++++++++ +++------ gas/config/obj-macho.h | 3 + 4 files changed, 310 insertions(+), 48 deletions(-) diff --git a/bfd/mach-o.c b/bfd/mach-o.c index 6913b1d..9511665 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -2079,6 +2079,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, @@ -2135,9 +2162,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; @@ -2146,11 +2175,38 @@ 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: + { + unsigned j, num; + bfd_mach_o_asymbol **isyms = sec->indirect_syms; + + num = bfd_mach_o_section_get_nbr_indirect (abfd, sec); + if (isyms == NULL || num == 0) + break; + /* Record the starting index in the reserved1 field. */ + sec->reserved1 = n; + for (j = 0; j < num; j++, n++) + { + if (isyms[j] == NULL) + dsym->indirect_syms[n] = 0x80000000; + else + dsym->indirect_syms[n] = isyms[j]->symbol.udata.i; + } + } + break; + default: + break; + } } } diff --git a/bfd/mach-o.h b/bfd/mach-o.h index ca810a0..7f54961 100644 --- a/bfd/mach-o.h +++ b/bfd/mach-o.h @@ -42,6 +42,18 @@ typedef struct bfd_mach_o_header } bfd_mach_o_header; +typedef struct bfd_mach_o_asymbol +{ + /* The actual symbol which the rest of BFD works with. */ + asymbol symbol; + + /* Mach-O symbol fields. */ + unsigned char n_type; + unsigned char n_sect; + unsigned short n_desc; +} +bfd_mach_o_asymbol; + #define BFD_MACH_O_SEGNAME_SIZE 16 #define BFD_MACH_O_SECTNAME_SIZE 16 @@ -64,6 +76,12 @@ typedef struct bfd_mach_o_section /* Corresponding bfd section. */ asection *bfdsection; + /* An array holding the indirect symbols for this section. + NULL values indicate local symbols. + The number of symbols is determined from the section size and type. */ + + bfd_mach_o_asymbol **indirect_syms; + /* Simply linked list. */ struct bfd_mach_o_section *next; } @@ -105,26 +123,12 @@ typedef struct bfd_mach_o_reloc_info } bfd_mach_o_reloc_info; -typedef struct bfd_mach_o_asymbol -{ - /* The actual symbol which the rest of BFD works with. */ - asymbol symbol; - - /* Mach-O symbol fields. */ - unsigned char n_type; - unsigned char n_sect; - unsigned short n_desc; -} -bfd_mach_o_asymbol; - /* The symbol table is sorted like this: (1) local. (otherwise in order of generation) (2) external defined (sorted by name) - (3) external undefined - (sorted by name) - (4) common + (3) external undefined / common (sorted by name) */ diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c index 43f4fba..cf94de5 100644 --- a/gas/config/obj-macho.c +++ b/gas/config/obj-macho.c @@ -1032,6 +1032,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 +1132,79 @@ 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. */ +typedef struct obj_mach_o_indirect_sym +{ + symbolS *sym; + segT sect; + struct obj_mach_o_indirect_sym *next; +} obj_mach_o_indirect_sym; + +/* We store in order an maintain a pointer to the last one - to save reversing + later. */ +obj_mach_o_indirect_sym *indirect_syms; +obj_mach_o_indirect_sym *indirect_syms_tail; 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); + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + if (obj_mach_o_is_static) + as_bad (_("use of .indirect_symbols requires `-dynamic'")); + + switch (sec->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: + { + obj_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; + + isym = (obj_mach_o_indirect_sym *) + xmalloc (sizeof (obj_mach_o_indirect_sym)); + if (isym == NULL) + abort (); + + /* Just record the data for now, we will validate it when we + compute the output. */ + isym->sym = sym; + isym->sect = now_seg; + isym->next = NULL; + if (indirect_syms == NULL) + indirect_syms = isym; + else + indirect_syms_tail->next = isym; + indirect_syms_tail = isym; + } + 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 +1298,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 +1337,25 @@ 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. */ + + if (S_IS_LOCAL (sp)) + return; + + 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 +1384,41 @@ 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. */ + if (S_IS_LOCAL (sp)) + return 0; + + 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 +1437,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 +1473,120 @@ obj_macho_frob_symbol (struct symbol *sp) return 0; } +static void +obj_mach_o_set_indirect_symbols (bfd *abfd, asection *sec, + void *xxx ATTRIBUTE_UNUSED) +{ + bfd_vma sect_size = bfd_section_size (abfd, sec); + bfd_mach_o_section *ms = bfd_mach_o_get_mach_o_section (sec); + unsigned lazy = 0; + + /* See if we have any indirect syms to consider. */ + if (indirect_syms == NULL) + return; + + /* 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: + lazy = LAZY; + /* Fall through. */ + case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS: + { + unsigned int nactual = 0; + unsigned int ncalc; + obj_mach_o_indirect_sym *isym; + obj_mach_o_indirect_sym *list = NULL; + obj_mach_o_indirect_sym *list_tail = NULL; + unsigned long eltsiz = + bfd_mach_o_section_get_entry_size (abfd, ms); + + for (isym = indirect_syms; isym != NULL; isym = isym->next) + { + if (isym->sect == sec) + { + nactual++; + if (list == NULL) + list = isym; + else + list_tail->next = isym; + list_tail = isym; + } + } + + /* If none are in this section, stop here. */ + if (nactual == 0) + break; + + /* If we somehow added indirect symbols to a section with a zero + entry size, we're dead ... */ + gas_assert (eltsiz != 0); + + ncalc = (unsigned int) (sect_size / eltsiz); + 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"); + else + { + unsigned n; + bfd_mach_o_asymbol *sym; + ms->indirect_syms = + bfd_zalloc (abfd, + nactual * sizeof (bfd_mach_o_asymbol *)); + + gas_assert (ms->indirect_syms != NULL); + + for (isym = list, n = 0; isym != NULL; isym = isym->next, n++) + { + /* Array is init to NULL & NULL signals a local symbol + If the section is lazy-bound, we need to keep the + reference to the symbol, since dyld can override. */ + if (S_IS_LOCAL (isym->sym) && ! lazy) + ; + else + { + sym = (bfd_mach_o_asymbol *)symbol_get_bfdsym (isym->sym); + if (sym == NULL) + ; + /* If the symbols is external ... */ + else if (S_IS_EXTERNAL (isym->sym) + || (sym->n_type & BFD_MACH_O_N_EXT) + || ! S_IS_DEFINED (isym->sym) + || lazy) + { + sym->n_desc &= ~LAZY; + /* ... and can be lazy, if not defined or hidden. */ + if ((sym->n_type & BFD_MACH_O_N_TYPE) + == BFD_MACH_O_N_UNDF + && ! (sym->n_type & BFD_MACH_O_N_PEXT) + && (sym->n_type & BFD_MACH_O_N_EXT)) + sym->n_desc |= lazy; + ms->indirect_syms[n] = sym; + } + } + } + } + } + break; + + default: + break; + } +} + +/* The process of relocation could alter what's externally visible, thus we + leave setting the indirect symbols until last. */ + +void +obj_mach_o_frob_file_after_relocs (void) +{ + bfd_map_over_sections (stdoutput, obj_mach_o_set_indirect_symbols, (char *) 0); +} + /* Support stabs for mach-o. */ void diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h index cbc3a4f..9f1f3db 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_file_after_relocs obj_mach_o_frob_file_after_relocs +extern void obj_mach_o_frob_file_after_relocs (void); + #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) ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Patch macho/bfd/gas] .indirect_symbol, take 3. 2012-01-12 8:37 ` [Patch macho/bfd/gas] .indirect_symbol, take 3 Iain Sandoe @ 2012-01-12 8:49 ` Tristan Gingold 2012-01-12 14:24 ` Iain Sandoe 0 siblings, 1 reply; 5+ messages in thread From: Tristan Gingold @ 2012-01-12 8:49 UTC (permalink / raw) To: Iain Sandoe; +Cc: binutils Development On Jan 12, 2012, at 9:36 AM, Iain Sandoe wrote: > > On 10 Jan 2012, at 13:03, Tristan Gingold wrote: > >>> Here is a different implementation of the .indirect_symbol patch. > > V3 ;-) > >>> In this we keep indirect_symbols in a linked list in the section to which they belong. >> >> I don't think that linked list is the best choice. The overhead is large (at least 2x), and the list structure is useful only for creating it (i.e. for gas). I would prefer to have an array in BFD, and the linked list in GAS. > > well, it's a bit like a balloon - push in one place and it pops out in another - this version is lighter in BFD, but heavier in GAS. Sure, but there are many binaries linked with BFD that don't need a linked list! >>> 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. >> >> Yes, this is an issue. I need to investigate how to address that. > > I guess we could request a bit in the symbol flags... >> >> Use bfd_assert instead. >> >> Note that we should take care of local and absolute symbols. > > I think locals are now done.. I will investigate ABS as a follow-on… Ok. >>> >>> 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. */ >> >> Unrelated chunk ? > > no, symbol stubs and lazy pointer section symbols are, by default, lazy but this gets cancelled if they are defined (or local). ok. >>> >>> + if (nactual != ncalc) >>> + as_bad (_("there %s %d indirect_symbol%sin section %s but" >>> + " %d %s expected"), (nactual == 1)?"is":"are", nactual, >> >> "is":"are" don't make sense with other languages ! > > ... and in some languages plurals are indicated by additional words ... > > Does this not get handled by the translation process? > > I don't especially like grammatically incorrect error/warning messages.. > > If it is un-handled, what is the usual solution? The best solution is rewording, such as "too few indirect_symbols in section %s (%d instead of %d)". You know english better than me, so you could improve my wording. > ==== > > Naturally, the changelog needs some tweaking, but I trust that we can do this once we're agreed on the basic patch... > > OK for this version? > Iain > > bfd/mach-o.c | 64 +++++++++++- > bfd/mach-o.h | 34 ++++--- > gas/config/obj-macho.c | 257 ++++++++++++++++++++++++++++++++++++++++++------ > gas/config/obj-macho.h | 3 + > 4 files changed, 310 insertions(+), 48 deletions(-) > > diff --git a/bfd/mach-o.c b/bfd/mach-o.c > index 6913b1d..9511665 100644 > --- a/bfd/mach-o.c > +++ b/bfd/mach-o.c > @@ -2079,6 +2079,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, > @@ -2135,9 +2162,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; > @@ -2146,11 +2175,38 @@ 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: > + { > + unsigned j, num; > + bfd_mach_o_asymbol **isyms = sec->indirect_syms; > + > + num = bfd_mach_o_section_get_nbr_indirect (abfd, sec); > + if (isyms == NULL || num == 0) > + break; > + /* Record the starting index in the reserved1 field. */ > + sec->reserved1 = n; > + for (j = 0; j < num; j++, n++) > + { > + if (isyms[j] == NULL) > + dsym->indirect_syms[n] = 0x80000000; We need a constant for that (ok, not your fault). > + else > + dsym->indirect_syms[n] = isyms[j]->symbol.udata.i; > + } > + } > + break; > + default: > + break; > + } > } > } > > diff --git a/bfd/mach-o.h b/bfd/mach-o.h > index ca810a0..7f54961 100644 > --- a/bfd/mach-o.h > +++ b/bfd/mach-o.h > @@ -42,6 +42,18 @@ typedef struct bfd_mach_o_header > } > bfd_mach_o_header; > > +typedef struct bfd_mach_o_asymbol > +{ > + /* The actual symbol which the rest of BFD works with. */ > + asymbol symbol; > + > + /* Mach-O symbol fields. */ > + unsigned char n_type; > + unsigned char n_sect; > + unsigned short n_desc; > +} > +bfd_mach_o_asymbol; > + > #define BFD_MACH_O_SEGNAME_SIZE 16 > #define BFD_MACH_O_SECTNAME_SIZE 16 > > @@ -64,6 +76,12 @@ typedef struct bfd_mach_o_section > /* Corresponding bfd section. */ > asection *bfdsection; > > + /* An array holding the indirect symbols for this section. > + NULL values indicate local symbols. > + The number of symbols is determined from the section size and type. */ > + > + bfd_mach_o_asymbol **indirect_syms; > + > /* Simply linked list. */ > struct bfd_mach_o_section *next; > } > @@ -105,26 +123,12 @@ typedef struct bfd_mach_o_reloc_info > } > bfd_mach_o_reloc_info; > > -typedef struct bfd_mach_o_asymbol > -{ > - /* The actual symbol which the rest of BFD works with. */ > - asymbol symbol; > - > - /* Mach-O symbol fields. */ > - unsigned char n_type; > - unsigned char n_sect; > - unsigned short n_desc; > -} > -bfd_mach_o_asymbol; > - > /* The symbol table is sorted like this: > (1) local. > (otherwise in order of generation) > (2) external defined > (sorted by name) > - (3) external undefined > - (sorted by name) > - (4) common > + (3) external undefined / common > (sorted by name) > */ > > diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c > index 43f4fba..cf94de5 100644 > --- a/gas/config/obj-macho.c > +++ b/gas/config/obj-macho.c > @@ -1032,6 +1032,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 +1132,79 @@ 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. */ > +typedef struct obj_mach_o_indirect_sym > +{ > + symbolS *sym; > + segT sect; > + struct obj_mach_o_indirect_sym *next; > +} obj_mach_o_indirect_sym; > + > +/* We store in order an maintain a pointer to the last one - to save reversing > + later. */ > +obj_mach_o_indirect_sym *indirect_syms; > +obj_mach_o_indirect_sym *indirect_syms_tail; > > 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); > + > +#ifdef md_flush_pending_output > + md_flush_pending_output (); > +#endif > + > + if (obj_mach_o_is_static) > + as_bad (_("use of .indirect_symbols requires `-dynamic'")); > + > + switch (sec->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: > + { > + obj_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; > + > + isym = (obj_mach_o_indirect_sym *) > + xmalloc (sizeof (obj_mach_o_indirect_sym)); > + if (isym == NULL) > + abort (); xmalloc can't fail. > + > + /* Just record the data for now, we will validate it when we > + compute the output. */ > + isym->sym = sym; > + isym->sect = now_seg; > + isym->next = NULL; > + if (indirect_syms == NULL) > + indirect_syms = isym; > + else > + indirect_syms_tail->next = isym; > + indirect_syms_tail = isym; > + } > + 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 +1298,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 +1337,25 @@ 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. */ > + > + if (S_IS_LOCAL (sp)) > + return; > + > + 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 +1384,41 @@ 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. */ > + if (S_IS_LOCAL (sp)) > + return 0; > + > + 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 +1437,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 +1473,120 @@ obj_macho_frob_symbol (struct symbol *sp) > return 0; > } > > +static void > +obj_mach_o_set_indirect_symbols (bfd *abfd, asection *sec, > + void *xxx ATTRIBUTE_UNUSED) > +{ > + bfd_vma sect_size = bfd_section_size (abfd, sec); > + bfd_mach_o_section *ms = bfd_mach_o_get_mach_o_section (sec); > + unsigned lazy = 0; > + > + /* See if we have any indirect syms to consider. */ > + if (indirect_syms == NULL) > + return; > + > + /* 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: > + lazy = LAZY; > + /* Fall through. */ > + case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS: > + { > + unsigned int nactual = 0; > + unsigned int ncalc; > + obj_mach_o_indirect_sym *isym; > + obj_mach_o_indirect_sym *list = NULL; > + obj_mach_o_indirect_sym *list_tail = NULL; > + unsigned long eltsiz = > + bfd_mach_o_section_get_entry_size (abfd, ms); > + > + for (isym = indirect_syms; isym != NULL; isym = isym->next) > + { > + if (isym->sect == sec) > + { > + nactual++; > + if (list == NULL) > + list = isym; > + else > + list_tail->next = isym; > + list_tail = isym; > + } > + } > + > + /* If none are in this section, stop here. */ > + if (nactual == 0) > + break; > + > + /* If we somehow added indirect symbols to a section with a zero > + entry size, we're dead ... */ > + gas_assert (eltsiz != 0); > + > + ncalc = (unsigned int) (sect_size / eltsiz); > + 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"); > + else > + { > + unsigned n; > + bfd_mach_o_asymbol *sym; > + ms->indirect_syms = > + bfd_zalloc (abfd, > + nactual * sizeof (bfd_mach_o_asymbol *)); > + > + gas_assert (ms->indirect_syms != NULL); But bfd_zalloc can, so you should do an explicit check (IMHO). > + > + for (isym = list, n = 0; isym != NULL; isym = isym->next, n++) > + { > + /* Array is init to NULL & NULL signals a local symbol > + If the section is lazy-bound, we need to keep the > + reference to the symbol, since dyld can override. */ > + if (S_IS_LOCAL (isym->sym) && ! lazy) > + ; > + else > + { > + sym = (bfd_mach_o_asymbol *)symbol_get_bfdsym (isym->sym); > + if (sym == NULL) > + ; > + /* If the symbols is external ... */ > + else if (S_IS_EXTERNAL (isym->sym) > + || (sym->n_type & BFD_MACH_O_N_EXT) > + || ! S_IS_DEFINED (isym->sym) > + || lazy) > + { > + sym->n_desc &= ~LAZY; > + /* ... and can be lazy, if not defined or hidden. */ > + if ((sym->n_type & BFD_MACH_O_N_TYPE) > + == BFD_MACH_O_N_UNDF > + && ! (sym->n_type & BFD_MACH_O_N_PEXT) > + && (sym->n_type & BFD_MACH_O_N_EXT)) > + sym->n_desc |= lazy; > + ms->indirect_syms[n] = sym; > + } > + } > + } > + } > + } > + break; > + > + default: > + break; > + } > +} > + > +/* The process of relocation could alter what's externally visible, thus we > + leave setting the indirect symbols until last. */ > + > +void > +obj_mach_o_frob_file_after_relocs (void) > +{ > + bfd_map_over_sections (stdoutput, obj_mach_o_set_indirect_symbols, (char *) 0); > +} > + > /* Support stabs for mach-o. */ > > void > diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h > index cbc3a4f..9f1f3db 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_file_after_relocs obj_mach_o_frob_file_after_relocs > +extern void obj_mach_o_frob_file_after_relocs (void); > + > #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) > Ok with the suggested change, no need to resubmit. Thank you for your perseverance! Tristan. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Patch macho/bfd/gas] .indirect_symbol, take 3. 2012-01-12 8:49 ` Tristan Gingold @ 2012-01-12 14:24 ` Iain Sandoe 0 siblings, 0 replies; 5+ messages in thread From: Iain Sandoe @ 2012-01-12 14:24 UTC (permalink / raw) To: Tristan Gingold; +Cc: binutils Development [-- Attachment #1: Type: text/plain, Size: 420 bytes --] Hi Tristan, On 12 Jan 2012, at 08:49, Tristan Gingold wrote: >> >> + if (isyms[j] == NULL) >> + dsym->indirect_syms[n] = 0x80000000; > We need a constant for that (ok, not your fault). me being impatient .. sorry, I've taken the liberty of adding a constant for this and ABS to loader.h > Ok with the suggested change, no need to resubmit. committed as attached, with the test-cases. thanks Iain [-- Attachment #2: 12011214-indirect-code.txt --] [-- Type: text/plain, Size: 17619 bytes --] Index: bfd/ChangeLog =================================================================== RCS file: /cvs/src/src/bfd/ChangeLog,v retrieving revision 1.5584 diff -u -p -r1.5584 ChangeLog --- bfd/ChangeLog 11 Jan 2012 15:24:09 -0000 1.5584 +++ bfd/ChangeLog 12 Jan 2012 13:59:41 -0000 @@ -1,3 +1,10 @@ +2012-01-12 Iain Sandoe <idsandoe@googlemail.com> + + * mach-o.c (bfd_mach_o_count_indirect_symbols): New. + (bfd_mach_o_build_dysymtab_command): Populate indirect symbol table. + * mach-o.h (bfd_mach_o_asymbol): Move declaration to start of the + file. (bfd_mach_o_section): Add indirect_syms field. + 2012-01-11 Iain Sandoe <idsandoe@googlemail.com> * mach-o.c (bfd_mach_o_build_seg_command): Separate computation of Index: bfd/mach-o.c =================================================================== RCS file: /cvs/src/src/bfd/mach-o.c,v retrieving revision 1.95 diff -u -p -r1.95 mach-o.c --- bfd/mach-o.c 11 Jan 2012 15:24:10 -0000 1.95 +++ bfd/mach-o.c 12 Jan 2012 13:59:45 -0000 @@ -2079,6 +2079,33 @@ bfd_mach_o_build_seg_command (const char 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, @@ -2135,9 +2162,11 @@ bfd_mach_o_build_dysymtab_command (bfd * 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; @@ -2146,11 +2175,38 @@ bfd_mach_o_build_dysymtab_command (bfd * 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: + { + unsigned j, num; + bfd_mach_o_asymbol **isyms = sec->indirect_syms; + + num = bfd_mach_o_section_get_nbr_indirect (abfd, sec); + if (isyms == NULL || num == 0) + break; + /* Record the starting index in the reserved1 field. */ + sec->reserved1 = n; + for (j = 0; j < num; j++, n++) + { + if (isyms[j] == NULL) + dsym->indirect_syms[n] = BFD_MACH_O_INDIRECT_SYM_LOCAL; + else + dsym->indirect_syms[n] = isyms[j]->symbol.udata.i; + } + } + break; + default: + break; + } } } Index: bfd/mach-o.h =================================================================== RCS file: /cvs/src/src/bfd/mach-o.h,v retrieving revision 1.41 diff -u -p -r1.41 mach-o.h --- bfd/mach-o.h 9 Jan 2012 10:47:45 -0000 1.41 +++ bfd/mach-o.h 12 Jan 2012 13:59:45 -0000 @@ -42,6 +42,18 @@ typedef struct bfd_mach_o_header } bfd_mach_o_header; +typedef struct bfd_mach_o_asymbol +{ + /* The actual symbol which the rest of BFD works with. */ + asymbol symbol; + + /* Mach-O symbol fields. */ + unsigned char n_type; + unsigned char n_sect; + unsigned short n_desc; +} +bfd_mach_o_asymbol; + #define BFD_MACH_O_SEGNAME_SIZE 16 #define BFD_MACH_O_SECTNAME_SIZE 16 @@ -64,6 +76,12 @@ typedef struct bfd_mach_o_section /* Corresponding bfd section. */ asection *bfdsection; + /* An array holding the indirect symbols for this section. + NULL values indicate local symbols. + The number of symbols is determined from the section size and type. */ + + bfd_mach_o_asymbol **indirect_syms; + /* Simply linked list. */ struct bfd_mach_o_section *next; } @@ -105,26 +123,12 @@ typedef struct bfd_mach_o_reloc_info } bfd_mach_o_reloc_info; -typedef struct bfd_mach_o_asymbol -{ - /* The actual symbol which the rest of BFD works with. */ - asymbol symbol; - - /* Mach-O symbol fields. */ - unsigned char n_type; - unsigned char n_sect; - unsigned short n_desc; -} -bfd_mach_o_asymbol; - /* The symbol table is sorted like this: (1) local. (otherwise in order of generation) (2) external defined (sorted by name) - (3) external undefined - (sorted by name) - (4) common + (3) external undefined / common (sorted by name) */ Index: gas/config/obj-macho.c =================================================================== RCS file: /cvs/src/src/gas/config/obj-macho.c,v retrieving revision 1.10 diff -u -p -r1.10 obj-macho.c --- gas/config/obj-macho.c 9 Jan 2012 10:47:47 -0000 1.10 +++ gas/config/obj-macho.c 12 Jan 2012 13:59:57 -0000 @@ -1032,6 +1032,7 @@ obj_mach_o_set_symbol_qualifier (symbolS case OBJ_MACH_O_SYM_PRIV_EXT: s->n_type |= BFD_MACH_O_N_PEXT ; + s->n_desc &= ~LAZY; /* The native tool switches this off too. */ /* We follow the system tools in marking PEXT as also global. */ /* Fall through. */ @@ -1131,13 +1132,77 @@ 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. */ +typedef struct obj_mach_o_indirect_sym +{ + symbolS *sym; + segT sect; + struct obj_mach_o_indirect_sym *next; +} obj_mach_o_indirect_sym; + +/* We store in order an maintain a pointer to the last one - to save reversing + later. */ +obj_mach_o_indirect_sym *indirect_syms; +obj_mach_o_indirect_sym *indirect_syms_tail; 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); + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + if (obj_mach_o_is_static) + as_bad (_("use of .indirect_symbols requires `-dynamic'")); + + switch (sec->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: + { + obj_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; + + isym = (obj_mach_o_indirect_sym *) + xmalloc (sizeof (obj_mach_o_indirect_sym)); + + /* Just record the data for now, we will validate it when we + compute the output in obj_mach_o_set_indirect_symbols. */ + isym->sym = sym; + isym->sect = now_seg; + isym->next = NULL; + if (indirect_syms == NULL) + indirect_syms = isym; + else + indirect_syms_tail->next = isym; + indirect_syms_tail = isym; + } + 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 +1296,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 +1335,25 @@ obj_mach_o_type_for_symbol (bfd_mach_o_a 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. */ + + if (S_IS_LOCAL (sp)) + return; + + 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 +1382,41 @@ void obj_macho_frob_label (struct symbol 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. */ + if (S_IS_LOCAL (sp)) + return 0; + + 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 do comm. */ + s->n_type |= BFD_MACH_O_N_EXT; + S_SET_EXTERNAL (sp); } else { @@ -1353,6 +1435,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 +1471,125 @@ obj_macho_frob_symbol (struct symbol *sp return 0; } +static void +obj_mach_o_set_indirect_symbols (bfd *abfd, asection *sec, + void *xxx ATTRIBUTE_UNUSED) +{ + bfd_vma sect_size = bfd_section_size (abfd, sec); + bfd_mach_o_section *ms = bfd_mach_o_get_mach_o_section (sec); + unsigned lazy = 0; + + /* See if we have any indirect syms to consider. */ + if (indirect_syms == NULL) + return; + + /* Process indirect symbols. + Check for errors, if OK attach them as a flat array to the section + for which they are defined. */ + + switch (ms->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: + { + unsigned int nactual = 0; + unsigned int ncalc; + obj_mach_o_indirect_sym *isym; + obj_mach_o_indirect_sym *list = NULL; + obj_mach_o_indirect_sym *list_tail = NULL; + unsigned long eltsiz = + bfd_mach_o_section_get_entry_size (abfd, ms); + + for (isym = indirect_syms; isym != NULL; isym = isym->next) + { + if (isym->sect == sec) + { + nactual++; + if (list == NULL) + list = isym; + else + list_tail->next = isym; + list_tail = isym; + } + } + + /* If none are in this section, stop here. */ + if (nactual == 0) + break; + + /* If we somehow added indirect symbols to a section with a zero + entry size, we're dead ... */ + gas_assert (eltsiz != 0); + + ncalc = (unsigned int) (sect_size / eltsiz); + if (nactual != ncalc) + as_bad (_("the number of .indirect_symbols defined in section %s" + " does not match the number expected (%d defined, %d" + " expected)"), sec->name, nactual, ncalc); + else + { + unsigned n; + bfd_mach_o_asymbol *sym; + ms->indirect_syms = + bfd_zalloc (abfd, + nactual * sizeof (bfd_mach_o_asymbol *)); + + if (ms->indirect_syms == NULL) + { + as_fatal (_("internal error: failed to allocate %d indirect" + "symbol pointers"), nactual); + } + + for (isym = list, n = 0; isym != NULL; isym = isym->next, n++) + { + /* Array is init to NULL & NULL signals a local symbol + If the section is lazy-bound, we need to keep the + reference to the symbol, since dyld can override. */ + if (S_IS_LOCAL (isym->sym) && ! lazy) + ; + else + { + sym = (bfd_mach_o_asymbol *)symbol_get_bfdsym (isym->sym); + if (sym == NULL) + ; + /* If the symbols is external ... */ + else if (S_IS_EXTERNAL (isym->sym) + || (sym->n_type & BFD_MACH_O_N_EXT) + || ! S_IS_DEFINED (isym->sym) + || lazy) + { + sym->n_desc &= ~LAZY; + /* ... it can be lazy, if not defined or hidden. */ + if ((sym->n_type & BFD_MACH_O_N_TYPE) + == BFD_MACH_O_N_UNDF + && ! (sym->n_type & BFD_MACH_O_N_PEXT) + && (sym->n_type & BFD_MACH_O_N_EXT)) + sym->n_desc |= lazy; + ms->indirect_syms[n] = sym; + } + } + } + } + } + break; + + default: + break; + } +} + +/* The process of relocation could alter what's externally visible, thus we + leave setting the indirect symbols until last. */ + +void +obj_mach_o_frob_file_after_relocs (void) +{ + bfd_map_over_sections (stdoutput, obj_mach_o_set_indirect_symbols, (char *) 0); +} + /* Support stabs for mach-o. */ void Index: gas/config/obj-macho.h =================================================================== RCS file: /cvs/src/src/gas/config/obj-macho.h,v retrieving revision 1.5 diff -u -p -r1.5 obj-macho.h --- gas/config/obj-macho.h 9 Jan 2012 10:47:47 -0000 1.5 +++ gas/config/obj-macho.h 12 Jan 2012 14:00:04 -0000 @@ -62,6 +62,9 @@ extern void obj_macho_frob_label (struct #define obj_frob_symbol(s, punt) punt = obj_macho_frob_symbol(s) extern int obj_macho_frob_symbol (struct symbol *); +#define obj_frob_file_after_relocs obj_mach_o_frob_file_after_relocs +extern void obj_mach_o_frob_file_after_relocs (void); + #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) Index: include/mach-o/ChangeLog =================================================================== RCS file: /cvs/src/src/include/mach-o/ChangeLog,v retrieving revision 1.7 diff -u -p -r1.7 ChangeLog --- include/mach-o/ChangeLog 4 Jan 2012 10:37:36 -0000 1.7 +++ include/mach-o/ChangeLog 12 Jan 2012 14:00:04 -0000 @@ -1,3 +1,8 @@ +2012-01-12 Iain Sandoe <idsandoe@googlemail.com> + + * loader.h (BFD_MACH_O_INDIRECT_SYM_LOCAL): New. + (BFD_MACH_O_INDIRECT_SYM_ABS): New + 2012-01-04 Tristan Gingold <gingold@adacore.com> * external.h (mach_o_fvmlib_command_external): New structure. Index: include/mach-o/loader.h =================================================================== RCS file: /cvs/src/src/include/mach-o/loader.h,v retrieving revision 1.5 diff -u -p -r1.5 loader.h --- include/mach-o/loader.h 4 Jan 2012 10:25:14 -0000 1.5 +++ include/mach-o/loader.h 12 Jan 2012 14:00:04 -0000 @@ -320,6 +320,9 @@ bfd_mach_o_section_attribute; #define BFD_MACH_O_N_NO_DEAD_STRIP 0x20 #define BFD_MACH_O_N_WEAK_REF 0x40 #define BFD_MACH_O_N_WEAK_DEF 0x80 + +#define BFD_MACH_O_INDIRECT_SYM_LOCAL 0x80000000 +#define BFD_MACH_O_INDIRECT_SYM_ABS 0x40000000 \f /* Thread constants. */ [-- Attachment #3: Type: text/plain, Size: 1 bytes --] ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-01-12 14:24 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-01-09 13:00 [Patch macho/bfd/gas] .indirect_symbol, take 2 Iain Sandoe 2012-01-10 13:03 ` Tristan Gingold 2012-01-12 8:37 ` [Patch macho/bfd/gas] .indirect_symbol, take 3 Iain Sandoe 2012-01-12 8:49 ` Tristan Gingold 2012-01-12 14:24 ` Iain Sandoe
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).