#include "../bfd/libbfd.h"
+#define MIN(a,b) ((a) < (b)? (a) : (b))
/* This vector is used to turn an internal segment into a section #
suitable for insertion into a coff symbol table
*/
static void EXFUN(fixup_segment,(fixS * fixP,
segT this_segment_type));
+
+static void EXFUN(fixup_mdeps,(fragS *));
+
+
static void EXFUN(fill_section,(bfd *abfd ,
struct internal_filehdr *f, unsigned
long *));
static void EXFUN( obj_coff_tag,(void));
static void EXFUN( obj_coff_type,(void));
static void EXFUN( obj_coff_val,(void));
-static void EXFUN( obj_coff_section,(void));
+void EXFUN( obj_coff_section,(void));
static void EXFUN( tag_init,(void));
static void EXFUN( tag_insert,(char *name, symbolS *symbolP));
{ "type", obj_coff_type, 0 },
{ "val", obj_coff_val, 0 },
{ "section", obj_coff_section, 0 },
+ { "use", obj_coff_section, 0 },
+ { "sect", obj_coff_section, 0 },
{ "text", obj_coff_text, 0 },
{ "data", obj_coff_data, 0 },
/* we don't yet handle this. */
/* calculate the size of the frag chain and fill in the section header
to contain all of it, also fill in the addr of the sections */
-static unsigned int DEFUN(size_section,(abfd, idx),
- bfd *abfd AND
- unsigned int idx)
+static unsigned int
+DEFUN(size_section,(abfd, idx),
+ bfd *abfd AND
+ unsigned int idx)
{
unsigned int size = 0;
fragS *frag = segment_info[idx].frchainP->frch_root;
while (frag) {
+ size = frag->fr_address;
+#if 0
if (frag->fr_address != size) {
printf("Out of step\n");
size = frag->fr_address;
}
- size += frag->fr_fix;
+
switch (frag->fr_type) {
+#ifdef TC_COFF_SIZEMACHDEP
+ case rs_machine_dependent:
+ size += TC_COFF_SIZEMACHDEP(frag);
+ break;
+#endif
case rs_fill:
case rs_org:
+ size += frag->fr_fix;
size += frag->fr_offset * frag->fr_var;
break;
case rs_align:
+ size += frag->fr_fix;
size += relax_align(size, frag->fr_offset);
}
+#endif
frag = frag->fr_next;
}
segment_info[idx].scnhdr.s_size = size;
{
unsigned int nrelocs;
unsigned int idx;
-
+ unsigned int addr = 0;
for (idx = SEG_E0; idx < SEG_E9; idx++)
{
if (segment_info[idx].scnhdr.s_name[0])
struct external_reloc *external_reloc_vec;
unsigned int external_reloc_size;
unsigned int count = 0;
- unsigned int base = segment_info[idx].scnhdr.s_paddr;
+ unsigned int base = addr;
fixS * fix_ptr = segment_info[idx].fix_root;
nrelocs = count_entries_in_chain(idx);
*file_cursor += external_reloc_size;
free( external_reloc_vec);
}
+#ifndef ZERO_BASED_SEGMENTS
+ /* Supposedly setting segment addresses non-zero causes problems
+ for some platforms, although it shouldn't. If you define
+ ZERO_BASED_SEGMENTS, all the segments will be based at 0.
+ Please don't make this the default, since some systems (e.g.,
+ SVR3.2) require the segments to be non-zero based. Ian Taylor
+ <ian@cygnus.com>. */
+ addr += segment_info[idx].scnhdr.s_size;
+#endif
}
}
unsigned long *file_cursor)
{
- unsigned int i;
- unsigned int paddr = 0;
+ unsigned int i;
- for (i = SEG_E0; i < SEG_UNKNOWN; i++)
- {
- unsigned int offset = 0;
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ unsigned int offset = 0;
- struct internal_scnhdr *s = &( segment_info[i].scnhdr);
+ struct internal_scnhdr *s = &( segment_info[i].scnhdr);
- if (s->s_name[0])
- {
- fragS *frag = segment_info[i].frchainP->frch_root;
- char *buffer = malloc(s->s_size);
- if (s->s_size != 0)
+ if (s->s_name[0])
+ {
+ fragS *frag = segment_info[i].frchainP->frch_root;
+ char *buffer = malloc(s->s_size);
+ if (s->s_size != 0)
+ s->s_scnptr = *file_cursor;
+ else
+ s->s_scnptr = 0;
+
+ s->s_flags = STYP_REG;
+ if (strcmp(s->s_name,".text")==0)
+ s->s_flags |= STYP_TEXT;
+ else if (strcmp(s->s_name,".data")==0)
+ s->s_flags |= STYP_DATA;
+ else if (strcmp(s->s_name,".bss")==0)
+ s->s_flags |= STYP_BSS | STYP_NOLOAD;
+ else if (strcmp(s->s_name,".lit")==0)
+ s->s_flags = STYP_LIT | STYP_TEXT;
+
+
+ while (frag) {
+ unsigned int fill_size;
+ switch (frag->fr_type) {
+ case rs_machine_dependent:
+ if(frag->fr_fix)
{
- s->s_scnptr = *file_cursor;
- s->s_paddr = paddr;
- s->s_vaddr = paddr;
-
+ memcpy(buffer + frag->fr_address,
+ frag->fr_literal,
+ frag->fr_fix);
+ offset += frag->fr_fix;
}
- else
- {
- s->s_scnptr = 0;
- s->s_paddr = 0;
- s->s_vaddr = 0;
+ break;
+ case rs_fill:
+ case rs_align:
+ case rs_org:
+ if(frag->fr_fix)
+ {
+ memcpy(buffer + frag->fr_address,
+ frag->fr_literal,
+ frag->fr_fix);
+ offset += frag->fr_fix;
}
-
-
- s->s_flags = STYP_REG;
- if (strcmp(s->s_name,".text")==0)
- s->s_flags |= STYP_TEXT;
- else if (strcmp(s->s_name,".data")==0)
- s->s_flags |= STYP_DATA;
- else if (strcmp(s->s_name,".bss")==0)
- s->s_flags |= STYP_BSS | STYP_NOLOAD;
-
- while (frag) {
- unsigned int fill_size;
- switch (frag->fr_type) {
-
- case rs_fill:
- case rs_align:
- case rs_org:
- if(frag->fr_fix)
- {
- memcpy(buffer + frag->fr_address,
- frag->fr_literal,
- frag->fr_fix);
- offset += frag->fr_fix;
- }
- fill_size = frag->fr_var;
- if (fill_size)
- {
- unsigned int count ;
- unsigned int off = frag->fr_fix;
- for (count = frag->fr_offset; count; count--)
- {
- memcpy(buffer + frag->fr_address + off,
- frag->fr_literal + frag->fr_fix,
- fill_size);
- off += fill_size;
- offset += fill_size;
+ fill_size = frag->fr_var;
+ if (fill_size)
+ {
+ unsigned int count ;
+ unsigned int off = frag->fr_fix;
+ for (count = frag->fr_offset; count; count--)
+ {
+ memcpy(buffer + frag->fr_address + off,
+ frag->fr_literal + frag->fr_fix,
+ fill_size);
+ off += fill_size;
+ offset += fill_size;
- }
-
- }
- break;
- default:
- abort();
- }
- frag = frag->fr_next;
}
+
+ }
+ break;
+ case rs_broken_word:
+ break;
+ default:
+ abort();
+ }
+ frag = frag->fr_next;
+ }
- bfd_write(buffer, s->s_size,1,abfd);
- free(buffer);
+ bfd_write(buffer, s->s_size,1,abfd);
+ free(buffer);
- *file_cursor += s->s_size;
- paddr += s->s_size;
- }
- }
+ *file_cursor += s->s_size;
+
+ }
+ }
}
case C_FCN:
S_SET_SEGMENT(def_symbol_in_progress, SEG_E0);
- if (def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][1] == 'b') { /* .bf */
+ if (def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][1] == 'b'
+ && def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][2] == 'f') { /* .bf */
if (function_lineoff < 0) {
fprintf(stderr, "`.bf' symbol without preceding function\n");
} /* missing function symbol */
}
}
-
+int machine;
+int coff_flags;
extern void DEFUN_VOID(write_object_file)
{
int i;
struct internal_aouthdr aouthdr;
unsigned long file_cursor;
bfd *abfd;
- unsigned int addr = 0;
+ unsigned int addr;
abfd = bfd_openw(out_file_name, TARGET_FORMAT);
exit(42);
}
bfd_set_format(abfd, bfd_object);
- bfd_set_arch_mach(abfd, BFD_ARCH, 0);
+ bfd_set_arch_mach(abfd, BFD_ARCH, machine);
{
relax_segment(segment_info[i].frchainP->frch_root, i);
}
-
-
-
-
filehdr.f_nscns = 0;
- /* Find out how big the sections are */
+ /* Find out how big the sections are, and set the addresses. */
+ addr = 0;
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
+ segment_info[i].scnhdr.s_paddr = addr;
+ segment_info[i].scnhdr.s_vaddr = addr;
if (segment_info[i].scnhdr.s_name[0])
{
filehdr.f_nscns++;
}
+#ifndef ZERO_BASED_SEGMENTS
+ /* See the comment at the previous ZERO_BASED_SEGMENTS check. */
if (i == SEG_E2)
{
- /* THis is a special case, we leave the size alone, which will have */
- /* been made up from all and any lcomms seen */
+ /* This is a special case, we leave the size alone, which
+ will have been made up from all and any lcomms seen. */
+ addr += segment_info[i].scnhdr.s_size;
}
- else {
- addr += size_section(abfd, i);
- }
+ else
+ {
+ addr += size_section(abfd, i);
+ }
+#endif
}
/* Turn the gas native symbol table shape into a coff symbol table */
crawl_symbols(&filehdr, abfd);
-#ifndef TC_H8300
+#if !defined(TC_H8300) && !defined(TC_Z8K)
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
- fixup_segment(segment_info[i].fix_root, i);
+ fixup_mdeps(segment_info[i].frchainP->frch_root);
+ fixup_segment(segment_info[i].fix_root, i);
}
#endif
fill_section(abfd,&filehdr, &file_cursor);
+
+
filehdr.f_magic = COFF_MAGIC;
filehdr.f_timdat = time(0);
- filehdr.f_flags = COFF_FLAGS ;
+ filehdr.f_flags = COFF_FLAGS | coff_flags;
if (!had_lineno)
{
}
coff_header_append(abfd, &filehdr, &aouthdr);
- bfd_close_all_done(abfd);
+ if (bfd_close_all_done(abfd) == false)
+ as_fatal ("Can't close %s: %s", out_file_name,
+ bfd_errmsg (bfd_error));
}
subseg_new(i, exp);
}
-static void
+void
DEFUN_VOID(obj_coff_section)
{
/* Strip out the section name */
if (line_number == 0)
{
-last_line_symbol = symbol;
+ last_line_symbol = symbol;
new_line->line.l_addr.l_symndx = (long)symbol;
}
else
{
s->lineno_list_tail->next = new_line;
}
- s->lineno_list_tail = new_line;
+ s->lineno_list_tail = new_line;
return LINESZ * s->scnhdr.s_nlnno ++;
}
static void DEFUN_VOID(obj_coff_lcomm)
{
- char *name;
- char c;
- int temp;
- char *p;
- symbolS *symbolP;
- name = input_line_pointer;
+ char *name;
+ char c;
+ int temp;
+ char *p;
+ unsigned long vma;
+ symbolS *symbolP;
+ name = input_line_pointer;
- c = get_symbol_end();
- p = input_line_pointer;
- *p = c;
- SKIP_WHITESPACE();
- if (*input_line_pointer != ',') {
- as_bad("Expected comma after name");
- ignore_rest_of_line();
- return;
- }
- if (*input_line_pointer == '\n') {
- as_bad("Missing size expression");
- return;
- }
- input_line_pointer++;
- if ((temp = get_absolute_expression ()) < 0) {
- as_warn("lcomm length (%d.) <0! Ignored.", temp);
- ignore_rest_of_line();
- return;
- }
- *p = 0;
- symbolP = symbol_find_or_make(name);
- S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
- S_SET_SEGMENT(symbolP, SEG_E2);
- segment_info[SEG_E2].scnhdr.s_size += temp;
- S_SET_STORAGE_CLASS(symbolP, C_STAT);
- demand_empty_rest_of_line();
+ c = get_symbol_end();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != ',') {
+ as_bad("Expected comma after name");
+ ignore_rest_of_line();
+ return;
+ }
+ if (*input_line_pointer == '\n') {
+ as_bad("Missing size expression");
+ return;
+ }
+ input_line_pointer++;
+ if ((temp = get_absolute_expression ()) < 0) {
+ as_warn("lcomm length (%d.) <0! Ignored.", temp);
+ ignore_rest_of_line();
+ return;
+ }
+ *p = 0;
+
+ {
+ /* Allocate zero static local data in the .data section now
+ instead of the bss section as a symbol with a value */
+ char *x;
+ segT oldseg = now_seg;
+ int oldsubseg = now_subseg;
+
+ subseg_new(SEG_DATA, 10);
+ colon(name);
+ frag_align(2,0);
+ record_alignment(SEG_DATA, 4);
+ x = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0,
+ temp, (char *)0);
+ * x= 0;
+
+ subseg_new(oldseg, oldsubseg);
+ }
+ demand_empty_rest_of_line();
}
+static void DEFUN(fixup_mdeps,(frags),
+ fragS *frags)
+{
+ while (frags)
+ {
+ switch (frags->fr_type)
+ {
+ case rs_align:
+ case rs_org:
+ frags->fr_type = rs_fill;
+ frags->fr_offset =
+ (frags->fr_next->fr_address - frags->fr_address - frags->fr_fix);
+ break;
+ case rs_machine_dependent:
+ md_convert_frag(0, frags);
+ break;
+ default:
+ ;
+ }
+ frags = frags->fr_next;
+ }
+}
#if 1
static void DEFUN(fixup_segment,(fixP, this_segment_type),
register fixS * fixP AND
} /* not absolute */
add_number -= S_GET_VALUE(sub_symbolP);
+ fixP->fx_subsy = 0;
/* if sub_symbol is in the same segment that add_symbol
and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
continue;
} /* COBR */
#endif /* TC_I960 */
-
-
-
+#ifdef TC_I386
+ /* 386 COFF uses a peculiar format in
+ which the value of a common symbol is
+ stored in the .text segment (I've
+ checked this on SVR3.2 and SCO 3.2.2)
+ Ian Taylor <ian@cygnus.com>. */
+ add_number += S_GET_VALUE(add_symbolP);
+#endif
break;
if (!fixP->fx_bit_fixP) {
if ((size==1 &&
- (add_number& ~0xFF) && (add_number&~0xFF!=(-1&~0xFF))) ||
+ (add_number& ~0xFF) && ((add_number&~0xFF)!=(-1&~0xFF))) ||
(size==2 &&
- (add_number& ~0xFFFF) && (add_number&~0xFFFF!=(-1&~0xFFFF)))) {
+ (add_number& ~0xFFFF) && ((add_number&~0xFFFF)!=(-1&~0xFFFF)))) {
as_bad("Value of %d too large for field of %d bytes at 0x%x",
add_number, size, fragP->fr_address + where);
} /* generic error checking */
+#ifdef WARN_SIGNED_OVERFLOW_WORD
+ /* Warn if a .word value is too large when treated as
+ a signed number. We already know it is not too
+ negative. This is to catch over-large switches
+ generated by gcc on the 68k. */
+ if (! flagseen['J']
+ && size == 2
+ && add_number > 0x7fff)
+ as_bad ("Signed .word overflow; switch may be too large; %d at 0x%x",
+ add_number, fragP->fr_address + where);
+#endif
} /* not a bit fix */
/* once this fix has been applied, we don't have to output anything
nothing more need be done -*/