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));
/* 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;
*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 int i;
- unsigned int paddr = 0;
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
fragS *frag = segment_info[i].frchainP->frch_root;
char *buffer = malloc(s->s_size);
if (s->s_size != 0)
- {
s->s_scnptr = *file_cursor;
- s->s_paddr = paddr;
- s->s_vaddr = paddr;
-
- }
else
- {
s->s_scnptr = 0;
- s->s_paddr = 0;
- s->s_vaddr = 0;
-
- }
-
s->s_flags = STYP_REG;
if (strcmp(s->s_name,".text")==0)
while (frag) {
unsigned int fill_size;
switch (frag->fr_type) {
+ case rs_machine_dependent:
+ if(frag->fr_fix)
+ {
+ memcpy(buffer + frag->fr_address,
+ frag->fr_literal,
+ frag->fr_fix);
+ offset += frag->fr_fix;
+ }
+ break;
case rs_fill:
case rs_align:
case rs_org:
}
break;
+ case rs_broken_word:
+ break;
default:
abort();
}
free(buffer);
*file_cursor += s->s_size;
- paddr += s->s_size;
+
}
}
}
}
-
+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);
}
+#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
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 */
static void DEFUN_VOID(obj_coff_lcomm)
{
- char *name;
- char c;
- int temp;
- char *p;
- unsigned long vma;
+ char *name;
+ char c;
+ int temp;
+ char *p;
+ unsigned long vma;
- symbolS *symbolP;
- name = input_line_pointer;
+ 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;
- 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);
- vma = segment_info[SEG_E2].scnhdr.s_size;
- vma += relax_align(vma, MIN(8, temp));
- S_SET_VALUE(symbolP,vma);
- S_SET_SEGMENT(symbolP, SEG_E2);
- segment_info[SEG_E2].scnhdr.s_size = vma + temp;
- S_SET_STORAGE_CLASS(symbolP, C_STAT);
- demand_empty_rest_of_line();
+ {
+ /* 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 -*/