aboutsummaryrefslogtreecommitdiff
path: root/bfd/peigen.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/peigen.c')
-rw-r--r--bfd/peigen.c98
1 files changed, 76 insertions, 22 deletions
diff --git a/bfd/peigen.c b/bfd/peigen.c
index 3593ba9..f58ba0e 100644
--- a/bfd/peigen.c
+++ b/bfd/peigen.c
@@ -566,31 +566,27 @@ _bfd_pei_swap_aouthdr_out (abfd, in, out)
/* first null out all data directory entries .. */
memset (extra->DataDirectory, sizeof (extra->DataDirectory), 0);
- add_data_entry (abfd, extra, 0, ".edata", ib);
- add_data_entry (abfd, extra, 1, ".idata", ib);
- add_data_entry (abfd, extra, 2, ".rsrc" ,ib);
+ add_data_entry (abfd, extra, 0, ".edata", 0);
-#ifdef POWERPC_LE_PE
- /* FIXME: do other PE platforms use this? */
- add_data_entry (abfd, extra, 3, ".pdata" ,ib);
-#endif
+ /* Don't call add_data_entry for .idata$2 or .idata$5. It's done in
+ bfd_coff_final_link where all the required information is
+ available. */
- add_data_entry (abfd, extra, 5, ".reloc", ib);
+ /* However, until other .idata fixes are made (pending patch), the
+ entry for .idata is needed for backwards compatability. FIXME. */
+ add_data_entry (abfd, extra, 1, ".idata" ,0);
-#ifdef POWERPC_LE_PE
- /* On the PPC NT system, this field is set up as follows. It is not
- an "officially" reserved field, so it currently has no title.
- first_thunk_address is idata$5, and the thunk_size is the size of
- the idata$5 chunk of the idata section. */
- extra->DataDirectory[12].VirtualAddress = first_thunk_address;
- extra->DataDirectory[12].Size = thunk_size;
-
- /* On the PPC NT system, the size of the directory entry is not the
- size of the entire section. It's actually offset to the end of
- the idata$3 component of the idata section. This is the size of
- the entire import table. (also known as the start of idata$4). */
- extra->DataDirectory[1].Size = import_table_size;
-#endif
+ add_data_entry (abfd, extra, 2, ".rsrc" ,0);
+
+ add_data_entry (abfd, extra, 3, ".pdata", 0);
+
+ /* For some reason, the virtual size (which is what's set by
+ add_data_entry) for .reloc is not the same as the size recorded
+ in this slot by MSVC; it doesn't seem to cause problems (so far),
+ but since it's the best we've got, use it. It does do the right
+ thing for .pdata. */
+ if (pe_data (abfd)->has_reloc_section)
+ add_data_entry (abfd, extra, 5, ".reloc", 0);
{
asection *sec;
@@ -1856,3 +1852,61 @@ _bfd_pe_get_symbol_info (abfd, symbol, ret)
&& ! bfd_is_abs_section (symbol->section))
ret->value += pe_data (abfd)->pe_opthdr.ImageBase;
}
+
+/* Handle the .idata section and other things that need symbol table
+ access. */
+
+boolean
+_bfd_pei_final_link_postscript (abfd, pfinfo)
+ bfd *abfd;
+ struct coff_final_link_info *pfinfo;
+{
+ struct coff_link_hash_entry *h1;
+ struct bfd_link_info *info = pfinfo->info;
+
+ /* There are a few fields that need to be filled in now while we
+ have symbol table access.
+
+ The .idata subsections aren't directly available as sections, but
+ they are in the symbol table, so get them from there. */
+
+ /* The import directory. This is the address of .idata$2, with size
+ of .idata$2 + .idata$3. */
+ h1 = coff_link_hash_lookup (coff_hash_table (info),
+ ".idata$2", false, false, true);
+ if (h1 != NULL)
+ {
+ pe_data(abfd)->pe_opthdr.DataDirectory[1].VirtualAddress =
+ (h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset);
+ h1 = coff_link_hash_lookup (coff_hash_table (info),
+ ".idata$4", false, false, true);
+ pe_data (abfd)->pe_opthdr.DataDirectory[1].Size =
+ ((h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset)
+ - pe_data(abfd)->pe_opthdr.DataDirectory[1].VirtualAddress);
+
+ /* The import address table. This is the size/address of
+ .idata$5. */
+ h1 = coff_link_hash_lookup (coff_hash_table (info),
+ ".idata$5", false, false, true);
+ pe_data (abfd)->pe_opthdr.DataDirectory[12].VirtualAddress =
+ (h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset);
+ h1 = coff_link_hash_lookup (coff_hash_table (info),
+ ".idata$6", false, false, true);
+ pe_data (abfd)->pe_opthdr.DataDirectory[12].Size =
+ ((h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset)
+ - pe_data(abfd)->pe_opthdr.DataDirectory[12].VirtualAddress);
+ }
+
+ /* If we couldn't find idata$2, we either have an excessively
+ trivial program or are in DEEP trouble; we have to assume trivial
+ program.... */
+ return true;
+}