From 7f3072381b852817638295d676689b211af03c50 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Tue, 3 Jan 2012 10:54:01 +0000 Subject: [PATCH] add dysymtab write support to bfd/mach-o. bfd: * mach-o.c (bfd_mach_o_write_symtab): Fill in the string table index as the value of an indirect symbol. Keep the string table index in non-indirect syms for reference. (bfd_mach_o_write_dysymtab): New. (bfd_mach_o_primary_symbol_sort_key): New. (bfd_mach_o_cf_symbols): New. (bfd_mach_o_sort_symbol_table): New. (bfd_mach_o_mangle_symbols): Return early if no symbols. Sort symbols. If we are emitting a dysymtab, process indirect symbols and count the number of each other kind. (bfd_mach_o_mangle_sections): New. (bfd_mach_o_write_contents): Split out some pre-requisite code into the command builder. Write dysymtab if the command is present. (bfd_mach_o_count_sections_for_seg): New. (bfd_mach_o_build_seg_command): New. (bfd_mach_o_build_dysymtab_command): New. (bfd_mach_o_build_commands): Reorganize to support the fact that some commands are optional and should not be emitted if there are no sections or symbols. (bfd_mach_o_set_section_contents): Amend comment. * mach-o.h: Amend and add to comments. (mach_o_data_struct): Add fields for dysymtab symbols counts and a pointer to the indirects, when present. (bfd_mach_o_should_emit_dysymtab): New macro. (IS_MACHO_INDIRECT): Likewise. gas/testsuite: * gas/mach-o/dysymtab-1-64.d: New. * gas/mach-o/dysymtab-1.d: New. * gas/mach-o/symbols-1-64.d: New. * gas/mach-o/symbols-1.d: New. * gas/mach-o/symbols-base-64.s: New. * gas/mach-o/symbols-base.s: New. --- bfd/ChangeLog | 28 + bfd/mach-o.c | 829 +++++++++++++++++++++++++---- bfd/mach-o.h | 39 +- gas/testsuite/ChangeLog | 9 + gas/testsuite/gas/mach-o/dysymtab-1-64.d | 15 + gas/testsuite/gas/mach-o/dysymtab-1.d | 15 + gas/testsuite/gas/mach-o/symbols-1-64.d | 70 +++ gas/testsuite/gas/mach-o/symbols-1.d | 70 +++ gas/testsuite/gas/mach-o/symbols-base-64.s | 97 ++++ gas/testsuite/gas/mach-o/symbols-base.s | 97 ++++ 10 files changed, 1164 insertions(+), 105 deletions(-) create mode 100644 gas/testsuite/gas/mach-o/dysymtab-1-64.d create mode 100644 gas/testsuite/gas/mach-o/dysymtab-1.d create mode 100644 gas/testsuite/gas/mach-o/symbols-1-64.d create mode 100644 gas/testsuite/gas/mach-o/symbols-1.d create mode 100644 gas/testsuite/gas/mach-o/symbols-base-64.s create mode 100644 gas/testsuite/gas/mach-o/symbols-base.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9af9565..7406ddd 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,31 @@ +2012-01-03 Iain Sandoe + + * mach-o.c (bfd_mach_o_write_symtab): Fill in the string table index + as the value of an indirect symbol. Keep the string table index in + non-indirect syms for reference. + (bfd_mach_o_write_dysymtab): New. + (bfd_mach_o_primary_symbol_sort_key): New. + (bfd_mach_o_cf_symbols): New. + (bfd_mach_o_sort_symbol_table): New. + (bfd_mach_o_mangle_symbols): Return early if no symbols. Sort symbols. + If we are emitting a dysymtab, process indirect symbols and count the + number of each other kind. + (bfd_mach_o_mangle_sections): New. + (bfd_mach_o_write_contents): Split out some pre-requisite code into + the command builder. Write dysymtab if the command is present. + (bfd_mach_o_count_sections_for_seg): New. + (bfd_mach_o_build_seg_command): New. + (bfd_mach_o_build_dysymtab_command): New. + (bfd_mach_o_build_commands): Reorganize to support the fact that some + commands are optional and should not be emitted if there are no + sections or symbols. + (bfd_mach_o_set_section_contents): Amend comment. + * mach-o.h: Amend and add to comments. + (mach_o_data_struct): Add fields for dysymtab symbols counts and a + pointer to the indirects, when present. + (bfd_mach_o_should_emit_dysymtab): New macro. + (IS_MACHO_INDIRECT): Likewise. + 2011-12-24 Jan Kratochvil * elf32-rl78.c (rl78_elf_relocate_section, rl78_dump_symtab) diff --git a/bfd/mach-o.c b/bfd/mach-o.c index cc68d89..b2c4dff 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -1,6 +1,6 @@ /* Mach-O support for BFD. Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010, 2011 + 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -29,6 +29,8 @@ #include "mach-o/reloc.h" #include "mach-o/external.h" #include +#include +#include #define bfd_mach_o_object_p bfd_mach_o_gen_object_p #define bfd_mach_o_core_p bfd_mach_o_gen_core_p @@ -1351,13 +1353,34 @@ bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command) bfd_size_type str_index; bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; - /* Compute name index. */ - /* An index of 0 always means the empty string. */ + /* For a bare indirect symbol, the system tools expect that the symbol + value will be the string table offset for its referenced counterpart. + + Normally, indirect syms will not be written this way, but rather as + part of the dysymtab command. + + In either case, correct operation depends on the symbol table being + sorted such that the indirect symbols are at the end (since the + string table index is filled in below). */ + + if (IS_MACHO_INDIRECT (s->n_type)) + /* A pointer to the referenced symbol will be stored in the udata + field. Use that to find the string index. */ + s->symbol.value = + ((bfd_mach_o_asymbol *)s->symbol.udata.p)->symbol.udata.i; + if (s->symbol.name == 0 || s->symbol.name[0] == '\0') + /* An index of 0 always means the empty string. */ str_index = 0; else { str_index = _bfd_stringtab_add (strtab, s->symbol.name, TRUE, FALSE); + /* Record the string index. This can be looked up by an indirect sym + which retains a pointer to its referenced counterpart, until it is + actually output. */ + if (IS_MACHO_INDIRECT (s->n_type)) + s->symbol.udata.i = str_index; + if (str_index == (bfd_size_type) -1) goto err; } @@ -1420,15 +1443,316 @@ bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command) return FALSE; } -/* Process the symbols and generate Mach-O specific fields. - Number them. */ +/* Write a dysymtab command. + TODO: Possibly coalesce writes of smaller objects. */ + +static bfd_boolean +bfd_mach_o_write_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) +{ + bfd_mach_o_dysymtab_command *cmd = &command->command.dysymtab; + + BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB); + + if (cmd->nmodtab != 0) + { + unsigned int i; + + if (bfd_seek (abfd, cmd->modtaboff, SEEK_SET) != 0) + return FALSE; + + for (i = 0; i < cmd->nmodtab; i++) + { + bfd_mach_o_dylib_module *module = &cmd->dylib_module[i]; + unsigned int iinit; + unsigned int ninit; + + iinit = module->iinit & 0xffff; + iinit |= ((module->iterm & 0xffff) << 16); + + ninit = module->ninit & 0xffff; + ninit |= ((module->nterm & 0xffff) << 16); + + if (bfd_mach_o_wide_p (abfd)) + { + struct mach_o_dylib_module_64_external w; + + bfd_h_put_32 (abfd, module->module_name_idx, &w.module_name); + bfd_h_put_32 (abfd, module->iextdefsym, &w.iextdefsym); + bfd_h_put_32 (abfd, module->nextdefsym, &w.nextdefsym); + bfd_h_put_32 (abfd, module->irefsym, &w.irefsym); + bfd_h_put_32 (abfd, module->nrefsym, &w.nrefsym); + bfd_h_put_32 (abfd, module->ilocalsym, &w.ilocalsym); + bfd_h_put_32 (abfd, module->nlocalsym, &w.nlocalsym); + bfd_h_put_32 (abfd, module->iextrel, &w.iextrel); + bfd_h_put_32 (abfd, module->nextrel, &w.nextrel); + bfd_h_put_32 (abfd, iinit, &w.iinit_iterm); + bfd_h_put_32 (abfd, ninit, &w.ninit_nterm); + bfd_h_put_64 (abfd, module->objc_module_info_addr, + &w.objc_module_info_addr); + bfd_h_put_32 (abfd, module->objc_module_info_size, + &w.objc_module_info_size); + + if (bfd_bwrite ((void *) &w, sizeof (w), abfd) != sizeof (w)) + return FALSE; + } + else + { + struct mach_o_dylib_module_external n; + + bfd_h_put_32 (abfd, module->module_name_idx, &n.module_name); + bfd_h_put_32 (abfd, module->iextdefsym, &n.iextdefsym); + bfd_h_put_32 (abfd, module->nextdefsym, &n.nextdefsym); + bfd_h_put_32 (abfd, module->irefsym, &n.irefsym); + bfd_h_put_32 (abfd, module->nrefsym, &n.nrefsym); + bfd_h_put_32 (abfd, module->ilocalsym, &n.ilocalsym); + bfd_h_put_32 (abfd, module->nlocalsym, &n.nlocalsym); + bfd_h_put_32 (abfd, module->iextrel, &n.iextrel); + bfd_h_put_32 (abfd, module->nextrel, &n.nextrel); + bfd_h_put_32 (abfd, iinit, &n.iinit_iterm); + bfd_h_put_32 (abfd, ninit, &n.ninit_nterm); + bfd_h_put_32 (abfd, module->objc_module_info_addr, + &n.objc_module_info_addr); + bfd_h_put_32 (abfd, module->objc_module_info_size, + &n.objc_module_info_size); + + if (bfd_bwrite ((void *) &n, sizeof (n), abfd) != sizeof (n)) + return FALSE; + } + } + } + + if (cmd->ntoc != 0) + { + unsigned int i; + + if (bfd_seek (abfd, cmd->tocoff, SEEK_SET) != 0) + return FALSE; + + for (i = 0; i < cmd->ntoc; i++) + { + struct mach_o_dylib_table_of_contents_external raw; + bfd_mach_o_dylib_table_of_content *toc = &cmd->dylib_toc[i]; + + bfd_h_put_32 (abfd, toc->symbol_index, &raw.symbol_index); + bfd_h_put_32 (abfd, toc->module_index, &raw.module_index); + + if (bfd_bwrite (&raw, sizeof (raw), abfd) != sizeof (raw)) + return FALSE; + } + } + + if (cmd->nindirectsyms > 0) + { + unsigned int i; + + if (bfd_seek (abfd, cmd->indirectsymoff, SEEK_SET) != 0) + return FALSE; + + for (i = 0; i < cmd->nindirectsyms; ++i) + { + unsigned char raw[4]; + + bfd_h_put_32 (abfd, cmd->indirect_syms[i], &raw); + if (bfd_bwrite (raw, sizeof (raw), abfd) != sizeof (raw)) + return FALSE; + } + } + + if (cmd->nextrefsyms != 0) + { + unsigned int i; + + if (bfd_seek (abfd, cmd->extrefsymoff, SEEK_SET) != 0) + return FALSE; + + for (i = 0; i < cmd->nextrefsyms; i++) + { + unsigned long v; + unsigned char raw[4]; + bfd_mach_o_dylib_reference *ref = &cmd->ext_refs[i]; + + /* Fields isym and flags are written as bit-fields, thus we need + a specific processing for endianness. */ + + if (bfd_big_endian (abfd)) + { + v = ((ref->isym & 0xffffff) << 8); + v |= ref->flags & 0xff; + } + else + { + v = ref->isym & 0xffffff; + v |= ((ref->flags & 0xff) << 24); + } + + bfd_h_put_32 (abfd, v, raw); + if (bfd_bwrite (raw, sizeof (raw), abfd) != sizeof (raw)) + return FALSE; + } + } + + /* The command. */ + if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0) + return FALSE; + else + { + struct mach_o_dysymtab_command_external raw; + + bfd_h_put_32 (abfd, cmd->ilocalsym, &raw.ilocalsym); + bfd_h_put_32 (abfd, cmd->nlocalsym, &raw.nlocalsym); + bfd_h_put_32 (abfd, cmd->iextdefsym, &raw.iextdefsym); + bfd_h_put_32 (abfd, cmd->nextdefsym, &raw.nextdefsym); + bfd_h_put_32 (abfd, cmd->iundefsym, &raw.iundefsym); + bfd_h_put_32 (abfd, cmd->nundefsym, &raw.nundefsym); + bfd_h_put_32 (abfd, cmd->tocoff, &raw.tocoff); + bfd_h_put_32 (abfd, cmd->ntoc, &raw.ntoc); + bfd_h_put_32 (abfd, cmd->modtaboff, &raw.modtaboff); + bfd_h_put_32 (abfd, cmd->nmodtab, &raw.nmodtab); + bfd_h_put_32 (abfd, cmd->extrefsymoff, &raw.extrefsymoff); + bfd_h_put_32 (abfd, cmd->nextrefsyms, &raw.nextrefsyms); + bfd_h_put_32 (abfd, cmd->indirectsymoff, &raw.indirectsymoff); + bfd_h_put_32 (abfd, cmd->nindirectsyms, &raw.nindirectsyms); + bfd_h_put_32 (abfd, cmd->extreloff, &raw.extreloff); + bfd_h_put_32 (abfd, cmd->nextrel, &raw.nextrel); + bfd_h_put_32 (abfd, cmd->locreloff, &raw.locreloff); + bfd_h_put_32 (abfd, cmd->nlocrel, &raw.nlocrel); + + if (bfd_bwrite (&raw, sizeof (raw), abfd) != sizeof (raw)) + return FALSE; + } + + return TRUE; +} + +static unsigned +bfd_mach_o_primary_symbol_sort_key (unsigned type, unsigned ext) +{ + /* TODO: Determine the correct ordering of stabs symbols. */ + /* We make indirect symbols a local/synthetic. */ + if (type == BFD_MACH_O_N_INDR) + return 3; + + /* Local (we should never see an undefined local AFAICT). */ + if (! ext) + return 0; + + /* Common symbols look like undefined externs. */ + if (type == BFD_MACH_O_N_UNDF) + return 2; + + /* A defined symbol that's not indirect or extern. */ + return 1; +} + +static int +bfd_mach_o_cf_symbols (const void *a, const void *b) +{ + bfd_mach_o_asymbol *sa = *(bfd_mach_o_asymbol **) a; + bfd_mach_o_asymbol *sb = *(bfd_mach_o_asymbol **) b; + unsigned int soa, sob; + + soa = bfd_mach_o_primary_symbol_sort_key + (sa->n_type & BFD_MACH_O_N_TYPE, + sa->n_type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)); + sob = bfd_mach_o_primary_symbol_sort_key + (sb->n_type & BFD_MACH_O_N_TYPE, + sb->n_type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)); + if (soa < sob) + return -1; + + if (soa > sob) + return 1; + + /* If it's local, just preserve the input order. */ + if (soa == 0) + { + if (sa->symbol.udata.i < sb->symbol.udata.i) + return -1; + if (sa->symbol.udata.i > sb->symbol.udata.i) + return 1; + return 0; + } + + /* Unless it's an indirect the second sort key is name. */ + if (soa < 3) + return strcmp (sa->symbol.name, sb->symbol.name); + + /* Here be indirect symbols, which have different sort rules. */ + + /* Next sort key for indirect, is the section index. */ + if (sa->n_sect < sb->n_sect) + return -1; + + if (sa->n_sect > sb->n_sect) + return 1; + + /* Last sort key is the order of definition - which should be in line with + the value, since a stub size of 0 is meaninglesss. */ + + if (sa->symbol.value < sb->symbol.value) + return -1; + + if (sa->symbol.value > sb->symbol.value) + return 1; + + /* In the final analysis, this is probably an error ... but leave it alone + for now. */ + return 0; +} + +/* When this is finished, return the number of non-indirect symbols. */ + +static unsigned int +bfd_mach_o_sort_symbol_table (asymbol **symbols, unsigned int nin) +{ + qsort (symbols, (size_t) nin, sizeof (void *), bfd_mach_o_cf_symbols); + + /* Find the last non-indirect symbol. + There must be at least one non-indirect symbol otherwise there's + nothing for the indirect(s) to refer to. */ + do + { + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[nin - 1]; + if (IS_MACHO_INDIRECT (s->n_type)) + nin--; + else + break; + } while (nin - 1 > 0); + return nin; +} + +/* Process the symbols. + + This should be OK for single-module files - but it is not likely to work + for multi-module shared libraries. + + (a) If the application has not filled in the relevant mach-o fields, make + an estimate. + + (b) Order them, like this: + ( i) local. + (unsorted) + ( ii) external defined + (by name) + (iii) external undefined + (by name) + ( iv) common + (by name) + ( v) indirect + (by section) + (by position within section). + + (c) Indirect symbols are moved to the end of the list. */ static bfd_boolean -bfd_mach_o_mangle_symbols (bfd *abfd) +bfd_mach_o_mangle_symbols (bfd *abfd, bfd_mach_o_data_struct *mdata) { unsigned long i; asymbol **symbols = bfd_get_outsymbols (abfd); + if (symbols == NULL || bfd_get_symcount (abfd) == 0) + return TRUE; + for (i = 0; i < bfd_get_symcount (abfd); i++) { bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; @@ -1445,6 +1769,8 @@ bfd_mach_o_mangle_symbols (bfd *abfd) s->n_type = BFD_MACH_O_N_UNDF; if (s->symbol.flags & BSF_WEAK) s->n_desc |= BFD_MACH_O_N_WEAK_REF; + /* mach-o automatically makes undefined symbols extern. */ + s->n_type |= BFD_MACH_O_N_EXT; } else if (s->symbol.section == bfd_com_section_ptr) s->n_type = BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT; @@ -1455,15 +1781,116 @@ bfd_mach_o_mangle_symbols (bfd *abfd) s->n_type |= BFD_MACH_O_N_EXT; } - /* Compute section index. */ + /* Put the section index in, where required. */ if (s->symbol.section != bfd_abs_section_ptr && s->symbol.section != bfd_und_section_ptr && s->symbol.section != bfd_com_section_ptr) s->n_sect = s->symbol.section->target_index; - /* Number symbols. */ - s->symbol.udata.i = i; + /* Unless we're looking at an indirect sym, note the input ordering. + We use this to keep local symbols ordered as per the input. */ + if (IS_MACHO_INDIRECT (s->n_type)) + s->symbol.udata.i = i; + } + + /* Sort the symbols and determine how many will remain in the main symbol + table, and how many will be emitted as indirect (assuming that we will + be emitting a dysymtab). Renumber the sorted symbols so that the right + index will be found during indirection. */ + i = bfd_mach_o_sort_symbol_table (symbols, bfd_get_symcount (abfd)); + if (bfd_mach_o_should_emit_dysymtab ()) + { + /* Point at the first indirect symbol. */ + if (i < bfd_get_symcount (abfd)) + { + mdata->indirect_syms = &symbols[i]; + mdata->nindirect = bfd_get_symcount (abfd) - i; + /* This is, essentially, local to the output section of mach-o, + and therefore should be safe. */ + abfd->symcount = i; + } + + /* Now setup the counts for each type of symbol. */ + for (i = 0; i < bfd_get_symcount (abfd); ++i) + { + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; + s->symbol.udata.i = i; /* renumber. */ + if (s->n_type & (BFD_MACH_O_N_EXT | BFD_MACH_O_N_PEXT)) + break; + } + mdata->nlocal = i; + for (; i < bfd_get_symcount (abfd); ++i) + { + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; + s->symbol.udata.i = i; /* renumber. */ + if ((s->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_UNDF) + break; + } + mdata->ndefext = i - mdata->nlocal; + mdata->nundefext = bfd_get_symcount (abfd) + - mdata->ndefext + - mdata->nlocal; + for (; i < bfd_get_symcount (abfd); ++i) + { + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; + s->symbol.udata.i = i; /* renumber. */ + } + } + + return TRUE; +} + +/* We build a flat table of sections, which can be re-ordered if necessary. + Fill in the section number and other mach-o-specific data. */ + +static bfd_boolean +bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata) +{ + asection *sec; + unsigned target_index; + unsigned nsect; + + nsect = bfd_count_sections (abfd); + + /* Don't do it if it's already set - assume the application knows what it's + doing. */ + if (mdata->nsects == nsect + && (mdata->nsects == 0 || mdata->sections != NULL)) + return TRUE; + + mdata->nsects = nsect; + mdata->sections = bfd_alloc (abfd, + mdata->nsects * sizeof (bfd_mach_o_section *)); + if (mdata->sections == NULL) + return FALSE; + + /* We need to check that this can be done... */ + if (nsect > 255) + (*_bfd_error_handler) (_("mach-o: there are too many sections (%d)" + " maximum is 255,\n"), nsect); + + /* Create Mach-O sections. + Section type, attribute and align should have been set when the + section was created - either read in or specified. */ + target_index = 0; + for (sec = abfd->sections; sec; sec = sec->next) + { + unsigned bfd_align = bfd_get_section_alignment (abfd, sec); + bfd_mach_o_section *msect = bfd_mach_o_get_mach_o_section (sec); + + mdata->sections[target_index] = msect; + + msect->addr = bfd_get_section_vma (abfd, sec); + msect->size = bfd_get_section_size (sec); + + /* Use the largest alignment set, in case it was bumped after the + section was created. */ + msect->align = msect->align > bfd_align ? msect->align : bfd_align; + + msect->offset = 0; + sec->target_index = ++target_index; } + return TRUE; } @@ -1473,27 +1900,14 @@ bfd_mach_o_write_contents (bfd *abfd) unsigned int i; bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); + /* Make the commands, if not already present. */ if (mdata->header.ncmds == 0) if (!bfd_mach_o_build_commands (abfd)) return FALSE; - /* Now write header information. */ - if (mdata->header.filetype == 0) - { - if (abfd->flags & EXEC_P) - mdata->header.filetype = BFD_MACH_O_MH_EXECUTE; - else if (abfd->flags & DYNAMIC) - mdata->header.filetype = BFD_MACH_O_MH_DYLIB; - else - mdata->header.filetype = BFD_MACH_O_MH_OBJECT; - } if (!bfd_mach_o_write_header (abfd, &mdata->header)) return FALSE; - /* Assign a number to each symbols. */ - if (!bfd_mach_o_mangle_symbols (abfd)) - return FALSE; - for (i = 0; i < mdata->header.ncmds; i++) { struct mach_o_load_command_external raw; @@ -1523,6 +1937,10 @@ bfd_mach_o_write_contents (bfd *abfd) if (!bfd_mach_o_write_symtab (abfd, cur)) return FALSE; break; + case BFD_MACH_O_LC_DYSYMTAB: + if (!bfd_mach_o_write_dysymtab (abfd, cur)) + return FALSE; + break; case BFD_MACH_O_LC_SYMSEG: break; case BFD_MACH_O_LC_THREAD: @@ -1535,7 +1953,6 @@ bfd_mach_o_write_contents (bfd *abfd) case BFD_MACH_O_LC_IDENT: case BFD_MACH_O_LC_FVMFILE: case BFD_MACH_O_LC_PREPAGE: - case BFD_MACH_O_LC_DYSYMTAB: case BFD_MACH_O_LC_LOAD_DYLIB: case BFD_MACH_O_LC_LOAD_WEAK_DYLIB: case BFD_MACH_O_LC_ID_DYLIB: @@ -1591,7 +2008,171 @@ bfd_mach_o_set_section_flags_from_bfd (bfd *abfd ATTRIBUTE_UNUSED, asection *sec s->flags = BFD_MACH_O_S_REGULAR; } -/* Build Mach-O load commands from the sections. */ +/* Count the number of sections in the list for the segment named. + + The special case of NULL or "" for the segment name is valid for + an MH_OBJECT file and means 'all sections available'. + + Requires that the sections table in mdata be filled in. + + Returns the number of sections (0 is valid). + Any number > 255 signals an invalid section count, although we will, + perhaps, allow the file to be written (in line with Darwin tools up + to XCode 4). + + A section count of (unsigned long) -1 signals a definite error. */ + +static unsigned long +bfd_mach_o_count_sections_for_seg (const char *segment, + bfd_mach_o_data_struct *mdata) +{ + unsigned i,j; + if (mdata == NULL || mdata->sections == NULL) + return (unsigned long) -1; + + /* The MH_OBJECT case, all sections are considered; Although nsects is + is an unsigned long, the maximum valid section count is 255 and this + will have been checked already by mangle_sections. */ + if (segment == NULL || segment[0] == '\0') + return mdata->nsects; + + /* Count the number of sections we see in this segment. */ + j = 0; + for (i = 0; i < mdata->nsects; ++i) + { + bfd_mach_o_section *s = mdata->sections[i]; + if (strncmp (segment, s->segname, BFD_MACH_O_SEGNAME_SIZE) == 0) + j++; + } + return j; +} + +static bfd_boolean +bfd_mach_o_build_seg_command (const char *segment, + bfd_mach_o_data_struct *mdata, + bfd_mach_o_segment_command *seg) +{ + unsigned i; + int is_mho = (segment == NULL || segment[0] == '\0'); + + /* Fill segment command. */ + if (is_mho) + memset (seg->segname, 0, sizeof (seg->segname)); + else + strncpy (seg->segname, segment, sizeof (seg->segname)); + + /* TODO: fix this up for non-MH_OBJECT cases. */ + seg->vmaddr = 0; + + seg->fileoff = mdata->filelen; + seg->filesize = 0; + seg->maxprot = BFD_MACH_O_PROT_READ | BFD_MACH_O_PROT_WRITE + | BFD_MACH_O_PROT_EXECUTE; + seg->initprot = seg->maxprot; + seg->flags = 0; + seg->sect_head = NULL; + seg->sect_tail = NULL; + + /* Append sections to the segment. */ + + for (i = 0; i < mdata->nsects; ++i) + { + bfd_mach_o_section *s = mdata->sections[i]; + asection *sec = s->bfdsection; + + /* If we're not making an MH_OBJECT, check whether this section is from + our segment, and skip if not. Otherwise, just add all sections. */ + if (! is_mho + && strncmp (segment, s->segname, BFD_MACH_O_SEGNAME_SIZE) != 0) + continue; + + bfd_mach_o_append_section_to_segment (seg, sec); + + if (s->size == 0) + s->offset = 0; + else + { + mdata->filelen = FILE_ALIGN (mdata->filelen, s->align); + s->offset = mdata->filelen; + } + + sec->filepos = s->offset; + + mdata->filelen += s->size; + } + + seg->filesize = mdata->filelen - seg->fileoff; + seg->vmsize = seg->filesize; + + return TRUE; +} + +static bfd_boolean +bfd_mach_o_build_dysymtab_command (bfd *abfd, + bfd_mach_o_data_struct *mdata, + bfd_mach_o_load_command *cmd) +{ + bfd_mach_o_dysymtab_command *dsym = &cmd->command.dysymtab; + + /* TODO: + We are not going to try and fill these in yet and, moreover, we are + going to bail if they are already set. */ + if (dsym->nmodtab != 0 + || dsym->ntoc != 0 + || dsym->nextrefsyms != 0) + { + (*_bfd_error_handler) (_("sorry: modtab, toc and extrefsyms are not yet" + " implemented for dysymtab commands.")); + return FALSE; + } + + dsym->ilocalsym = 0; + dsym->nlocalsym = mdata->nlocal; + dsym->iextdefsym = dsym->nlocalsym; + dsym->nextdefsym = mdata->ndefext; + dsym->iundefsym = dsym->nextdefsym + dsym->iextdefsym; + dsym->nundefsym = mdata->nundefext; + + if (mdata->nindirect > 0) + { + unsigned i, sect; + + mdata->filelen = FILE_ALIGN (mdata->filelen, 2); + dsym->indirectsymoff = mdata->filelen; + mdata->filelen += mdata->nindirect * 4; + + dsym->indirect_syms = bfd_zalloc (abfd, mdata->nindirect * 4); + if (dsym->indirect_syms == NULL) + return FALSE; + dsym->nindirectsyms = mdata->nindirect; + + /* So fill in the indices, and point the section reserved1 fields + at the right one. */ + sect = (unsigned) -1; + for (i = 0; i < mdata->nindirect; ++i) + { + bfd_mach_o_asymbol *s = + (bfd_mach_o_asymbol *) mdata->indirect_syms[i]; + /* Lookup the index of the referenced symbol. */ + dsym->indirect_syms[i] = + ((bfd_mach_o_asymbol *) s->symbol.udata.p)->symbol.udata.i; + if (s->n_sect != sect) + { + /* Mach-o sections are 1-based, but the section table + is 0-based. */ + bfd_mach_o_section *sc = mdata->sections[s->n_sect-1]; + sc->reserved1 = i; + sect = s->n_sect; + } + } + } + + return TRUE; +} + +/* Build Mach-O load commands (currently assuming an MH_OBJECT file). + TODO: Other file formats, rebuilding symtab/dysymtab commands for strip + and copy functionality. */ bfd_boolean bfd_mach_o_build_commands (bfd *abfd) @@ -1599,102 +2180,148 @@ bfd_mach_o_build_commands (bfd *abfd) bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); unsigned int wide = mach_o_wide_p (&mdata->header); bfd_mach_o_segment_command *seg; - asection *sec; bfd_mach_o_load_command *cmd; bfd_mach_o_load_command *symtab_cmd; - int target_index; + unsigned symcind; - /* Return now if commands are already built. */ + /* Return now if commands are already present. */ if (mdata->header.ncmds) return FALSE; - /* Very simple version: a command (segment) to contain all the sections and - a command for the symbol table. */ - mdata->header.ncmds = 2; - mdata->commands = bfd_alloc (abfd, mdata->header.ncmds - * sizeof (bfd_mach_o_load_command)); - if (mdata->commands == NULL) - return FALSE; - cmd = &mdata->commands[0]; - seg = &cmd->command.segment; - - seg->nsects = bfd_count_sections (abfd); + /* Fill in the file type, if not already set. */ - /* Set segment command. */ - if (wide) + if (mdata->header.filetype == 0) { - cmd->type = BFD_MACH_O_LC_SEGMENT_64; - cmd->offset = BFD_MACH_O_HEADER_64_SIZE; - cmd->len = BFD_MACH_O_LC_SEGMENT_64_SIZE - + BFD_MACH_O_SECTION_64_SIZE * seg->nsects; + if (abfd->flags & EXEC_P) + mdata->header.filetype = BFD_MACH_O_MH_EXECUTE; + else if (abfd->flags & DYNAMIC) + mdata->header.filetype = BFD_MACH_O_MH_DYLIB; + else + mdata->header.filetype = BFD_MACH_O_MH_OBJECT; } - else + + /* If hasn't already been done, flatten sections list, and sort + if/when required. Must be done before the symbol table is adjusted, + since that depends on properly numbered sections. */ + if (mdata->nsects == 0 || mdata->sections == NULL) + if (! bfd_mach_o_mangle_sections (abfd, mdata)) + return FALSE; + + /* Order the symbol table, fill-in/check mach-o specific fields and + partition out any indirect symbols. */ + if (!bfd_mach_o_mangle_symbols (abfd, mdata)) + return FALSE; + + /* It's valid to have a file with only absolute symbols... */ + if (mdata->nsects > 0) { - cmd->type = BFD_MACH_O_LC_SEGMENT; - cmd->offset = BFD_MACH_O_HEADER_SIZE; - cmd->len = BFD_MACH_O_LC_SEGMENT_SIZE - + BFD_MACH_O_SECTION_SIZE * seg->nsects; + mdata->header.ncmds = 1; + symcind = 1; } - cmd->type_required = FALSE; - mdata->header.sizeofcmds = cmd->len; - mdata->filelen = cmd->offset + cmd->len; + else + symcind = 0; - /* Set symtab command. */ - symtab_cmd = &mdata->commands[1]; - - symtab_cmd->type = BFD_MACH_O_LC_SYMTAB; - symtab_cmd->offset = cmd->offset + cmd->len; - symtab_cmd->len = 6 * 4; - symtab_cmd->type_required = FALSE; - - mdata->header.sizeofcmds += symtab_cmd->len; - mdata->filelen += symtab_cmd->len; + /* It's OK to have a file with only section statements. */ + if (bfd_get_symcount (abfd) > 0) + mdata->header.ncmds += 1; - /* Fill segment command. */ - memset (seg->segname, 0, sizeof (seg->segname)); - seg->vmaddr = 0; - seg->fileoff = mdata->filelen; - seg->filesize = 0; - seg->maxprot = BFD_MACH_O_PROT_READ | BFD_MACH_O_PROT_WRITE - | BFD_MACH_O_PROT_EXECUTE; - seg->initprot = seg->maxprot; - seg->flags = 0; - seg->sect_head = NULL; - seg->sect_tail = NULL; + /* Very simple version (only really applicable to MH_OBJECTs): + a command (segment) to contain all the sections, + a command for the symbol table + a n (optional) command for the dysymtab. - /* Create Mach-O sections. - Section type, attribute and align should have been set when the - section was created - either read in or specified. */ - target_index = 0; - for (sec = abfd->sections; sec; sec = sec->next) - { - unsigned bfd_align = bfd_get_section_alignment (abfd, sec); - bfd_mach_o_section *msect = bfd_mach_o_get_mach_o_section (sec); + ??? maybe we should assert that this is an MH_OBJECT? */ - bfd_mach_o_append_section_to_segment (seg, sec); + if (bfd_mach_o_should_emit_dysymtab () + && bfd_get_symcount (abfd) > 0) + mdata->header.ncmds += 1; - msect->addr = bfd_get_section_vma (abfd, sec); - msect->size = bfd_get_section_size (sec); - /* Use the largest alignment set, in case it was bumped after the - section was created. */ - msect->align = msect->align > bfd_align ? msect->align : bfd_align; + /* A bit weird, but looks like no content; + as -n empty.s -o empty.o */ + if (mdata->header.ncmds == 0) + return TRUE; - if (msect->size != 0) - { - mdata->filelen = FILE_ALIGN (mdata->filelen, msect->align); - msect->offset = mdata->filelen; - } + mdata->commands = bfd_zalloc (abfd, mdata->header.ncmds + * sizeof (bfd_mach_o_load_command)); + if (mdata->commands == NULL) + return FALSE; + + if (mdata->nsects > 0) + { + cmd = &mdata->commands[0]; + seg = &cmd->command.segment; + + /* Count the segctions in the special blank segment used for MH_OBJECT. */ + seg->nsects = bfd_mach_o_count_sections_for_seg (NULL, mdata); + if (seg->nsects == (unsigned long) -1) + return FALSE; + + /* Init segment command. */ + if (wide) + { + cmd->type = BFD_MACH_O_LC_SEGMENT_64; + cmd->offset = BFD_MACH_O_HEADER_64_SIZE; + cmd->len = BFD_MACH_O_LC_SEGMENT_64_SIZE + + BFD_MACH_O_SECTION_64_SIZE * seg->nsects; + } else - msect->offset = 0; + { + cmd->type = BFD_MACH_O_LC_SEGMENT; + cmd->offset = BFD_MACH_O_HEADER_SIZE; + cmd->len = BFD_MACH_O_LC_SEGMENT_SIZE + + BFD_MACH_O_SECTION_SIZE * seg->nsects; + } + cmd->type_required = FALSE; + mdata->header.sizeofcmds = cmd->len; + mdata->filelen = cmd->offset + cmd->len; + } - sec->filepos = msect->offset; - sec->target_index = ++target_index; + if (bfd_get_symcount (abfd) > 0) + { + /* Init symtab command. */ + symtab_cmd = &mdata->commands[symcind]; + + symtab_cmd->type = BFD_MACH_O_LC_SYMTAB; + if (symcind > 0) + symtab_cmd->offset = mdata->commands[0].offset + + mdata->commands[0].len; + else + symtab_cmd->offset = 0; + symtab_cmd->len = 6 * 4; + symtab_cmd->type_required = FALSE; + + mdata->header.sizeofcmds += symtab_cmd->len; + mdata->filelen += symtab_cmd->len; + } - mdata->filelen += msect->size; + /* If required, setup symtab command. */ + if (bfd_mach_o_should_emit_dysymtab () + && bfd_get_symcount (abfd) > 0) + { + cmd = &mdata->commands[symcind+1]; + cmd->type = BFD_MACH_O_LC_DYSYMTAB; + cmd->offset = symtab_cmd->offset + symtab_cmd->len; + cmd->type_required = FALSE; + cmd->len = 18 * 4 + BFD_MACH_O_LC_SIZE; + + mdata->header.sizeofcmds += cmd->len; + mdata->filelen += cmd->len; } - seg->filesize = mdata->filelen - seg->fileoff; - seg->vmsize = seg->filesize; + /* So, now we have sized the commands and the filelen set to that. + Now we can build the segment command and set the section file offsets. */ + if (mdata->nsects > 0 + && ! bfd_mach_o_build_seg_command (NULL, mdata, seg)) + return FALSE; + + /* If we're doing a dysymtab, cmd points to its load command. */ + if (bfd_mach_o_should_emit_dysymtab () + && bfd_get_symcount (abfd) > 0 + && ! bfd_mach_o_build_dysymtab_command (abfd, mdata, + &mdata->commands[symcind+1])) + return FALSE; + + /* The symtab command is filled in when the symtab is written. */ return TRUE; } @@ -1709,8 +2336,8 @@ bfd_mach_o_set_section_contents (bfd *abfd, { file_ptr pos; - /* This must be done first, because bfd_set_section_contents is - going to set output_has_begun to TRUE. */ + /* Trying to write the first section contents will trigger the creation of + the load commands if they are not already present. */ if (! abfd->output_has_begun && ! bfd_mach_o_build_commands (abfd)) return FALSE; diff --git a/bfd/mach-o.h b/bfd/mach-o.h index 89dce1a..24a1645 100644 --- a/bfd/mach-o.h +++ b/bfd/mach-o.h @@ -1,6 +1,6 @@ /* Mach-O support for BFD. - Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2011 - Free Software Foundation, Inc. + Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2011, + 2012 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -109,13 +109,24 @@ typedef struct bfd_mach_o_asymbol /* The actual symbol which the rest of BFD works with. */ asymbol symbol; - /* Fields from Mach-O 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 + (sorted by name) +*/ + typedef struct bfd_mach_o_symtab_command { unsigned int symoff; @@ -507,7 +518,7 @@ typedef struct mach_o_data_struct unsigned long nsects; bfd_mach_o_section **sections; - /* Used while writting: current length of the output file. This is used + /* Used while writing: current length of the output file. This is used to allocate space in the file. */ ufile_ptr filelen; @@ -517,6 +528,18 @@ typedef struct mach_o_data_struct bfd_mach_o_symtab_command *symtab; bfd_mach_o_dysymtab_command *dysymtab; + /* Base values used for building the dysymtab for a single-module object. */ + unsigned long nlocal; + unsigned long ndefext; + unsigned long nundefext; + + /* If this is non-zero, then the pointer below is populated. */ + unsigned long nindirect; + /* A set of synthetic symbols representing the 'indirect' ones in the file. + These should be sorted (a) by the section they represent and (b) by the + order that they appear within each section. */ + asymbol **indirect_syms; + /* A place to stash dwarf2 info for this bfd. */ void *dwarf2_find_line_info; @@ -600,6 +623,10 @@ unsigned int bfd_mach_o_section_get_entry_size (bfd *, bfd_mach_o_section *); bfd_boolean bfd_mach_o_read_symtab_symbols (bfd *); bfd_boolean bfd_mach_o_read_symtab_strtab (bfd *abfd); +/* A placeholder in case we need to suppress emitting the dysymtab for some + reason (e.g. compatibility with older system versions). */ +#define bfd_mach_o_should_emit_dysymtab(x) TRUE + extern const bfd_mach_o_xlat_name bfd_mach_o_section_attribute_name[]; extern const bfd_mach_o_xlat_name bfd_mach_o_section_type_name[]; @@ -640,4 +667,8 @@ typedef struct bfd_mach_o_backend_data } bfd_mach_o_backend_data; +/* Symbol type tests. */ + +#define IS_MACHO_INDIRECT(x) (((x) & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_INDR) + #endif /* _BFD_MACH_O_H_ */ diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 80f9a73..624ee9f 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2012-01-03 Iain Sandoe + + * gas/mach-o/dysymtab-1-64.d: New. + * gas/mach-o/dysymtab-1.d: New. + * gas/mach-o/symbols-1-64.d: New. + * gas/mach-o/symbols-1.d: New. + * gas/mach-o/symbols-base-64.s: New. + * gas/mach-o/symbols-base.s: New. + 2011-12-29 Iain Sandoe * gas/mach-o/sections-1.d: Amend to recognize that bss is not emitted diff --git a/gas/testsuite/gas/mach-o/dysymtab-1-64.d b/gas/testsuite/gas/mach-o/dysymtab-1-64.d new file mode 100644 index 0000000..2b2b419 --- /dev/null +++ b/gas/testsuite/gas/mach-o/dysymtab-1-64.d @@ -0,0 +1,15 @@ +#objdump: -P dysymtab +#target: x86_64-*-darwin* powerpc64-*-darwin* +#source: symbols-base-64.s +.*: +file format mach-o.* +#... +Load command dysymtab: + local symbols: idx: 0 num: 6.*\(nxtidx: 6\) + external symbols: idx: 6 num: 18.*\(nxtidx: 24\) + undefined symbols: idx: 24 num: 21.*\(nxtidx: 45\) + table of content: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + module table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + external reference table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + indirect symbol table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + external relocation table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + local relocation table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) diff --git a/gas/testsuite/gas/mach-o/dysymtab-1.d b/gas/testsuite/gas/mach-o/dysymtab-1.d new file mode 100644 index 0000000..48db498 --- /dev/null +++ b/gas/testsuite/gas/mach-o/dysymtab-1.d @@ -0,0 +1,15 @@ +#objdump: -P dysymtab +#target: i?86-*-darwin* powerpc-*-darwin* +#source: symbols-base.s +.*: +file format mach-o.* +#... +Load command dysymtab: + local symbols: idx: 0 num: 6.*\(nxtidx: 6\) + external symbols: idx: 6 num: 18.*\(nxtidx: 24\) + undefined symbols: idx: 24 num: 21.*\(nxtidx: 45\) + table of content: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + module table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + external reference table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + indirect symbol table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + external relocation table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) + local relocation table: off: 0x00000000 num: 0.*\(endoff: 0x00000000\) diff --git a/gas/testsuite/gas/mach-o/symbols-1-64.d b/gas/testsuite/gas/mach-o/symbols-1-64.d new file mode 100644 index 0000000..9d23ee1 --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-1-64.d @@ -0,0 +1,70 @@ +#as: -L +#objdump: -t +#target: x86_64-*-darwin* powerpc64-*-darwin* +#source: symbols-base-64.s +.*: +file format mach-o.* +#... +SYMBOL TABLE: +0000000000000000 l.*0e SECT 01 0000 \[.text\] Lzt0 +0000000000000002 l.*0e SECT 01 0000 \[.text\] Lmt0 +0000000000000004 l.*0e SECT 01 0000 \[.text\] Lat0 +0000000000000000 l.*0e SECT 02 0000 \[.data\] Lzd0 +0000000000000002 l.*0e SECT 02 0000 \[.data\] Lmd0 +0000000000000005 l.*0e SECT 02 0000 \[.data\] Lad0 +0000000000000000 l.*0e SECT 03 0000 \[.bss\] zlcomm0 +0000000000000006 l.*0e SECT 03 0000 \[.bss\] mlcomm0 +000000000000000c l.*0e SECT 03 0000 \[.bss\] alcomm0 +0000000000000000 l.*0e SECT 04 0000 \[__HERE.__there\] Lzs0 +0000000000000002 l.*0e SECT 04 0000 \[__HERE.__there\] Lms0 +0000000000000004 l.*0e SECT 04 0000 \[__HERE.__there\] Las0 +000000000000001e l.*0e SECT 01 0000 \[.text\] Lzt1 +0000000000000021 l.*0e SECT 01 0000 \[.text\] Lmt1 +0000000000000023 l.*0e SECT 01 0000 \[.text\] Lat1 +000000000000001e l.*0e SECT 02 0000 \[.data\] Lzd1 +0000000000000020 l.*0e SECT 02 0000 \[.data\] Lmd1 +0000000000000023 l.*0e SECT 02 0000 \[.data\] Lad1 +0000000000000012 l.*0e SECT 03 0000 \[.bss\] zlcomm1 +0000000000000018 l.*0e SECT 03 0000 \[.bss\] mlcomm1 +000000000000001e l.*0e SECT 03 0000 \[.bss\] alcomm1 +0000000000000026 l.*0e SECT 04 0000 \[__HERE.__there\] Lzs1 +0000000000000032 l.*0e SECT 04 0000 \[__HERE.__there\] Lms1 +0000000000000033 l.*0e SECT 04 0000 \[__HERE.__there\] Las1 +0000000000000004 g.*0f SECT 02 0000 \[.data\] adg0 +0000000000000022 g.*0f SECT 02 0000 \[.data\] adg1 +0000000000000005 g.*0f SECT 04 0000 \[__HERE.__there\] asg0 +0000000000000031 g.*0f SECT 04 0000 \[__HERE.__there\] asg1 +0000000000000005 g.*0f SECT 01 0000 \[.text\] atg0 +0000000000000022 g.*0f SECT 01 0000 \[.text\] atg1 +0000000000000003 g.*0f SECT 02 0000 \[.data\] mdg0 +0000000000000021 g.*0f SECT 02 0000 \[.data\] mdg1 +0000000000000003 g.*0f SECT 04 0000 \[__HERE.__there\] msg0 +0000000000000030 g.*0f SECT 04 0000 \[__HERE.__there\] msg1 +0000000000000003 g.*0f SECT 01 0000 \[.text\] mtg0 +0000000000000020 g.*0f SECT 01 0000 \[.text\] mtg1 +0000000000000001 g.*0f SECT 02 0000 \[.data\] zdg0 +000000000000001f g.*0f SECT 02 0000 \[.data\] zdg1 +0000000000000001 g.*0f SECT 04 0000 \[__HERE.__there\] zsg0 +0000000000000027 g.*0f SECT 04 0000 \[__HERE.__there\] zsg1 +0000000000000001 g.*0f SECT 01 0000 \[.text\] ztg0 +000000000000001f g.*0f SECT 01 0000 \[.text\] ztg1 +0000000000000000 g.*01 UND 00 0000 _aud0 +0000000000000000 g.*01 UND 00 0000 _aud1 +0000000000000000 g.*01 UND 00 0000 _aus0 +0000000000000000 g.*01 UND 00 0000 _aus1 +0000000000000000 g.*01 UND 00 0000 _aut0 +0000000000000000 g.*01 UND 00 0000 _mud0 +0000000000000000 g.*01 UND 00 0000 _mud1 +0000000000000000 g.*01 UND 00 0000 _mus0 +0000000000000000 g.*01 UND 00 0000 _mus1 +0000000000000000 g.*01 UND 00 0000 _mut0 +0000000000000000 g.*01 UND 00 0000 _zud0 +0000000000000000 g.*01 UND 00 0000 _zud1 +0000000000000000 g.*01 UND 00 0000 _zus0 +0000000000000000 g.*01 UND 00 0000 _zus1 +0000000000000000 g.*01 UND 00 0000 _zut0 +000000000000000a.*01 COM 00 0300 acommon0 +000000000000000a.*01 COM 00 0300 acommon1 +000000000000000a.*01 COM 00 0300 mcommon0 +000000000000000a.*01 COM 00 0300 mcommon1 +000000000000000a.*01 COM 00 0300 zcommon0 +000000000000000a.*01 COM 00 0300 zcommon1 \ No newline at end of file diff --git a/gas/testsuite/gas/mach-o/symbols-1.d b/gas/testsuite/gas/mach-o/symbols-1.d new file mode 100644 index 0000000..cfc1dca --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-1.d @@ -0,0 +1,70 @@ +#as: -L +#objdump: -t +#target: i?86-*-darwin* powerpc-*-darwin* +#source: symbols-base.s +.*: +file format mach-o.* +#... +SYMBOL TABLE: +00000000 l.*0e SECT 01 0000 \[.text\] Lzt0 +00000002 l.*0e SECT 01 0000 \[.text\] Lmt0 +00000004 l.*0e SECT 01 0000 \[.text\] Lat0 +00000000 l.*0e SECT 02 0000 \[.data\] Lzd0 +00000002 l.*0e SECT 02 0000 \[.data\] Lmd0 +00000005 l.*0e SECT 02 0000 \[.data\] Lad0 +00000000 l.*0e SECT 03 0000 \[.bss\] zlcomm0 +00000006 l.*0e SECT 03 0000 \[.bss\] mlcomm0 +0000000c l.*0e SECT 03 0000 \[.bss\] alcomm0 +00000000 l.*0e SECT 04 0000 \[__HERE.__there\] Lzs0 +00000002 l.*0e SECT 04 0000 \[__HERE.__there\] Lms0 +00000004 l.*0e SECT 04 0000 \[__HERE.__there\] Las0 +00000012 l.*0e SECT 01 0000 \[.text\] Lzt1 +00000015 l.*0e SECT 01 0000 \[.text\] Lmt1 +00000017 l.*0e SECT 01 0000 \[.text\] Lat1 +00000012 l.*0e SECT 02 0000 \[.data\] Lzd1 +00000014 l.*0e SECT 02 0000 \[.data\] Lmd1 +00000017 l.*0e SECT 02 0000 \[.data\] Lad1 +00000012 l.*0e SECT 03 0000 \[.bss\] zlcomm1 +00000018 l.*0e SECT 03 0000 \[.bss\] mlcomm1 +0000001e l.*0e SECT 03 0000 \[.bss\] alcomm1 +00000016 l.*0e SECT 04 0000 \[__HERE.__there\] Lzs1 +0000001e l.*0e SECT 04 0000 \[__HERE.__there\] Lms1 +0000001f l.*0e SECT 04 0000 \[__HERE.__there\] Las1 +00000004 g.*0f SECT 02 0000 \[.data\] adg0 +00000016 g.*0f SECT 02 0000 \[.data\] adg1 +00000005 g.*0f SECT 04 0000 \[__HERE.__there\] asg0 +0000001d g.*0f SECT 04 0000 \[__HERE.__there\] asg1 +00000005 g.*0f SECT 01 0000 \[.text\] atg0 +00000016 g.*0f SECT 01 0000 \[.text\] atg1 +00000003 g.*0f SECT 02 0000 \[.data\] mdg0 +00000015 g.*0f SECT 02 0000 \[.data\] mdg1 +00000003 g.*0f SECT 04 0000 \[__HERE.__there\] msg0 +0000001c g.*0f SECT 04 0000 \[__HERE.__there\] msg1 +00000003 g.*0f SECT 01 0000 \[.text\] mtg0 +00000014 g.*0f SECT 01 0000 \[.text\] mtg1 +00000001 g.*0f SECT 02 0000 \[.data\] zdg0 +00000013 g.*0f SECT 02 0000 \[.data\] zdg1 +00000001 g.*0f SECT 04 0000 \[__HERE.__there\] zsg0 +00000017 g.*0f SECT 04 0000 \[__HERE.__there\] zsg1 +00000001 g.*0f SECT 01 0000 \[.text\] ztg0 +00000013 g.*0f SECT 01 0000 \[.text\] ztg1 +00000000 g.*01 UND 00 0000 _aud0 +00000000 g.*01 UND 00 0000 _aud1 +00000000 g.*01 UND 00 0000 _aus0 +00000000 g.*01 UND 00 0000 _aus1 +00000000 g.*01 UND 00 0000 _aut0 +00000000 g.*01 UND 00 0000 _mud0 +00000000 g.*01 UND 00 0000 _mud1 +00000000 g.*01 UND 00 0000 _mus0 +00000000 g.*01 UND 00 0000 _mus1 +00000000 g.*01 UND 00 0000 _mut0 +00000000 g.*01 UND 00 0000 _zud0 +00000000 g.*01 UND 00 0000 _zud1 +00000000 g.*01 UND 00 0000 _zus0 +00000000 g.*01 UND 00 0000 _zus1 +00000000 g.*01 UND 00 0000 _zut0 +0000000a.*01 COM 00 0300 acommon0 +0000000a.*01 COM 00 0300 acommon1 +0000000a.*01 COM 00 0300 mcommon0 +0000000a.*01 COM 00 0300 mcommon1 +0000000a.*01 COM 00 0300 zcommon0 +0000000a.*01 COM 00 0300 zcommon1 \ No newline at end of file diff --git a/gas/testsuite/gas/mach-o/symbols-base-64.s b/gas/testsuite/gas/mach-o/symbols-base-64.s new file mode 100644 index 0000000..604501c --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-base-64.s @@ -0,0 +1,97 @@ +# baseline symbols in sections. +Lzt0: .space 1 + .globl ztg0 +ztg0: .space 1 +Lmt0: .space 1 + .globl mtg0 +mtg0: .space 1 +Lat0: .space 1 + .globl atg0 +atg0: .space 1 + + .quad _zut0 + .quad _mut0 + .quad _aut0 + + .comm zcommon0, 10, 3 + .comm mcommon0, 10, 3 + .comm acommon0, 10, 3 + + .data +Lzd0: .space 1 + .globl zdg0 +zdg0: .space 1 +Lmd0: .space 1 + .globl mdg0 +mdg0: .space 1 +adg0: .space 1 + .globl adg0 +Lad0: .space 1 + + .quad _zud0 + .quad _mud0 + .quad _aud0 + + .lcomm zlcomm0, 5, 1 + .lcomm mlcomm0, 5, 1 + .lcomm alcomm0, 5, 1 + + .section __HERE,__there +Lzs0: .space 1 + .globl zsg0 +zsg0: .space 1 +Lms0: .space 1 + .globl msg0 +msg0: .space 1 +Las0: .space 1 +asg0: .space 1 + .globl asg0 + + .quad _zus0 + .quad _mus0 + .quad _aus0 + + .text +Lzt1: .space 1 + .globl ztg1 +ztg1: .space 1 + .globl mtg1 +mtg1: .space 1 +Lmt1: .space 1 +atg1: .space 1 + .globl atg1 +Lat1: .space 1 + + .comm zcommon1, 10, 3 + .comm mcommon1, 10, 3 + .comm acommon1, 10, 3 + + .data +Lzd1: .space 1 + .globl zdg1, mdg1, adg1 +zdg1: .space 1 +Lmd1: .space 1 +mdg1: .space 1 +adg1: .space 1 +Lad1: .space 1 + + .quad _zud1 + .quad _mud1 + .quad _aud1 + + .lcomm zlcomm1, 5, 1 + .lcomm mlcomm1, 5, 1 + .lcomm alcomm1, 5, 1 + + .section __HERE,__there + .quad _zus1 +Lzs1: .space 1 +zsg1: .space 1 + .quad _mus1 +msg1: .space 1 +asg1: .space 1 + .globl zsg1, msg1, asg1 +Lms1: .space 1 +Las1: .space 1 + + .quad _aus1 diff --git a/gas/testsuite/gas/mach-o/symbols-base.s b/gas/testsuite/gas/mach-o/symbols-base.s new file mode 100644 index 0000000..a7b8e75 --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-base.s @@ -0,0 +1,97 @@ +# baseline symbols in sections. +Lzt0: .space 1 + .globl ztg0 +ztg0: .space 1 +Lmt0: .space 1 + .globl mtg0 +mtg0: .space 1 +Lat0: .space 1 + .globl atg0 +atg0: .space 1 + + .long _zut0 + .long _mut0 + .long _aut0 + + .comm zcommon0, 10, 3 + .comm mcommon0, 10, 3 + .comm acommon0, 10, 3 + + .data +Lzd0: .space 1 + .globl zdg0 +zdg0: .space 1 +Lmd0: .space 1 + .globl mdg0 +mdg0: .space 1 +adg0: .space 1 + .globl adg0 +Lad0: .space 1 + + .long _zud0 + .long _mud0 + .long _aud0 + + .lcomm zlcomm0, 5, 1 + .lcomm mlcomm0, 5, 1 + .lcomm alcomm0, 5, 1 + + .section __HERE,__there +Lzs0: .space 1 + .globl zsg0 +zsg0: .space 1 +Lms0: .space 1 + .globl msg0 +msg0: .space 1 +Las0: .space 1 +asg0: .space 1 + .globl asg0 + + .long _zus0 + .long _mus0 + .long _aus0 + + .text +Lzt1: .space 1 + .globl ztg1 +ztg1: .space 1 + .globl mtg1 +mtg1: .space 1 +Lmt1: .space 1 +atg1: .space 1 + .globl atg1 +Lat1: .space 1 + + .comm zcommon1, 10, 3 + .comm mcommon1, 10, 3 + .comm acommon1, 10, 3 + + .data +Lzd1: .space 1 + .globl zdg1, mdg1, adg1 +zdg1: .space 1 +Lmd1: .space 1 +mdg1: .space 1 +adg1: .space 1 +Lad1: .space 1 + + .long _zud1 + .long _mud1 + .long _aud1 + + .lcomm zlcomm1, 5, 1 + .lcomm mlcomm1, 5, 1 + .lcomm alcomm1, 5, 1 + + .section __HERE,__there + .long _zus1 +Lzs1: .space 1 +zsg1: .space 1 + .long _mus1 +msg1: .space 1 +asg1: .space 1 + .globl zsg1, msg1, asg1 +Lms1: .space 1 +Las1: .space 1 + + .long _aus1 -- 2.7.4