aboutsummaryrefslogtreecommitdiff
path: root/bfd/coffcode.h
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/coffcode.h')
-rw-r--r--bfd/coffcode.h273
1 files changed, 230 insertions, 43 deletions
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 6c7eea9..cdb94eb 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -22,6 +22,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
Most of this hacked by Steve Chamberlain,
sac@cygnus.com
*/
+
+#include <assert.h>
+#include <stdio.h>
+
/*
SECTION
@@ -377,23 +381,34 @@ static flagword
DEFUN(styp_to_sec_flags, (styp_flags),
long styp_flags)
{
- flagword sec_flags=0;
-
- if ((styp_flags & STYP_TEXT) || (styp_flags & STYP_DATA))
- sec_flags = (SEC_LOAD | SEC_ALLOC);
- else if (styp_flags & STYP_BSS)
- sec_flags = SEC_ALLOC;
+ flagword sec_flags=0;
-#ifdef STYP_LIT /* A29k readonly text/data section type */
- if ((styp_flags & STYP_LIT) == STYP_LIT)
- sec_flags = (SEC_LOAD | SEC_ALLOC | SEC_READONLY);
-#endif /* STYP_LIT */
-#ifdef STYP_OTHER_LOAD /* Other loaded sections */
- if (styp_flags & STYP_OTHER_LOAD)
- sec_flags = (SEC_LOAD | SEC_ALLOC);
-#endif /* STYP_SDATA */
+ if ((styp_flags & STYP_TEXT) || (styp_flags & STYP_DATA))
+ {
+ sec_flags = SEC_LOAD | SEC_ALLOC;
+ }
+ else if (styp_flags & STYP_BSS)
+ {
+ sec_flags = SEC_ALLOC;
+ }
+ else
+ {
+ sec_flags = SEC_ALLOC | SEC_LOAD;
+ }
+#ifdef STYP_LIT /* A29k readonly text/data section type */
+ if ((styp_flags & STYP_LIT) == STYP_LIT)
+ {
+ sec_flags = (SEC_LOAD | SEC_ALLOC | SEC_READONLY);
+ }
+#endif /* STYP_LIT */
+#ifdef STYP_OTHER_LOAD /* Other loaded sections */
+ if (styp_flags & STYP_OTHER_LOAD)
+ {
+ sec_flags = (SEC_LOAD | SEC_ALLOC);
+ }
+#endif /* STYP_SDATA */
- return(sec_flags);
+ return(sec_flags);
}
#define get_index(symbol) ((int) (symbol)->udata)
@@ -884,27 +899,22 @@ DEFUN(coff_swap_scnhdr_out,(abfd, in, out),
*/
static boolean
-DEFUN(coff_new_section_hook,(abfd_ignore, section),
- bfd *abfd_ignore AND
+DEFUN(coff_new_section_hook,(abfd, section),
+ bfd *abfd AND
asection *section)
{
- section->alignment_power = abfd_ignore->xvec->align_power_min;
+ section->alignment_power = abfd->xvec->align_power_min;
+ /* Allocate aux records for section symbols, to store size and
+ related info.
+
+ @@ Shouldn't use constant multiplier here! */
+ coffsymbol (section->symbol)->native =
+ (combined_entry_type *) bfd_zalloc (abfd,
+ sizeof (combined_entry_type) * 10);
return true;
}
-static asection bfd_debug_section =
-{ "*DEBUG*" };
-
-
-
-static void
-DEFUN(make_abs_section,(abfd),
- bfd *abfd)
-{
-
-
-
-}
+static asection bfd_debug_section = { "*DEBUG*" };
/* Take a section header read from a coff file (in HOST byte order),
and make a BFD "section" out of it. */
@@ -1336,6 +1346,30 @@ DEFUN(coff_renumber_symbols,(bfd_ptr),
unsigned int native_index = 0;
struct internal_syment *last_file = (struct internal_syment *)NULL;
unsigned int symbol_index;
+
+ /* COFF demands that undefined symbols come after all other symbols.
+ Since we don't need to impose this extra knowledge on all our client
+ programs, deal with that here. Sort the symbol table; just move the
+ undefined symbols to the end, leaving the rest alone. */
+ /* @@ Do we have some condition we could test for, so we don't always
+ have to do this? I don't think relocatability is quite right, but
+ I'm not certain. [raeburn:19920508.1711EST] */
+ {
+ asymbol **newsyms;
+ int i;
+
+ newsyms = (asymbol **) bfd_alloc_by_size_t (bfd_ptr,
+ sizeof (asymbol *) * symbol_count);
+ bfd_ptr->outsymbols = newsyms;
+ for (i = 0; i < symbol_count; i++)
+ if (symbol_ptr_ptr[i]->section != &bfd_und_section)
+ *newsyms++ = symbol_ptr_ptr[i];
+ for (i = 0; i < symbol_count; i++)
+ if (symbol_ptr_ptr[i]->section == &bfd_und_section)
+ *newsyms++ = symbol_ptr_ptr[i];
+ symbol_ptr_ptr = bfd_ptr->outsymbols;
+ }
+
for (symbol_index = 0; symbol_index < symbol_count; symbol_index++)
{
coff_symbol_type *coff_symbol_ptr = coff_symbol_from(bfd_ptr, symbol_ptr_ptr[symbol_index]);
@@ -1365,6 +1399,7 @@ DEFUN(coff_renumber_symbols,(bfd_ptr),
native_index++;
}
}
+ obj_conv_table_size (bfd_ptr) = native_index;
}
@@ -1475,6 +1510,12 @@ unsigned int written)
int class = native->u.syment.n_sclass;
SYMENT buf;
unsigned int j;
+
+ /* @@ bfd_debug_section isn't accessible outside this file, but we know
+ that C_FILE symbols belong there. So move them. */
+ if (native->u.syment.n_sclass == C_FILE)
+ symbol->section = &bfd_debug_section;
+
if (symbol->section == &bfd_abs_section)
{
native->u.syment.n_scnum = N_ABS;
@@ -1588,7 +1629,7 @@ coff_symbol_type *symbol AND
unsigned int written)
{
/*
- Does this symbol have an ascociated line number - if so then
+ Does this symbol have an associated line number - if so then
make it remember this symbol index. Also tag the auxent of
this symbol to point to the right place in the lineno table
*/
@@ -1748,9 +1789,20 @@ DEFUN(coff_write_relocs,(abfd),
struct internal_reloc n;
arelent *q = p[i];
memset((PTR)&n, 0, sizeof(n));
+
+ /* @@FIXME COFF relocs don't support addends. Code should probably be
+ in the target-independent code, using a target flag to decide whether
+ to fold the addend into the section contents. */
+ if (q->addend != 0)
+ abort ();
+
n.r_vaddr = q->address + s->vma;
if (q->sym_ptr_ptr) {
n.r_symndx = get_index((*(q->sym_ptr_ptr)));
+ /* Take notice if the symbol reloc points to a symbol we don't have
+ in our symbol table. What should we do for this?? */
+ if (n.r_symndx > obj_conv_table_size (abfd))
+ abort ();
}
#ifdef SELECT_RELOC
/* Work out reloc type from what is required */
@@ -1823,6 +1875,7 @@ bfd *abfd;
bfd_error = no_memory;
return (NULL);
} /* on error */
+ new->symbol.section = 0;
new->native = 0;
new->lineno = (alent *) NULL;
new->done_lineno = false;
@@ -1832,6 +1885,26 @@ bfd *abfd;
#ifndef NO_COFF_SYMBOLS
+static asymbol *
+DEFUN (coff_make_debug_symbol, (abfd, ptr, sz),
+ bfd *abfd AND
+ PTR ptr AND
+ unsigned long sz)
+{
+ coff_symbol_type *new = (coff_symbol_type *) bfd_alloc(abfd, sizeof(coff_symbol_type));
+ if (new == NULL) {
+ bfd_error = no_memory;
+ return (NULL);
+ } /* on error */
+ /* @@ This shouldn't be using a constant multiplier. */
+ new->native = (combined_entry_type *) bfd_zalloc (abfd, sizeof (combined_entry_type) * 10);
+ new->symbol.section = &bfd_debug_section;
+ new->lineno = (alent *) NULL;
+ new->done_lineno = false;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
static void
DEFUN(coff_print_symbol,(ignore_abfd, filep, symbol, how),
bfd *ignore_abfd AND
@@ -2128,8 +2201,115 @@ DEFUN(coff_compute_section_file_positions,(abfd),
obj_relocbase(abfd) = sofar;
}
+#ifndef NO_COFF_SYMBOLS
+static asymbol *
+coff_section_symbol (abfd, name)
+ bfd *abfd;
+ char *name;
+{
+ asection *sec = bfd_get_section_by_name (abfd, name);
+ asymbol *sym;
+ combined_entry_type *csym;
+
+ if (!sec)
+ {
+ /* create empty symbol */
+ abort ();
+ }
+ sym = sec->symbol;
+ if (coff_symbol_from (abfd, sym))
+ csym = coff_symbol_from (abfd, sym)->native;
+ else
+ csym = 0;
+ /* Make sure back-end COFF stuff is there. */
+ if (csym == 0)
+ {
+ struct foo {
+ coff_symbol_type sym;
+ /* @@FIXME This shouldn't use a fixed size!! */
+ combined_entry_type e[10];
+ };
+ struct foo *f;
+ f = (struct foo *) bfd_alloc_by_size_t (abfd, sizeof (*f));
+ bzero ((char *) f, sizeof (*f));
+ coff_symbol_from (abfd, sym)->native = csym = f->e;
+ }
+ csym[0].u.syment.n_sclass = C_STAT;
+ csym[0].u.syment.n_numaux = 1;
+/* SF_SET_STATICS (sym); @@ ??? */
+ if (sec)
+ {
+ csym[1].u.auxent.x_scn.x_scnlen = sec->_raw_size;
+ csym[1].u.auxent.x_scn.x_nreloc = sec->reloc_count;
+ csym[1].u.auxent.x_scn.x_nlinno = sec->lineno_count;
+ }
+ else
+ {
+ csym[1].u.auxent.x_scn.x_scnlen = 0;
+ csym[1].u.auxent.x_scn.x_nreloc = 0;
+ csym[1].u.auxent.x_scn.x_nlinno = 0;
+ }
+ return sym;
+}
+/* If .file, .text, .data, .bss symbols are missing, add them. */
+/* @@ Should we only be adding missing symbols, or overriding the aux
+ values for existing section symbols? */
+static void
+coff_add_missing_symbols (abfd)
+ bfd *abfd;
+{
+ unsigned int nsyms = bfd_get_symcount (abfd);
+ asymbol **sympp = abfd->outsymbols;
+ asymbol **sympp2;
+ unsigned int i;
+ int need_text = 1, need_data = 1, need_bss = 1, need_file = 1;
+ coff_data_type *cdata = coff_data (abfd);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ coff_symbol_type *csym = coff_symbol_from (abfd, sympp[i]);
+ CONST char *name;
+ if (csym->native->u.syment.n_sclass == C_FILE)
+ {
+ need_file = 0;
+ continue;
+ }
+ name = csym->symbol.name;
+ if (!name)
+ continue;
+ if (!strcmp (name, _TEXT))
+ need_text = 0;
+ else if (!strcmp (name, _DATA))
+ need_data = 0;
+ else if (!strcmp (name, _BSS))
+ need_bss = 0;
+ }
+ /* Now i == bfd_get_symcount (abfd). */
+ /* @@ For now, don't deal with .file symbol. */
+ need_file = 0;
+
+ if (!need_text && !need_data && !need_bss && !need_file)
+ return;
+ nsyms += need_text + need_data + need_bss + need_file;
+ sympp2 = (asymbol**) bfd_alloc_by_size_t (abfd, nsyms * sizeof (asymbol *));
+ memcpy (sympp2, sympp, i * sizeof (asymbol *));
+ if (need_file)
+ {
+ /* @@ Generate fake .file symbol, in sympp2[i], and increment i. */
+ abort ();
+ }
+ if (need_text)
+ sympp2[i++] = coff_section_symbol (abfd, _TEXT);
+ if (need_data)
+ sympp2[i++] = coff_section_symbol (abfd, _DATA);
+ if (need_bss)
+ sympp2[i++] = coff_section_symbol (abfd, _BSS);
+ assert (i == nsyms);
+ bfd_set_symtab (abfd, sympp2, nsyms);
+}
+#endif /* NO_COFF_SYMBOLS */
/* SUPPRESS 558 */
/* SUPPRESS 529 */
@@ -2159,12 +2339,15 @@ DEFUN(coff_write_object_contents,(abfd),
bfd_error = system_call_error;
/* Number the output sections, starting from one on the first section
- with a name which doesn't start with a * */
+ with a name which doesn't start with a *.
+ @@ The code doesn't make this check. Is it supposed to be done,
+ or isn't it?? */
count = 1;
for (current = abfd->sections; current != (asection *)NULL;
current = current->next)
{
current->target_index = count;
+ count++;
}
@@ -2424,6 +2607,7 @@ DEFUN(coff_write_object_contents,(abfd),
#ifndef NO_COFF_SYMBOLS
if (bfd_get_symcount(abfd) != 0) {
+ coff_add_missing_symbols (abfd);
coff_renumber_symbols(abfd);
coff_mangle_symbols(abfd);
coff_write_symbols(abfd);
@@ -3149,6 +3333,7 @@ DEFUN(coff_slurp_symbol_table,(abfd),
obj_symbols(abfd) = cached_area;
obj_raw_syments(abfd) = native_symbols;
+ obj_conv_table_size (abfd) = bfd_get_symcount (abfd);
bfd_get_symcount(abfd) = number_of_symbols;
obj_convert(abfd) = table_ptr;
/* Slurp the line tables for each section too */
@@ -3324,16 +3509,18 @@ DEFUN(coff_slurp_reloc_table,(abfd, asect, symbols),
cache_ptr->address = dst.r_vaddr;
if (dst.r_symndx != -1)
- {
+ {
+ /* @@ Should never be greater than count of symbols! */
+ if (dst.r_symndx >= obj_conv_table_size (abfd))
+ abort ();
cache_ptr->sym_ptr_ptr = symbols + obj_convert(abfd)[dst.r_symndx];
ptr = *(cache_ptr->sym_ptr_ptr);
- }
+ }
else
- {
- cache_ptr->sym_ptr_ptr= bfd_abs_section.symbol_ptr_ptr;
- ptr = 0;
-
- }
+ {
+ cache_ptr->sym_ptr_ptr= bfd_abs_section.symbol_ptr_ptr;
+ ptr = 0;
+ }
/*
The symbols definitions that we have read in have been
@@ -3723,15 +3910,15 @@ DEFUN(bfd_coff_relax_section,(abfd, i, symbols),
}
static bfd_byte *
-DEFUN(bfd_coff_get_relocated_section_contents,(in_abfd, seclet),
+DEFUN(bfd_coff_get_relocated_section_contents,(in_abfd, seclet, data),
bfd *in_abfd AND
- bfd_seclet_type *seclet)
+ bfd_seclet_type *seclet AND
+ bfd_byte *data)
{
/* Get enough memory to hold the stuff */
bfd *input_bfd = seclet->u.indirect.section->owner;
asection *input_section = seclet->u.indirect.section;
- bfd_byte *data = (bfd_byte *)malloc(input_section->_raw_size);
bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd,
input_section);
arelent **reloc_vector = (arelent **)bfd_xmalloc(reloc_size);