/* Routines to help build PEI-format DLLs (Win32 etc)
- Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Written by DJ Delorie <dj@cygnus.com>
This file is part of GLD, the Gnu Linker.
You should have received a copy of the GNU General Public License
along with GLD; see the file COPYING. If not, write to the Free
- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
#include "bfd.h"
#include "sysdep.h"
static bfd_vma image_base;
static bfd *filler_bfd;
-static struct sec *edata_s, *reloc_s;
+static struct bfd_section *edata_s, *reloc_s;
static unsigned char *edata_d, *reloc_d;
static size_t edata_sz, reloc_sz;
static int runtime_pseudo_relocs_created = 0;
defined, since we can't export symbols we don't have. */
static bfd_vma *exported_symbol_offsets;
-static struct sec **exported_symbol_sections;
+static struct bfd_section **exported_symbol_sections;
static int export_table_size;
static int count_exported;
static int count_exported_byname;
libname = lbasename (abfd->my_archive->filename);
/* We should not re-export imported stuff. */
- if (strncmp (n, "_imp__", 6) == 0)
+ if (strncmp (n, "_imp_", 5) == 0)
return 0;
for (i = 0; i < d->num_exports; i++)
int i, j;
struct bfd_link_hash_entry *blhe;
bfd *b;
- struct sec *s;
+ struct bfd_section *s;
def_file_export *e = 0;
if (!pe_def_file)
s = bfd_get_section_by_name (b, ".drectve");
if (s)
{
- int size = bfd_get_section_size_before_reloc (s);
+ long size = s->size;
char *buf = xmalloc (size);
bfd_get_section_contents (b, s, buf, 0, size);
/* If we are not building a DLL, when there are no exports
we do not build an export table at all. */
if (!pe_dll_export_everything && pe_def_file->num_exports == 0
- && !info->shared)
+ && info->executable)
return;
/* Now, maybe export everything else the default way. */
e = pe_def_file->exports;
exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma));
- exported_symbol_sections = xmalloc (NE * sizeof (struct sec *));
+ exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *));
- memset (exported_symbol_sections, 0, NE * sizeof (struct sec *));
+ memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *));
max_ordinal = 0;
min_ordinal = 65536;
count_exported = 0;
{
int s, hint;
unsigned char *edirectory;
- unsigned long *eaddresses;
- unsigned long *enameptrs;
- unsigned short *eordinals;
- unsigned char *enamestr;
+ unsigned char *eaddresses;
+ unsigned char *enameptrs;
+ unsigned char *eordinals;
+ char *enamestr;
time_t now;
time (&now);
/* Note use of array pointer math here. */
edirectory = edata_d;
- eaddresses = (unsigned long *) (edata_d + 40);
- enameptrs = eaddresses + export_table_size;
- eordinals = (unsigned short *) (enameptrs + count_exported_byname);
- enamestr = (char *) (eordinals + count_exported_byname);
+ eaddresses = edata_d + 40;
+ enameptrs = eaddresses + 4 * export_table_size;
+ eordinals = enameptrs + 4 * count_exported_byname;
+ enamestr = (char *) eordinals + 2 * count_exported_byname;
#define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) \
+ edata_s->output_section->vma - image_base)
hint = 0;
for (s = 0; s < NE; s++)
{
- if (pe_def_file->exports[s].ordinal != -1)
+ struct bfd_section *ssec = exported_symbol_sections[s];
+ if (ssec && pe_def_file->exports[s].ordinal != -1)
{
- struct sec *ssec = exported_symbol_sections[s];
unsigned long srva = (exported_symbol_offsets[s]
+ ssec->output_section->vma
+ ssec->output_offset);
int ord = pe_def_file->exports[s].ordinal;
bfd_put_32 (abfd, srva - image_base,
- (void *) (eaddresses + ord - min_ordinal));
+ eaddresses + 4 * (ord - min_ordinal));
if (!pe_def_file->exports[s].flag_noname)
{
char *ename = pe_def_file->exports[s].name;
- bfd_put_32 (abfd, ERVA (enamestr), (void *) enameptrs);
- enameptrs++;
+ bfd_put_32 (abfd, ERVA (enamestr), enameptrs);
+ enameptrs += 4;
strcpy (enamestr, ename);
enamestr += strlen (enamestr) + 1;
- bfd_put_16 (abfd, ord - min_ordinal, (void *) eordinals);
- eordinals++;
+ bfd_put_16 (abfd, ord - min_ordinal, eordinals);
+ eordinals += 2;
pe_def_file->exports[s].hint = hint++;
}
}
}
-static struct sec *current_sec;
+static struct bfd_section *current_sec;
void
pe_walk_relocs_of_symbol (struct bfd_link_info *info,
for (i = 0; i < nrelocs; i++)
{
- struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;
+ struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
if (!strcmp (name, sym->name))
cb (relocs[i], s);
unsigned long page_ptr, page_count;
int bi;
bfd *b;
- struct sec *s;
+ struct bfd_section *s;
total_relocs = 0;
for (b = info->input_bfds; b; b = b->link_next)
{
if (pe_dll_extra_pe_debug)
{
- struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;
+ struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
printf ("rel: %s\n", sym->name);
}
if (!relocs[i]->howto->pc_relative
&& relocs[i]->howto->type != pe_details->imagebase_reloc)
{
bfd_vma sym_vma;
- struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;
+ struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
sym_vma = (relocs[i]->addend
+ sym->value
total_relocs++;
break;
case BITS_AND_SHIFT (24, 2):
- if (relocs[i]->howto->type == 5)
+ /* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c
+ Those ARM_xxx definitions should go in proper
+ header someday. */
+ if (relocs[i]->howto->type == 0
+ /* Older GNU linkers used 5 instead of 0 for this reloc. */
+ || relocs[i]->howto->type == 5)
/* This is an ARM_26D reloc, which is an ARM_26 reloc
that has already been fully processed during a
previous link stage, so ignore it here. */
free (relocs);
/* Warning: the allocated symbols are remembered in BFD and
reused later, so don't free them! */
-#if 0
- free (symbol);
-#endif
}
}
if (page_ptr != (unsigned long) -1)
bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
- while (reloc_sz < reloc_s->_raw_size)
+ while (reloc_sz < reloc_s->size)
reloc_d[reloc_sz++] = 0;
}
bfd_set_section_size (abfd, id7, len);
d7 = xmalloc (len);
id7->contents = d7;
- strcpy (d7, dll_filename);
+ strcpy ((char *) d7, dll_filename);
bfd_set_symtab (abfd, symtab, symptr);
if (*exp->internal_name == '@')
{
- if (! exp->flag_data)
- quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
BSF_GLOBAL, 0);
+ if (! exp->flag_data)
+ quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
quick_symbol (abfd, U ("_imp_"), exp->internal_name, "", id5,
BSF_GLOBAL, 0);
/* Fastcall applies only to functions,
}
else
{
+ quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
+ BSF_GLOBAL, 0);
if (! exp->flag_data)
quick_symbol (abfd, U (""), exp->internal_name, "", tx,
BSF_GLOBAL, 0);
- quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
- BSF_GLOBAL, 0);
quick_symbol (abfd, U ("_imp__"), exp->internal_name, "", id5,
BSF_GLOBAL, 0);
/* Symbol to reference ord/name of imported
d7 = xmalloc (4);
id7->contents = d7;
memset (d7, 0, 4);
- quick_reloc (abfd, 0, BFD_RELOC_RVA, 6);
+ quick_reloc (abfd, 0, BFD_RELOC_RVA, 5);
save_relocs (id7);
bfd_set_section_size (abfd, id5, 4);
memset (d6, 0, len);
d6[0] = exp->hint & 0xff;
d6[1] = exp->hint >> 8;
- strcpy (d6 + 2, exp->name);
+ strcpy ((char *) d6 + 2, exp->name);
}
bfd_set_symtab (abfd, symtab, symptr);
static char *fixup_name = NULL;
static size_t buffer_len = 0;
- struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
+ struct bfd_symbol *sym = *rel->sym_ptr_ptr;
bfd *abfd = bfd_asymbol_bfd (sym);
struct bfd_link_hash_entry *bh;
symtab = xmalloc (6 * sizeof (asymbol *));
id3 = quick_section (abfd, ".idata$3", SEC_HAS_CONTENTS, 2);
-#if 0
- quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0);
-#endif
quick_symbol (abfd, U ("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0);
quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
pe_create_import_fixup (arelent *rel, asection *s, int addend)
{
char buf[300];
- struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
+ struct bfd_symbol *sym = *rel->sym_ptr_ptr;
struct bfd_link_hash_entry *name_thunk_sym;
const char *name = sym->name;
char *fixup_name = make_import_fixup_mark (rel);
/* If we ever use autoimport, we have to cast text section writable. */
config.text_read_only = FALSE;
+ output_bfd->flags &= ~WP_TEXT;
}
if (addend == 0 || link_info.pei386_runtime_pseudo_reloc)
if (!ISALNUM (dll_symname[i]))
dll_symname[i] = '_';
- unlink (impfilename);
+ unlink_if_ordinary (impfilename);
outarch = bfd_openw (impfilename, 0);
char *internal = def->exports[i].internal_name;
bfd *n;
+ /* Don't add PRIVATE entries to import lib. */
+ if (pe_def_file->exports[i].flag_private)
+ continue;
def->exports[i].internal_name = def->exports[i].name;
n = make_one (def->exports + i, outarch);
n->next = head;
return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
}
-#if 0 /* This is not currently used. */
-
-static unsigned int
-pe_as16 (void *ptr)
-{
- unsigned char *b = ptr;
-
- return b[0] + (b[1] << 8);
-}
-
-#endif
-
static unsigned int
pe_as32 (void *ptr)
{
unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
unsigned long export_rva, export_size, nsections, secptr, expptr;
unsigned long exp_funcbase;
- unsigned char *expdata, *erva;
+ unsigned char *expdata;
+ char *erva;
unsigned long name_rvas, ordinals, nexp, ordbase;
const char *dll_name;
/* Initialization with start > end guarantees that is_data
will not be set by mistake, and avoids compiler warning. */
unsigned long data_start = 1;
- unsigned long data_end = 0;
- unsigned long bss_start = 1;
- unsigned long bss_end = 0;
+ unsigned long data_end = 0;
+ unsigned long rdata_start = 1;
+ unsigned long rdata_end = 0;
+ unsigned long bss_start = 1;
+ unsigned long bss_end = 0;
/* No, I can't use bfd here. kernel32.dll puts its export table in
the middle of the .rdata section. */
data_start = vaddr;
data_end = vaddr + vsize;
+ if (pe_dll_extra_pe_debug)
+ printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
+ __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
+ }
+ else if (strcmp(sec_name,".rdata") == 0)
+ {
+ rdata_start = vaddr;
+ rdata_end = vaddr + vsize;
+
if (pe_dll_extra_pe_debug)
printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
__FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
expdata = xmalloc (export_size);
bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
bfd_bread (expdata, (bfd_size_type) export_size, dll);
- erva = expdata - export_rva;
+ erva = (char *) expdata - export_rva;
if (pe_def_file == 0)
pe_def_file = def_file_empty ();
/* Use internal dll name instead of filename
to enable symbolic dll linking. */
- dll_name = pe_as32 (expdata + 12) + erva;
+ dll_name = erva + pe_as32 (expdata + 12);
/* Check to see if the dll has already been added to
the definition list and if so return without error.
exported in buggy auto-import releases. */
if (strncmp (erva + name_rva, "_nm_", 4) != 0)
{
- /* is_data is true if the address is in the data or bss segment. */
+ /* is_data is true if the address is in the data, rdata or bss
+ segment. */
is_data =
(func_rva >= data_start && func_rva < data_end)
+ || (func_rva >= rdata_start && func_rva < rdata_end)
|| (func_rva >= bss_start && func_rva < bss_end);
imp = def_file_add_import (pe_def_file, erva + name_rva,
bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
/* Resize the sections. */
- lang_size_sections (stat_ptr->head, abs_output_section,
- &stat_ptr->head, 0, 0, NULL, TRUE);
+ lang_reset_memory_regions ();
+ lang_size_sections (NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
/* Do the assignments again. */
- lang_do_assignments (stat_ptr->head, abs_output_section, NULL, 0);
+ lang_do_assignments ();
}
fill_edata (abfd, info);
- if (info->shared)
+ if (info->shared && !info->pie)
pe_data (abfd)->dll = 1;
edata_s->contents = edata_d;
bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
/* Resize the sections. */
- lang_size_sections (stat_ptr->head, abs_output_section,
- &stat_ptr->head, 0, 0, NULL, TRUE);
+ lang_reset_memory_regions ();
+ lang_size_sections (NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
/* Do the assignments again. */
- lang_do_assignments (stat_ptr->head, abs_output_section, NULL, 0);
+ lang_do_assignments ();
}
reloc_s->contents = reloc_d;
}