diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9d90a79bac..7c1ab8ed76 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,15 @@ Tue Nov 14 11:52:23 1995 Ian Lance Taylor + * peicode.h (coff_swap_aouthdr_out): For PPC PE, start isize at 0, + not at the file position of the first section. + * coffcode.h (coff_compute_section_file_positions): Avoid using + unportable #elif. + (coff_write_object_contents): When generating a PPC PE executable + with no symbols, round up the file size to a COFF_PAGE_SIZE + boundary. + * cofflink.c (_bfd_coff_final_link): If there are no symbols, + don't write out a string table. + * elf.c (bfd_section_from_shdr): When using a different section header, pass the new one to _bfd_elf_make_section_from_shdr. (elf_fake_sections): Don't set sh_info and sh_entsize fields. diff --git a/bfd/peicode.h b/bfd/peicode.h index 8a31732fb4..f3bc8fc375 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -188,7 +188,6 @@ coff_swap_reloc_in (abfd, src, dst) reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET(abfd, (bfd_byte *) reloc_src->r_offset); #endif - } @@ -247,7 +246,8 @@ coff_swap_filehdr_in (abfd, src, dst) filehdr_dst->f_flags &= ~HAS_SYMS; } - filehdr_dst->f_opthdr = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_opthdr); + filehdr_dst->f_opthdr = bfd_h_get_16(abfd, + (bfd_byte *)filehdr_src-> f_opthdr); } #ifdef COFF_IMAGE_WITH_PE @@ -326,7 +326,6 @@ coff_swap_filehdr_out (abfd, in, out) bfd_h_put_16(abfd, filehdr_in->f_opthdr, (bfd_byte *) filehdr_out->f_opthdr); bfd_h_put_16(abfd, filehdr_in->f_flags, (bfd_byte *) filehdr_out->f_flags); - /* put in extra dos header stuff. This data remains essentially constant, it just has to be tacked on to the beginning of all exes for NT */ @@ -426,6 +425,7 @@ coff_swap_sym_in (abfd, ext1, in1) memcpy(in->_n._n_name, ext->e.e_name, SYMNMLEN); #endif } + in->n_value = bfd_h_get_32(abfd, (bfd_byte *) ext->e_value); in->n_scnum = bfd_h_get_16(abfd, (bfd_byte *) ext->e_scnum); if (sizeof(ext->e_type) == 2){ @@ -455,6 +455,10 @@ coff_swap_sym_in (abfd, ext1, in1) /* else */ /* in->n_scnum = 2; */ } + +#ifdef coff_swap_sym_in_hook + coff_swap_sym_in_hook(abfd, ext1, in1); +#endif } static unsigned int @@ -476,6 +480,7 @@ coff_swap_sym_out (abfd, inp, extp) memcpy(ext->e.e_name, in->_n._n_name, SYMNMLEN); #endif } + bfd_h_put_32(abfd, in->n_value , (bfd_byte *) ext->e_value); bfd_h_put_16(abfd, in->n_scnum , (bfd_byte *) ext->e_scnum); if (sizeof(ext->e_type) == 2) @@ -488,6 +493,7 @@ coff_swap_sym_out (abfd, inp, extp) } bfd_h_put_8(abfd, in->n_sclass , ext->e_sclass); bfd_h_put_8(abfd, in->n_numaux , ext->e_numaux); + return sizeof(SYMENT); } @@ -771,7 +777,6 @@ static void add_data_entry (abfd, aout, idx, name, base) } } - static unsigned int coff_swap_aouthdr_out (abfd, in, out) bfd *abfd; @@ -809,12 +814,39 @@ coff_swap_aouthdr_out (abfd, in, out) add_data_entry (abfd, extra, 0, ".edata", ib); add_data_entry (abfd, extra, 1, ".idata", ib); add_data_entry (abfd, extra, 2, ".rsrc" ,ib); + +#ifdef POWERPC_LE_PE + /* FIXME: do other PE platforms use this? */ + add_data_entry (abfd, extra, 3, ".pdata" ,ib); +#endif + add_data_entry (abfd, extra, 5, ".reloc", ib); + +#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 + { asection *sec; bfd_vma dsize= 0; bfd_vma isize = SA(abfd->sections->filepos); bfd_vma tsize= 0; +#ifdef PPC + isize = 0; +#endif for (sec = abfd->sections; sec; sec = sec->next) { int rounded = FA(sec->_raw_size); @@ -832,7 +864,15 @@ coff_swap_aouthdr_out (abfd, in, out) extra->SizeOfHeaders = abfd->sections->filepos; bfd_h_put_16(abfd, aouthdr_in->magic, (bfd_byte *) aouthdr_out->standard.magic); + +#ifdef POWERPC_LE_PE + /* this little piece of magic sets the "linker version" field to 2.60 */ + bfd_h_put_16(abfd, 2 + 60 * 256, (bfd_byte *) aouthdr_out->standard.vstamp); +#else + /* this little piece of magic sets the "linker version" field to 2.55 */ bfd_h_put_16(abfd, 2 + 55 * 256, (bfd_byte *) aouthdr_out->standard.vstamp); +#endif + PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, (bfd_byte *) aouthdr_out->standard.tsize); PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, (bfd_byte *) aouthdr_out->standard.dsize); PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, (bfd_byte *) aouthdr_out->standard.bsize); @@ -897,7 +937,6 @@ coff_swap_aouthdr_out (abfd, in, out) } } - return sizeof(AOUTHDR); } @@ -953,7 +992,6 @@ coff_swap_scnhdr_out (abfd, in, out) memcpy(scnhdr_ext->s_name, scnhdr_int->s_name, sizeof(scnhdr_int->s_name)); - PUT_SCNHDR_VADDR (abfd, (scnhdr_int->s_vaddr - pe_data(abfd)->pe_opthdr.ImageBase), @@ -1021,7 +1059,9 @@ coff_swap_scnhdr_out (abfd, in, out) else if (strcmp (scnhdr_int->s_name, ".pdata") == 0) flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ ; - else if (strcmp (scnhdr_int->s_name, ".reldata") == 0) + /* Remember this field is a max of 8 chars, so the null is _not_ there + for an 8 character name like ".reldata". (yep. Stupid bug) */ + else if (strncmp (scnhdr_int->s_name, ".reldata", strlen(".reldata")) == 0) flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_8BYTES | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ; else if (strcmp (scnhdr_int->s_name, ".ydata") == 0) @@ -1058,16 +1098,351 @@ coff_swap_scnhdr_out (abfd, in, out) } return ret; } + +static char * dir_names[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = +{ + "Export Directory [.edata]", + "Import Directory [parts of .idata]", + "Resource Directory [.rsrc]", + "Exception Directory [.pdata]", + "Security Directory", + "Base Relocation Directory [.reloc]", + "Debug Directory", + "Description Directory", + "Special Directory", + "Thread Storage Directory [.tls]", + "Load Configuration Directory", + "Reserved", + "Reserved [first thunk address on PPC]", + "Reserved", + "Reserved", + "Reserved" +}; + /**********************************************************************/ static boolean -pe_print_private_bfd_data (abfd, vfile) +pe_print_idata(abfd, vfile) bfd*abfd; void *vfile; +{ + FILE *file = vfile; + bfd_byte *data = 0; + asection *section = bfd_get_section_by_name (abfd, ".idata"); + +#ifdef POWERPC_LE_PE + asection *rel_section = bfd_get_section_by_name (abfd, ".reldata"); +#endif + + bfd_size_type datasize = 0; + bfd_size_type i; + bfd_size_type start, stop; + int onaline = 20; + bfd_vma addr_value; + bfd_vma loadable_toc_address; + bfd_vma toc_address; + bfd_vma start_address; + + pe_data_type *pe = pe_data (abfd); + struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; + + if (section == 0) + return true; + +#ifdef POWERPC_LE_PE + if (rel_section != 0 && bfd_section_size (abfd, rel_section) != 0) + { + /* The toc address can be found by taking the starting address, + which on the PPC locates a function descriptor. The descriptor + consists of the function code starting address followed by the + address of the toc. The starting address we get from the bfd, + and the descriptor is supposed to be in the .reldata section. + */ + + bfd_byte *data = 0; + int offset; + data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, + rel_section)); + datasize = bfd_section_size (abfd, rel_section); + + bfd_get_section_contents (abfd, + rel_section, + (PTR) data, 0, + bfd_section_size (abfd, rel_section)); + + offset = abfd->start_address - rel_section->vma; + + start_address = bfd_get_32(abfd, data+offset); + loadable_toc_address = bfd_get_32(abfd, data+offset+4); + toc_address = loadable_toc_address - 32768; + fprintf(file, + "\nFunction descriptor located at the start address:\n"); + fprintf (file, + " %04lx code-base %08lx toc (loadable) %08lx toc (actual) %08lx\n", + (unsigned long int) (abfd->start_address), + start_address, loadable_toc_address, toc_address); + } + else + { + loadable_toc_address = 0; + toc_address = 0; + start_address = 0; + } +#endif + + fprintf(file, + "\nThe Import Tables (interpreted .idata section contents)\n"); + fprintf(file, + " vma: Hint Time Forward DLL First\n"); + fprintf(file, + " Table Stamp Chain Name Thunk\n"); + + if (bfd_section_size (abfd, section) == 0) + return true; + + data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, section)); + datasize = bfd_section_size (abfd, section); + + bfd_get_section_contents (abfd, + section, + (PTR) data, 0, + bfd_section_size (abfd, section)); + + start = 0; + + stop = bfd_section_size (abfd, section); + + for (i = start; i < stop; i += onaline) + { + bfd_vma hint_addr; + bfd_vma time_stamp; + bfd_vma forward_chain; + bfd_vma dll_name; + bfd_vma first_thunk; + int idx; + int j; + char *dll; + int adj = extra->ImageBase - section->vma; + + fprintf (file, + " %04lx\t", + (unsigned long int) (i + section->vma)); + + if (i+20 > stop) + { + /* check stuff */ + ; + } + + hint_addr = bfd_get_32(abfd, data+i); + time_stamp = bfd_get_32(abfd, data+i+4); + forward_chain = bfd_get_32(abfd, data+i+8); + dll_name = bfd_get_32(abfd, data+i+12); + first_thunk = bfd_get_32(abfd, data+i+16); + + fprintf(file, "%08lx %08lx %08lx %08lx %08lx\n", + hint_addr, + time_stamp, + forward_chain, + dll_name, + first_thunk); + + if (hint_addr ==0) + { + break; + } + + /* the image base is present in the section->vma */ + dll = data + dll_name + adj; + fprintf(file, "\n\tDLL Name: %s\n", dll); + fprintf(file, "\tvma: Ordinal Member-Name\n"); + + idx = hint_addr + adj; + + for (j=0;j>> Ran out of IAT members!\n"); + } + else + { + ordinal = bfd_get_16(abfd, + data + iat_member + adj); + member_name = data + iat_member + adj + 2; + fprintf(file, "\t%04lx\t %4d %s\n", + iat_member, ordinal, member_name); + } + break; + } + if (hint_member == 0) + break; + } + if (differ == 0) + { + fprintf(file, + "\tThe Import Address Table is identical\n"); + } + } + + fprintf(file, "\n"); + + } + + + free (data); +} +static boolean +pe_print_pdata(abfd, vfile) + bfd*abfd; + void *vfile; +{ + FILE *file = vfile; + bfd_byte *data = 0; + asection *section = bfd_get_section_by_name (abfd, ".pdata"); + bfd_size_type datasize = 0; + bfd_size_type i; + bfd_size_type start, stop; + int onaline = 20; + bfd_vma addr_value; + + if (section == 0) + return true; + + fprintf(file, + "\nThe Function Table (interpreted .pdata section contents)\n"); + fprintf(file, + " vma: Begin End EH EH PrologEnd\n"); + fprintf(file, + " Address Address Handler Data Address\n"); + + if (bfd_section_size (abfd, section) == 0) + return true; + + data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, section)); + datasize = bfd_section_size (abfd, section); + + bfd_get_section_contents (abfd, + section, + (PTR) data, 0, + bfd_section_size (abfd, section)); + + start = 0; + + stop = bfd_section_size (abfd, section); + + for (i = start; i < stop; i += onaline) + { + bfd_vma begin_addr; + bfd_vma end_addr; + bfd_vma eh_handler; + bfd_vma eh_data; + bfd_vma prolog_end_addr; + + if (i+20 > stop) + break; + + begin_addr = bfd_get_32(abfd, data+i); + end_addr = bfd_get_32(abfd, data+i+4); + eh_handler = bfd_get_32(abfd, data+i+8); + eh_data = bfd_get_32(abfd, data+i+12); + prolog_end_addr = bfd_get_32(abfd, data+i+16); + + if (begin_addr == 0) + { + /* We are probably into the padding of the + section now */ + break; + } + + fprintf (file, + " %04lx\t", + (unsigned long int) (i + section->vma)); + + fprintf(file, "%08lx %08lx %08lx %08lx %08lx", + begin_addr, + end_addr, + eh_handler, + eh_data, + prolog_end_addr); + +#ifdef POWERPC_LE_PE + if (eh_handler == 0 && eh_data != 0) + { + /* Special bits here, although the meaning may */ + /* be a little mysterious. The only one I know */ + /* for sure is 0x03. */ + /* Code Significance */ + /* 0x00 None */ + /* 0x01 Register Save Millicode */ + /* 0x02 Register Restore Millicode */ + /* 0x03 Glue Code Sequence */ + switch (eh_data) + { + case 0x01: + fprintf(file, " Register save millicode"); + break; + case 0x02: + fprintf(file, " Register restore millicode"); + break; + case 0x03: + fprintf(file, " Glue code sequence"); + break; + default: + break; + } + } +#endif + fprintf(file, "\n"); + } + + free (data); +} + +static boolean +pe_print_private_bfd_data (abfd, vfile) + bfd *abfd; + void *vfile; { FILE *file = vfile; int j; pe_data_type *pe = pe_data (abfd); struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr; + fprintf (file,"\nImageBase\t\t"); fprintf_vma (file, i->ImageBase); fprintf (file,"\nSectionAlignment\t"); @@ -1097,13 +1472,18 @@ pe_print_private_bfd_data (abfd, vfile) fprintf (file,"\nLoaderFlags\t\t%08lx\n", i->LoaderFlags); fprintf (file,"NumberOfRvaAndSizes\t%08lx\n", i->NumberOfRvaAndSizes); + fprintf (file,"\nThe Data Directory\n"); for (j = 0; j < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; j++) { - fprintf (file, "Entry %2d ", j); + fprintf (file, "Entry %1x ", j); fprintf_vma (file, i->DataDirectory[j].VirtualAddress); - fprintf (file, " %08lx\n", i->DataDirectory[j].Size); + fprintf (file, " %08lx ", i->DataDirectory[j].Size); + fprintf (file, "%s\n", dir_names[j]); } + pe_print_idata(abfd, vfile); + pe_print_pdata(abfd, vfile); + return true; } @@ -1158,6 +1538,7 @@ pe_mkobject_hook (abfd, filehdr, aouthdr) obj_conv_table_size (abfd) = internal_f->f_nsyms; + pe->real_flags = internal_f->f_flags; #ifdef COFF_IMAGE_WITH_PE if (aouthdr)