*/
-#ifndef IMAGE_BASE
-#define IMAGE_BASE 0
+#ifdef COFF_IMAGE_WITH_PE
+#include "peicode.h"
+#else
+#include "coffswap.h"
#endif
-
-static bfd_vma
-pe_value(ptr, def)
- bfd_link_pe_info_dval *ptr;
- bfd_vma def;
-{
- if (ptr && ptr->defined)
- return ptr->value;
- return def;
-}
-
-
-#include "coffswap.h"
\f
/* void warning(); */
#endif /* ! I960 */
+#ifndef coff_mkobject
static boolean
coff_mkobject (abfd)
bfd * abfd;
coff->relocbase = 0;
/* make_abs_section(abfd);*/
-#ifdef COFF_WITH_PE
- obj_pe (abfd) = 1;
-#endif
return true;
}
+#endif
/* Create the COFF backend specific information. */
-
+#ifndef coff_mkobject_hook
static PTR
coff_mkobject_hook (abfd, filehdr, aouthdr)
bfd * abfd;
return (PTR) coff;
}
+#endif
/* Determine the machine architecture and type. FIXME: This is target
dependent because the magic numbers are defined in the target
int page_size;
if (coff_data (abfd)->link_info)
{
- page_size = pe_value (&(coff_data (abfd)->link_info->pe_info->file_alignment),
- PE_DEF_FILE_ALIGNMENT);
+ page_size = pe_data (abfd)->pe_opthdr.FileAlignment;
}
else
page_size = PE_DEF_FILE_ALIGNMENT;
&& (current->flags & SEC_ALLOC) != 0)
sofar += (current->vma - sofar) % page_size;
#endif
-
current->filepos = sofar;
+#ifdef COFF_IMAGE_WITH_PE
+ /* With PE we have to pad each section to be a multiple of its page size
+ too, and remember both sizes. Cooked_size becomes very useful. */
+ current->_cooked_size = current->_raw_size;
+ current->_raw_size = (current->_raw_size + page_size -1) & -page_size;
+#endif
+
sofar += current->_raw_size;
+
#ifndef I960
/* make sure that this section is of the right size too */
old_sofar = sofar;
previous = current;
}
-#ifdef COFF_IMAGE_WITH_PE
- /* Normally, the starting location for the symbol table will be at the end
- of the last section. However, when dealing with NT, the last section
- must be as long as its size rounded up to the next page (0x1000). */
- sofar = (sofar + page_size - 1) & -page_size;
-
- if (previous)
- previous->_raw_size = (previous->_raw_size + page_size -1) & -page_size;
-#endif
obj_relocbase (abfd) = sofar;
abfd->output_has_begun = true;
#endif /* ! defined (RS6000COFF_C) */
-#ifdef COFF_WITH_PE
-static void add_data_entry (abfd, aout, idx, name, base)
- bfd *abfd;
- struct internal_aouthdr *aout;
- int idx;
- char *name;
- bfd_vma base;
-{
- asection *sec = bfd_get_section_by_name (abfd, name);
-
- /* add import directory information if it exists */
- if (sec != NULL)
- {
- aout->pe->DataDirectory[idx].VirtualAddress = sec->lma - base;
- aout->pe->DataDirectory[idx].Size = sec->_raw_size;
- sec->flags |= SEC_DATA;
- }
-}
-
-
-static void
-fill_pe_header_info (abfd, internal_f, internal_a)
- bfd *abfd;
- struct internal_filehdr *internal_f;
- struct internal_aouthdr *internal_a;
-{
- /* assign other filehdr fields for DOS header and NT signature */
-
- int sa;
- int fa;
- bfd_vma ib;
- bfd_link_pe_info *pe_info = coff_data (abfd)->link_info->pe_info;
-
- internal_f->f_timdat = time (0);
-
- if (pe_value (&pe_info->dll, 0))
- internal_f->f_flags |= F_DLL ;
-
-
- if (bfd_get_section_by_name (abfd, ".reloc"))
- internal_f->f_flags &= ~F_RELFLG;
-
-
- memset (internal_f->pe, 0, sizeof (struct internal_extra_pe_filehdr));
- memset (internal_a->pe, 0, sizeof (struct internal_extra_pe_aouthdr));
-
-
- ib = internal_a->pe->ImageBase = pe_value (&pe_info->image_base, NT_EXE_IMAGE_BASE);
-
- if (internal_a->tsize)
- internal_a->text_start -= ib;
- if (internal_a->dsize)
- internal_a->data_start -= ib;
- if (internal_a->entry)
- internal_a->entry -= ib;
-
-
- sa = internal_a->pe->SectionAlignment = pe_value (&pe_info->section_alignment,
- NT_SECTION_ALIGNMENT);
-
- fa = internal_a->pe->FileAlignment = pe_value (&pe_info->file_alignment,
- NT_FILE_ALIGNMENT);
-
-#define FA(x) (((x) + fa -1 ) & (- fa))
-#define SA(x) (((x) + sa -1 ) & (- sa))
-
- /* We like to have the sizes aligned */
-
- internal_a->bsize = FA (internal_a->bsize);
-
- internal_f->pe->e_magic = DOSMAGIC;
- internal_f->pe->e_cblp = 0x90;
- internal_f->pe->e_cp = 0x3;
- internal_f->pe->e_crlc = 0x0;
- internal_f->pe->e_cparhdr = 0x4;
- internal_f->pe->e_minalloc = 0x0;
- internal_f->pe->e_maxalloc = 0xffff;
- internal_f->pe->e_ss = 0x0;
- internal_f->pe->e_sp = 0xb8;
- internal_f->pe->e_csum = 0x0;
- internal_f->pe->e_ip = 0x0;
- internal_f->pe->e_cs = 0x0;
- internal_f->pe->e_lfarlc = 0x40;
- internal_f->pe->e_ovno = 0x0;
- {
- int idx;
- for (idx=0; idx < 4; idx++)
- internal_f->pe->e_res[idx] = 0x0;
- }
- internal_f->pe->e_oemid = 0x0;
- internal_f->pe->e_oeminfo = 0x0;
- {
- int idx;
- for (idx=0; idx < 10; idx++)
- internal_f->pe->e_res2[idx] = 0x0;
- }
- internal_f->pe->e_lfanew = 0x80;
-
- /* this next collection of data are mostly just characters. It appears
- to be constant within the headers put on NT exes */
- internal_f->pe->dos_message[0] = 0x0eba1f0e;
- internal_f->pe->dos_message[1] = 0xcd09b400;
- internal_f->pe->dos_message[2] = 0x4c01b821;
- internal_f->pe->dos_message[3] = 0x685421cd;
- internal_f->pe->dos_message[4] = 0x70207369;
- internal_f->pe->dos_message[5] = 0x72676f72;
- internal_f->pe->dos_message[6] = 0x63206d61;
- internal_f->pe->dos_message[7] = 0x6f6e6e61;
- internal_f->pe->dos_message[8] = 0x65622074;
- internal_f->pe->dos_message[9] = 0x6e757220;
- internal_f->pe->dos_message[10] = 0x206e6920;
- internal_f->pe->dos_message[11] = 0x20534f44;
- internal_f->pe->dos_message[12] = 0x65646f6d;
- internal_f->pe->dos_message[13] = 0x0a0d0d2e;
- internal_f->pe->dos_message[14] = 0x24;
- internal_f->pe->dos_message[15] = 0x0;
- internal_f->pe->nt_signature = NT_SIGNATURE;
-
-
- /* write all of the other optional header data */
-
- internal_a->pe->MajorOperatingSystemVersion =
- pe_value (&pe_info->major_os_version, 1);
-
- internal_a->pe->MinorOperatingSystemVersion =
- pe_value (&pe_info->minor_os_version, 0);
-
- internal_a->pe->MajorImageVersion =
- pe_value (&pe_info->major_image_version, 1);
-
- internal_a->pe->MinorImageVersion =
- pe_value (&pe_info->minor_image_version, 0);
-
-
- internal_a->pe->MajorSubsystemVersion =
- pe_value (&pe_info->major_subsystem_version, 3);
-
-
- internal_a->pe->MinorSubsystemVersion =
- pe_value (&pe_info->minor_subsystem_version, 10);
-
- internal_a->pe->Subsystem =
- pe_value (&pe_info->subsystem, BFD_PE_CONSOLE);
- /* Virtual start address, take virtual start address of last section,
- add its physical size and round up the next page (NT_SECTION_ALIGNMENT).
- An assumption has been made that the sections stored in the abfd
- structure are in order and that I have successfully saved the last
- section's address and size. */
-
- /* The headers go up to where the first section starts. */
-
- internal_a->pe->SizeOfHeaders = abfd->sections->filepos;
- internal_a->pe->CheckSum = 0;
- internal_a->pe->DllCharacteristics = 0;
-
- internal_a->pe->SizeOfStackReserve = pe_value (&pe_info->stack_reserve,
- NT_DEF_RESERVE);
- internal_a->pe->SizeOfStackCommit = pe_value (&pe_info->stack_commit,
- NT_DEF_COMMIT);
-
- internal_a->pe->SizeOfHeapReserve = pe_value (&pe_info->heap_reserve,
- NT_DEF_RESERVE);
- internal_a->pe->SizeOfHeapCommit = pe_value (&pe_info->heap_commit,
- NT_DEF_COMMIT);
-
- internal_a->pe->LoaderFlags = 0;
- internal_a->pe->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; /* 0x10 */
-
- /* first null out all data directory entries .. */
- memset (internal_a->pe->DataDirectory, sizeof (internal_a->pe->DataDirectory), 0);
-
- add_data_entry (abfd, internal_a, 0, ".edata", ib);
- add_data_entry (abfd, internal_a, 1, ".idata", ib);
- add_data_entry (abfd, internal_a, 2, ".rsrc" ,ib);
- add_data_entry (abfd, internal_a, 5, ".reloc", ib);
- {
- asection *sec;
- bfd_vma dsize= 0;
- bfd_vma isize = SA(abfd->sections->filepos);
- bfd_vma tsize= 0;
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- int rounded = FA(sec->_raw_size);
- if (sec->flags & SEC_DATA)
- dsize += rounded;
- if (sec->flags & SEC_CODE)
- tsize += rounded;
- isize += SA(rounded);
- }
-
- internal_a->dsize = dsize;
- internal_a->tsize = tsize;
- internal_a->pe->SizeOfImage = isize;
- }
-
-}
-#endif
/* SUPPRESS 558 */
/* SUPPRESS 529 */
struct internal_filehdr internal_f;
struct internal_aouthdr internal_a;
-#ifdef COFF_IMAGE_WITH_PE
- struct internal_extra_pe_aouthdr extra_a;
- struct internal_extra_pe_filehdr extra_f;
- bfd_link_pe_info defs;
- struct bfd_link_info dummy_info;
- struct bfd_link_info *info ;
- struct bfd_link_pe_info *pe_info;
-
- if (coff_data (abfd)->link_info)
- info =coff_data (abfd)->link_info;
- else
- {
- coff_data (abfd)->link_info = info = &dummy_info;
- info->pe_info = 0;
- }
- pe_info = (struct bfd_link_pe_info *)(info->pe_info);
-
- if (!pe_info)
- {
- /* Just use sensible defaults */
- memset (&defs, 0, sizeof (defs));
- coff_data (abfd)->link_info->pe_info = &defs;
- }
-#endif
-
bfd_set_error (bfd_error_system_call);
if (abfd->output_has_begun == false)
{
continue;
}
+
+ /* If we've got a .reloc section, remember. */
+
+ if (strcmp (current->name, ".reloc") == 0)
+ {
+ pe_data (abfd)->has_reloc_section = 1;
+ }
#endif
internal_f.f_nscns++;
strncpy (&(section.s_name[0]), current->name, 8);
section.s_vaddr = 0;
else
#endif
- section.s_vaddr = current->lma;
+ section.s_vaddr = current->lma;
section.s_paddr = current->lma;
- section.s_size = current->_raw_size;
+ section.s_size = current->_raw_size;
+
+#ifdef COFF_WITH_PE
+ section.s_paddr = current->_cooked_size;
+#endif
/*
If this section has no size or is unloadable then the scnptr
internal_a.entry = bfd_get_start_address (abfd);
internal_f.f_nsyms = obj_raw_syment_count (abfd);
-
-
-#ifdef COFF_IMAGE_WITH_PE
-
- internal_f.pe = & extra_f;
- internal_a.pe = & extra_a;
-
- fill_pe_header_info (abfd, &internal_f, &internal_a);
-#endif
-
/* now write them */
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
return false;
#define coff_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
#define coff_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
+#ifndef coff_bfd_print_private_bfd_data
+#define coff_bfd_print_private_bfd_data \
+ _bfd_generic_bfd_print_private_bfd_data
+#endif
+
#ifndef coff_bfd_is_local_label
#define coff_bfd_is_local_label bfd_generic_is_local_label
#endif
/* BFD COFF object file private structure.
- Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfdlink.h"
#define coff_data(bfd) ((bfd)->tdata.coff_obj_data)
#define exec_hdr(bfd) (coff_data(bfd)->hdr)
+#define obj_pe(bfd) (coff_data(bfd)->pe)
#define obj_symbols(bfd) (coff_data(bfd)->symbols)
#define obj_sym_filepos(bfd) (coff_data(bfd)->sym_filepos)
#define obj_conv_table_size(bfd) (coff_data(bfd)->conv_table_size)
#define obj_coff_external_syms(bfd) (coff_data (bfd)->external_syms)
+#define obj_coff_keep_syms(bfd) (coff_data (bfd)->keep_syms)
#define obj_coff_strings(bfd) (coff_data (bfd)->strings)
+#define obj_coff_keep_strings(bfd) (coff_data (bfd)->keep_strings)
#define obj_coff_sym_hashes(bfd) (coff_data (bfd)->sym_hashes)
/* `Tdata' information kept for COFF files. */
unsigned local_auxesz;
unsigned local_linesz;
- /* Used by the COFF backend linker. */
+ /* The unswapped external symbols. May be NULL. Read by
+ _bfd_coff_get_external_symbols. */
PTR external_syms;
+ /* If this is true, the external_syms may not be freed. */
+ boolean keep_syms;
+
+ /* The string table. May be NULL. Read by
+ _bfd_coff_read_string_table. */
char *strings;
+ /* If this is true, the strings may not be freed. */
+ boolean keep_strings;
+
+ /* is this a PE format coff file */
+ int pe;
+ /* Used by the COFF backend linker. */
struct coff_link_hash_entry **sym_hashes;
+
+ struct bfd_link_info *link_info;
} coff_data_type;
+/* Tdata for pe image files. */
+typedef struct pe_tdata
+{
+ coff_data_type coff;
+ struct internal_extra_pe_aouthdr pe_opthdr;
+ int dll;
+ int has_reloc_section;
+} pe_data_type;
+
+#define pe_data(bfd) ((bfd)->tdata.pe_obj_data)
+
+
/* We take the address of the first element of a asymbol to ensure that the
* macro is only ever applied to an asymbol. */
#define coffsymbol(asymbol) ((coff_symbol_type *)(&((asymbol)->the_bfd)))
+/* The used_by_bfd field of a section may be set to a pointer to this
+ structure. */
+
+struct coff_section_tdata
+{
+ /* The relocs, swapped into COFF internal form. This may be NULL. */
+ struct internal_reloc *relocs;
+ /* If this is true, the relocs entry may not be freed. */
+ boolean keep_relocs;
+ /* The section contents. This may be NULL. */
+ bfd_byte *contents;
+ /* If this is true, the contents entry may not be freed. */
+ boolean keep_contents;
+};
+
+/* An accessor macro for the coff_section_tdata structure. */
+#define coff_section_data(abfd, sec) \
+ ((struct coff_section_tdata *) (sec)->used_by_bfd)
+
/* COFF linker hash table entries. */
struct coff_link_hash_entry
extern long coff_get_symtab PARAMS ((bfd *, asymbol **));
extern int coff_count_linenumbers PARAMS ((bfd *));
extern struct coff_symbol_struct *coff_symbol_from PARAMS ((bfd *, asymbol *));
-extern boolean coff_renumber_symbols PARAMS ((bfd *));
+extern boolean coff_renumber_symbols PARAMS ((bfd *, int *));
extern void coff_mangle_symbols PARAMS ((bfd *));
extern boolean coff_write_symbols PARAMS ((bfd *));
extern boolean coff_write_linenumbers PARAMS ((bfd *));
extern alent *coff_get_lineno PARAMS ((bfd *, asymbol *));
extern asymbol *coff_section_symbol PARAMS ((bfd *, char *));
+extern boolean _bfd_coff_get_external_symbols PARAMS ((bfd *));
+extern const char *_bfd_coff_read_string_table PARAMS ((bfd *));
+extern boolean _bfd_coff_free_symbols PARAMS ((bfd *));
extern struct coff_ptr_struct *coff_get_normalized_symtab PARAMS ((bfd *));
extern long coff_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
extern asymbol *coff_make_empty_symbol PARAMS ((bfd *));
PARAMS ((bfd *, struct bfd_link_info *));
extern boolean _bfd_coff_final_link
PARAMS ((bfd *, struct bfd_link_info *));
+extern struct internal_reloc *_bfd_coff_read_internal_relocs
+ PARAMS ((bfd *, asection *, boolean, bfd_byte *, boolean,
+ struct internal_reloc *));
+extern boolean _bfd_coff_generic_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ struct internal_reloc *, struct internal_syment *, asection **));
/* And more taken from the source .. */
PTR in;
PTR out;
{
+ int idx;
struct internal_filehdr *filehdr_in = (struct internal_filehdr *)in;
FILHDR *filehdr_out = (FILHDR *)out;
- if (bfd_get_section_by_name (abfd, ".reloc"))
+ if (pe_data (abfd)->has_reloc_section)
filehdr_in->f_flags &= ~F_RELFLG;
if (pe_data (abfd)->dll)
filehdr_in->pe.e_cs = 0x0;
filehdr_in->pe.e_lfarlc = 0x40;
filehdr_in->pe.e_ovno = 0x0;
- {
- int idx;
- for (idx=0; idx < 4; idx++)
- filehdr_in->pe.e_res[idx] = 0x0;
- }
+
+ for (idx=0; idx < 4; idx++)
+ filehdr_in->pe.e_res[idx] = 0x0;
+
filehdr_in->pe.e_oemid = 0x0;
filehdr_in->pe.e_oeminfo = 0x0;
- {
- int idx;
- for (idx=0; idx < 10; idx++)
- filehdr_in->pe.e_res2[idx] = 0x0;
- }
+
+ for (idx=0; idx < 10; idx++)
+ filehdr_in->pe.e_res2[idx] = 0x0;
+
filehdr_in->pe.e_lfanew = 0x80;
/* this next collection of data are mostly just characters. It appears
GET_SCNHDR_PADDR (abfd, (bfd_byte *) scnhdr_ext->s_paddr);
scnhdr_int->s_size =
GET_SCNHDR_SIZE (abfd, (bfd_byte *) scnhdr_ext->s_size);
-
scnhdr_int->s_scnptr =
GET_SCNHDR_SCNPTR (abfd, (bfd_byte *) scnhdr_ext->s_scnptr);
scnhdr_int->s_relptr =
struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *)in;
SCNHDR *scnhdr_ext = (SCNHDR *)out;
unsigned int ret = sizeof (SCNHDR);
+ bfd_vma s;
memcpy(scnhdr_ext->s_name, scnhdr_int->s_name, sizeof(scnhdr_int->s_name));
- pe_data(abfd)->pe_opthdr.ImageBase),
(bfd_byte *) scnhdr_ext->s_vaddr);
- /* NT wants the physical address data to be the size (s_size data) of
- the section */
- PUT_SCNHDR_PADDR (abfd, scnhdr_int->s_size,
- (bfd_byte *) scnhdr_ext->s_paddr);
+ /* Note that we're really stuffing in the raw size into here. */
+
+
+ PUT_SCNHDR_SIZE (abfd, scnhdr_int->s_size,
+ (bfd_byte *) scnhdr_ext->s_size);
+
/* NT wants the size data to be rounded up to the next NT_FILE_ALIGNMENT
value except for the BSS section, its s_size should be 0 */
- if (strcmp (scnhdr_int->s_name, _BSS) == 0)
- PUT_SCNHDR_SIZE (abfd, 0, (bfd_byte *) scnhdr_ext->s_size);
+
+ if (strcmp (scnhdr_int->s_name, _BSS) == 0)
+ s = 0;
else
- {
- bfd_vma rounded_size;
- rounded_size = ((scnhdr_int->s_size + NT_FILE_ALIGNMENT - 1) /
- NT_FILE_ALIGNMENT) *
- NT_FILE_ALIGNMENT;
- PUT_SCNHDR_SIZE (abfd, rounded_size, (bfd_byte *) scnhdr_ext->s_size);
- }
+ s = scnhdr_int->s_paddr;
+
+ PUT_SCNHDR_PADDR (abfd, s, (bfd_byte *) scnhdr_ext->s_paddr);
PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr,
(bfd_byte *) scnhdr_ext->s_scnptr);