1 |
/* Routines to link ECOFF debugging information. |
/* Routines to link ECOFF debugging information. |
2 |
Copyright 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002 |
Copyright 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, |
3 |
Free Software Foundation, Inc. |
2004, 2005 Free Software Foundation, Inc. |
4 |
Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>. |
Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>. |
5 |
|
|
6 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
7 |
|
|
8 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
9 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
10 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
11 |
(at your option) any later version. |
(at your option) any later version. |
12 |
|
|
13 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
14 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
GNU General Public License for more details. |
GNU General Public License for more details. |
17 |
|
|
18 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
19 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
20 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
21 |
|
|
22 |
#include "bfd.h" |
#include "bfd.h" |
23 |
#include "sysdep.h" |
#include "sysdep.h" |
32 |
#include "libcoff.h" |
#include "libcoff.h" |
33 |
#include "libecoff.h" |
#include "libecoff.h" |
34 |
|
|
35 |
static boolean ecoff_add_bytes PARAMS ((char **buf, char **bufend, |
static bfd_boolean ecoff_add_bytes |
36 |
size_t need)); |
PARAMS ((char **buf, char **bufend, size_t need)); |
37 |
static struct bfd_hash_entry *string_hash_newfunc |
static struct bfd_hash_entry *string_hash_newfunc |
38 |
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, |
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, |
39 |
const char *)); |
const char *)); |
40 |
static void ecoff_align_debug PARAMS ((bfd *abfd, |
static void ecoff_align_debug |
41 |
struct ecoff_debug_info *debug, |
PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, |
42 |
const struct ecoff_debug_swap *swap)); |
const struct ecoff_debug_swap *swap)); |
43 |
static boolean ecoff_write_symhdr PARAMS ((bfd *, struct ecoff_debug_info *, |
static bfd_boolean ecoff_write_symhdr |
44 |
const struct ecoff_debug_swap *, |
PARAMS ((bfd *, struct ecoff_debug_info *, const struct ecoff_debug_swap *, |
45 |
file_ptr where)); |
file_ptr where)); |
46 |
static int cmp_fdrtab_entry PARAMS ((const PTR, const PTR)); |
static int cmp_fdrtab_entry |
47 |
static boolean mk_fdrtab PARAMS ((bfd *, |
PARAMS ((const PTR, const PTR)); |
48 |
struct ecoff_debug_info * const, |
static bfd_boolean mk_fdrtab |
49 |
const struct ecoff_debug_swap * const, |
PARAMS ((bfd *, struct ecoff_debug_info * const, |
50 |
struct ecoff_find_line *)); |
const struct ecoff_debug_swap * const, struct ecoff_find_line *)); |
51 |
static long fdrtab_lookup PARAMS ((struct ecoff_find_line *, bfd_vma)); |
static long fdrtab_lookup |
52 |
static boolean lookup_line |
PARAMS ((struct ecoff_find_line *, bfd_vma)); |
53 |
|
static bfd_boolean lookup_line |
54 |
PARAMS ((bfd *, struct ecoff_debug_info * const, |
PARAMS ((bfd *, struct ecoff_debug_info * const, |
55 |
const struct ecoff_debug_swap * const, struct ecoff_find_line *)); |
const struct ecoff_debug_swap * const, struct ecoff_find_line *)); |
56 |
|
|
254 |
|
|
255 |
/* Add bytes to a buffer. Return success. */ |
/* Add bytes to a buffer. Return success. */ |
256 |
|
|
257 |
static boolean |
static bfd_boolean |
258 |
ecoff_add_bytes (buf, bufend, need) |
ecoff_add_bytes (buf, bufend, need) |
259 |
char **buf; |
char **buf; |
260 |
char **bufend; |
char **bufend; |
275 |
} |
} |
276 |
newbuf = (char *) bfd_realloc (*buf, (bfd_size_type) have + want); |
newbuf = (char *) bfd_realloc (*buf, (bfd_size_type) have + want); |
277 |
if (newbuf == NULL) |
if (newbuf == NULL) |
278 |
return false; |
return FALSE; |
279 |
*buf = newbuf; |
*buf = newbuf; |
280 |
*bufend = *buf + have + want; |
*bufend = *buf + have + want; |
281 |
return true; |
return TRUE; |
282 |
} |
} |
283 |
|
|
284 |
/* We keep a hash table which maps strings to numbers. We use it to |
/* We keep a hash table which maps strings to numbers. We use it to |
348 |
/* The length of the information. */ |
/* The length of the information. */ |
349 |
unsigned long size; |
unsigned long size; |
350 |
/* Whether this information comes from a file or not. */ |
/* Whether this information comes from a file or not. */ |
351 |
boolean filep; |
bfd_boolean filep; |
352 |
union |
union |
353 |
{ |
{ |
354 |
struct |
struct |
401 |
|
|
402 |
/* Add a file entry to a shuffle list. */ |
/* Add a file entry to a shuffle list. */ |
403 |
|
|
404 |
static boolean add_file_shuffle PARAMS ((struct accumulate *, |
static bfd_boolean add_file_shuffle |
405 |
struct shuffle **, |
PARAMS ((struct accumulate *, struct shuffle **, struct shuffle **, |
406 |
struct shuffle **, bfd *, file_ptr, |
bfd *, file_ptr, unsigned long)); |
|
unsigned long)); |
|
407 |
|
|
408 |
static boolean |
static bfd_boolean |
409 |
add_file_shuffle (ainfo, head, tail, input_bfd, offset, size) |
add_file_shuffle (ainfo, head, tail, input_bfd, offset, size) |
410 |
struct accumulate *ainfo; |
struct accumulate *ainfo; |
411 |
struct shuffle **head; |
struct shuffle **head; |
425 |
(*tail)->size += size; |
(*tail)->size += size; |
426 |
if ((*tail)->size > ainfo->largest_file_shuffle) |
if ((*tail)->size > ainfo->largest_file_shuffle) |
427 |
ainfo->largest_file_shuffle = (*tail)->size; |
ainfo->largest_file_shuffle = (*tail)->size; |
428 |
return true; |
return TRUE; |
429 |
} |
} |
430 |
|
|
431 |
n = (struct shuffle *) objalloc_alloc (ainfo->memory, |
n = (struct shuffle *) objalloc_alloc (ainfo->memory, |
433 |
if (!n) |
if (!n) |
434 |
{ |
{ |
435 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
436 |
return false; |
return FALSE; |
437 |
} |
} |
438 |
n->next = NULL; |
n->next = NULL; |
439 |
n->size = size; |
n->size = size; |
440 |
n->filep = true; |
n->filep = TRUE; |
441 |
n->u.file.input_bfd = input_bfd; |
n->u.file.input_bfd = input_bfd; |
442 |
n->u.file.offset = offset; |
n->u.file.offset = offset; |
443 |
if (*head == (struct shuffle *) NULL) |
if (*head == (struct shuffle *) NULL) |
447 |
*tail = n; |
*tail = n; |
448 |
if (size > ainfo->largest_file_shuffle) |
if (size > ainfo->largest_file_shuffle) |
449 |
ainfo->largest_file_shuffle = size; |
ainfo->largest_file_shuffle = size; |
450 |
return true; |
return TRUE; |
451 |
} |
} |
452 |
|
|
453 |
/* Add a memory entry to a shuffle list. */ |
/* Add a memory entry to a shuffle list. */ |
454 |
|
|
455 |
static boolean add_memory_shuffle PARAMS ((struct accumulate *, |
static bfd_boolean add_memory_shuffle |
456 |
struct shuffle **head, |
PARAMS ((struct accumulate *, struct shuffle **head, struct shuffle **tail, |
457 |
struct shuffle **tail, |
bfd_byte *data, unsigned long size)); |
|
bfd_byte *data, unsigned long size)); |
|
458 |
|
|
459 |
static boolean |
static bfd_boolean |
460 |
add_memory_shuffle (ainfo, head, tail, data, size) |
add_memory_shuffle (ainfo, head, tail, data, size) |
461 |
struct accumulate *ainfo; |
struct accumulate *ainfo; |
462 |
struct shuffle **head; |
struct shuffle **head; |
471 |
if (!n) |
if (!n) |
472 |
{ |
{ |
473 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
474 |
return false; |
return FALSE; |
475 |
} |
} |
476 |
n->next = NULL; |
n->next = NULL; |
477 |
n->size = size; |
n->size = size; |
478 |
n->filep = false; |
n->filep = FALSE; |
479 |
n->u.memory = (PTR) data; |
n->u.memory = (PTR) data; |
480 |
if (*head == (struct shuffle *) NULL) |
if (*head == (struct shuffle *) NULL) |
481 |
*head = n; |
*head = n; |
482 |
if (*tail != (struct shuffle *) NULL) |
if (*tail != (struct shuffle *) NULL) |
483 |
(*tail)->next = n; |
(*tail)->next = n; |
484 |
*tail = n; |
*tail = n; |
485 |
return true; |
return TRUE; |
486 |
} |
} |
487 |
|
|
488 |
/* Initialize the FDR hash table. This returns a handle which is then |
/* Initialize the FDR hash table. This returns a handle which is then |
526 |
|
|
527 |
ainfo->largest_file_shuffle = 0; |
ainfo->largest_file_shuffle = 0; |
528 |
|
|
529 |
if (! info->relocateable) |
if (! info->relocatable) |
530 |
{ |
{ |
531 |
if (! bfd_hash_table_init (&ainfo->str_hash.table, string_hash_newfunc)) |
if (! bfd_hash_table_init (&ainfo->str_hash.table, string_hash_newfunc)) |
532 |
return NULL; |
return NULL; |
559 |
|
|
560 |
bfd_hash_table_free (&ainfo->fdr_hash.table); |
bfd_hash_table_free (&ainfo->fdr_hash.table); |
561 |
|
|
562 |
if (! info->relocateable) |
if (! info->relocatable) |
563 |
bfd_hash_table_free (&ainfo->str_hash.table); |
bfd_hash_table_free (&ainfo->str_hash.table); |
564 |
|
|
565 |
objalloc_free (ainfo->memory); |
objalloc_free (ainfo->memory); |
575 |
linker information structure. HANDLE is returned by |
linker information structure. HANDLE is returned by |
576 |
bfd_ecoff_debug_init. */ |
bfd_ecoff_debug_init. */ |
577 |
|
|
578 |
boolean |
bfd_boolean |
579 |
bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap, |
bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap, |
580 |
input_bfd, input_debug, input_swap, |
input_bfd, input_debug, input_swap, |
581 |
info) |
info) |
671 |
if (!input_debug->ifdmap || !rfd_out) |
if (!input_debug->ifdmap || !rfd_out) |
672 |
{ |
{ |
673 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
674 |
return false; |
return FALSE; |
675 |
} |
} |
676 |
if (!add_memory_shuffle (ainfo, &ainfo->rfd, &ainfo->rfd_end, rfd_out, sz)) |
if (!add_memory_shuffle (ainfo, &ainfo->rfd, &ainfo->rfd_end, rfd_out, sz)) |
677 |
return false; |
return FALSE; |
678 |
|
|
679 |
copied = 0; |
copied = 0; |
680 |
|
|
715 |
|
|
716 |
lookup = (char *) bfd_malloc ((bfd_size_type) strlen (name) + 20); |
lookup = (char *) bfd_malloc ((bfd_size_type) strlen (name) + 20); |
717 |
if (lookup == NULL) |
if (lookup == NULL) |
718 |
return false; |
return FALSE; |
719 |
sprintf (lookup, "%s %lx %lx", name, fdr.csym, fdr.caux); |
sprintf (lookup, "%s %lx %lx", name, fdr.csym, fdr.caux); |
720 |
|
|
721 |
fh = string_hash_lookup (&ainfo->fdr_hash, lookup, true, true); |
fh = string_hash_lookup (&ainfo->fdr_hash, lookup, TRUE, TRUE); |
722 |
free (lookup); |
free (lookup); |
723 |
if (fh == (struct string_hash_entry *) NULL) |
if (fh == (struct string_hash_entry *) NULL) |
724 |
return false; |
return FALSE; |
725 |
|
|
726 |
if (fh->val != -1) |
if (fh->val != -1) |
727 |
{ |
{ |
772 |
if (!fdr_out) |
if (!fdr_out) |
773 |
{ |
{ |
774 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
775 |
return false; |
return FALSE; |
776 |
} |
} |
777 |
if (!add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, fdr_out, sz)) |
if (!add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, fdr_out, sz)) |
778 |
return false; |
return FALSE; |
779 |
for (fdr_ptr = fdr_start, i = 0; |
for (fdr_ptr = fdr_start, i = 0; |
780 |
fdr_ptr < fdr_end; |
fdr_ptr < fdr_end; |
781 |
fdr_ptr += fdr_add, i++) |
fdr_ptr += fdr_add, i++) |
785 |
bfd_byte *sym_out; |
bfd_byte *sym_out; |
786 |
bfd_byte *lraw_src; |
bfd_byte *lraw_src; |
787 |
bfd_byte *lraw_end; |
bfd_byte *lraw_end; |
788 |
boolean fgotfilename; |
bfd_boolean fgotfilename; |
789 |
|
|
790 |
if (input_debug->ifdmap[i] < output_symhdr->ifdMax) |
if (input_debug->ifdmap[i] < output_symhdr->ifdMax) |
791 |
{ |
{ |
800 |
|
|
801 |
fdr_adr = fdr.adr; |
fdr_adr = fdr.adr; |
802 |
|
|
|
/* Adjust the FDR address for any changes that may have been |
|
|
made by relaxing. */ |
|
|
if (input_debug->adjust != (struct ecoff_value_adjust *) NULL) |
|
|
{ |
|
|
struct ecoff_value_adjust *adjust; |
|
|
|
|
|
for (adjust = input_debug->adjust; |
|
|
adjust != (struct ecoff_value_adjust *) NULL; |
|
|
adjust = adjust->next) |
|
|
if (fdr_adr >= adjust->start |
|
|
&& fdr_adr < adjust->end) |
|
|
fdr.adr += adjust->adjust; |
|
|
} |
|
|
|
|
803 |
/* FIXME: It is conceivable that this FDR points to the .init or |
/* FIXME: It is conceivable that this FDR points to the .init or |
804 |
.fini section, in which case this will not do the right |
.fini section, in which case this will not do the right |
805 |
thing. */ |
thing. */ |
807 |
|
|
808 |
/* Swap in the local symbols, adjust their values, and swap them |
/* Swap in the local symbols, adjust their values, and swap them |
809 |
out again. */ |
out again. */ |
810 |
fgotfilename = false; |
fgotfilename = FALSE; |
811 |
sz = fdr.csym * external_sym_size; |
sz = fdr.csym * external_sym_size; |
812 |
sym_out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); |
sym_out = (bfd_byte *) objalloc_alloc (ainfo->memory, sz); |
813 |
if (!sym_out) |
if (!sym_out) |
814 |
{ |
{ |
815 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
816 |
return false; |
return FALSE; |
817 |
} |
} |
818 |
if (!add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, sym_out, |
if (!add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, sym_out, |
819 |
sz)) |
sz)) |
820 |
return false; |
return FALSE; |
821 |
lraw_src = ((bfd_byte *) input_debug->external_sym |
lraw_src = ((bfd_byte *) input_debug->external_sym |
822 |
+ fdr.isymBase * input_swap->external_sym_size); |
+ fdr.isymBase * input_swap->external_sym_size); |
823 |
lraw_end = lraw_src + fdr.csym * input_swap->external_sym_size; |
lraw_end = lraw_src + fdr.csym * input_swap->external_sym_size; |
842 |
case stLabel: |
case stLabel: |
843 |
case stProc: |
case stProc: |
844 |
case stStaticProc: |
case stStaticProc: |
|
if (input_debug->adjust != (struct ecoff_value_adjust *) NULL) |
|
|
{ |
|
|
bfd_vma value; |
|
|
struct ecoff_value_adjust *adjust; |
|
|
|
|
|
value = internal_sym.value; |
|
|
for (adjust = input_debug->adjust; |
|
|
adjust != (struct ecoff_value_adjust *) NULL; |
|
|
adjust = adjust->next) |
|
|
if (value >= adjust->start |
|
|
&& value < adjust->end) |
|
|
internal_sym.value += adjust->adjust; |
|
|
} |
|
845 |
internal_sym.value += section_adjust[internal_sym.sc]; |
internal_sym.value += section_adjust[internal_sym.sc]; |
846 |
break; |
break; |
847 |
|
|
852 |
/* If we are doing a final link, we hash all the strings in |
/* If we are doing a final link, we hash all the strings in |
853 |
the local symbol table together. This reduces the amount |
the local symbol table together. This reduces the amount |
854 |
of space required by debugging information. We don't do |
of space required by debugging information. We don't do |
855 |
this when performing a relocateable link because it would |
this when performing a relocatable link because it would |
856 |
prevent us from easily merging different FDR's. */ |
prevent us from easily merging different FDR's. */ |
857 |
if (! info->relocateable) |
if (! info->relocatable) |
858 |
{ |
{ |
859 |
boolean ffilename; |
bfd_boolean ffilename; |
860 |
const char *name; |
const char *name; |
861 |
|
|
862 |
if (! fgotfilename && internal_sym.iss == fdr.rss) |
if (! fgotfilename && internal_sym.iss == fdr.rss) |
863 |
ffilename = true; |
ffilename = TRUE; |
864 |
else |
else |
865 |
ffilename = false; |
ffilename = FALSE; |
866 |
|
|
867 |
/* Hash the name into the string table. */ |
/* Hash the name into the string table. */ |
868 |
name = input_debug->ss + fdr.issBase + internal_sym.iss; |
name = input_debug->ss + fdr.issBase + internal_sym.iss; |
872 |
{ |
{ |
873 |
struct string_hash_entry *sh; |
struct string_hash_entry *sh; |
874 |
|
|
875 |
sh = string_hash_lookup (&ainfo->str_hash, name, true, true); |
sh = string_hash_lookup (&ainfo->str_hash, name, TRUE, TRUE); |
876 |
if (sh == (struct string_hash_entry *) NULL) |
if (sh == (struct string_hash_entry *) NULL) |
877 |
return false; |
return FALSE; |
878 |
if (sh->val == -1) |
if (sh->val == -1) |
879 |
{ |
{ |
880 |
sh->val = output_symhdr->issMax; |
sh->val = output_symhdr->issMax; |
892 |
if (ffilename) |
if (ffilename) |
893 |
{ |
{ |
894 |
fdr.rss = internal_sym.iss; |
fdr.rss = internal_sym.iss; |
895 |
fgotfilename = true; |
fgotfilename = TRUE; |
896 |
} |
} |
897 |
} |
} |
898 |
|
|
914 |
file_ptr pos = input_symhdr->cbLineOffset + fdr.cbLineOffset; |
file_ptr pos = input_symhdr->cbLineOffset + fdr.cbLineOffset; |
915 |
if (!add_file_shuffle (ainfo, &ainfo->line, &ainfo->line_end, |
if (!add_file_shuffle (ainfo, &ainfo->line, &ainfo->line_end, |
916 |
input_bfd, pos, (unsigned long) fdr.cbLine)) |
input_bfd, pos, (unsigned long) fdr.cbLine)) |
917 |
return false; |
return FALSE; |
918 |
fdr.ilineBase = output_symhdr->ilineMax; |
fdr.ilineBase = output_symhdr->ilineMax; |
919 |
fdr.cbLineOffset = output_symhdr->cbLine; |
fdr.cbLineOffset = output_symhdr->cbLine; |
920 |
output_symhdr->ilineMax += fdr.cline; |
output_symhdr->ilineMax += fdr.cline; |
927 |
if (!add_file_shuffle (ainfo, &ainfo->aux, &ainfo->aux_end, |
if (!add_file_shuffle (ainfo, &ainfo->aux, &ainfo->aux_end, |
928 |
input_bfd, pos, |
input_bfd, pos, |
929 |
fdr.caux * sizeof (union aux_ext))) |
fdr.caux * sizeof (union aux_ext))) |
930 |
return false; |
return FALSE; |
931 |
fdr.iauxBase = output_symhdr->iauxMax; |
fdr.iauxBase = output_symhdr->iauxMax; |
932 |
output_symhdr->iauxMax += fdr.caux; |
output_symhdr->iauxMax += fdr.caux; |
933 |
} |
} |
934 |
if (! info->relocateable) |
if (! info->relocatable) |
935 |
{ |
{ |
936 |
|
|
937 |
/* When are are hashing strings, we lie about the number of |
/* When are are hashing strings, we lie about the number of |
946 |
file_ptr pos = input_symhdr->cbSsOffset + fdr.issBase; |
file_ptr pos = input_symhdr->cbSsOffset + fdr.issBase; |
947 |
if (!add_file_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, |
if (!add_file_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, |
948 |
input_bfd, pos, (unsigned long) fdr.cbSs)) |
input_bfd, pos, (unsigned long) fdr.cbSs)) |
949 |
return false; |
return FALSE; |
950 |
fdr.issBase = output_symhdr->issMax; |
fdr.issBase = output_symhdr->issMax; |
951 |
output_symhdr->issMax += fdr.cbSs; |
output_symhdr->issMax += fdr.cbSs; |
952 |
} |
} |
953 |
|
|
954 |
if ((output_bfd->xvec->header_byteorder |
if (output_bfd->xvec->header_byteorder |
955 |
== input_bfd->xvec->header_byteorder) |
== input_bfd->xvec->header_byteorder) |
|
&& input_debug->adjust == (struct ecoff_value_adjust *) NULL) |
|
956 |
{ |
{ |
957 |
/* The two BFD's have the same endianness, and we don't have |
/* The two BFD's have the same endianness, and we don't have |
958 |
to adjust the PDR addresses, so simply copying the |
to adjust the PDR addresses, so simply copying the |
965 |
unsigned long size = fdr.cpd * external_pdr_size; |
unsigned long size = fdr.cpd * external_pdr_size; |
966 |
if (!add_file_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, |
if (!add_file_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, |
967 |
input_bfd, pos, size)) |
input_bfd, pos, size)) |
968 |
return false; |
return FALSE; |
969 |
} |
} |
970 |
BFD_ASSERT (external_opt_size == input_swap->external_opt_size); |
BFD_ASSERT (external_opt_size == input_swap->external_opt_size); |
971 |
if (fdr.copt > 0) |
if (fdr.copt > 0) |
975 |
unsigned long size = fdr.copt * external_opt_size; |
unsigned long size = fdr.copt * external_opt_size; |
976 |
if (!add_file_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, |
if (!add_file_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, |
977 |
input_bfd, pos, size)) |
input_bfd, pos, size)) |
978 |
return false; |
return FALSE; |
979 |
} |
} |
980 |
} |
} |
981 |
else |
else |
998 |
if (!out) |
if (!out) |
999 |
{ |
{ |
1000 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
1001 |
return false; |
return FALSE; |
1002 |
} |
} |
1003 |
if (!add_memory_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, out, |
if (!add_memory_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, out, |
1004 |
sz)) |
sz)) |
1005 |
return false; |
return FALSE; |
1006 |
for (; in < end; in += insz, out += outsz) |
for (; in < end; in += insz, out += outsz) |
1007 |
{ |
{ |
1008 |
PDR pdr; |
PDR pdr; |
1009 |
|
|
1010 |
(*input_swap->swap_pdr_in) (input_bfd, (PTR) in, &pdr); |
(*input_swap->swap_pdr_in) (input_bfd, (PTR) in, &pdr); |
|
|
|
|
/* If we have been relaxing, we may have to adjust the |
|
|
address. */ |
|
|
if (input_debug->adjust != (struct ecoff_value_adjust *) NULL) |
|
|
{ |
|
|
bfd_vma adr; |
|
|
struct ecoff_value_adjust *adjust; |
|
|
|
|
|
adr = fdr_adr + pdr.adr; |
|
|
for (adjust = input_debug->adjust; |
|
|
adjust != (struct ecoff_value_adjust *) NULL; |
|
|
adjust = adjust->next) |
|
|
if (adr >= adjust->start |
|
|
&& adr < adjust->end) |
|
|
pdr.adr += adjust->adjust; |
|
|
} |
|
|
|
|
1011 |
(*output_swap->swap_pdr_out) (output_bfd, &pdr, (PTR) out); |
(*output_swap->swap_pdr_out) (output_bfd, &pdr, (PTR) out); |
1012 |
} |
} |
1013 |
|
|
1022 |
if (!out) |
if (!out) |
1023 |
{ |
{ |
1024 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
1025 |
return false; |
return FALSE; |
1026 |
} |
} |
1027 |
if (!add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out, |
if (!add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out, |
1028 |
sz)) |
sz)) |
1029 |
return false; |
return FALSE; |
1030 |
for (; in < end; in += insz, out += outsz) |
for (; in < end; in += insz, out += outsz) |
1031 |
{ |
{ |
1032 |
OPTR opt; |
OPTR opt; |
1058 |
++output_symhdr->ifdMax; |
++output_symhdr->ifdMax; |
1059 |
} |
} |
1060 |
|
|
1061 |
return true; |
return TRUE; |
1062 |
} |
} |
1063 |
|
|
1064 |
/* Add a string to the debugging information we are accumulating. |
/* Add a string to the debugging information we are accumulating. |
1065 |
Return the offset from the fdr string base. */ |
Return the offset from the fdr string base. */ |
1066 |
|
|
1067 |
static long ecoff_add_string PARAMS ((struct accumulate *, |
static long ecoff_add_string |
1068 |
struct bfd_link_info *, |
PARAMS ((struct accumulate *, struct bfd_link_info *, |
1069 |
struct ecoff_debug_info *, |
struct ecoff_debug_info *, FDR *fdr, const char *string)); |
|
FDR *fdr, const char *string)); |
|
1070 |
|
|
1071 |
static long |
static long |
1072 |
ecoff_add_string (ainfo, info, debug, fdr, string) |
ecoff_add_string (ainfo, info, debug, fdr, string) |
1082 |
|
|
1083 |
symhdr = &debug->symbolic_header; |
symhdr = &debug->symbolic_header; |
1084 |
len = strlen (string); |
len = strlen (string); |
1085 |
if (info->relocateable) |
if (info->relocatable) |
1086 |
{ |
{ |
1087 |
if (!add_memory_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, (PTR) string, |
if (!add_memory_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, (PTR) string, |
1088 |
len + 1)) |
len + 1)) |
1095 |
{ |
{ |
1096 |
struct string_hash_entry *sh; |
struct string_hash_entry *sh; |
1097 |
|
|
1098 |
sh = string_hash_lookup (&ainfo->str_hash, string, true, true); |
sh = string_hash_lookup (&ainfo->str_hash, string, TRUE, TRUE); |
1099 |
if (sh == (struct string_hash_entry *) NULL) |
if (sh == (struct string_hash_entry *) NULL) |
1100 |
return -1; |
return -1; |
1101 |
if (sh->val == -1) |
if (sh->val == -1) |
1117 |
|
|
1118 |
/* Add debugging information from a non-ECOFF file. */ |
/* Add debugging information from a non-ECOFF file. */ |
1119 |
|
|
1120 |
boolean |
bfd_boolean |
1121 |
bfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug, |
bfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug, |
1122 |
output_swap, input_bfd, info) |
output_swap, input_bfd, info) |
1123 |
PTR handle; |
PTR handle; |
1154 |
fdr.issBase = output_symhdr->issMax; |
fdr.issBase = output_symhdr->issMax; |
1155 |
fdr.cbSs = 0; |
fdr.cbSs = 0; |
1156 |
fdr.rss = ecoff_add_string (ainfo, info, output_debug, &fdr, |
fdr.rss = ecoff_add_string (ainfo, info, output_debug, &fdr, |
1157 |
bfd_archive_filename (input_bfd)); |
input_bfd->filename); |
1158 |
if (fdr.rss == -1) |
if (fdr.rss == -1) |
1159 |
return false; |
return FALSE; |
1160 |
fdr.isymBase = output_symhdr->isymMax; |
fdr.isymBase = output_symhdr->isymMax; |
1161 |
|
|
1162 |
/* Get the local symbols from the input BFD. */ |
/* Get the local symbols from the input BFD. */ |
1163 |
symsize = bfd_get_symtab_upper_bound (input_bfd); |
symsize = bfd_get_symtab_upper_bound (input_bfd); |
1164 |
if (symsize < 0) |
if (symsize < 0) |
1165 |
return false; |
return FALSE; |
1166 |
symbols = (asymbol **) bfd_alloc (output_bfd, (bfd_size_type) symsize); |
symbols = (asymbol **) bfd_alloc (output_bfd, (bfd_size_type) symsize); |
1167 |
if (symbols == (asymbol **) NULL) |
if (symbols == (asymbol **) NULL) |
1168 |
return false; |
return FALSE; |
1169 |
symcount = bfd_canonicalize_symtab (input_bfd, symbols); |
symcount = bfd_canonicalize_symtab (input_bfd, symbols); |
1170 |
if (symcount < 0) |
if (symcount < 0) |
1171 |
return false; |
return FALSE; |
1172 |
sym_end = symbols + symcount; |
sym_end = symbols + symcount; |
1173 |
|
|
1174 |
/* Handle the local symbols. Any external symbols are handled |
/* Handle the local symbols. Any external symbols are handled |
1186 |
(*sym_ptr)->name); |
(*sym_ptr)->name); |
1187 |
|
|
1188 |
if (internal_sym.iss == -1) |
if (internal_sym.iss == -1) |
1189 |
return false; |
return FALSE; |
1190 |
if (bfd_is_com_section ((*sym_ptr)->section) |
if (bfd_is_com_section ((*sym_ptr)->section) |
1191 |
|| bfd_is_und_section ((*sym_ptr)->section)) |
|| bfd_is_und_section ((*sym_ptr)->section)) |
1192 |
internal_sym.value = (*sym_ptr)->value; |
internal_sym.value = (*sym_ptr)->value; |
1203 |
if (!external_sym) |
if (!external_sym) |
1204 |
{ |
{ |
1205 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
1206 |
return false; |
return FALSE; |
1207 |
} |
} |
1208 |
(*swap_sym_out) (output_bfd, &internal_sym, external_sym); |
(*swap_sym_out) (output_bfd, &internal_sym, external_sym); |
1209 |
add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, |
add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, |
1224 |
if (!external_fdr) |
if (!external_fdr) |
1225 |
{ |
{ |
1226 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
1227 |
return false; |
return FALSE; |
1228 |
} |
} |
1229 |
(*output_swap->swap_fdr_out) (output_bfd, &fdr, external_fdr); |
(*output_swap->swap_fdr_out) (output_bfd, &fdr, external_fdr); |
1230 |
add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, |
add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, |
1233 |
|
|
1234 |
++output_symhdr->ifdMax; |
++output_symhdr->ifdMax; |
1235 |
|
|
1236 |
return true; |
return TRUE; |
1237 |
} |
} |
1238 |
|
|
1239 |
/* Set up ECOFF debugging information for the external symbols. |
/* Set up ECOFF debugging information for the external symbols. |
1241 |
probably be changed to use a shuffle structure. The assembler uses |
probably be changed to use a shuffle structure. The assembler uses |
1242 |
this interface, so that must be changed to do something else. */ |
this interface, so that must be changed to do something else. */ |
1243 |
|
|
1244 |
boolean |
bfd_boolean |
1245 |
bfd_ecoff_debug_externals (abfd, debug, swap, relocateable, get_extr, |
bfd_ecoff_debug_externals (abfd, debug, swap, relocatable, get_extr, |
1246 |
set_index) |
set_index) |
1247 |
bfd *abfd; |
bfd *abfd; |
1248 |
struct ecoff_debug_info *debug; |
struct ecoff_debug_info *debug; |
1249 |
const struct ecoff_debug_swap *swap; |
const struct ecoff_debug_swap *swap; |
1250 |
boolean relocateable; |
bfd_boolean relocatable; |
1251 |
boolean (*get_extr) PARAMS ((asymbol *, EXTR *)); |
bfd_boolean (*get_extr) PARAMS ((asymbol *, EXTR *)); |
1252 |
void (*set_index) PARAMS ((asymbol *, bfd_size_type)); |
void (*set_index) PARAMS ((asymbol *, bfd_size_type)); |
1253 |
{ |
{ |
1254 |
HDRR * const symhdr = &debug->symbolic_header; |
HDRR * const symhdr = &debug->symbolic_header; |
1257 |
|
|
1258 |
sym_ptr_ptr = bfd_get_outsymbols (abfd); |
sym_ptr_ptr = bfd_get_outsymbols (abfd); |
1259 |
if (sym_ptr_ptr == NULL) |
if (sym_ptr_ptr == NULL) |
1260 |
return true; |
return TRUE; |
1261 |
|
|
1262 |
for (c = bfd_get_symcount (abfd); c > 0; c--, sym_ptr_ptr++) |
for (c = bfd_get_symcount (abfd); c > 0; c--, sym_ptr_ptr++) |
1263 |
{ |
{ |
1272 |
|
|
1273 |
/* If we're producing an executable, move common symbols into |
/* If we're producing an executable, move common symbols into |
1274 |
bss. */ |
bss. */ |
1275 |
if (! relocateable) |
if (! relocatable) |
1276 |
{ |
{ |
1277 |
if (esym.asym.sc == scCommon) |
if (esym.asym.sc == scCommon) |
1278 |
esym.asym.sc = scBss; |
esym.asym.sc = scBss; |
1302 |
|
|
1303 |
if (! bfd_ecoff_debug_one_external (abfd, debug, swap, |
if (! bfd_ecoff_debug_one_external (abfd, debug, swap, |
1304 |
sym_ptr->name, &esym)) |
sym_ptr->name, &esym)) |
1305 |
return false; |
return FALSE; |
1306 |
} |
} |
1307 |
|
|
1308 |
return true; |
return TRUE; |
1309 |
} |
} |
1310 |
|
|
1311 |
/* Add a single external symbol to the debugging information. */ |
/* Add a single external symbol to the debugging information. */ |
1312 |
|
|
1313 |
boolean |
bfd_boolean |
1314 |
bfd_ecoff_debug_one_external (abfd, debug, swap, name, esym) |
bfd_ecoff_debug_one_external (abfd, debug, swap, name, esym) |
1315 |
bfd *abfd; |
bfd *abfd; |
1316 |
struct ecoff_debug_info *debug; |
struct ecoff_debug_info *debug; |
1332 |
if (! ecoff_add_bytes ((char **) &debug->ssext, |
if (! ecoff_add_bytes ((char **) &debug->ssext, |
1333 |
(char **) &debug->ssext_end, |
(char **) &debug->ssext_end, |
1334 |
symhdr->issExtMax + namelen + 1)) |
symhdr->issExtMax + namelen + 1)) |
1335 |
return false; |
return FALSE; |
1336 |
} |
} |
1337 |
if ((size_t) ((char *) debug->external_ext_end |
if ((size_t) ((char *) debug->external_ext_end |
1338 |
- (char *) debug->external_ext) |
- (char *) debug->external_ext) |
1341 |
if (! ecoff_add_bytes ((char **) &debug->external_ext, |
if (! ecoff_add_bytes ((char **) &debug->external_ext, |
1342 |
(char **) &debug->external_ext_end, |
(char **) &debug->external_ext_end, |
1343 |
(symhdr->iextMax + 1) * (size_t) external_ext_size)) |
(symhdr->iextMax + 1) * (size_t) external_ext_size)) |
1344 |
return false; |
return FALSE; |
1345 |
} |
} |
1346 |
|
|
1347 |
esym->asym.iss = symhdr->issExtMax; |
esym->asym.iss = symhdr->issExtMax; |
1355 |
strcpy (debug->ssext + symhdr->issExtMax, name); |
strcpy (debug->ssext + symhdr->issExtMax, name); |
1356 |
symhdr->issExtMax += namelen + 1; |
symhdr->issExtMax += namelen + 1; |
1357 |
|
|
1358 |
return true; |
return TRUE; |
1359 |
} |
} |
1360 |
|
|
1361 |
/* Align the ECOFF debugging information. */ |
/* Align the ECOFF debugging information. */ |
1456 |
going to be placed at. This assumes that the counts are set |
going to be placed at. This assumes that the counts are set |
1457 |
correctly. */ |
correctly. */ |
1458 |
|
|
1459 |
static boolean |
static bfd_boolean |
1460 |
ecoff_write_symhdr (abfd, debug, swap, where) |
ecoff_write_symhdr (abfd, debug, swap, where) |
1461 |
bfd *abfd; |
bfd *abfd; |
1462 |
struct ecoff_debug_info *debug; |
struct ecoff_debug_info *debug; |
1470 |
|
|
1471 |
/* Go to the right location in the file. */ |
/* Go to the right location in the file. */ |
1472 |
if (bfd_seek (abfd, where, SEEK_SET) != 0) |
if (bfd_seek (abfd, where, SEEK_SET) != 0) |
1473 |
return false; |
return FALSE; |
1474 |
|
|
1475 |
where += swap->external_hdr_size; |
where += swap->external_hdr_size; |
1476 |
|
|
1510 |
|
|
1511 |
if (buff != NULL) |
if (buff != NULL) |
1512 |
free (buff); |
free (buff); |
1513 |
return true; |
return TRUE; |
1514 |
error_return: |
error_return: |
1515 |
if (buff != NULL) |
if (buff != NULL) |
1516 |
free (buff); |
free (buff); |
1517 |
return false; |
return FALSE; |
1518 |
} |
} |
1519 |
|
|
1520 |
/* Write out the ECOFF debugging information. This function assumes |
/* Write out the ECOFF debugging information. This function assumes |
1523 |
information to. This function fills in the file offsets in the |
information to. This function fills in the file offsets in the |
1524 |
symbolic header. */ |
symbolic header. */ |
1525 |
|
|
1526 |
boolean |
bfd_boolean |
1527 |
bfd_ecoff_write_debug (abfd, debug, swap, where) |
bfd_ecoff_write_debug (abfd, debug, swap, where) |
1528 |
bfd *abfd; |
bfd *abfd; |
1529 |
struct ecoff_debug_info *debug; |
struct ecoff_debug_info *debug; |
1533 |
HDRR * const symhdr = &debug->symbolic_header; |
HDRR * const symhdr = &debug->symbolic_header; |
1534 |
|
|
1535 |
if (! ecoff_write_symhdr (abfd, debug, swap, where)) |
if (! ecoff_write_symhdr (abfd, debug, swap, where)) |
1536 |
return false; |
return FALSE; |
1537 |
|
|
1538 |
#define WRITE(ptr, count, size, offset) \ |
#define WRITE(ptr, count, size, offset) \ |
1539 |
BFD_ASSERT (symhdr->offset == 0 \ |
BFD_ASSERT (symhdr->offset == 0 \ |
1540 |
|| (bfd_vma) bfd_tell (abfd) == symhdr->offset); \ |
|| (bfd_vma) bfd_tell (abfd) == symhdr->offset); \ |
1541 |
if (bfd_bwrite ((PTR) debug->ptr, (bfd_size_type) size * symhdr->count, abfd)\ |
if (bfd_bwrite ((PTR) debug->ptr, (bfd_size_type) size * symhdr->count, abfd)\ |
1542 |
!= size * symhdr->count) \ |
!= size * symhdr->count) \ |
1543 |
return false; |
return FALSE; |
1544 |
|
|
1545 |
WRITE (line, cbLine, sizeof (unsigned char), cbLineOffset); |
WRITE (line, cbLine, sizeof (unsigned char), cbLineOffset); |
1546 |
WRITE (external_dnr, idnMax, swap->external_dnr_size, cbDnOffset); |
WRITE (external_dnr, idnMax, swap->external_dnr_size, cbDnOffset); |
1556 |
WRITE (external_ext, iextMax, swap->external_ext_size, cbExtOffset); |
WRITE (external_ext, iextMax, swap->external_ext_size, cbExtOffset); |
1557 |
#undef WRITE |
#undef WRITE |
1558 |
|
|
1559 |
return true; |
return TRUE; |
1560 |
} |
} |
1561 |
|
|
1562 |
/* Write out a shuffle list. */ |
/* Write out a shuffle list. */ |
1563 |
|
|
1564 |
static boolean ecoff_write_shuffle PARAMS ((bfd *, |
static bfd_boolean ecoff_write_shuffle |
1565 |
const struct ecoff_debug_swap *, |
PARAMS ((bfd *, const struct ecoff_debug_swap *, struct shuffle *, |
1566 |
struct shuffle *, PTR space)); |
PTR space)); |
1567 |
|
|
1568 |
static boolean |
static bfd_boolean |
1569 |
ecoff_write_shuffle (abfd, swap, shuffle, space) |
ecoff_write_shuffle (abfd, swap, shuffle, space) |
1570 |
bfd *abfd; |
bfd *abfd; |
1571 |
const struct ecoff_debug_swap *swap; |
const struct ecoff_debug_swap *swap; |
1582 |
{ |
{ |
1583 |
if (bfd_bwrite (l->u.memory, (bfd_size_type) l->size, abfd) |
if (bfd_bwrite (l->u.memory, (bfd_size_type) l->size, abfd) |
1584 |
!= l->size) |
!= l->size) |
1585 |
return false; |
return FALSE; |
1586 |
} |
} |
1587 |
else |
else |
1588 |
{ |
{ |
1590 |
|| bfd_bread (space, (bfd_size_type) l->size, |
|| bfd_bread (space, (bfd_size_type) l->size, |
1591 |
l->u.file.input_bfd) != l->size |
l->u.file.input_bfd) != l->size |
1592 |
|| bfd_bwrite (space, (bfd_size_type) l->size, abfd) != l->size) |
|| bfd_bwrite (space, (bfd_size_type) l->size, abfd) != l->size) |
1593 |
return false; |
return FALSE; |
1594 |
} |
} |
1595 |
total += l->size; |
total += l->size; |
1596 |
} |
} |
1603 |
i = swap->debug_align - (total & (swap->debug_align - 1)); |
i = swap->debug_align - (total & (swap->debug_align - 1)); |
1604 |
s = (bfd_byte *) bfd_zmalloc ((bfd_size_type) i); |
s = (bfd_byte *) bfd_zmalloc ((bfd_size_type) i); |
1605 |
if (s == NULL && i != 0) |
if (s == NULL && i != 0) |
1606 |
return false; |
return FALSE; |
1607 |
|
|
1608 |
if (bfd_bwrite ((PTR) s, (bfd_size_type) i, abfd) != i) |
if (bfd_bwrite ((PTR) s, (bfd_size_type) i, abfd) != i) |
1609 |
{ |
{ |
1610 |
free (s); |
free (s); |
1611 |
return false; |
return FALSE; |
1612 |
} |
} |
1613 |
free (s); |
free (s); |
1614 |
} |
} |
1615 |
|
|
1616 |
return true; |
return TRUE; |
1617 |
} |
} |
1618 |
|
|
1619 |
/* Write out debugging information using accumulated linker |
/* Write out debugging information using accumulated linker |
1620 |
information. */ |
information. */ |
1621 |
|
|
1622 |
boolean |
bfd_boolean |
1623 |
bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where) |
bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where) |
1624 |
PTR handle; |
PTR handle; |
1625 |
bfd *abfd; |
bfd *abfd; |
1649 |
|
|
1650 |
/* The string table is written out from the hash table if this is a |
/* The string table is written out from the hash table if this is a |
1651 |
final link. */ |
final link. */ |
1652 |
if (info->relocateable) |
if (info->relocatable) |
1653 |
{ |
{ |
1654 |
BFD_ASSERT (ainfo->ss_hash == (struct string_hash_entry *) NULL); |
BFD_ASSERT (ainfo->ss_hash == (struct string_hash_entry *) NULL); |
1655 |
if (! ecoff_write_shuffle (abfd, swap, ainfo->ss, space)) |
if (! ecoff_write_shuffle (abfd, swap, ainfo->ss, space)) |
1737 |
|
|
1738 |
if (space != NULL) |
if (space != NULL) |
1739 |
free (space); |
free (space); |
1740 |
return true; |
return TRUE; |
1741 |
|
|
1742 |
error_return: |
error_return: |
1743 |
if (space != NULL) |
if (space != NULL) |
1744 |
free (space); |
free (space); |
1745 |
return false; |
return FALSE; |
1746 |
} |
} |
1747 |
|
|
1748 |
/* Handle the find_nearest_line function for both ECOFF and MIPS ELF |
/* Handle the find_nearest_line function for both ECOFF and MIPS ELF |
1773 |
table will be sorted by address so we can look it up via binary |
table will be sorted by address so we can look it up via binary |
1774 |
search. */ |
search. */ |
1775 |
|
|
1776 |
static boolean |
static bfd_boolean |
1777 |
mk_fdrtab (abfd, debug_info, debug_swap, line_info) |
mk_fdrtab (abfd, debug_info, debug_swap, line_info) |
1778 |
bfd *abfd; |
bfd *abfd; |
1779 |
struct ecoff_debug_info * const debug_info; |
struct ecoff_debug_info * const debug_info; |
1784 |
FDR *fdr_ptr; |
FDR *fdr_ptr; |
1785 |
FDR *fdr_start; |
FDR *fdr_start; |
1786 |
FDR *fdr_end; |
FDR *fdr_end; |
1787 |
boolean stabs; |
bfd_boolean stabs; |
1788 |
long len; |
long len; |
1789 |
bfd_size_type amt; |
bfd_size_type amt; |
1790 |
|
|
1791 |
fdr_start = debug_info->fdr; |
fdr_start = debug_info->fdr; |
1792 |
fdr_end = fdr_start + debug_info->symbolic_header.ifdMax; |
fdr_end = fdr_start + debug_info->symbolic_header.ifdMax; |
1793 |
|
|
1794 |
/* First, let's see how long the table needs to be: */ |
/* First, let's see how long the table needs to be. */ |
1795 |
for (len = 0, fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) |
for (len = 0, fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) |
1796 |
{ |
{ |
1797 |
if (fdr_ptr->cpd == 0) /* skip FDRs that have no PDRs */ |
if (fdr_ptr->cpd == 0) /* Skip FDRs that have no PDRs. */ |
1798 |
continue; |
continue; |
1799 |
++len; |
++len; |
1800 |
} |
} |
1801 |
|
|
1802 |
/* Now, create and fill in the table: */ |
/* Now, create and fill in the table. */ |
|
|
|
1803 |
amt = (bfd_size_type) len * sizeof (struct ecoff_fdrtab_entry); |
amt = (bfd_size_type) len * sizeof (struct ecoff_fdrtab_entry); |
1804 |
line_info->fdrtab = (struct ecoff_fdrtab_entry*) bfd_zalloc (abfd, amt); |
line_info->fdrtab = (struct ecoff_fdrtab_entry*) bfd_zalloc (abfd, amt); |
1805 |
if (line_info->fdrtab == NULL) |
if (line_info->fdrtab == NULL) |
1806 |
return false; |
return FALSE; |
1807 |
line_info->fdrtab_len = len; |
line_info->fdrtab_len = len; |
1808 |
|
|
1809 |
tab = line_info->fdrtab; |
tab = line_info->fdrtab; |
1815 |
/* Check whether this file has stabs debugging information. In |
/* Check whether this file has stabs debugging information. In |
1816 |
a file with stabs debugging information, the second local |
a file with stabs debugging information, the second local |
1817 |
symbol is named @stabs. */ |
symbol is named @stabs. */ |
1818 |
stabs = false; |
stabs = FALSE; |
1819 |
if (fdr_ptr->csym >= 2) |
if (fdr_ptr->csym >= 2) |
1820 |
{ |
{ |
1821 |
char *sym_ptr; |
char *sym_ptr; |
1822 |
SYMR sym; |
SYMR sym; |
1823 |
|
|
1824 |
sym_ptr = ((char *) debug_info->external_sym |
sym_ptr = ((char *) debug_info->external_sym |
1825 |
+ (fdr_ptr->isymBase + 1)*debug_swap->external_sym_size); |
+ (fdr_ptr->isymBase + 1) * debug_swap->external_sym_size); |
1826 |
(*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); |
(*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); |
1827 |
if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss, |
if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss, |
1828 |
STABS_SYMBOL) == 0) |
STABS_SYMBOL) == 0) |
1829 |
stabs = true; |
stabs = TRUE; |
1830 |
} |
} |
1831 |
|
|
1832 |
if (!stabs) |
if (!stabs) |
1833 |
{ |
{ |
1834 |
bfd_size_type external_pdr_size; |
/* eraxxon: There are at least two problems with this computation: |
1835 |
char *pdr_ptr; |
1) PDRs do *not* contain offsets but full vma's; and typically the |
1836 |
PDR pdr; |
address of the first PDR is the address of the FDR, which will |
1837 |
|
make (most) of the results of the original computation 0! |
1838 |
external_pdr_size = debug_swap->external_pdr_size; |
2) Once in a wacky while, the Compaq compiler generated PDR |
1839 |
|
addresses do not equal the FDR vma, but they (the PDR address) |
1840 |
pdr_ptr = ((char *) debug_info->external_pdr |
are still vma's and not offsets. Cf. comments in |
1841 |
+ fdr_ptr->ipdFirst * external_pdr_size); |
'lookup_line'. */ |
|
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); |
|
1842 |
/* The address of the first PDR is the offset of that |
/* The address of the first PDR is the offset of that |
1843 |
procedure relative to the beginning of file FDR. */ |
procedure relative to the beginning of file FDR. */ |
1844 |
tab->base_addr = fdr_ptr->adr - pdr.adr; |
tab->base_addr = fdr_ptr->adr; |
1845 |
} |
} |
1846 |
else |
else |
1847 |
{ |
{ |
1848 |
/* XXX I don't know about stabs, so this is a guess |
/* XXX I don't know about stabs, so this is a guess |
1849 |
(davidm@cs.arizona.edu): */ |
(davidm@cs.arizona.edu). */ |
1850 |
tab->base_addr = fdr_ptr->adr; |
tab->base_addr = fdr_ptr->adr; |
1851 |
} |
} |
1852 |
tab->fdr = fdr_ptr; |
tab->fdr = fdr_ptr; |
1860 |
qsort ((PTR) line_info->fdrtab, (size_t) len, |
qsort ((PTR) line_info->fdrtab, (size_t) len, |
1861 |
sizeof (struct ecoff_fdrtab_entry), cmp_fdrtab_entry); |
sizeof (struct ecoff_fdrtab_entry), cmp_fdrtab_entry); |
1862 |
|
|
1863 |
return true; |
return TRUE; |
1864 |
} |
} |
1865 |
|
|
1866 |
/* Return index of first FDR that covers to OFFSET. */ |
/* Return index of first FDR that covers to OFFSET. */ |
1890 |
else |
else |
1891 |
low = mid + 1; |
low = mid + 1; |
1892 |
} |
} |
1893 |
|
|
1894 |
|
/* eraxxon: at this point 'offset' is either lower than the lowest entry or |
1895 |
|
higher than the highest entry. In the former case high = low = mid = 0; |
1896 |
|
we want to return -1. In the latter case, low = high and mid = low - 1; |
1897 |
|
we want to return the index of the highest entry. Only in former case |
1898 |
|
will the following 'catch-all' test be true. */ |
1899 |
++mid; |
++mid; |
1900 |
|
|
1901 |
/* last entry is catch-all for all higher addresses: */ |
/* Last entry is catch-all for all higher addresses. */ |
1902 |
if (offset < tab[mid].base_addr) |
if (offset < tab[mid].base_addr) |
1903 |
return -1; |
return -1; |
1904 |
|
|
1905 |
find_min: |
find_min: |
1906 |
|
|
1907 |
|
/* eraxxon: There may be multiple FDRs in the table with the |
1908 |
|
same base_addr; make sure that we are at the first one. */ |
1909 |
while (mid > 0 && tab[mid - 1].base_addr == tab[mid].base_addr) |
while (mid > 0 && tab[mid - 1].base_addr == tab[mid].base_addr) |
1910 |
--mid; |
--mid; |
1911 |
|
|
1915 |
/* Look up a line given an address, storing the information in |
/* Look up a line given an address, storing the information in |
1916 |
LINE_INFO->cache. */ |
LINE_INFO->cache. */ |
1917 |
|
|
1918 |
static boolean |
static bfd_boolean |
1919 |
lookup_line (abfd, debug_info, debug_swap, line_info) |
lookup_line (abfd, debug_info, debug_swap, line_info) |
1920 |
bfd *abfd; |
bfd *abfd; |
1921 |
struct ecoff_debug_info * const debug_info; |
struct ecoff_debug_info * const debug_info; |
1924 |
{ |
{ |
1925 |
struct ecoff_fdrtab_entry *tab; |
struct ecoff_fdrtab_entry *tab; |
1926 |
bfd_vma offset; |
bfd_vma offset; |
1927 |
boolean stabs; |
bfd_boolean stabs; |
1928 |
FDR *fdr_ptr; |
FDR *fdr_ptr; |
1929 |
int i; |
int i; |
1930 |
|
|
1931 |
|
/* eraxxon: note that 'offset' is the full vma, not a section offset. */ |
1932 |
offset = line_info->cache.start; |
offset = line_info->cache.start; |
1933 |
|
|
1934 |
/* Build FDR table (sorted by object file's base-address) if we |
/* Build FDR table (sorted by object file's base-address) if we |
1935 |
don't have it already. */ |
don't have it already. */ |
1936 |
if (line_info->fdrtab == NULL |
if (line_info->fdrtab == NULL |
1937 |
&& !mk_fdrtab (abfd, debug_info, debug_swap, line_info)) |
&& !mk_fdrtab (abfd, debug_info, debug_swap, line_info)) |
1938 |
return false; |
return FALSE; |
1939 |
|
|
1940 |
tab = line_info->fdrtab; |
tab = line_info->fdrtab; |
1941 |
|
|
1942 |
/* find first FDR for address OFFSET */ |
/* Find first FDR for address OFFSET. */ |
1943 |
i = fdrtab_lookup (line_info, offset); |
i = fdrtab_lookup (line_info, offset); |
1944 |
if (i < 0) |
if (i < 0) |
1945 |
return false; /* no FDR, no fun... */ |
return FALSE; /* no FDR, no fun... */ |
1946 |
|
|
1947 |
|
/* eraxxon: 'fdrtab_lookup' doesn't give what we want, at least for Compaq's |
1948 |
|
C++ compiler 6.2. Consider three FDRs with starting addresses of x, y, |
1949 |
|
and z, respectively, such that x < y < z. Assume further that |
1950 |
|
y < 'offset' < z. It is possible at times that the PDR for 'offset' is |
1951 |
|
associated with FDR x and *not* with FDR y. Erg!! |
1952 |
|
|
1953 |
|
From a binary dump of my C++ test case 'moo' using Compaq's coffobjanl |
1954 |
|
(output format has been edited for our purposes): |
1955 |
|
|
1956 |
|
FDR [2]: (main.C): First instruction: 0x12000207c <x> |
1957 |
|
PDR [5] for File [2]: LoopTest__Xv <0x1200020a0> (a) |
1958 |
|
PDR [7] for File [2]: foo__Xv <0x120002168> |
1959 |
|
FDR [1]: (-1): First instruction: 0x1200020e8 <y> |
1960 |
|
PDR [3] for File [1]: <0x120001ad0> (b) |
1961 |
|
FDR [6]: (-1): First instruction: 0x1200026f0 <z> |
1962 |
|
|
1963 |
|
(a) In the case of PDR5, the vma is such that the first few instructions |
1964 |
|
of the procedure can be found. But since the size of this procedure is |
1965 |
|
160b, the vma will soon cross into the 'address space' of FDR1 and no |
1966 |
|
debugging info will be found. How repugnant! |
1967 |
|
|
1968 |
|
(b) It is also possible for a PDR to have a *lower* vma than its associated |
1969 |
|
FDR; see FDR1 and PDR3. Gross! |
1970 |
|
|
1971 |
|
Since the FDRs that are causing so much havok (in this case) 1) do not |
1972 |
|
describe actual files (fdr.rss == -1), and 2) contain only compiler |
1973 |
|
generated routines, I thought a simple fix would be to exclude them from |
1974 |
|
the FDR table in 'mk_fdrtab'. But, besides not knowing for certain |
1975 |
|
whether this would be correct, it creates an additional problem. If we |
1976 |
|
happen to ask for source file info on a compiler generated (procedure) |
1977 |
|
symbol -- which is still in the symbol table -- the result can be |
1978 |
|
information from a real procedure! This is because compiler generated |
1979 |
|
procedures with vma's higher than the last FDR in the fdr table will be |
1980 |
|
associated with a PDR from this FDR, specifically the PDR with the |
1981 |
|
highest vma. This wasn't a problem before, because each procedure had a |
1982 |
|
PDR. (Yes, this problem could be eliminated if we kept the size of the |
1983 |
|
last PDR around, but things are already getting ugly). |
1984 |
|
|
1985 |
|
Probably, a better solution would be to have a sorted PDR table. Each |
1986 |
|
PDR would have a pointer to its FDR so file information could still be |
1987 |
|
obtained. A FDR table could still be constructed if necessary -- since |
1988 |
|
it only contains pointers, not much extra memory would be used -- but |
1989 |
|
the PDR table would be searched to locate debugging info. |
1990 |
|
|
1991 |
|
There is still at least one remaining issue. Sometimes a FDR can have a |
1992 |
|
bogus name, but contain PDRs that should belong to another FDR with a |
1993 |
|
real name. E.g: |
1994 |
|
|
1995 |
|
FDR [3]: 0000000120001b50 (/home/.../Array.H~alt~deccxx_5E5A62AD) |
1996 |
|
PDR [a] for File [3]: 0000000120001b50 |
1997 |
|
PDR [b] for File [3]: 0000000120001cf0 |
1998 |
|
PDR [c] for File [3]: 0000000120001dc8 |
1999 |
|
PDR [d] for File [3]: 0000000120001e40 |
2000 |
|
PDR [e] for File [3]: 0000000120001eb8 |
2001 |
|
PDR [f] for File [3]: 0000000120001f4c |
2002 |
|
FDR [4]: 0000000120001b50 (/home/.../Array.H) |
2003 |
|
|
2004 |
|
Here, FDR4 has the correct name, but should (seemingly) contain PDRa-f. |
2005 |
|
The symbol table for PDR4 does contain symbols for PDRa-f, but so does |
2006 |
|
the symbol table for FDR3. However the former is different; perhaps this |
2007 |
|
can be detected easily. (I'm not sure at this point.) This problem only |
2008 |
|
seems to be associated with files with templates. I am assuming the idea |
2009 |
|
is that there is a 'fake' FDR (with PDRs) for each differently typed set |
2010 |
|
of templates that must be generated. Currently, FDR4 is completely |
2011 |
|
excluded from the FDR table in 'mk_fdrtab' because it contains no PDRs. |
2012 |
|
|
2013 |
|
Since I don't have time to prepare a real fix for this right now, be |
2014 |
|
prepared for 'A Horrible Hack' to force the inspection of all non-stabs |
2015 |
|
FDRs. It's coming... */ |
2016 |
fdr_ptr = tab[i].fdr; |
fdr_ptr = tab[i].fdr; |
2017 |
|
|
2018 |
/* Check whether this file has stabs debugging information. In a |
/* Check whether this file has stabs debugging information. In a |
2019 |
file with stabs debugging information, the second local symbol is |
file with stabs debugging information, the second local symbol is |
2020 |
named @stabs. */ |
named @stabs. */ |
2021 |
stabs = false; |
stabs = FALSE; |
2022 |
if (fdr_ptr->csym >= 2) |
if (fdr_ptr->csym >= 2) |
2023 |
{ |
{ |
2024 |
char *sym_ptr; |
char *sym_ptr; |
2029 |
(*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); |
(*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); |
2030 |
if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss, |
if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss, |
2031 |
STABS_SYMBOL) == 0) |
STABS_SYMBOL) == 0) |
2032 |
stabs = true; |
stabs = TRUE; |
2033 |
} |
} |
2034 |
|
|
2035 |
if (!stabs) |
if (!stabs) |
2038 |
char *pdr_ptr; |
char *pdr_ptr; |
2039 |
char *best_pdr = NULL; |
char *best_pdr = NULL; |
2040 |
FDR *best_fdr; |
FDR *best_fdr; |
2041 |
bfd_vma best_dist = ~(bfd_vma) 0; |
bfd_signed_vma best_dist = -1; |
2042 |
PDR pdr; |
PDR pdr; |
2043 |
unsigned char *line_ptr; |
unsigned char *line_ptr; |
2044 |
unsigned char *line_end; |
unsigned char *line_end; |
2100 |
considerably, which is undesirable. */ |
considerably, which is undesirable. */ |
2101 |
external_pdr_size = debug_swap->external_pdr_size; |
external_pdr_size = debug_swap->external_pdr_size; |
2102 |
|
|
2103 |
/* Make offset relative to object file's start-address: */ |
/* eraxxon: The Horrible Hack: Because of the problems above, set 'i' |
2104 |
offset -= tab[i].base_addr; |
to 0 so we look through all FDRs. |
2105 |
|
|
2106 |
|
Because FDR's without any symbols are assumed to be non-stabs, |
2107 |
|
searching through all FDRs may cause the following code to try to |
2108 |
|
read stabs FDRs as ECOFF ones. However, I don't think this will |
2109 |
|
harm anything. */ |
2110 |
|
i = 0; |
2111 |
|
|
2112 |
/* Search FDR list starting at tab[i] for the PDR that best matches |
/* Search FDR list starting at tab[i] for the PDR that best matches |
2113 |
OFFSET. Normally, the FDR list is only one entry long. */ |
OFFSET. Normally, the FDR list is only one entry long. */ |
2114 |
best_fdr = NULL; |
best_fdr = NULL; |
2115 |
do |
do |
2116 |
{ |
{ |
2117 |
bfd_vma dist, min_dist = 0; |
/* eraxxon: 'dist' and 'min_dist' can be negative now |
2118 |
|
because we iterate over every FDR rather than just ones |
2119 |
|
with a base address less than or equal to 'offset'. */ |
2120 |
|
bfd_signed_vma dist = -1, min_dist = -1; |
2121 |
char *pdr_hold; |
char *pdr_hold; |
2122 |
char *pdr_end; |
char *pdr_end; |
2123 |
|
|
2140 |
if (offset >= (pdr.adr - 0x10 * pdr.prof)) |
if (offset >= (pdr.adr - 0x10 * pdr.prof)) |
2141 |
{ |
{ |
2142 |
dist = offset - (pdr.adr - 0x10 * pdr.prof); |
dist = offset - (pdr.adr - 0x10 * pdr.prof); |
2143 |
if (!pdr_hold || dist < min_dist) |
|
2144 |
|
/* eraxxon: 'dist' can be negative now. Note that |
2145 |
|
'min_dist' can be negative if 'pdr_hold' below is NULL. */ |
2146 |
|
if (!pdr_hold || (dist >= 0 && dist < min_dist)) |
2147 |
{ |
{ |
2148 |
min_dist = dist; |
min_dist = dist; |
2149 |
pdr_hold = pdr_ptr; |
pdr_hold = pdr_ptr; |
2151 |
} |
} |
2152 |
} |
} |
2153 |
|
|
2154 |
if (!best_pdr || min_dist < best_dist) |
if (!best_pdr || (min_dist >= 0 && min_dist < best_dist)) |
2155 |
{ |
{ |
2156 |
best_dist = min_dist; |
best_dist = (bfd_vma) min_dist; |
2157 |
best_fdr = fdr_ptr; |
best_fdr = fdr_ptr; |
2158 |
best_pdr = pdr_hold; |
best_pdr = pdr_hold; |
2159 |
} |
} |
2160 |
/* continue looping until base_addr of next entry is different: */ |
/* Continue looping until base_addr of next entry is different. */ |
2161 |
} |
} |
2162 |
while (++i < line_info->fdrtab_len |
/* eraxxon: We want to iterate over all FDRs. |
2163 |
&& tab[i].base_addr == tab[i - 1].base_addr); |
See previous comment about 'fdrtab_lookup'. */ |
2164 |
|
while (++i < line_info->fdrtab_len); |
2165 |
|
|
2166 |
if (!best_fdr || !best_pdr) |
if (!best_fdr || !best_pdr) |
2167 |
return false; /* shouldn't happen... */ |
return FALSE; /* Shouldn't happen... */ |
2168 |
|
|
2169 |
/* phew, finally we got something that we can hold onto: */ |
/* Phew, finally we got something that we can hold onto. */ |
2170 |
fdr_ptr = best_fdr; |
fdr_ptr = best_fdr; |
2171 |
pdr_ptr = best_pdr; |
pdr_ptr = best_pdr; |
2172 |
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); |
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); |
2176 |
number entries. */ |
number entries. */ |
2177 |
line_end = debug_info->line + fdr_ptr->cbLineOffset + fdr_ptr->cbLine; |
line_end = debug_info->line + fdr_ptr->cbLineOffset + fdr_ptr->cbLine; |
2178 |
|
|
2179 |
/* Make offset relative to procedure entry: */ |
/* Make offset relative to procedure entry. */ |
2180 |
offset -= pdr.adr - 0x10 * pdr.prof; |
offset -= pdr.adr - 0x10 * pdr.prof; |
2181 |
lineno = pdr.lnLow; |
lineno = pdr.lnLow; |
2182 |
line_ptr = debug_info->line + fdr_ptr->cbLineOffset + pdr.cbLineOffset; |
line_ptr = debug_info->line + fdr_ptr->cbLineOffset + pdr.cbLineOffset; |
2257 |
const char *line_file_name; |
const char *line_file_name; |
2258 |
bfd_vma low_func_vma; |
bfd_vma low_func_vma; |
2259 |
bfd_vma low_line_vma; |
bfd_vma low_line_vma; |
2260 |
boolean past_line; |
bfd_boolean past_line; |
2261 |
boolean past_fn; |
bfd_boolean past_fn; |
2262 |
char *sym_ptr, *sym_ptr_end; |
char *sym_ptr, *sym_ptr_end; |
2263 |
size_t len, funclen; |
size_t len, funclen; |
2264 |
char *buffer = NULL; |
char *buffer = NULL; |
2284 |
line_file_name = NULL; |
line_file_name = NULL; |
2285 |
low_func_vma = 0; |
low_func_vma = 0; |
2286 |
low_line_vma = 0; |
low_line_vma = 0; |
2287 |
past_line = false; |
past_line = FALSE; |
2288 |
past_fn = false; |
past_fn = FALSE; |
2289 |
|
|
2290 |
external_sym_size = debug_swap->external_sym_size; |
external_sym_size = debug_swap->external_sym_size; |
2291 |
|
|
2335 |
|
|
2336 |
case N_FUN: |
case N_FUN: |
2337 |
if (sym.value > offset) |
if (sym.value > offset) |
2338 |
past_fn = true; |
past_fn = TRUE; |
2339 |
else if (sym.value >= low_func_vma) |
else if (sym.value >= low_func_vma) |
2340 |
{ |
{ |
2341 |
low_func_vma = sym.value; |
low_func_vma = sym.value; |
2348 |
else if (sym.st == stLabel && sym.index != indexNil) |
else if (sym.st == stLabel && sym.index != indexNil) |
2349 |
{ |
{ |
2350 |
if (sym.value > offset) |
if (sym.value > offset) |
2351 |
past_line = true; |
past_line = TRUE; |
2352 |
else if (sym.value >= low_line_vma) |
else if (sym.value >= low_line_vma) |
2353 |
{ |
{ |
2354 |
low_line_vma = sym.value; |
low_line_vma = sym.value; |
2380 |
free (line_info->find_buffer); |
free (line_info->find_buffer); |
2381 |
buffer = (char *) bfd_malloc ((bfd_size_type) len); |
buffer = (char *) bfd_malloc ((bfd_size_type) len); |
2382 |
if (buffer == NULL) |
if (buffer == NULL) |
2383 |
return false; |
return FALSE; |
2384 |
line_info->find_buffer = buffer; |
line_info->find_buffer = buffer; |
2385 |
} |
} |
2386 |
|
|
2408 |
} |
} |
2409 |
} |
} |
2410 |
|
|
2411 |
return true; |
return TRUE; |
2412 |
} |
} |
2413 |
|
|
2414 |
/* Do the work of find_nearest_line. */ |
/* Do the work of find_nearest_line. */ |
2415 |
|
|
2416 |
boolean |
bfd_boolean |
2417 |
_bfd_ecoff_locate_line (abfd, section, offset, debug_info, debug_swap, |
_bfd_ecoff_locate_line (abfd, section, offset, debug_info, debug_swap, |
2418 |
line_info, filename_ptr, functionname_ptr, retline_ptr) |
line_info, filename_ptr, functionname_ptr, retline_ptr) |
2419 |
bfd *abfd; |
bfd *abfd; |
2439 |
if (! lookup_line (abfd, debug_info, debug_swap, line_info)) |
if (! lookup_line (abfd, debug_info, debug_swap, line_info)) |
2440 |
{ |
{ |
2441 |
line_info->cache.sect = NULL; |
line_info->cache.sect = NULL; |
2442 |
return false; |
return FALSE; |
2443 |
} |
} |
2444 |
} |
} |
2445 |
|
|
2447 |
*functionname_ptr = line_info->cache.functionname; |
*functionname_ptr = line_info->cache.functionname; |
2448 |
*retline_ptr = line_info->cache.line_num; |
*retline_ptr = line_info->cache.line_num; |
2449 |
|
|
2450 |
return true; |
return TRUE; |
2451 |
} |
} |
2452 |
|
|
2453 |
/* These routines copy symbolic information into a memory buffer. |
/* These routines copy symbolic information into a memory buffer. |
2460 |
|
|
2461 |
/* Collect a shuffle into a memory buffer. */ |
/* Collect a shuffle into a memory buffer. */ |
2462 |
|
|
2463 |
static boolean ecoff_collect_shuffle PARAMS ((struct shuffle *, bfd_byte *)); |
static bfd_boolean ecoff_collect_shuffle |
2464 |
|
PARAMS ((struct shuffle *, bfd_byte *)); |
2465 |
|
|
2466 |
static boolean |
static bfd_boolean |
2467 |
ecoff_collect_shuffle (l, buff) |
ecoff_collect_shuffle (l, buff) |
2468 |
struct shuffle *l; |
struct shuffle *l; |
2469 |
bfd_byte *buff; |
bfd_byte *buff; |
2480 |
if (bfd_seek (l->u.file.input_bfd, l->u.file.offset, SEEK_SET) != 0 |
if (bfd_seek (l->u.file.input_bfd, l->u.file.offset, SEEK_SET) != 0 |
2481 |
|| (bfd_bread (buff, (bfd_size_type) l->size, l->u.file.input_bfd) |
|| (bfd_bread (buff, (bfd_size_type) l->size, l->u.file.input_bfd) |
2482 |
!= l->size)) |
!= l->size)) |
2483 |
return false; |
return FALSE; |
2484 |
} |
} |
2485 |
total += l->size; |
total += l->size; |
2486 |
buff += l->size; |
buff += l->size; |
2487 |
} |
} |
2488 |
|
|
2489 |
return true; |
return TRUE; |
2490 |
} |
} |
2491 |
|
|
2492 |
/* Copy PDR information into a memory buffer. */ |
/* Copy PDR information into a memory buffer. */ |
2493 |
|
|
2494 |
boolean |
bfd_boolean |
2495 |
_bfd_ecoff_get_accumulated_pdr (handle, buff) |
_bfd_ecoff_get_accumulated_pdr (handle, buff) |
2496 |
PTR handle; |
PTR handle; |
2497 |
bfd_byte *buff; |
bfd_byte *buff; |
2503 |
|
|
2504 |
/* Copy symbol information into a memory buffer. */ |
/* Copy symbol information into a memory buffer. */ |
2505 |
|
|
2506 |
boolean |
bfd_boolean |
2507 |
_bfd_ecoff_get_accumulated_sym (handle, buff) |
_bfd_ecoff_get_accumulated_sym (handle, buff) |
2508 |
PTR handle; |
PTR handle; |
2509 |
bfd_byte *buff; |
bfd_byte *buff; |
2515 |
|
|
2516 |
/* Copy the string table into a memory buffer. */ |
/* Copy the string table into a memory buffer. */ |
2517 |
|
|
2518 |
boolean |
bfd_boolean |
2519 |
_bfd_ecoff_get_accumulated_ss (handle, buff) |
_bfd_ecoff_get_accumulated_ss (handle, buff) |
2520 |
PTR handle; |
PTR handle; |
2521 |
bfd_byte *buff; |
bfd_byte *buff; |
2542 |
buff += len + 1; |
buff += len + 1; |
2543 |
} |
} |
2544 |
|
|
2545 |
return true; |
return TRUE; |
2546 |
} |
} |