Index: libpei.h =================================================================== RCS file: /cvs/src/src/bfd/libpei.h,v retrieving revision 1.18 diff -u -p -r1.18 libpei.h --- libpei.h 3 Jul 2007 14:26:42 -0000 1.18 +++ libpei.h 16 Nov 2007 15:13:28 -0000 @@ -237,6 +237,12 @@ #define _bfd_XXi_swap_sym_in _bfd_pex64i_swap_sym_in #define _bfd_XXi_swap_sym_out _bfd_pex64i_swap_sym_out +#define _bfd_XX_get_libraries _bfd_pex64_get_libraries +#define _bfd_XX_get_imports _bfd_pex64_get_imports +#define _bfd_XX_get_exports _bfd_pex64_get_exports +#define _bfd_XX_print_imports _bfd_pex64_print_imports +#define _bfd_XX_print_exports _bfd_pex64_print_exports + #elif defined COFF_WITH_pep #define GET_OPTHDR_IMAGE_BASE H_GET_64 @@ -268,6 +274,12 @@ #define _bfd_XXi_swap_sym_in _bfd_pepi_swap_sym_in #define _bfd_XXi_swap_sym_out _bfd_pepi_swap_sym_out +#define _bfd_XX_get_libraries _bfd_pep_get_libraries +#define _bfd_XX_get_imports _bfd_pep_get_imports +#define _bfd_XX_get_exports _bfd_pep_get_exports +#define _bfd_XX_print_imports _bfd_pep_print_imports +#define _bfd_XX_print_exports _bfd_pep_print_exports + #else /* !COFF_WITH_pep */ #define GET_OPTHDR_IMAGE_BASE H_GET_32 @@ -299,6 +311,12 @@ #define _bfd_XXi_swap_sym_in _bfd_pei_swap_sym_in #define _bfd_XXi_swap_sym_out _bfd_pei_swap_sym_out +#define _bfd_XX_get_libraries _bfd_pe_get_libraries +#define _bfd_XX_get_imports _bfd_pe_get_imports +#define _bfd_XX_get_exports _bfd_pe_get_exports +#define _bfd_XX_print_imports _bfd_pe_print_imports +#define _bfd_XX_print_exports _bfd_pe_print_exports + #endif /* !COFF_WITH_pep */ /* Returns true if the target is a PE executable target. */ @@ -363,6 +381,12 @@ bfd_boolean _bfd_XX_bfd_copy_private_bfd void _bfd_XX_get_symbol_info (bfd *, asymbol *, symbol_info *); bfd_boolean _bfd_XXi_final_link_postscript (bfd *, struct coff_final_link_info *); +bfd_boolean _bfd_XX_get_libraries (bfd *, bfd_boolean (*func) (bfd *, struct bfd_import_library *, void *), void *); +bfd_boolean _bfd_XX_get_imports (bfd *, struct bfd_import_library *, bfd_boolean (*func) (bfd *, struct bfd_import_library *, struct bfd_import *, void *), void *); +bfd_boolean _bfd_XX_get_exports (bfd *, bfd_boolean (*func) (bfd *, struct bfd_export *, void *), void *); +bfd_boolean _bfd_XX_print_imports (bfd *, void *); +bfd_boolean _bfd_XX_print_exports (bfd *, void *); + /* The following are needed only for ONE of pe or pei, but don't otherwise vary; peicode.h fixes up ifdefs but we provide the prototype. */ Index: peXXigen.c =================================================================== RCS file: /cvs/src/src/bfd/peXXigen.c,v retrieving revision 1.43 diff -u -p -r1.43 peXXigen.c --- peXXigen.c 13 Nov 2007 20:17:43 -0000 1.43 +++ peXXigen.c 16 Nov 2007 15:13:31 -0000 @@ -1809,6 +1809,488 @@ pe_print_reloc (bfd * abfd, void * vfile return TRUE; } +struct pe_import_data +{ + bfd_vma hint_addr; + bfd_vma time_stamp; + bfd_vma forward_chain; + bfd_vma dll_name; + bfd_vma first_thunk; + + bfd_byte *secdata; + bfd_size_type datasize; +}; + +bfd_boolean +_bfd_XX_get_libraries (bfd *abfd, bfd_boolean (*func) (bfd *, struct bfd_import_library *, void *), void *user_storage) +{ + bfd_byte *data; + asection *section; + bfd_signed_vma adj; + +#ifdef POWERPC_LE_PE + asection *rel_section = bfd_get_section_by_name (abfd, ".reldata"); +#endif + + bfd_size_type datasize = 0; + bfd_size_type dataoff; + bfd_size_type i; + int onaline = 20; + + pe_data_type *pe = pe_data (abfd); + struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; + + bfd_vma addr; + + addr = extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress; + + if (addr == 0 && extra->DataDirectory[PE_IMPORT_TABLE].Size == 0) + { + /* Maybe the extra header isn't there. Look for the section. */ + section = bfd_get_section_by_name (abfd, ".idata"); + if (section == NULL) + return TRUE; + + addr = section->vma; + datasize = section->size; + if (datasize == 0) + return TRUE; + } + else + { + addr += extra->ImageBase; + for (section = abfd->sections; section != NULL; section = section->next) + { + datasize = section->size; + if (addr >= section->vma && addr < section->vma + datasize) + break; + } + + if (section == NULL) + return FALSE; /* _("\nThere is an import table, but the section containing it could not be found\n") */ + } + + dataoff = addr - section->vma; + datasize -= dataoff; + +#ifdef POWERPC_LE_PE + if (rel_section != 0 && rel_section->size != 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_vma loadable_toc_address; + bfd_vma toc_address; + bfd_vma start_address; + bfd_byte *data; + bfd_vma offset; + + if (!bfd_malloc_and_get_section (abfd, rel_section, &data)) + { + if (data != NULL) + free (data); + return FALSE; + } + + offset = abfd->start_address - rel_section->vma; + + if (offset >= rel_section->size || offset + 8 > rel_section->size) + { + if (data != NULL) + free (data); + return FALSE; + } + + start_address = bfd_get_32 (abfd, data + offset); + loadable_toc_address = bfd_get_32 (abfd, data + offset + 4); + toc_address = loadable_toc_address - 32768; + + if (data != NULL) + free (data); + } +#endif + + /* Read the whole section. Some of the fields might be before dataoff. */ + if (!bfd_malloc_and_get_section (abfd, section, &data)) + { + if (data != NULL) + free (data); + return FALSE; + } + + adj = section->vma - extra->ImageBase; + + + /* Print all image import descriptors. */ + for (i = 0; i < datasize; i += onaline) + { + struct bfd_import_library temp; + struct pe_import_data dlldata; + + memset(&temp, 0, sizeof (struct bfd_import_library)); + + temp.sec = section; + temp.vma = section->vma + i + dataoff; + temp.size = onaline; + temp.libname = NULL; + temp.data = &dlldata; + + dlldata.hint_addr = bfd_get_32 (abfd, data + i + dataoff); + dlldata.time_stamp = bfd_get_32 (abfd, data + i + 4 + dataoff); + dlldata.forward_chain = bfd_get_32 (abfd, data + i + 8 + dataoff); + dlldata.dll_name = bfd_get_32 (abfd, data + i + 12 + dataoff); + dlldata.first_thunk = bfd_get_32 (abfd, data + i + 16 + dataoff); + dlldata.secdata = data; + dlldata.datasize = datasize; + + if (dlldata.hint_addr == 0 && dlldata.first_thunk == 0) { +/* func(abfd, &temp, user_storage); */ + break; + } + + if (dlldata.dll_name - adj >= section->size) { +/* func(abfd, &temp, user_storage); */ + break; + } + + /* XXX, do we need check if dll_name is NUL-terminated? */ + temp.libname = (char *) data + dlldata.dll_name - adj; + func(abfd, &temp, user_storage); + } + + free (data); + + return TRUE; +} + +bfd_boolean +_bfd_XX_get_imports (bfd *abfd, struct bfd_import_library *library, bfd_boolean (*func) (bfd *, struct bfd_import_library *, struct bfd_import *, void *), void *user_storage) +{ + struct pe_import_data *dlldata = library->data; + pe_data_type *pe = pe_data (abfd); + struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; + + bfd_signed_vma adj; + bfd_byte *data = dlldata->secdata; + bfd_size_type datasize = dlldata->datasize; + + int idx = 0; + bfd_size_type j; + bfd_byte *ft_data; + asection *ft_section; + bfd_vma ft_addr; + bfd_size_type ft_datasize; + int ft_idx; + int ft_allocated = 0; + + if (dlldata->hint_addr == 0) + return TRUE; + + adj = library->sec->vma - extra->ImageBase; + + idx = dlldata->hint_addr - adj; + + ft_addr = dlldata->first_thunk + extra->ImageBase; + ft_data = dlldata->secdata; + ft_idx = dlldata->first_thunk - adj; + + if (dlldata->first_thunk != dlldata->hint_addr) + { + /* Find the section which contains the first thunk. */ + for (ft_section = abfd->sections; + ft_section != NULL; + ft_section = ft_section->next) + { + ft_datasize = ft_section->size; + if (ft_addr >= ft_section->vma + && ft_addr < ft_section->vma + ft_datasize) + break; + } + + if (ft_section == NULL) + { + return FALSE; /* XXX: _("\nThere is a first thunk, but the section containing it could not be found\n")); */ + } + + /* Now check to see if this section is the same as our current + section. If it is not then we will have to load its data in. */ + if (ft_section == library->sec) + { + ft_data = dlldata->secdata; + ft_idx = dlldata->first_thunk - adj; + } + else + { + /* XXX datasize = ft_datasize ?! */ + ft_idx = dlldata->first_thunk - (ft_section->vma - extra->ImageBase); + ft_data = bfd_malloc (dlldata->datasize); /* XXX, ft_datasize ?! */ + if (ft_data == NULL) + return FALSE; /* XXX: fails to allocate memory */ + + /* Read datasize bfd_bytes starting at offset ft_idx. */ + if (! bfd_get_section_contents + (abfd, ft_section, ft_data, (bfd_vma) ft_idx, datasize)) + { + free (ft_data); + return FALSE; /* XXX: fails to read contents */ + } + + ft_idx = 0; + ft_allocated = 1; + } + } + + /* Print HintName vector entries. */ +#ifdef COFF_WITH_pex64 + for (j = 0; j < datasize; j += 8) + { + struct bfd_import temp; + unsigned long member = bfd_get_32 (abfd, data + idx + j); + unsigned long member_high = bfd_get_32 (abfd, data + idx + j + 4); + + if (!member && !member_high) + break; + + memset(&temp, 0, sizeof (struct bfd_import)); + + temp.vma = dlldata->first_thunk + extra->ImageBase + j; + temp.size = 8; + + if (member_high & 0x80000000) + { + temp.funcid = ((member_high & 0x7fffffff) << 32) | member; + } + else + { + temp.funcid = bfd_get_16 (abfd, data + member - adj); + temp.funcname = (char *) data + member - adj + 2; + } + + /* If the time stamp is not zero, the import address + table holds actual addresses. */ +#if 0 + if (time_stamp != 0 + && dlldata->first_thunk != 0 + && dlldata->first_thunk != hint_addr) + fprintf (file, "\t%04lx", + (long) bfd_get_32 (abfd, ft_data + ft_idx + j)); +#endif + func (abfd, library, &temp, user_storage); + } +#else + for (j = 0; j < datasize; j += 4) + { + struct bfd_import temp; + unsigned long member = bfd_get_32 (abfd, data + idx + j); + + /* Print single IMAGE_IMPORT_BY_NAME vector. */ + if (member == 0) + break; + + memset (&temp, 0, sizeof (struct bfd_import)); + + temp.vma = dlldata->first_thunk + extra->ImageBase + j; + temp.size = 4; + + if (member & 0x80000000) + { + temp.funcid = member & 0x7fffffff; + } + else + { + temp.funcid = bfd_get_16 (abfd, data + member - adj); + temp.funcname = (char *) data + member - adj + 2; + } + + /* If the time stamp is not zero, the import address + table holds actual addresses. */ +#if 0 + if (time_stamp != 0 + && first_thunk != 0 + && first_thunk != hint_addr) + fprintf (file, "\t%04lx", + (long) bfd_get_32 (abfd, ft_data + ft_idx + j)); +#endif + + func (abfd, library, &temp, user_storage); + } +#endif + if (ft_allocated) + free (ft_data); + + return TRUE; +} + +bfd_boolean +_bfd_XX_get_exports (bfd *abfd, bfd_boolean (*func) (bfd *, struct bfd_export *, void *), void *user_storage) +{ + bfd_byte *data; + asection *section; + bfd_size_type datasize = 0; + bfd_size_type dataoff; + bfd_size_type i; + bfd_signed_vma adj; + struct EDT_type + { + long export_flags; /* Reserved - should be zero. */ + long time_stamp; + short major_ver; + short minor_ver; + bfd_vma name; /* RVA - relative to image base. */ + long base; /* Ordinal base. */ + unsigned long num_functions;/* Number in the export address table. */ + unsigned long num_names; /* Number in the name pointer table. */ + bfd_vma eat_addr; /* RVA to the export address table. */ + bfd_vma npt_addr; /* RVA to the Export Name Pointer Table. */ + bfd_vma ot_addr; /* RVA to the Ordinal Table. */ + } edt; + + pe_data_type *pe = pe_data (abfd); + struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; + + bfd_vma addr; + + addr = extra->DataDirectory[PE_EXPORT_TABLE].VirtualAddress; + + if (addr == 0 && extra->DataDirectory[PE_EXPORT_TABLE].Size == 0) + { + /* Maybe the extra header isn't there. Look for the section. */ + section = bfd_get_section_by_name (abfd, ".edata"); + if (section == NULL) + return TRUE; + + addr = section->vma; + dataoff = 0; + datasize = section->size; + if (datasize == 0) + return TRUE; + } + else + { + addr += extra->ImageBase; + + for (section = abfd->sections; section != NULL; section = section->next) + if (addr >= section->vma && addr < section->vma + section->size) + break; + + if (section == NULL) + { + return FALSE; /* _("\nThere is an export table, but the section containing it could not be found\n") */ + } + + dataoff = addr - section->vma; + datasize = extra->DataDirectory[PE_EXPORT_TABLE].Size; + if (datasize > section->size - dataoff) + { + return FALSE; /* _("\nThere is an export table in %s, but it does not fit into that section\n") */ + } + } + + data = bfd_malloc (datasize); + if (data == NULL) + return FALSE; + + if (! bfd_get_section_contents (abfd, section, data, + (file_ptr) dataoff, datasize)) + return FALSE; + + /* Go get Export Directory Table. */ + edt.export_flags = bfd_get_32 (abfd, data + 0); + edt.time_stamp = bfd_get_32 (abfd, data + 4); + edt.major_ver = bfd_get_16 (abfd, data + 8); + edt.minor_ver = bfd_get_16 (abfd, data + 10); + edt.name = bfd_get_32 (abfd, data + 12); + edt.base = bfd_get_32 (abfd, data + 16); + edt.num_functions = bfd_get_32 (abfd, data + 20); + edt.num_names = bfd_get_32 (abfd, data + 24); + edt.eat_addr = bfd_get_32 (abfd, data + 28); + edt.npt_addr = bfd_get_32 (abfd, data + 32); + edt.ot_addr = bfd_get_32 (abfd, data + 36); + + adj = section->vma - extra->ImageBase + dataoff; + + /* XXX, we callback only functions which has got names */ + /* XXX, implement support for ordinal only */ + + /* The Export Name Pointer Table is paired with the Export Ordinal Table. */ + for (i = 0; i < edt.num_names; ++i) + { + struct bfd_export temp; + + bfd_vma name_ptr = bfd_get_32 (abfd, + data + + edt.npt_addr + + (i*4) - adj); + + bfd_vma ord = bfd_get_16 (abfd, + data + + edt.ot_addr + + (i*2) - adj); + + if (!(ord < edt.num_functions)) + continue; + + memset (&temp, 0, sizeof (struct bfd_export)); + temp.sec = NULL; + temp.vma = -1; + + { + bfd_vma eat_member = bfd_get_32 (abfd, + data + edt.eat_addr + (ord * 4) - adj); + if (eat_member == 0) + continue; + + if (eat_member - adj <= datasize) + { + /* This rva is to a name (forwarding function) in our section. */ + /* Should locate a function descriptor. */ +#if 0 + fprintf (file, + "\t[%4ld] +base[%4ld] %04lx %s -- %s\n", + (long) i, + (long) (i + edt.base), + (unsigned long) eat_member, + _("Forwarder RVA"), + data + eat_member - adj); +#endif + /* XXX, untested */ + continue; + } + else + { + /* XXX, what about (ord + edt.base) ? */ + /* Should locate a function descriptor in the reldata section. */ + temp.vma = extra->ImageBase + eat_member; + } + } + + temp.funcname = (char *) data + name_ptr - adj; + + func (abfd, &temp, user_storage); + } + + free (data); + + return TRUE; +} + +bfd_boolean +_bfd_XX_print_imports (bfd *abfd, void *vfile) +{ + return pe_print_idata (abfd, vfile); +} + +bfd_boolean +_bfd_XX_print_exports (bfd *abfd, void *vfile) +{ + return pe_print_edata (abfd, vfile); +} + + /* Print out the program headers. */ bfd_boolean @@ -1973,8 +2455,8 @@ _bfd_XX_print_private_bfd_data_common (b fprintf (file, "%s\n", dir_names[j]); } - pe_print_idata (abfd, vfile); - pe_print_edata (abfd, vfile); + _bfd_XX_print_imports (abfd, vfile); + _bfd_XX_print_exports (abfd, vfile); pe_print_pdata (abfd, vfile); pe_print_reloc (abfd, vfile); Index: peicode.h =================================================================== RCS file: /cvs/src/src/bfd/peicode.h,v retrieving revision 1.55 diff -u -p -r1.55 peicode.h --- peicode.h 12 Nov 2007 21:55:50 -0000 1.55 +++ peicode.h 16 Nov 2007 15:13:32 -0000 @@ -57,6 +57,8 @@ #include "libpei.h" +/* Copy */ + static bfd_boolean (*pe_saved_coff_bfd_print_private_bfd_data) (bfd *, void *) = #ifndef coff_bfd_print_private_bfd_data NULL; @@ -79,6 +81,30 @@ static bfd_boolean (*pe_saved_coff_bfd_c static bfd_boolean pe_bfd_copy_private_bfd_data (bfd *, bfd *); #define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data +/* IMPORTS */ + +#undef _bfd_noimport_bfd_get_libraries +static bfd_boolean pe_bfd_get_libraries (bfd *, bfd_boolean (*func) (bfd *, struct bfd_import_library *, void *), void *); +#define _bfd_noimport_bfd_get_libraries pe_bfd_get_libraries + +#undef _bfd_noimport_bfd_get_imports +static bfd_boolean pe_bfd_get_imports( bfd *, struct bfd_import_library *, bfd_boolean (*func) (bfd *, struct bfd_import_library *, struct bfd_import *, void *), void *); +#define _bfd_noimport_bfd_get_imports pe_bfd_get_imports + +#undef _bfd_noimport_bfd_get_exports +static bfd_boolean pe_bfd_get_exports( bfd *, bfd_boolean (*func) (bfd *, struct bfd_export *, void *), void *); +#define _bfd_noimport_bfd_get_exports pe_bfd_get_exports + +#undef _bfd_noimport_bfd_print_imports +static bfd_boolean pe_bfd_print_imports( bfd *, void *); +#define _bfd_noimport_bfd_print_imports pe_bfd_print_imports + +#undef _bfd_noimport_bfd_print_exports +static bfd_boolean pe_bfd_print_exports( bfd *, void *); +#define _bfd_noimport_bfd_print_exports pe_bfd_print_exports + +/* ... */ + #define coff_mkobject pe_mkobject #define coff_mkobject_hook pe_mkobject_hook @@ -369,6 +395,43 @@ pe_bfd_copy_private_bfd_data (bfd *ibfd, #define coff_bfd_copy_private_section_data \ _bfd_XX_bfd_copy_private_section_data + +/* Imports */ + +static bfd_boolean +pe_bfd_get_libraries( bfd *abfd, bfd_boolean (*func) (bfd *, struct bfd_import_library *, void *), void *user_storage) +{ + return _bfd_XX_get_libraries (abfd, func, user_storage); +} + +static bfd_boolean +pe_bfd_get_imports( bfd *abfd, struct bfd_import_library *library, bfd_boolean (*func) (bfd *, struct bfd_import_library *, struct bfd_import *, void *), void *user_storage) +{ + return _bfd_XX_get_imports (abfd, library, func, user_storage); +} + +static bfd_boolean +pe_bfd_get_exports( bfd *abfd, bfd_boolean (*func) (bfd *, struct bfd_export *, void *), void *user_storage) +{ + return _bfd_XX_get_exports (abfd, func, user_storage); +} + +static bfd_boolean +pe_bfd_print_imports( bfd *abfd, void * vfile) +{ + FILE *file = (FILE *) vfile; + + return _bfd_XX_print_imports (abfd, file); +} + +static bfd_boolean +pe_bfd_print_exports( bfd *abfd, void * vfile) +{ + FILE *file = (FILE *) vfile; + + return _bfd_XX_print_imports (abfd, file); +} + #define coff_get_symbol_info _bfd_XX_get_symbol_info #ifdef COFF_IMAGE_WITH_PE