ecoff gprof related fixes & improvements from David Mosberger-Tang
This commit is contained in:
parent
23244cd6e0
commit
97d5a14949
@ -1,3 +1,14 @@
|
||||
Mon Feb 6 20:01:24 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
|
||||
|
||||
Sat Feb 4 14:20:24 1995 David Mosberger-Tang <davidm@piston.cs.arizona.edu>
|
||||
|
||||
* 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 <ian@cygnus.com>
|
||||
|
||||
* libelf.h (struct elf_link_hash_table): Add saw_needed field.
|
||||
|
400
bfd/ecoff.c
400
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!best_fdr || !best_pdr)
|
||||
return false; /* shouldn't happen... */
|
||||
|
||||
/* 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;
|
||||
|
||||
/* The address of the first PDR is an offset which applies to
|
||||
the addresses of all the PDR's. */
|
||||
first_off = pdr.adr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Now change pdr and pdr_ptr to the one we want. */
|
||||
pdr_ptr -= external_pdr_size;
|
||||
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
|
||||
|
||||
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
|
||||
|
112
bfd/ecoffswap.h
112
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user