From: Ken Raeburn Date: Tue, 7 Feb 1995 01:06:25 +0000 (+0000) Subject: ecoff gprof related fixes & improvements from David Mosberger-Tang X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=97d5a149495f725047a0e1ee7cbb1e419e30a13e;p=binutils-gdb.git ecoff gprof related fixes & improvements from David Mosberger-Tang --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index be78ac049ce..6434308b4c5 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +Mon Feb 6 20:01:24 1995 Ken Raeburn + + Sat Feb 4 14:20:24 1995 David Mosberger-Tang + + * ecoffswap.h (ecoff_swap_pdr_in, ecoff_swap_pdr_out): added + internalizing/externalizing new "prof" field. + + * libecoff.h (ecoff_tdata): added fdrtab. + + * ecoff.c (_bfd_ecoff_find_nearest_line): Fixed. + Mon Feb 6 14:25:24 1995 Ian Lance Taylor * libelf.h (struct elf_link_hash_table): Add saw_needed field. diff --git a/bfd/ecoff.c b/bfd/ecoff.c index d6fbea93581..4d80edc5d9b 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -2002,6 +2002,172 @@ _bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols) return section->reloc_count; } + +static int +cmp_fdrtab_entry (const void *leftp, const void *rightp) +{ + const struct ecoff_fdrtab_entry *lp = leftp; + const struct ecoff_fdrtab_entry *rp = rightp; + + if (lp->base_addr < rp->base_addr) + return -1; + if (lp->base_addr > rp->base_addr) + return 1; + return 0; +} + +/* + * Each file descriptor (FDR) has a memory address, to simplify + * looking up an FDR by address, we build a table covering all FDRs + * that have a least one procedure descriptor in them. The final + * table will be sorted by address so we can look it up via binary + * search. + */ +static boolean +mk_fdrtab (bfd *abfd) +{ + struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info; + const struct ecoff_debug_swap * const debug_swap + = &ecoff_backend (abfd)->debug_swap; + struct ecoff_fdrtab_entry *tab; + FDR *fdr_ptr; + FDR *fdr_start; + FDR *fdr_end; + boolean stabs; + long len; + + /* Make sure we have the FDR's. */ + if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info) + || bfd_get_symcount (abfd) == 0) + return false; + + fdr_start = debug_info->fdr; + fdr_end = fdr_start + debug_info->symbolic_header.ifdMax; + + /* First, let's see how long the table needs to be: */ + for (len = 0, fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) + { + if (fdr_ptr->cpd == 0) /* skip FDRs that have no PDRs */ + continue; + ++len; + } + + /* Now, create and fill in the table: */ + + ecoff_data (abfd)->fdrtab = (struct ecoff_fdrtab_entry*) + bfd_zalloc (abfd,len * sizeof (struct ecoff_fdrtab_entry)); + if (ecoff_data (abfd)->fdrtab == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + ecoff_data (abfd)->fdrtab_len = len; + + tab = ecoff_data (abfd)->fdrtab; + for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) + { + if (fdr_ptr->cpd == 0) + continue; + + /* + * Check whether this file has stabs debugging information. In + * a file with stabs debugging information, the second local + * symbol is named @stabs. + */ + stabs = false; + if (fdr_ptr->csym >= 2) + { + char *sym_ptr; + SYMR sym; + + sym_ptr = ((char *) debug_info->external_sym + + (fdr_ptr->isymBase + 1)*debug_swap->external_sym_size); + (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); + if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss, + STABS_SYMBOL) == 0) + stabs = true; + } + + if (!stabs) + { + bfd_size_type external_pdr_size; + char *pdr_ptr; + PDR pdr; + + external_pdr_size = debug_swap->external_pdr_size; + + pdr_ptr = ((char *) debug_info->external_pdr + + fdr_ptr->ipdFirst * external_pdr_size); + (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + /* + * The address of the first PDR is the offset of that + * procedure relative to the beginning of file FDR. + */ + tab->base_addr = fdr_ptr->adr - pdr.adr; + } + else + { + /* + * XXX I don't know about stabs, so this is a guess + * (davidm@cs.arizona.edu): + */ + tab->base_addr = fdr_ptr->adr; + } + tab->fdr = fdr_ptr; + ++tab; + } + /* + * Finally, the table is sorted in increasing memory-address order. + * The table is mostly sorted already, but there are cases (e.g., + * static functions in include files), where this does not hold + * Use "odump -PFv" to verify... + */ + qsort((char*) ecoff_data (abfd)->fdrtab, len, + sizeof(struct ecoff_fdrtab_entry), cmp_fdrtab_entry); + + return true; +} + +/* + * Return index of first FDR that covers to OFFSET. + */ +static long +lookup (bfd *abfd, bfd_vma offset) +{ + long low, high, len; + long mid = -1; + struct ecoff_fdrtab_entry *tab; + + len = ecoff_data(abfd)->fdrtab_len; + if (!len) + return -1; + + tab = ecoff_data(abfd)->fdrtab; + for (low = 0, high = len - 1 ; low != high ;) + { + mid = (high + low) / 2; + if (offset >= tab[mid].base_addr && offset < tab[mid + 1].base_addr) + goto find_min; + + if (tab[mid].base_addr > offset) + high = mid; + else + low = mid + 1; + } + ++mid; + + /* last entry is catch-all for all higher addresses: */ + if (offset < tab[mid].base_addr) + return -1; + + find_min: + + while (mid > 0 && tab[mid - 1].base_addr == tab[mid].base_addr) + --mid; + + return mid; +} + /* Provided a BFD, a section and an offset into the section, calculate and return the name of the source file and the line nearest to the wanted location. */ @@ -2021,49 +2187,39 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset, const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (abfd)->debug_swap; struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info; - FDR *fdr_ptr; - FDR *fdr_start; - FDR *fdr_end; - FDR *fdr_hold; + struct ecoff_fdrtab_entry *tab; boolean stabs; + FDR *fdr_ptr; + int i; offset += section->vma; - - /* If we're not in the .text section, we don't have any line - numbers. */ + /* + * If we're not in the .text section, we don't have any line + * numbers. + */ if (strcmp (section->name, _TEXT) != 0 || offset < ecoff_data (abfd)->text_start || offset >= ecoff_data (abfd)->text_end) return false; + /* + * Build FDR table (sorted by object file's base-address) if + * we don't have it already: + */ + if (!ecoff_data (abfd)->fdrtab && !mk_fdrtab (abfd)) { + return false; + } + tab = ecoff_data (abfd)->fdrtab; - /* Make sure we have the FDR's. */ - if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info) - || bfd_get_symcount (abfd) == 0) - return false; + i = lookup(abfd, offset); /* find first FDR for address OFFSET */ + if (i < 0) + return false; /* no FDR, no fun... */ + fdr_ptr = tab[i].fdr; - /* Each file descriptor (FDR) has a memory address. Here we track - down which FDR we want. The FDR's are stored in increasing - memory order. If speed is ever important, this can become a - binary search. We must ignore FDR's with no PDR entries; they - will have the adr of the FDR before or after them. */ - fdr_start = debug_info->fdr; - fdr_end = fdr_start + debug_info->symbolic_header.ifdMax; - fdr_hold = (FDR *) NULL; - for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) - { - if (fdr_ptr->cpd == 0) - continue; - if (offset < fdr_ptr->adr) - break; - fdr_hold = fdr_ptr; - } - if (fdr_hold == (FDR *) NULL) - return false; - fdr_ptr = fdr_hold; - - /* Check whether this file has stabs debugging information. In a - file with stabs debugging information, the second local symbol is - named @stabs. */ + /* + * Check whether this file has stabs debugging information. In a + * file with stabs debugging information, the second local symbol is + * named @stabs. + */ stabs = false; if (fdr_ptr->csym >= 2) { @@ -2078,58 +2234,143 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset, stabs = true; } - if (! stabs) + if (!stabs) { bfd_size_type external_pdr_size; char *pdr_ptr; - char *pdr_end; + char *best_pdr = NULL; + FDR *best_fdr; + bfd_vma best_dist = ~0; PDR pdr; - bfd_vma first_off; unsigned char *line_ptr; unsigned char *line_end; int lineno; - - /* This file uses ECOFF debugging information. Each FDR has a - list of procedure descriptors (PDR). PDR's also have an - address, which is relative to the FDR address, and are also - stored in increasing memory order. */ - if (offset < fdr_ptr->adr) - return false; - offset -= fdr_ptr->adr; + /* + * This file uses ECOFF debugging information. Each FDR has a + * list of procedure descriptors (PDR). The address in the FDR + * is the absolute address of the first procedure. The address + * in the first PDR gives the offset of that procedure relative + * to the object file's base-address. The addresses in + * subsequent PDRs specify each procedure's address relative to + * the object file's base-address. To make things more juicy, + * whenever the PROF bit in the PDR is set, the real entry point + * of the procedure may be 16 bytes below what would normally be + * the procedure's entry point. Instead, DEC came up with a + * wicked scheme to create profiled libraries "on the fly": + * instead of shipping a regular and a profiled version of each + * library, they insert 16 bytes of unused space in front of + * each procedure and set the "prof" bit in the PDR to indicate + * that there is a gap there (this is done automagically by "as" + * when option "-pg" is specified). Thus, normally, you link + * against such a library and, except for lots of 16 byte gaps + * between functions, things will behave as usual. However, + * when invoking "ld" with option "-pg", it will fill those gaps + * with code that calls mcount(). It then moves the function's + * entry point down by 16 bytes, and out pops a binary that has + * all functions profiled. + * + * NOTE: Neither FDRs nor PDRs are strictly sorted in memory order. + * For example, when including header-files that define + * functions, the FDRs follow behind the including file, + * even though their code may have been generated at a lower + * address. File coff-alpha.c from libbfd illustrates this + * (use "odump -PFv" to look at a file's FDR/PDR). Similarly, + * PDRs are sometimes out of order as well. An example of this + * is OSF/1 v3.0 libc's malloc.c. I'm not sure why this happens, + * but it could be due to optimizations that reorder a function's + * position within an object-file. + * + * Strategy: + * + * On the first call to this function, we build a table of FDRs + * that is sorted by the base-address of the object-file the FDR + * is referring to. Notice that each object-file may contain + * code from multiple source files (e.g., due to code defined in + * include files). Thus, for any given base-address, there may + * be multiple FDRs (but this case is, fortunately, uncommon). + * lookup(addr) guarantees to return the first FDR that applies + * to address ADDR. Thus, after invoking lookup(), we have a + * list of FDRs that may contain the PDR for ADDR. Next, we walk + * through the PDRs of these FDRs and locate the one that is + * closest to ADDR (i.e., for which the difference between ADDR + * and the PDR's entry point is positive and minimal). Once, + * the right FDR and PDR are located, we simply walk through the + * line-number table to lookup the line-number that best matches + * ADDR. Obviously, things could be sped up by keeping a sorted + * list of PDRs instead of a sorted list of FDRs. However, this + * would increase space requirements considerably, which is + * undesirable. + */ external_pdr_size = debug_swap->external_pdr_size; - pdr_ptr = ((char *) debug_info->external_pdr - + fdr_ptr->ipdFirst * external_pdr_size); - pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size; - (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); - /* The address of the first PDR is an offset which applies to - the addresses of all the PDR's. */ - first_off = pdr.adr; + /* Make offset relative to object file's start-address: */ + offset -= tab[i].base_addr; + /* + * Search FDR list starting at tab[i] for the PDR that best matches + * OFFSET. Normally, the FDR list is only one entry long. + */ + best_fdr = NULL; + do { + bfd_vma dist, min_dist = 0; + char *pdr_hold; + char *pdr_end; + + fdr_ptr = tab[i].fdr; + + pdr_ptr = ((char *) debug_info->external_pdr + + fdr_ptr->ipdFirst * external_pdr_size); + pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size; + (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + /* + * Find PDR that is closest to OFFSET. If pdr.prof is set, + * the procedure entry-point *may* be 0x10 below pdr.adr. + * We simply pretend that pdr.prof *implies* a lower entry-point. + * This is safe because it just means that may identify + * 4 NOPs in front of the function as belonging to the function. + */ + for (pdr_hold = NULL; + pdr_ptr < pdr_end; + (pdr_ptr += external_pdr_size, + (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr))) + { + if (offset >= (pdr.adr - 0x10 * pdr.prof)) + { + dist = offset - (pdr.adr - 0x10 * pdr.prof); + if (!pdr_hold || dist < min_dist) + { + min_dist = dist; + pdr_hold = pdr_ptr; + } + } + } - for (pdr_ptr += external_pdr_size; - pdr_ptr < pdr_end; - pdr_ptr += external_pdr_size) - { - (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); - if (offset < pdr.adr - first_off) - break; - } + if (!best_pdr || min_dist < best_dist) + { + best_dist = min_dist; + best_fdr = fdr_ptr; + best_pdr = pdr_hold; + } + /* continue looping until base_addr of next entry is different: */ + } while (++i < ecoff_data (abfd)->fdrtab_len + && tab[i].base_addr == tab[i - 1].base_addr); - /* Now we can look for the actual line number. The line numbers - are stored in a very funky format, which I won't try to - describe. Note that right here pdr_ptr and pdr hold the PDR - *after* the one we want; we need this to compute line_end. */ - line_end = debug_info->line; - if (pdr_ptr == pdr_end) - line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine; - else - line_end += fdr_ptr->cbLineOffset + pdr.cbLineOffset; + if (!best_fdr || !best_pdr) + return false; /* shouldn't happen... */ - /* Now change pdr and pdr_ptr to the one we want. */ - pdr_ptr -= external_pdr_size; + /* phew, finally we got something that we can hold onto: */ + fdr_ptr = best_fdr; + pdr_ptr = best_pdr; (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + /* + * Now we can look for the actual line number. The line numbers + * are stored in a very funky format, which I won't try to + * describe. The search is bounded by the end of the FDRs line + * number entries. + */ + line_end = debug_info->line + fdr_ptr->cbLineOffset + fdr_ptr->cbLine; - offset -= pdr.adr - first_off; + /* Make offset relative to procedure entry: */ + offset -= pdr.adr - 0x10 * pdr.prof; lineno = pdr.lnLow; line_ptr = debug_info->line + fdr_ptr->cbLineOffset + pdr.cbLineOffset; while (line_ptr < line_end) @@ -2155,8 +2396,10 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset, offset -= count * 4; } - /* If fdr_ptr->rss is -1, then this file does not have full - symbols, at least according to gdb/mipsread.c. */ + /* + * If fdr_ptr->rss is -1, then this file does not have full + * symbols, at least according to gdb/mipsread.c. + */ if (fdr_ptr->rss == -1) { *filename_ptr = NULL; @@ -2346,6 +2589,7 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset, return true; } + /* Copy private BFD data. This is called by objcopy and strip. We use it to copy the ECOFF debugging information from one BFD to the diff --git a/bfd/ecoffswap.h b/bfd/ecoffswap.h index 087e0528b9c..4500f0fd742 100644 --- a/bfd/ecoffswap.h +++ b/bfd/ecoffswap.h @@ -53,12 +53,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ECOFF auxiliary information swapping routines. These are the same for all ECOFF targets, so they are defined in ecoff.c. */ -extern void ecoff_swap_tir_in PARAMS ((int, const struct tir_ext *, TIR *)); -extern void ecoff_swap_tir_out PARAMS ((int, const TIR *, struct tir_ext *)); -extern void ecoff_swap_rndx_in PARAMS ((int, const struct rndx_ext *, - RNDXR *)); -extern void ecoff_swap_rndx_out PARAMS ((int, const RNDXR *, - struct rndx_ext *)); +extern void _bfd_ecoff_swap_tir_in + PARAMS ((int, const struct tir_ext *, TIR *)); +extern void _bfd_ecoff_swap_tir_out + PARAMS ((int, const TIR *, struct tir_ext *)); +extern void _bfd_ecoff_swap_rndx_in + PARAMS ((int, const struct rndx_ext *, RNDXR *)); +extern void _bfd_ecoff_swap_rndx_out + PARAMS ((int, const RNDXR *, struct rndx_ext *)); /* Swap in the symbolic header. */ @@ -281,6 +283,9 @@ ecoff_swap_fdr_out (abfd, intern_copy, ext_ptr) #endif } +/* start-sanitize-mpw */ +#ifndef MPW_C +/* end-sanitize-mpw */ /* Swap in the procedure descriptor record. */ static void @@ -317,6 +322,7 @@ ecoff_swap_pdr_in (abfd, ext_copy, intern) { intern->gp_used = 0 != (ext->p_bits1[0] & PDR_BITS1_GP_USED_BIG); intern->reg_frame = 0 != (ext->p_bits1[0] & PDR_BITS1_REG_FRAME_BIG); + intern->prof = 0 != (ext->p_bits1[0] & PDR_BITS1_PROF_BIG); intern->reserved = (((ext->p_bits1[0] & PDR_BITS1_RESERVED_BIG) << PDR_BITS1_RESERVED_SH_LEFT_BIG) | ((ext->p_bits2[0] & PDR_BITS2_RESERVED_BIG) @@ -326,6 +332,7 @@ ecoff_swap_pdr_in (abfd, ext_copy, intern) { intern->gp_used = 0 != (ext->p_bits1[0] & PDR_BITS1_GP_USED_LITTLE); intern->reg_frame = 0 != (ext->p_bits1[0] & PDR_BITS1_REG_FRAME_LITTLE); + intern->prof = 0 != (ext->p_bits1[0] & PDR_BITS1_PROF_LITTLE); intern->reserved = (((ext->p_bits1[0] & PDR_BITS1_RESERVED_LITTLE) >> PDR_BITS1_RESERVED_SH_LITTLE) | ((ext->p_bits2[0] & PDR_BITS2_RESERVED_LITTLE) @@ -374,6 +381,7 @@ ecoff_swap_pdr_out (abfd, intern_copy, ext_ptr) { ext->p_bits1[0] = ((intern->gp_used ? PDR_BITS1_GP_USED_BIG : 0) | (intern->reg_frame ? PDR_BITS1_REG_FRAME_BIG : 0) + | (intern->prof ? PDR_BITS1_PROF_BIG : 0) | ((intern->reserved >> PDR_BITS1_RESERVED_SH_LEFT_BIG) & PDR_BITS1_RESERVED_BIG)); @@ -384,6 +392,7 @@ ecoff_swap_pdr_out (abfd, intern_copy, ext_ptr) { ext->p_bits1[0] = ((intern->gp_used ? PDR_BITS1_GP_USED_LITTLE : 0) | (intern->reg_frame ? PDR_BITS1_REG_FRAME_LITTLE : 0) + | (intern->prof ? PDR_BITS1_PROF_LITTLE : 0) | ((intern->reserved << PDR_BITS1_RESERVED_SH_LITTLE) & PDR_BITS1_RESERVED_LITTLE)); ext->p_bits2[0] = ((intern->reserved >> @@ -398,6 +407,81 @@ ecoff_swap_pdr_out (abfd, intern_copy, ext_ptr) abort(); #endif } +/* start-sanitize-mpw */ +#else /* MPW_C */ +/* Same routines, but with ECOFF_64 code removed, so ^&%$#&! MPW C doesn't + corrupt itself and then freak out. */ +/* Swap in the procedure descriptor record. */ + +static void +ecoff_swap_pdr_in (abfd, ext_copy, intern) + bfd *abfd; + PTR ext_copy; + PDR *intern; +{ + struct pdr_ext ext[1]; + + *ext = *(struct pdr_ext *) ext_copy; + + intern->adr = ecoff_get_off (abfd, (bfd_byte *)ext->p_adr); + intern->isym = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_isym); + intern->iline = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_iline); + intern->regmask = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_regmask); + intern->regoffset = bfd_h_get_signed_32 (abfd, + (bfd_byte *)ext->p_regoffset); + intern->iopt = bfd_h_get_signed_32 (abfd, (bfd_byte *)ext->p_iopt); + intern->fregmask = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_fregmask); + intern->fregoffset = bfd_h_get_signed_32 (abfd, + (bfd_byte *)ext->p_fregoffset); + intern->frameoffset = bfd_h_get_signed_32 (abfd, + (bfd_byte *)ext->p_frameoffset); + intern->framereg = bfd_h_get_16 (abfd, (bfd_byte *)ext->p_framereg); + intern->pcreg = bfd_h_get_16 (abfd, (bfd_byte *)ext->p_pcreg); + intern->lnLow = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_lnLow); + intern->lnHigh = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_lnHigh); + intern->cbLineOffset = ecoff_get_off (abfd, (bfd_byte *)ext->p_cbLineOffset); + +#ifdef TEST + if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) + abort(); +#endif +} + +/* Swap out the procedure descriptor record. */ + +static void +ecoff_swap_pdr_out (abfd, intern_copy, ext_ptr) + bfd *abfd; + const PDR *intern_copy; + PTR ext_ptr; +{ + struct pdr_ext *ext = (struct pdr_ext *) ext_ptr; + PDR intern[1]; + + *intern = *intern_copy; /* Make it reasonable to do in-place. */ + + ecoff_put_off (abfd, intern->adr, (bfd_byte *)ext->p_adr); + bfd_h_put_32 (abfd, intern->isym, (bfd_byte *)ext->p_isym); + bfd_h_put_32 (abfd, intern->iline, (bfd_byte *)ext->p_iline); + bfd_h_put_32 (abfd, intern->regmask, (bfd_byte *)ext->p_regmask); + bfd_h_put_32 (abfd, intern->regoffset, (bfd_byte *)ext->p_regoffset); + bfd_h_put_32 (abfd, intern->iopt, (bfd_byte *)ext->p_iopt); + bfd_h_put_32 (abfd, intern->fregmask, (bfd_byte *)ext->p_fregmask); + bfd_h_put_32 (abfd, intern->fregoffset, (bfd_byte *)ext->p_fregoffset); + bfd_h_put_32 (abfd, intern->frameoffset, (bfd_byte *)ext->p_frameoffset); + bfd_h_put_16 (abfd, intern->framereg, (bfd_byte *)ext->p_framereg); + bfd_h_put_16 (abfd, intern->pcreg, (bfd_byte *)ext->p_pcreg); + bfd_h_put_32 (abfd, intern->lnLow, (bfd_byte *)ext->p_lnLow); + bfd_h_put_32 (abfd, intern->lnHigh, (bfd_byte *)ext->p_lnHigh); + ecoff_put_off (abfd, intern->cbLineOffset, (bfd_byte *)ext->p_cbLineOffset); + +#ifdef TEST + if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) + abort(); +#endif +} +#endif /* MPW_C */ +/* end-sanitize-mpw */ /* Swap in a symbol record. */ @@ -555,11 +639,19 @@ ecoff_swap_ext_out (abfd, intern_copy, ext_ptr) | (intern->cobol_main ? EXT_BITS1_COBOL_MAIN_BIG : 0) | (intern->weakext ? EXT_BITS1_WEAKEXT_BIG : 0)); ext->es_bits2[0] = 0; +#ifdef ECOFF_64 + ext->es_bits2[1] = 0; + ext->es_bits2[2] = 0; +#endif } else { ext->es_bits1[0] = ((intern->jmptbl ? EXT_BITS1_JMPTBL_LITTLE : 0) | (intern->cobol_main ? EXT_BITS1_COBOL_MAIN_LITTLE : 0) | (intern->weakext ? EXT_BITS1_WEAKEXT_LITTLE : 0)); ext->es_bits2[0] = 0; +#ifdef ECOFF_64 + ext->es_bits2[1] = 0; + ext->es_bits2[2] = 0; +#endif } #ifdef ECOFF_32 @@ -643,8 +735,8 @@ ecoff_swap_opt_in (abfd, ext_copy, intern) | (ext->o_bits4[0] << OPT_BITS2_VALUE_SH_LEFT_LITTLE)); } - ecoff_swap_rndx_in (abfd->xvec->header_byteorder_big_p != false, - &ext->o_rndx, &intern->rndx); + _bfd_ecoff_swap_rndx_in (abfd->xvec->header_byteorder_big_p != false, + &ext->o_rndx, &intern->rndx); intern->offset = bfd_h_get_32 (abfd, (bfd_byte *) ext->o_offset); @@ -682,8 +774,8 @@ ecoff_swap_opt_out (abfd, intern_copy, ext_ptr) ext->o_bits4[0] = intern->value >> OPT_BITS4_VALUE_SH_LEFT_LITTLE; } - ecoff_swap_rndx_out (abfd->xvec->header_byteorder_big_p != false, - &intern->rndx, &ext->o_rndx); + _bfd_ecoff_swap_rndx_out (abfd->xvec->header_byteorder_big_p != false, + &intern->rndx, &ext->o_rndx); bfd_h_put_32 (abfd, intern->value, (bfd_byte *) ext->o_offset);