1*a9fa9459Szrj /* Support for the generic parts of PE/PEI; the common executable parts. 2*a9fa9459Szrj Copyright (C) 1995-2016 Free Software Foundation, Inc. 3*a9fa9459Szrj Written by Cygnus Solutions. 4*a9fa9459Szrj 5*a9fa9459Szrj This file is part of BFD, the Binary File Descriptor library. 6*a9fa9459Szrj 7*a9fa9459Szrj This program is free software; you can redistribute it and/or modify 8*a9fa9459Szrj it under the terms of the GNU General Public License as published by 9*a9fa9459Szrj the Free Software Foundation; either version 3 of the License, or 10*a9fa9459Szrj (at your option) any later version. 11*a9fa9459Szrj 12*a9fa9459Szrj This program is distributed in the hope that it will be useful, 13*a9fa9459Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of 14*a9fa9459Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*a9fa9459Szrj GNU General Public License for more details. 16*a9fa9459Szrj 17*a9fa9459Szrj You should have received a copy of the GNU General Public License 18*a9fa9459Szrj along with this program; if not, write to the Free Software 19*a9fa9459Szrj Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20*a9fa9459Szrj MA 02110-1301, USA. */ 21*a9fa9459Szrj 22*a9fa9459Szrj 23*a9fa9459Szrj /* Most of this hacked by Steve Chamberlain <sac@cygnus.com>. 24*a9fa9459Szrj 25*a9fa9459Szrj PE/PEI rearrangement (and code added): Donn Terry 26*a9fa9459Szrj Softway Systems, Inc. */ 27*a9fa9459Szrj 28*a9fa9459Szrj /* Hey look, some documentation [and in a place you expect to find it]! 29*a9fa9459Szrj 30*a9fa9459Szrj The main reference for the pei format is "Microsoft Portable Executable 31*a9fa9459Szrj and Common Object File Format Specification 4.1". Get it if you need to 32*a9fa9459Szrj do some serious hacking on this code. 33*a9fa9459Szrj 34*a9fa9459Szrj Another reference: 35*a9fa9459Szrj "Peering Inside the PE: A Tour of the Win32 Portable Executable 36*a9fa9459Szrj File Format", MSJ 1994, Volume 9. 37*a9fa9459Szrj 38*a9fa9459Szrj The *sole* difference between the pe format and the pei format is that the 39*a9fa9459Szrj latter has an MSDOS 2.0 .exe header on the front that prints the message 40*a9fa9459Szrj "This app must be run under Windows." (or some such). 41*a9fa9459Szrj (FIXME: Whether that statement is *really* true or not is unknown. 42*a9fa9459Szrj Are there more subtle differences between pe and pei formats? 43*a9fa9459Szrj For now assume there aren't. If you find one, then for God sakes 44*a9fa9459Szrj document it here!) 45*a9fa9459Szrj 46*a9fa9459Szrj The Microsoft docs use the word "image" instead of "executable" because 47*a9fa9459Szrj the former can also refer to a DLL (shared library). Confusion can arise 48*a9fa9459Szrj because the `i' in `pei' also refers to "image". The `pe' format can 49*a9fa9459Szrj also create images (i.e. executables), it's just that to run on a win32 50*a9fa9459Szrj system you need to use the pei format. 51*a9fa9459Szrj 52*a9fa9459Szrj FIXME: Please add more docs here so the next poor fool that has to hack 53*a9fa9459Szrj on this code has a chance of getting something accomplished without 54*a9fa9459Szrj wasting too much time. */ 55*a9fa9459Szrj 56*a9fa9459Szrj /* This expands into COFF_WITH_pe, COFF_WITH_pep, or COFF_WITH_pex64 57*a9fa9459Szrj depending on whether we're compiling for straight PE or PE+. */ 58*a9fa9459Szrj #define COFF_WITH_XX 59*a9fa9459Szrj 60*a9fa9459Szrj #include "sysdep.h" 61*a9fa9459Szrj #include "bfd.h" 62*a9fa9459Szrj #include "libbfd.h" 63*a9fa9459Szrj #include "coff/internal.h" 64*a9fa9459Szrj #include "bfdver.h" 65*a9fa9459Szrj #include "libiberty.h" 66*a9fa9459Szrj #ifdef HAVE_WCHAR_H 67*a9fa9459Szrj #include <wchar.h> 68*a9fa9459Szrj #endif 69*a9fa9459Szrj #ifdef HAVE_WCTYPE_H 70*a9fa9459Szrj #include <wctype.h> 71*a9fa9459Szrj #endif 72*a9fa9459Szrj 73*a9fa9459Szrj /* NOTE: it's strange to be including an architecture specific header 74*a9fa9459Szrj in what's supposed to be general (to PE/PEI) code. However, that's 75*a9fa9459Szrj where the definitions are, and they don't vary per architecture 76*a9fa9459Szrj within PE/PEI, so we get them from there. FIXME: The lack of 77*a9fa9459Szrj variance is an assumption which may prove to be incorrect if new 78*a9fa9459Szrj PE/PEI targets are created. */ 79*a9fa9459Szrj #if defined COFF_WITH_pex64 80*a9fa9459Szrj # include "coff/x86_64.h" 81*a9fa9459Szrj #elif defined COFF_WITH_pep 82*a9fa9459Szrj # include "coff/ia64.h" 83*a9fa9459Szrj #else 84*a9fa9459Szrj # include "coff/i386.h" 85*a9fa9459Szrj #endif 86*a9fa9459Szrj 87*a9fa9459Szrj #include "coff/pe.h" 88*a9fa9459Szrj #include "libcoff.h" 89*a9fa9459Szrj #include "libpei.h" 90*a9fa9459Szrj #include "safe-ctype.h" 91*a9fa9459Szrj 92*a9fa9459Szrj #if defined COFF_WITH_pep || defined COFF_WITH_pex64 93*a9fa9459Szrj # undef AOUTSZ 94*a9fa9459Szrj # define AOUTSZ PEPAOUTSZ 95*a9fa9459Szrj # define PEAOUTHDR PEPAOUTHDR 96*a9fa9459Szrj #endif 97*a9fa9459Szrj 98*a9fa9459Szrj #define HighBitSet(val) ((val) & 0x80000000) 99*a9fa9459Szrj #define SetHighBit(val) ((val) | 0x80000000) 100*a9fa9459Szrj #define WithoutHighBit(val) ((val) & 0x7fffffff) 101*a9fa9459Szrj 102*a9fa9459Szrj /* FIXME: This file has various tests of POWERPC_LE_PE. Those tests 103*a9fa9459Szrj worked when the code was in peicode.h, but no longer work now that 104*a9fa9459Szrj the code is in peigen.c. PowerPC NT is said to be dead. If 105*a9fa9459Szrj anybody wants to revive the code, you will have to figure out how 106*a9fa9459Szrj to handle those issues. */ 107*a9fa9459Szrj 108*a9fa9459Szrj void 109*a9fa9459Szrj _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1) 110*a9fa9459Szrj { 111*a9fa9459Szrj SYMENT *ext = (SYMENT *) ext1; 112*a9fa9459Szrj struct internal_syment *in = (struct internal_syment *) in1; 113*a9fa9459Szrj 114*a9fa9459Szrj if (ext->e.e_name[0] == 0) 115*a9fa9459Szrj { 116*a9fa9459Szrj in->_n._n_n._n_zeroes = 0; 117*a9fa9459Szrj in->_n._n_n._n_offset = H_GET_32 (abfd, ext->e.e.e_offset); 118*a9fa9459Szrj } 119*a9fa9459Szrj else 120*a9fa9459Szrj memcpy (in->_n._n_name, ext->e.e_name, SYMNMLEN); 121*a9fa9459Szrj 122*a9fa9459Szrj in->n_value = H_GET_32 (abfd, ext->e_value); 123*a9fa9459Szrj in->n_scnum = (short) H_GET_16 (abfd, ext->e_scnum); 124*a9fa9459Szrj 125*a9fa9459Szrj if (sizeof (ext->e_type) == 2) 126*a9fa9459Szrj in->n_type = H_GET_16 (abfd, ext->e_type); 127*a9fa9459Szrj else 128*a9fa9459Szrj in->n_type = H_GET_32 (abfd, ext->e_type); 129*a9fa9459Szrj 130*a9fa9459Szrj in->n_sclass = H_GET_8 (abfd, ext->e_sclass); 131*a9fa9459Szrj in->n_numaux = H_GET_8 (abfd, ext->e_numaux); 132*a9fa9459Szrj 133*a9fa9459Szrj #ifndef STRICT_PE_FORMAT 134*a9fa9459Szrj /* This is for Gnu-created DLLs. */ 135*a9fa9459Szrj 136*a9fa9459Szrj /* The section symbols for the .idata$ sections have class 0x68 137*a9fa9459Szrj (C_SECTION), which MS documentation indicates is a section 138*a9fa9459Szrj symbol. Unfortunately, the value field in the symbol is simply a 139*a9fa9459Szrj copy of the .idata section's flags rather than something useful. 140*a9fa9459Szrj When these symbols are encountered, change the value to 0 so that 141*a9fa9459Szrj they will be handled somewhat correctly in the bfd code. */ 142*a9fa9459Szrj if (in->n_sclass == C_SECTION) 143*a9fa9459Szrj { 144*a9fa9459Szrj char namebuf[SYMNMLEN + 1]; 145*a9fa9459Szrj const char *name = NULL; 146*a9fa9459Szrj 147*a9fa9459Szrj in->n_value = 0x0; 148*a9fa9459Szrj 149*a9fa9459Szrj /* Create synthetic empty sections as needed. DJ */ 150*a9fa9459Szrj if (in->n_scnum == 0) 151*a9fa9459Szrj { 152*a9fa9459Szrj asection *sec; 153*a9fa9459Szrj 154*a9fa9459Szrj name = _bfd_coff_internal_syment_name (abfd, in, namebuf); 155*a9fa9459Szrj if (name == NULL) 156*a9fa9459Szrj { 157*a9fa9459Szrj _bfd_error_handler (_("%B: unable to find name for empty section"), 158*a9fa9459Szrj abfd); 159*a9fa9459Szrj bfd_set_error (bfd_error_invalid_target); 160*a9fa9459Szrj return; 161*a9fa9459Szrj } 162*a9fa9459Szrj 163*a9fa9459Szrj sec = bfd_get_section_by_name (abfd, name); 164*a9fa9459Szrj if (sec != NULL) 165*a9fa9459Szrj in->n_scnum = sec->target_index; 166*a9fa9459Szrj } 167*a9fa9459Szrj 168*a9fa9459Szrj if (in->n_scnum == 0) 169*a9fa9459Szrj { 170*a9fa9459Szrj int unused_section_number = 0; 171*a9fa9459Szrj asection *sec; 172*a9fa9459Szrj flagword flags; 173*a9fa9459Szrj 174*a9fa9459Szrj for (sec = abfd->sections; sec; sec = sec->next) 175*a9fa9459Szrj if (unused_section_number <= sec->target_index) 176*a9fa9459Szrj unused_section_number = sec->target_index + 1; 177*a9fa9459Szrj 178*a9fa9459Szrj if (name == namebuf) 179*a9fa9459Szrj { 180*a9fa9459Szrj name = (const char *) bfd_alloc (abfd, strlen (namebuf) + 1); 181*a9fa9459Szrj if (name == NULL) 182*a9fa9459Szrj { 183*a9fa9459Szrj _bfd_error_handler (_("%B: out of memory creating name for empty section"), 184*a9fa9459Szrj abfd); 185*a9fa9459Szrj return; 186*a9fa9459Szrj } 187*a9fa9459Szrj strcpy ((char *) name, namebuf); 188*a9fa9459Szrj } 189*a9fa9459Szrj 190*a9fa9459Szrj flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD; 191*a9fa9459Szrj sec = bfd_make_section_anyway_with_flags (abfd, name, flags); 192*a9fa9459Szrj if (sec == NULL) 193*a9fa9459Szrj { 194*a9fa9459Szrj _bfd_error_handler (_("%B: unable to create fake empty section"), 195*a9fa9459Szrj abfd); 196*a9fa9459Szrj return; 197*a9fa9459Szrj } 198*a9fa9459Szrj 199*a9fa9459Szrj sec->vma = 0; 200*a9fa9459Szrj sec->lma = 0; 201*a9fa9459Szrj sec->size = 0; 202*a9fa9459Szrj sec->filepos = 0; 203*a9fa9459Szrj sec->rel_filepos = 0; 204*a9fa9459Szrj sec->reloc_count = 0; 205*a9fa9459Szrj sec->line_filepos = 0; 206*a9fa9459Szrj sec->lineno_count = 0; 207*a9fa9459Szrj sec->userdata = NULL; 208*a9fa9459Szrj sec->next = NULL; 209*a9fa9459Szrj sec->alignment_power = 2; 210*a9fa9459Szrj 211*a9fa9459Szrj sec->target_index = unused_section_number; 212*a9fa9459Szrj 213*a9fa9459Szrj in->n_scnum = unused_section_number; 214*a9fa9459Szrj } 215*a9fa9459Szrj in->n_sclass = C_STAT; 216*a9fa9459Szrj } 217*a9fa9459Szrj #endif 218*a9fa9459Szrj 219*a9fa9459Szrj #ifdef coff_swap_sym_in_hook 220*a9fa9459Szrj /* This won't work in peigen.c, but since it's for PPC PE, it's not 221*a9fa9459Szrj worth fixing. */ 222*a9fa9459Szrj coff_swap_sym_in_hook (abfd, ext1, in1); 223*a9fa9459Szrj #endif 224*a9fa9459Szrj } 225*a9fa9459Szrj 226*a9fa9459Szrj static bfd_boolean 227*a9fa9459Szrj abs_finder (bfd * abfd ATTRIBUTE_UNUSED, asection * sec, void * data) 228*a9fa9459Szrj { 229*a9fa9459Szrj bfd_vma abs_val = * (bfd_vma *) data; 230*a9fa9459Szrj 231*a9fa9459Szrj return (sec->vma <= abs_val) && ((sec->vma + (1ULL << 32)) > abs_val); 232*a9fa9459Szrj } 233*a9fa9459Szrj 234*a9fa9459Szrj unsigned int 235*a9fa9459Szrj _bfd_XXi_swap_sym_out (bfd * abfd, void * inp, void * extp) 236*a9fa9459Szrj { 237*a9fa9459Szrj struct internal_syment *in = (struct internal_syment *) inp; 238*a9fa9459Szrj SYMENT *ext = (SYMENT *) extp; 239*a9fa9459Szrj 240*a9fa9459Szrj if (in->_n._n_name[0] == 0) 241*a9fa9459Szrj { 242*a9fa9459Szrj H_PUT_32 (abfd, 0, ext->e.e.e_zeroes); 243*a9fa9459Szrj H_PUT_32 (abfd, in->_n._n_n._n_offset, ext->e.e.e_offset); 244*a9fa9459Szrj } 245*a9fa9459Szrj else 246*a9fa9459Szrj memcpy (ext->e.e_name, in->_n._n_name, SYMNMLEN); 247*a9fa9459Szrj 248*a9fa9459Szrj /* The PE32 and PE32+ formats only use 4 bytes to hold the value of a 249*a9fa9459Szrj symbol. This is a problem on 64-bit targets where we can generate 250*a9fa9459Szrj absolute symbols with values >= 1^32. We try to work around this 251*a9fa9459Szrj problem by finding a section whose base address is sufficient to 252*a9fa9459Szrj reduce the absolute value to < 1^32, and then transforming the 253*a9fa9459Szrj symbol into a section relative symbol. This of course is a hack. */ 254*a9fa9459Szrj if (sizeof (in->n_value) > 4 255*a9fa9459Szrj /* The strange computation of the shift amount is here in order to 256*a9fa9459Szrj avoid a compile time warning about the comparison always being 257*a9fa9459Szrj false. It does not matter if this test fails to work as expected 258*a9fa9459Szrj as the worst that can happen is that some absolute symbols are 259*a9fa9459Szrj needlessly converted into section relative symbols. */ 260*a9fa9459Szrj && in->n_value > ((1ULL << (sizeof (in->n_value) > 4 ? 32 : 31)) - 1) 261*a9fa9459Szrj && in->n_scnum == N_ABS) 262*a9fa9459Szrj { 263*a9fa9459Szrj asection * sec; 264*a9fa9459Szrj 265*a9fa9459Szrj sec = bfd_sections_find_if (abfd, abs_finder, & in->n_value); 266*a9fa9459Szrj if (sec) 267*a9fa9459Szrj { 268*a9fa9459Szrj in->n_value -= sec->vma; 269*a9fa9459Szrj in->n_scnum = sec->target_index; 270*a9fa9459Szrj } 271*a9fa9459Szrj /* else: FIXME: The value is outside the range of any section. This 272*a9fa9459Szrj happens for __image_base__ and __ImageBase and maybe some other 273*a9fa9459Szrj symbols as well. We should find a way to handle these values. */ 274*a9fa9459Szrj } 275*a9fa9459Szrj 276*a9fa9459Szrj H_PUT_32 (abfd, in->n_value, ext->e_value); 277*a9fa9459Szrj H_PUT_16 (abfd, in->n_scnum, ext->e_scnum); 278*a9fa9459Szrj 279*a9fa9459Szrj if (sizeof (ext->e_type) == 2) 280*a9fa9459Szrj H_PUT_16 (abfd, in->n_type, ext->e_type); 281*a9fa9459Szrj else 282*a9fa9459Szrj H_PUT_32 (abfd, in->n_type, ext->e_type); 283*a9fa9459Szrj 284*a9fa9459Szrj H_PUT_8 (abfd, in->n_sclass, ext->e_sclass); 285*a9fa9459Szrj H_PUT_8 (abfd, in->n_numaux, ext->e_numaux); 286*a9fa9459Szrj 287*a9fa9459Szrj return SYMESZ; 288*a9fa9459Szrj } 289*a9fa9459Szrj 290*a9fa9459Szrj void 291*a9fa9459Szrj _bfd_XXi_swap_aux_in (bfd * abfd, 292*a9fa9459Szrj void * ext1, 293*a9fa9459Szrj int type, 294*a9fa9459Szrj int in_class, 295*a9fa9459Szrj int indx ATTRIBUTE_UNUSED, 296*a9fa9459Szrj int numaux ATTRIBUTE_UNUSED, 297*a9fa9459Szrj void * in1) 298*a9fa9459Szrj { 299*a9fa9459Szrj AUXENT *ext = (AUXENT *) ext1; 300*a9fa9459Szrj union internal_auxent *in = (union internal_auxent *) in1; 301*a9fa9459Szrj 302*a9fa9459Szrj /* PR 17521: Make sure that all fields in the aux structure 303*a9fa9459Szrj are initialised. */ 304*a9fa9459Szrj memset (in, 0, sizeof * in); 305*a9fa9459Szrj switch (in_class) 306*a9fa9459Szrj { 307*a9fa9459Szrj case C_FILE: 308*a9fa9459Szrj if (ext->x_file.x_fname[0] == 0) 309*a9fa9459Szrj { 310*a9fa9459Szrj in->x_file.x_n.x_zeroes = 0; 311*a9fa9459Szrj in->x_file.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset); 312*a9fa9459Szrj } 313*a9fa9459Szrj else 314*a9fa9459Szrj memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN); 315*a9fa9459Szrj return; 316*a9fa9459Szrj 317*a9fa9459Szrj case C_STAT: 318*a9fa9459Szrj case C_LEAFSTAT: 319*a9fa9459Szrj case C_HIDDEN: 320*a9fa9459Szrj if (type == T_NULL) 321*a9fa9459Szrj { 322*a9fa9459Szrj in->x_scn.x_scnlen = GET_SCN_SCNLEN (abfd, ext); 323*a9fa9459Szrj in->x_scn.x_nreloc = GET_SCN_NRELOC (abfd, ext); 324*a9fa9459Szrj in->x_scn.x_nlinno = GET_SCN_NLINNO (abfd, ext); 325*a9fa9459Szrj in->x_scn.x_checksum = H_GET_32 (abfd, ext->x_scn.x_checksum); 326*a9fa9459Szrj in->x_scn.x_associated = H_GET_16 (abfd, ext->x_scn.x_associated); 327*a9fa9459Szrj in->x_scn.x_comdat = H_GET_8 (abfd, ext->x_scn.x_comdat); 328*a9fa9459Szrj return; 329*a9fa9459Szrj } 330*a9fa9459Szrj break; 331*a9fa9459Szrj } 332*a9fa9459Szrj 333*a9fa9459Szrj in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx); 334*a9fa9459Szrj in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx); 335*a9fa9459Szrj 336*a9fa9459Szrj if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type) 337*a9fa9459Szrj || ISTAG (in_class)) 338*a9fa9459Szrj { 339*a9fa9459Szrj in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext); 340*a9fa9459Szrj in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext); 341*a9fa9459Szrj } 342*a9fa9459Szrj else 343*a9fa9459Szrj { 344*a9fa9459Szrj in->x_sym.x_fcnary.x_ary.x_dimen[0] = 345*a9fa9459Szrj H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[0]); 346*a9fa9459Szrj in->x_sym.x_fcnary.x_ary.x_dimen[1] = 347*a9fa9459Szrj H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[1]); 348*a9fa9459Szrj in->x_sym.x_fcnary.x_ary.x_dimen[2] = 349*a9fa9459Szrj H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[2]); 350*a9fa9459Szrj in->x_sym.x_fcnary.x_ary.x_dimen[3] = 351*a9fa9459Szrj H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[3]); 352*a9fa9459Szrj } 353*a9fa9459Szrj 354*a9fa9459Szrj if (ISFCN (type)) 355*a9fa9459Szrj { 356*a9fa9459Szrj in->x_sym.x_misc.x_fsize = H_GET_32 (abfd, ext->x_sym.x_misc.x_fsize); 357*a9fa9459Szrj } 358*a9fa9459Szrj else 359*a9fa9459Szrj { 360*a9fa9459Szrj in->x_sym.x_misc.x_lnsz.x_lnno = GET_LNSZ_LNNO (abfd, ext); 361*a9fa9459Szrj in->x_sym.x_misc.x_lnsz.x_size = GET_LNSZ_SIZE (abfd, ext); 362*a9fa9459Szrj } 363*a9fa9459Szrj } 364*a9fa9459Szrj 365*a9fa9459Szrj unsigned int 366*a9fa9459Szrj _bfd_XXi_swap_aux_out (bfd * abfd, 367*a9fa9459Szrj void * inp, 368*a9fa9459Szrj int type, 369*a9fa9459Szrj int in_class, 370*a9fa9459Szrj int indx ATTRIBUTE_UNUSED, 371*a9fa9459Szrj int numaux ATTRIBUTE_UNUSED, 372*a9fa9459Szrj void * extp) 373*a9fa9459Szrj { 374*a9fa9459Szrj union internal_auxent *in = (union internal_auxent *) inp; 375*a9fa9459Szrj AUXENT *ext = (AUXENT *) extp; 376*a9fa9459Szrj 377*a9fa9459Szrj memset (ext, 0, AUXESZ); 378*a9fa9459Szrj 379*a9fa9459Szrj switch (in_class) 380*a9fa9459Szrj { 381*a9fa9459Szrj case C_FILE: 382*a9fa9459Szrj if (in->x_file.x_fname[0] == 0) 383*a9fa9459Szrj { 384*a9fa9459Szrj H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes); 385*a9fa9459Szrj H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset); 386*a9fa9459Szrj } 387*a9fa9459Szrj else 388*a9fa9459Szrj memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN); 389*a9fa9459Szrj 390*a9fa9459Szrj return AUXESZ; 391*a9fa9459Szrj 392*a9fa9459Szrj case C_STAT: 393*a9fa9459Szrj case C_LEAFSTAT: 394*a9fa9459Szrj case C_HIDDEN: 395*a9fa9459Szrj if (type == T_NULL) 396*a9fa9459Szrj { 397*a9fa9459Szrj PUT_SCN_SCNLEN (abfd, in->x_scn.x_scnlen, ext); 398*a9fa9459Szrj PUT_SCN_NRELOC (abfd, in->x_scn.x_nreloc, ext); 399*a9fa9459Szrj PUT_SCN_NLINNO (abfd, in->x_scn.x_nlinno, ext); 400*a9fa9459Szrj H_PUT_32 (abfd, in->x_scn.x_checksum, ext->x_scn.x_checksum); 401*a9fa9459Szrj H_PUT_16 (abfd, in->x_scn.x_associated, ext->x_scn.x_associated); 402*a9fa9459Szrj H_PUT_8 (abfd, in->x_scn.x_comdat, ext->x_scn.x_comdat); 403*a9fa9459Szrj return AUXESZ; 404*a9fa9459Szrj } 405*a9fa9459Szrj break; 406*a9fa9459Szrj } 407*a9fa9459Szrj 408*a9fa9459Szrj H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx); 409*a9fa9459Szrj H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx); 410*a9fa9459Szrj 411*a9fa9459Szrj if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type) 412*a9fa9459Szrj || ISTAG (in_class)) 413*a9fa9459Szrj { 414*a9fa9459Szrj PUT_FCN_LNNOPTR (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext); 415*a9fa9459Szrj PUT_FCN_ENDNDX (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext); 416*a9fa9459Szrj } 417*a9fa9459Szrj else 418*a9fa9459Szrj { 419*a9fa9459Szrj H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0], 420*a9fa9459Szrj ext->x_sym.x_fcnary.x_ary.x_dimen[0]); 421*a9fa9459Szrj H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1], 422*a9fa9459Szrj ext->x_sym.x_fcnary.x_ary.x_dimen[1]); 423*a9fa9459Szrj H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2], 424*a9fa9459Szrj ext->x_sym.x_fcnary.x_ary.x_dimen[2]); 425*a9fa9459Szrj H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3], 426*a9fa9459Szrj ext->x_sym.x_fcnary.x_ary.x_dimen[3]); 427*a9fa9459Szrj } 428*a9fa9459Szrj 429*a9fa9459Szrj if (ISFCN (type)) 430*a9fa9459Szrj H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_sym.x_misc.x_fsize); 431*a9fa9459Szrj else 432*a9fa9459Szrj { 433*a9fa9459Szrj PUT_LNSZ_LNNO (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext); 434*a9fa9459Szrj PUT_LNSZ_SIZE (abfd, in->x_sym.x_misc.x_lnsz.x_size, ext); 435*a9fa9459Szrj } 436*a9fa9459Szrj 437*a9fa9459Szrj return AUXESZ; 438*a9fa9459Szrj } 439*a9fa9459Szrj 440*a9fa9459Szrj void 441*a9fa9459Szrj _bfd_XXi_swap_lineno_in (bfd * abfd, void * ext1, void * in1) 442*a9fa9459Szrj { 443*a9fa9459Szrj LINENO *ext = (LINENO *) ext1; 444*a9fa9459Szrj struct internal_lineno *in = (struct internal_lineno *) in1; 445*a9fa9459Szrj 446*a9fa9459Szrj in->l_addr.l_symndx = H_GET_32 (abfd, ext->l_addr.l_symndx); 447*a9fa9459Szrj in->l_lnno = GET_LINENO_LNNO (abfd, ext); 448*a9fa9459Szrj } 449*a9fa9459Szrj 450*a9fa9459Szrj unsigned int 451*a9fa9459Szrj _bfd_XXi_swap_lineno_out (bfd * abfd, void * inp, void * outp) 452*a9fa9459Szrj { 453*a9fa9459Szrj struct internal_lineno *in = (struct internal_lineno *) inp; 454*a9fa9459Szrj struct external_lineno *ext = (struct external_lineno *) outp; 455*a9fa9459Szrj H_PUT_32 (abfd, in->l_addr.l_symndx, ext->l_addr.l_symndx); 456*a9fa9459Szrj 457*a9fa9459Szrj PUT_LINENO_LNNO (abfd, in->l_lnno, ext); 458*a9fa9459Szrj return LINESZ; 459*a9fa9459Szrj } 460*a9fa9459Szrj 461*a9fa9459Szrj void 462*a9fa9459Szrj _bfd_XXi_swap_aouthdr_in (bfd * abfd, 463*a9fa9459Szrj void * aouthdr_ext1, 464*a9fa9459Szrj void * aouthdr_int1) 465*a9fa9459Szrj { 466*a9fa9459Szrj PEAOUTHDR * src = (PEAOUTHDR *) aouthdr_ext1; 467*a9fa9459Szrj AOUTHDR * aouthdr_ext = (AOUTHDR *) aouthdr_ext1; 468*a9fa9459Szrj struct internal_aouthdr *aouthdr_int 469*a9fa9459Szrj = (struct internal_aouthdr *) aouthdr_int1; 470*a9fa9459Szrj struct internal_extra_pe_aouthdr *a = &aouthdr_int->pe; 471*a9fa9459Szrj 472*a9fa9459Szrj aouthdr_int->magic = H_GET_16 (abfd, aouthdr_ext->magic); 473*a9fa9459Szrj aouthdr_int->vstamp = H_GET_16 (abfd, aouthdr_ext->vstamp); 474*a9fa9459Szrj aouthdr_int->tsize = GET_AOUTHDR_TSIZE (abfd, aouthdr_ext->tsize); 475*a9fa9459Szrj aouthdr_int->dsize = GET_AOUTHDR_DSIZE (abfd, aouthdr_ext->dsize); 476*a9fa9459Szrj aouthdr_int->bsize = GET_AOUTHDR_BSIZE (abfd, aouthdr_ext->bsize); 477*a9fa9459Szrj aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry); 478*a9fa9459Szrj aouthdr_int->text_start = 479*a9fa9459Szrj GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start); 480*a9fa9459Szrj 481*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 482*a9fa9459Szrj /* PE32+ does not have data_start member! */ 483*a9fa9459Szrj aouthdr_int->data_start = 484*a9fa9459Szrj GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start); 485*a9fa9459Szrj a->BaseOfData = aouthdr_int->data_start; 486*a9fa9459Szrj #endif 487*a9fa9459Szrj 488*a9fa9459Szrj a->Magic = aouthdr_int->magic; 489*a9fa9459Szrj a->MajorLinkerVersion = H_GET_8 (abfd, aouthdr_ext->vstamp); 490*a9fa9459Szrj a->MinorLinkerVersion = H_GET_8 (abfd, aouthdr_ext->vstamp + 1); 491*a9fa9459Szrj a->SizeOfCode = aouthdr_int->tsize ; 492*a9fa9459Szrj a->SizeOfInitializedData = aouthdr_int->dsize ; 493*a9fa9459Szrj a->SizeOfUninitializedData = aouthdr_int->bsize ; 494*a9fa9459Szrj a->AddressOfEntryPoint = aouthdr_int->entry; 495*a9fa9459Szrj a->BaseOfCode = aouthdr_int->text_start; 496*a9fa9459Szrj a->ImageBase = GET_OPTHDR_IMAGE_BASE (abfd, src->ImageBase); 497*a9fa9459Szrj a->SectionAlignment = H_GET_32 (abfd, src->SectionAlignment); 498*a9fa9459Szrj a->FileAlignment = H_GET_32 (abfd, src->FileAlignment); 499*a9fa9459Szrj a->MajorOperatingSystemVersion = 500*a9fa9459Szrj H_GET_16 (abfd, src->MajorOperatingSystemVersion); 501*a9fa9459Szrj a->MinorOperatingSystemVersion = 502*a9fa9459Szrj H_GET_16 (abfd, src->MinorOperatingSystemVersion); 503*a9fa9459Szrj a->MajorImageVersion = H_GET_16 (abfd, src->MajorImageVersion); 504*a9fa9459Szrj a->MinorImageVersion = H_GET_16 (abfd, src->MinorImageVersion); 505*a9fa9459Szrj a->MajorSubsystemVersion = H_GET_16 (abfd, src->MajorSubsystemVersion); 506*a9fa9459Szrj a->MinorSubsystemVersion = H_GET_16 (abfd, src->MinorSubsystemVersion); 507*a9fa9459Szrj a->Reserved1 = H_GET_32 (abfd, src->Reserved1); 508*a9fa9459Szrj a->SizeOfImage = H_GET_32 (abfd, src->SizeOfImage); 509*a9fa9459Szrj a->SizeOfHeaders = H_GET_32 (abfd, src->SizeOfHeaders); 510*a9fa9459Szrj a->CheckSum = H_GET_32 (abfd, src->CheckSum); 511*a9fa9459Szrj a->Subsystem = H_GET_16 (abfd, src->Subsystem); 512*a9fa9459Szrj a->DllCharacteristics = H_GET_16 (abfd, src->DllCharacteristics); 513*a9fa9459Szrj a->SizeOfStackReserve = 514*a9fa9459Szrj GET_OPTHDR_SIZE_OF_STACK_RESERVE (abfd, src->SizeOfStackReserve); 515*a9fa9459Szrj a->SizeOfStackCommit = 516*a9fa9459Szrj GET_OPTHDR_SIZE_OF_STACK_COMMIT (abfd, src->SizeOfStackCommit); 517*a9fa9459Szrj a->SizeOfHeapReserve = 518*a9fa9459Szrj GET_OPTHDR_SIZE_OF_HEAP_RESERVE (abfd, src->SizeOfHeapReserve); 519*a9fa9459Szrj a->SizeOfHeapCommit = 520*a9fa9459Szrj GET_OPTHDR_SIZE_OF_HEAP_COMMIT (abfd, src->SizeOfHeapCommit); 521*a9fa9459Szrj a->LoaderFlags = H_GET_32 (abfd, src->LoaderFlags); 522*a9fa9459Szrj a->NumberOfRvaAndSizes = H_GET_32 (abfd, src->NumberOfRvaAndSizes); 523*a9fa9459Szrj 524*a9fa9459Szrj { 525*a9fa9459Szrj int idx; 526*a9fa9459Szrj 527*a9fa9459Szrj /* PR 17512: Corrupt PE binaries can cause seg-faults. */ 528*a9fa9459Szrj if (a->NumberOfRvaAndSizes > IMAGE_NUMBEROF_DIRECTORY_ENTRIES) 529*a9fa9459Szrj { 530*a9fa9459Szrj (*_bfd_error_handler) 531*a9fa9459Szrj (_("%B: aout header specifies an invalid number of data-directory entries: %d"), 532*a9fa9459Szrj abfd, a->NumberOfRvaAndSizes); 533*a9fa9459Szrj bfd_set_error (bfd_error_bad_value); 534*a9fa9459Szrj 535*a9fa9459Szrj /* Paranoia: If the number is corrupt, then assume that the 536*a9fa9459Szrj actual entries themselves might be corrupt as well. */ 537*a9fa9459Szrj a->NumberOfRvaAndSizes = 0; 538*a9fa9459Szrj } 539*a9fa9459Szrj 540*a9fa9459Szrj for (idx = 0; idx < a->NumberOfRvaAndSizes; idx++) 541*a9fa9459Szrj { 542*a9fa9459Szrj /* If data directory is empty, rva also should be 0. */ 543*a9fa9459Szrj int size = 544*a9fa9459Szrj H_GET_32 (abfd, src->DataDirectory[idx][1]); 545*a9fa9459Szrj 546*a9fa9459Szrj a->DataDirectory[idx].Size = size; 547*a9fa9459Szrj 548*a9fa9459Szrj if (size) 549*a9fa9459Szrj a->DataDirectory[idx].VirtualAddress = 550*a9fa9459Szrj H_GET_32 (abfd, src->DataDirectory[idx][0]); 551*a9fa9459Szrj else 552*a9fa9459Szrj a->DataDirectory[idx].VirtualAddress = 0; 553*a9fa9459Szrj } 554*a9fa9459Szrj 555*a9fa9459Szrj while (idx < IMAGE_NUMBEROF_DIRECTORY_ENTRIES) 556*a9fa9459Szrj { 557*a9fa9459Szrj a->DataDirectory[idx].Size = 0; 558*a9fa9459Szrj a->DataDirectory[idx].VirtualAddress = 0; 559*a9fa9459Szrj idx ++; 560*a9fa9459Szrj } 561*a9fa9459Szrj } 562*a9fa9459Szrj 563*a9fa9459Szrj if (aouthdr_int->entry) 564*a9fa9459Szrj { 565*a9fa9459Szrj aouthdr_int->entry += a->ImageBase; 566*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 567*a9fa9459Szrj aouthdr_int->entry &= 0xffffffff; 568*a9fa9459Szrj #endif 569*a9fa9459Szrj } 570*a9fa9459Szrj 571*a9fa9459Szrj if (aouthdr_int->tsize) 572*a9fa9459Szrj { 573*a9fa9459Szrj aouthdr_int->text_start += a->ImageBase; 574*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 575*a9fa9459Szrj aouthdr_int->text_start &= 0xffffffff; 576*a9fa9459Szrj #endif 577*a9fa9459Szrj } 578*a9fa9459Szrj 579*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 580*a9fa9459Szrj /* PE32+ does not have data_start member! */ 581*a9fa9459Szrj if (aouthdr_int->dsize) 582*a9fa9459Szrj { 583*a9fa9459Szrj aouthdr_int->data_start += a->ImageBase; 584*a9fa9459Szrj aouthdr_int->data_start &= 0xffffffff; 585*a9fa9459Szrj } 586*a9fa9459Szrj #endif 587*a9fa9459Szrj 588*a9fa9459Szrj #ifdef POWERPC_LE_PE 589*a9fa9459Szrj /* These three fields are normally set up by ppc_relocate_section. 590*a9fa9459Szrj In the case of reading a file in, we can pick them up from the 591*a9fa9459Szrj DataDirectory. */ 592*a9fa9459Szrj first_thunk_address = a->DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress; 593*a9fa9459Szrj thunk_size = a->DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size; 594*a9fa9459Szrj import_table_size = a->DataDirectory[PE_IMPORT_TABLE].Size; 595*a9fa9459Szrj #endif 596*a9fa9459Szrj } 597*a9fa9459Szrj 598*a9fa9459Szrj /* A support function for below. */ 599*a9fa9459Szrj 600*a9fa9459Szrj static void 601*a9fa9459Szrj add_data_entry (bfd * abfd, 602*a9fa9459Szrj struct internal_extra_pe_aouthdr *aout, 603*a9fa9459Szrj int idx, 604*a9fa9459Szrj char *name, 605*a9fa9459Szrj bfd_vma base) 606*a9fa9459Szrj { 607*a9fa9459Szrj asection *sec = bfd_get_section_by_name (abfd, name); 608*a9fa9459Szrj 609*a9fa9459Szrj /* Add import directory information if it exists. */ 610*a9fa9459Szrj if ((sec != NULL) 611*a9fa9459Szrj && (coff_section_data (abfd, sec) != NULL) 612*a9fa9459Szrj && (pei_section_data (abfd, sec) != NULL)) 613*a9fa9459Szrj { 614*a9fa9459Szrj /* If data directory is empty, rva also should be 0. */ 615*a9fa9459Szrj int size = pei_section_data (abfd, sec)->virt_size; 616*a9fa9459Szrj aout->DataDirectory[idx].Size = size; 617*a9fa9459Szrj 618*a9fa9459Szrj if (size) 619*a9fa9459Szrj { 620*a9fa9459Szrj aout->DataDirectory[idx].VirtualAddress = 621*a9fa9459Szrj (sec->vma - base) & 0xffffffff; 622*a9fa9459Szrj sec->flags |= SEC_DATA; 623*a9fa9459Szrj } 624*a9fa9459Szrj } 625*a9fa9459Szrj } 626*a9fa9459Szrj 627*a9fa9459Szrj unsigned int 628*a9fa9459Szrj _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out) 629*a9fa9459Szrj { 630*a9fa9459Szrj struct internal_aouthdr *aouthdr_in = (struct internal_aouthdr *) in; 631*a9fa9459Szrj pe_data_type *pe = pe_data (abfd); 632*a9fa9459Szrj struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; 633*a9fa9459Szrj PEAOUTHDR *aouthdr_out = (PEAOUTHDR *) out; 634*a9fa9459Szrj bfd_vma sa, fa, ib; 635*a9fa9459Szrj IMAGE_DATA_DIRECTORY idata2, idata5, tls; 636*a9fa9459Szrj 637*a9fa9459Szrj sa = extra->SectionAlignment; 638*a9fa9459Szrj fa = extra->FileAlignment; 639*a9fa9459Szrj ib = extra->ImageBase; 640*a9fa9459Szrj 641*a9fa9459Szrj idata2 = pe->pe_opthdr.DataDirectory[PE_IMPORT_TABLE]; 642*a9fa9459Szrj idata5 = pe->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE]; 643*a9fa9459Szrj tls = pe->pe_opthdr.DataDirectory[PE_TLS_TABLE]; 644*a9fa9459Szrj 645*a9fa9459Szrj if (aouthdr_in->tsize) 646*a9fa9459Szrj { 647*a9fa9459Szrj aouthdr_in->text_start -= ib; 648*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 649*a9fa9459Szrj aouthdr_in->text_start &= 0xffffffff; 650*a9fa9459Szrj #endif 651*a9fa9459Szrj } 652*a9fa9459Szrj 653*a9fa9459Szrj if (aouthdr_in->dsize) 654*a9fa9459Szrj { 655*a9fa9459Szrj aouthdr_in->data_start -= ib; 656*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 657*a9fa9459Szrj aouthdr_in->data_start &= 0xffffffff; 658*a9fa9459Szrj #endif 659*a9fa9459Szrj } 660*a9fa9459Szrj 661*a9fa9459Szrj if (aouthdr_in->entry) 662*a9fa9459Szrj { 663*a9fa9459Szrj aouthdr_in->entry -= ib; 664*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 665*a9fa9459Szrj aouthdr_in->entry &= 0xffffffff; 666*a9fa9459Szrj #endif 667*a9fa9459Szrj } 668*a9fa9459Szrj 669*a9fa9459Szrj #define FA(x) (((x) + fa -1 ) & (- fa)) 670*a9fa9459Szrj #define SA(x) (((x) + sa -1 ) & (- sa)) 671*a9fa9459Szrj 672*a9fa9459Szrj /* We like to have the sizes aligned. */ 673*a9fa9459Szrj aouthdr_in->bsize = FA (aouthdr_in->bsize); 674*a9fa9459Szrj 675*a9fa9459Szrj extra->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 676*a9fa9459Szrj 677*a9fa9459Szrj add_data_entry (abfd, extra, 0, ".edata", ib); 678*a9fa9459Szrj add_data_entry (abfd, extra, 2, ".rsrc", ib); 679*a9fa9459Szrj add_data_entry (abfd, extra, 3, ".pdata", ib); 680*a9fa9459Szrj 681*a9fa9459Szrj /* In theory we do not need to call add_data_entry for .idata$2 or 682*a9fa9459Szrj .idata$5. It will be done in bfd_coff_final_link where all the 683*a9fa9459Szrj required information is available. If however, we are not going 684*a9fa9459Szrj to perform a final link, eg because we have been invoked by objcopy 685*a9fa9459Szrj or strip, then we need to make sure that these Data Directory 686*a9fa9459Szrj entries are initialised properly. 687*a9fa9459Szrj 688*a9fa9459Szrj So - we copy the input values into the output values, and then, if 689*a9fa9459Szrj a final link is going to be performed, it can overwrite them. */ 690*a9fa9459Szrj extra->DataDirectory[PE_IMPORT_TABLE] = idata2; 691*a9fa9459Szrj extra->DataDirectory[PE_IMPORT_ADDRESS_TABLE] = idata5; 692*a9fa9459Szrj extra->DataDirectory[PE_TLS_TABLE] = tls; 693*a9fa9459Szrj 694*a9fa9459Szrj if (extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress == 0) 695*a9fa9459Szrj /* Until other .idata fixes are made (pending patch), the entry for 696*a9fa9459Szrj .idata is needed for backwards compatibility. FIXME. */ 697*a9fa9459Szrj add_data_entry (abfd, extra, 1, ".idata", ib); 698*a9fa9459Szrj 699*a9fa9459Szrj /* For some reason, the virtual size (which is what's set by 700*a9fa9459Szrj add_data_entry) for .reloc is not the same as the size recorded 701*a9fa9459Szrj in this slot by MSVC; it doesn't seem to cause problems (so far), 702*a9fa9459Szrj but since it's the best we've got, use it. It does do the right 703*a9fa9459Szrj thing for .pdata. */ 704*a9fa9459Szrj if (pe->has_reloc_section) 705*a9fa9459Szrj add_data_entry (abfd, extra, 5, ".reloc", ib); 706*a9fa9459Szrj 707*a9fa9459Szrj { 708*a9fa9459Szrj asection *sec; 709*a9fa9459Szrj bfd_vma hsize = 0; 710*a9fa9459Szrj bfd_vma dsize = 0; 711*a9fa9459Szrj bfd_vma isize = 0; 712*a9fa9459Szrj bfd_vma tsize = 0; 713*a9fa9459Szrj 714*a9fa9459Szrj for (sec = abfd->sections; sec; sec = sec->next) 715*a9fa9459Szrj { 716*a9fa9459Szrj int rounded = FA (sec->size); 717*a9fa9459Szrj 718*a9fa9459Szrj /* The first non-zero section filepos is the header size. 719*a9fa9459Szrj Sections without contents will have a filepos of 0. */ 720*a9fa9459Szrj if (hsize == 0) 721*a9fa9459Szrj hsize = sec->filepos; 722*a9fa9459Szrj if (sec->flags & SEC_DATA) 723*a9fa9459Szrj dsize += rounded; 724*a9fa9459Szrj if (sec->flags & SEC_CODE) 725*a9fa9459Szrj tsize += rounded; 726*a9fa9459Szrj /* The image size is the total VIRTUAL size (which is what is 727*a9fa9459Szrj in the virt_size field). Files have been seen (from MSVC 728*a9fa9459Szrj 5.0 link.exe) where the file size of the .data segment is 729*a9fa9459Szrj quite small compared to the virtual size. Without this 730*a9fa9459Szrj fix, strip munges the file. 731*a9fa9459Szrj 732*a9fa9459Szrj FIXME: We need to handle holes between sections, which may 733*a9fa9459Szrj happpen when we covert from another format. We just use 734*a9fa9459Szrj the virtual address and virtual size of the last section 735*a9fa9459Szrj for the image size. */ 736*a9fa9459Szrj if (coff_section_data (abfd, sec) != NULL 737*a9fa9459Szrj && pei_section_data (abfd, sec) != NULL) 738*a9fa9459Szrj isize = (sec->vma - extra->ImageBase 739*a9fa9459Szrj + SA (FA (pei_section_data (abfd, sec)->virt_size))); 740*a9fa9459Szrj } 741*a9fa9459Szrj 742*a9fa9459Szrj aouthdr_in->dsize = dsize; 743*a9fa9459Szrj aouthdr_in->tsize = tsize; 744*a9fa9459Szrj extra->SizeOfHeaders = hsize; 745*a9fa9459Szrj extra->SizeOfImage = isize; 746*a9fa9459Szrj } 747*a9fa9459Szrj 748*a9fa9459Szrj H_PUT_16 (abfd, aouthdr_in->magic, aouthdr_out->standard.magic); 749*a9fa9459Szrj 750*a9fa9459Szrj /* e.g. 219510000 is linker version 2.19 */ 751*a9fa9459Szrj #define LINKER_VERSION ((short) (BFD_VERSION / 1000000)) 752*a9fa9459Szrj 753*a9fa9459Szrj /* This piece of magic sets the "linker version" field to 754*a9fa9459Szrj LINKER_VERSION. */ 755*a9fa9459Szrj H_PUT_16 (abfd, (LINKER_VERSION / 100 + (LINKER_VERSION % 100) * 256), 756*a9fa9459Szrj aouthdr_out->standard.vstamp); 757*a9fa9459Szrj 758*a9fa9459Szrj PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, aouthdr_out->standard.tsize); 759*a9fa9459Szrj PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, aouthdr_out->standard.dsize); 760*a9fa9459Szrj PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, aouthdr_out->standard.bsize); 761*a9fa9459Szrj PUT_AOUTHDR_ENTRY (abfd, aouthdr_in->entry, aouthdr_out->standard.entry); 762*a9fa9459Szrj PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start, 763*a9fa9459Szrj aouthdr_out->standard.text_start); 764*a9fa9459Szrj 765*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 766*a9fa9459Szrj /* PE32+ does not have data_start member! */ 767*a9fa9459Szrj PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start, 768*a9fa9459Szrj aouthdr_out->standard.data_start); 769*a9fa9459Szrj #endif 770*a9fa9459Szrj 771*a9fa9459Szrj PUT_OPTHDR_IMAGE_BASE (abfd, extra->ImageBase, aouthdr_out->ImageBase); 772*a9fa9459Szrj H_PUT_32 (abfd, extra->SectionAlignment, aouthdr_out->SectionAlignment); 773*a9fa9459Szrj H_PUT_32 (abfd, extra->FileAlignment, aouthdr_out->FileAlignment); 774*a9fa9459Szrj H_PUT_16 (abfd, extra->MajorOperatingSystemVersion, 775*a9fa9459Szrj aouthdr_out->MajorOperatingSystemVersion); 776*a9fa9459Szrj H_PUT_16 (abfd, extra->MinorOperatingSystemVersion, 777*a9fa9459Szrj aouthdr_out->MinorOperatingSystemVersion); 778*a9fa9459Szrj H_PUT_16 (abfd, extra->MajorImageVersion, aouthdr_out->MajorImageVersion); 779*a9fa9459Szrj H_PUT_16 (abfd, extra->MinorImageVersion, aouthdr_out->MinorImageVersion); 780*a9fa9459Szrj H_PUT_16 (abfd, extra->MajorSubsystemVersion, 781*a9fa9459Szrj aouthdr_out->MajorSubsystemVersion); 782*a9fa9459Szrj H_PUT_16 (abfd, extra->MinorSubsystemVersion, 783*a9fa9459Szrj aouthdr_out->MinorSubsystemVersion); 784*a9fa9459Szrj H_PUT_32 (abfd, extra->Reserved1, aouthdr_out->Reserved1); 785*a9fa9459Szrj H_PUT_32 (abfd, extra->SizeOfImage, aouthdr_out->SizeOfImage); 786*a9fa9459Szrj H_PUT_32 (abfd, extra->SizeOfHeaders, aouthdr_out->SizeOfHeaders); 787*a9fa9459Szrj H_PUT_32 (abfd, extra->CheckSum, aouthdr_out->CheckSum); 788*a9fa9459Szrj H_PUT_16 (abfd, extra->Subsystem, aouthdr_out->Subsystem); 789*a9fa9459Szrj H_PUT_16 (abfd, extra->DllCharacteristics, aouthdr_out->DllCharacteristics); 790*a9fa9459Szrj PUT_OPTHDR_SIZE_OF_STACK_RESERVE (abfd, extra->SizeOfStackReserve, 791*a9fa9459Szrj aouthdr_out->SizeOfStackReserve); 792*a9fa9459Szrj PUT_OPTHDR_SIZE_OF_STACK_COMMIT (abfd, extra->SizeOfStackCommit, 793*a9fa9459Szrj aouthdr_out->SizeOfStackCommit); 794*a9fa9459Szrj PUT_OPTHDR_SIZE_OF_HEAP_RESERVE (abfd, extra->SizeOfHeapReserve, 795*a9fa9459Szrj aouthdr_out->SizeOfHeapReserve); 796*a9fa9459Szrj PUT_OPTHDR_SIZE_OF_HEAP_COMMIT (abfd, extra->SizeOfHeapCommit, 797*a9fa9459Szrj aouthdr_out->SizeOfHeapCommit); 798*a9fa9459Szrj H_PUT_32 (abfd, extra->LoaderFlags, aouthdr_out->LoaderFlags); 799*a9fa9459Szrj H_PUT_32 (abfd, extra->NumberOfRvaAndSizes, 800*a9fa9459Szrj aouthdr_out->NumberOfRvaAndSizes); 801*a9fa9459Szrj { 802*a9fa9459Szrj int idx; 803*a9fa9459Szrj 804*a9fa9459Szrj for (idx = 0; idx < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; idx++) 805*a9fa9459Szrj { 806*a9fa9459Szrj H_PUT_32 (abfd, extra->DataDirectory[idx].VirtualAddress, 807*a9fa9459Szrj aouthdr_out->DataDirectory[idx][0]); 808*a9fa9459Szrj H_PUT_32 (abfd, extra->DataDirectory[idx].Size, 809*a9fa9459Szrj aouthdr_out->DataDirectory[idx][1]); 810*a9fa9459Szrj } 811*a9fa9459Szrj } 812*a9fa9459Szrj 813*a9fa9459Szrj return AOUTSZ; 814*a9fa9459Szrj } 815*a9fa9459Szrj 816*a9fa9459Szrj unsigned int 817*a9fa9459Szrj _bfd_XXi_only_swap_filehdr_out (bfd * abfd, void * in, void * out) 818*a9fa9459Szrj { 819*a9fa9459Szrj int idx; 820*a9fa9459Szrj struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in; 821*a9fa9459Szrj struct external_PEI_filehdr *filehdr_out = (struct external_PEI_filehdr *) out; 822*a9fa9459Szrj 823*a9fa9459Szrj if (pe_data (abfd)->has_reloc_section 824*a9fa9459Szrj || pe_data (abfd)->dont_strip_reloc) 825*a9fa9459Szrj filehdr_in->f_flags &= ~F_RELFLG; 826*a9fa9459Szrj 827*a9fa9459Szrj if (pe_data (abfd)->dll) 828*a9fa9459Szrj filehdr_in->f_flags |= F_DLL; 829*a9fa9459Szrj 830*a9fa9459Szrj filehdr_in->pe.e_magic = DOSMAGIC; 831*a9fa9459Szrj filehdr_in->pe.e_cblp = 0x90; 832*a9fa9459Szrj filehdr_in->pe.e_cp = 0x3; 833*a9fa9459Szrj filehdr_in->pe.e_crlc = 0x0; 834*a9fa9459Szrj filehdr_in->pe.e_cparhdr = 0x4; 835*a9fa9459Szrj filehdr_in->pe.e_minalloc = 0x0; 836*a9fa9459Szrj filehdr_in->pe.e_maxalloc = 0xffff; 837*a9fa9459Szrj filehdr_in->pe.e_ss = 0x0; 838*a9fa9459Szrj filehdr_in->pe.e_sp = 0xb8; 839*a9fa9459Szrj filehdr_in->pe.e_csum = 0x0; 840*a9fa9459Szrj filehdr_in->pe.e_ip = 0x0; 841*a9fa9459Szrj filehdr_in->pe.e_cs = 0x0; 842*a9fa9459Szrj filehdr_in->pe.e_lfarlc = 0x40; 843*a9fa9459Szrj filehdr_in->pe.e_ovno = 0x0; 844*a9fa9459Szrj 845*a9fa9459Szrj for (idx = 0; idx < 4; idx++) 846*a9fa9459Szrj filehdr_in->pe.e_res[idx] = 0x0; 847*a9fa9459Szrj 848*a9fa9459Szrj filehdr_in->pe.e_oemid = 0x0; 849*a9fa9459Szrj filehdr_in->pe.e_oeminfo = 0x0; 850*a9fa9459Szrj 851*a9fa9459Szrj for (idx = 0; idx < 10; idx++) 852*a9fa9459Szrj filehdr_in->pe.e_res2[idx] = 0x0; 853*a9fa9459Szrj 854*a9fa9459Szrj filehdr_in->pe.e_lfanew = 0x80; 855*a9fa9459Szrj 856*a9fa9459Szrj /* This next collection of data are mostly just characters. It 857*a9fa9459Szrj appears to be constant within the headers put on NT exes. */ 858*a9fa9459Szrj filehdr_in->pe.dos_message[0] = 0x0eba1f0e; 859*a9fa9459Szrj filehdr_in->pe.dos_message[1] = 0xcd09b400; 860*a9fa9459Szrj filehdr_in->pe.dos_message[2] = 0x4c01b821; 861*a9fa9459Szrj filehdr_in->pe.dos_message[3] = 0x685421cd; 862*a9fa9459Szrj filehdr_in->pe.dos_message[4] = 0x70207369; 863*a9fa9459Szrj filehdr_in->pe.dos_message[5] = 0x72676f72; 864*a9fa9459Szrj filehdr_in->pe.dos_message[6] = 0x63206d61; 865*a9fa9459Szrj filehdr_in->pe.dos_message[7] = 0x6f6e6e61; 866*a9fa9459Szrj filehdr_in->pe.dos_message[8] = 0x65622074; 867*a9fa9459Szrj filehdr_in->pe.dos_message[9] = 0x6e757220; 868*a9fa9459Szrj filehdr_in->pe.dos_message[10] = 0x206e6920; 869*a9fa9459Szrj filehdr_in->pe.dos_message[11] = 0x20534f44; 870*a9fa9459Szrj filehdr_in->pe.dos_message[12] = 0x65646f6d; 871*a9fa9459Szrj filehdr_in->pe.dos_message[13] = 0x0a0d0d2e; 872*a9fa9459Szrj filehdr_in->pe.dos_message[14] = 0x24; 873*a9fa9459Szrj filehdr_in->pe.dos_message[15] = 0x0; 874*a9fa9459Szrj filehdr_in->pe.nt_signature = NT_SIGNATURE; 875*a9fa9459Szrj 876*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic); 877*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns); 878*a9fa9459Szrj 879*a9fa9459Szrj /* Only use a real timestamp if the option was chosen. */ 880*a9fa9459Szrj if ((pe_data (abfd)->insert_timestamp)) 881*a9fa9459Szrj H_PUT_32 (abfd, time (0), filehdr_out->f_timdat); 882*a9fa9459Szrj 883*a9fa9459Szrj PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr, 884*a9fa9459Szrj filehdr_out->f_symptr); 885*a9fa9459Szrj H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms); 886*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->f_opthdr, filehdr_out->f_opthdr); 887*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->f_flags, filehdr_out->f_flags); 888*a9fa9459Szrj 889*a9fa9459Szrj /* Put in extra dos header stuff. This data remains essentially 890*a9fa9459Szrj constant, it just has to be tacked on to the beginning of all exes 891*a9fa9459Szrj for NT. */ 892*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_magic, filehdr_out->e_magic); 893*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_cblp, filehdr_out->e_cblp); 894*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_cp, filehdr_out->e_cp); 895*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_crlc, filehdr_out->e_crlc); 896*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_cparhdr, filehdr_out->e_cparhdr); 897*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_minalloc, filehdr_out->e_minalloc); 898*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_maxalloc, filehdr_out->e_maxalloc); 899*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_ss, filehdr_out->e_ss); 900*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_sp, filehdr_out->e_sp); 901*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_csum, filehdr_out->e_csum); 902*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_ip, filehdr_out->e_ip); 903*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_cs, filehdr_out->e_cs); 904*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_lfarlc, filehdr_out->e_lfarlc); 905*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_ovno, filehdr_out->e_ovno); 906*a9fa9459Szrj 907*a9fa9459Szrj for (idx = 0; idx < 4; idx++) 908*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_res[idx], filehdr_out->e_res[idx]); 909*a9fa9459Szrj 910*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_oemid, filehdr_out->e_oemid); 911*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_oeminfo, filehdr_out->e_oeminfo); 912*a9fa9459Szrj 913*a9fa9459Szrj for (idx = 0; idx < 10; idx++) 914*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->pe.e_res2[idx], filehdr_out->e_res2[idx]); 915*a9fa9459Szrj 916*a9fa9459Szrj H_PUT_32 (abfd, filehdr_in->pe.e_lfanew, filehdr_out->e_lfanew); 917*a9fa9459Szrj 918*a9fa9459Szrj for (idx = 0; idx < 16; idx++) 919*a9fa9459Szrj H_PUT_32 (abfd, filehdr_in->pe.dos_message[idx], 920*a9fa9459Szrj filehdr_out->dos_message[idx]); 921*a9fa9459Szrj 922*a9fa9459Szrj /* Also put in the NT signature. */ 923*a9fa9459Szrj H_PUT_32 (abfd, filehdr_in->pe.nt_signature, filehdr_out->nt_signature); 924*a9fa9459Szrj 925*a9fa9459Szrj return FILHSZ; 926*a9fa9459Szrj } 927*a9fa9459Szrj 928*a9fa9459Szrj unsigned int 929*a9fa9459Szrj _bfd_XX_only_swap_filehdr_out (bfd * abfd, void * in, void * out) 930*a9fa9459Szrj { 931*a9fa9459Szrj struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in; 932*a9fa9459Szrj FILHDR *filehdr_out = (FILHDR *) out; 933*a9fa9459Szrj 934*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic); 935*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns); 936*a9fa9459Szrj H_PUT_32 (abfd, filehdr_in->f_timdat, filehdr_out->f_timdat); 937*a9fa9459Szrj PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr, filehdr_out->f_symptr); 938*a9fa9459Szrj H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms); 939*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->f_opthdr, filehdr_out->f_opthdr); 940*a9fa9459Szrj H_PUT_16 (abfd, filehdr_in->f_flags, filehdr_out->f_flags); 941*a9fa9459Szrj 942*a9fa9459Szrj return FILHSZ; 943*a9fa9459Szrj } 944*a9fa9459Szrj 945*a9fa9459Szrj unsigned int 946*a9fa9459Szrj _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out) 947*a9fa9459Szrj { 948*a9fa9459Szrj struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in; 949*a9fa9459Szrj SCNHDR *scnhdr_ext = (SCNHDR *) out; 950*a9fa9459Szrj unsigned int ret = SCNHSZ; 951*a9fa9459Szrj bfd_vma ps; 952*a9fa9459Szrj bfd_vma ss; 953*a9fa9459Szrj 954*a9fa9459Szrj memcpy (scnhdr_ext->s_name, scnhdr_int->s_name, sizeof (scnhdr_int->s_name)); 955*a9fa9459Szrj 956*a9fa9459Szrj PUT_SCNHDR_VADDR (abfd, 957*a9fa9459Szrj ((scnhdr_int->s_vaddr 958*a9fa9459Szrj - pe_data (abfd)->pe_opthdr.ImageBase) 959*a9fa9459Szrj & 0xffffffff), 960*a9fa9459Szrj scnhdr_ext->s_vaddr); 961*a9fa9459Szrj 962*a9fa9459Szrj /* NT wants the size data to be rounded up to the next 963*a9fa9459Szrj NT_FILE_ALIGNMENT, but zero if it has no content (as in .bss, 964*a9fa9459Szrj sometimes). */ 965*a9fa9459Szrj if ((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0) 966*a9fa9459Szrj { 967*a9fa9459Szrj if (bfd_pei_p (abfd)) 968*a9fa9459Szrj { 969*a9fa9459Szrj ps = scnhdr_int->s_size; 970*a9fa9459Szrj ss = 0; 971*a9fa9459Szrj } 972*a9fa9459Szrj else 973*a9fa9459Szrj { 974*a9fa9459Szrj ps = 0; 975*a9fa9459Szrj ss = scnhdr_int->s_size; 976*a9fa9459Szrj } 977*a9fa9459Szrj } 978*a9fa9459Szrj else 979*a9fa9459Szrj { 980*a9fa9459Szrj if (bfd_pei_p (abfd)) 981*a9fa9459Szrj ps = scnhdr_int->s_paddr; 982*a9fa9459Szrj else 983*a9fa9459Szrj ps = 0; 984*a9fa9459Szrj 985*a9fa9459Szrj ss = scnhdr_int->s_size; 986*a9fa9459Szrj } 987*a9fa9459Szrj 988*a9fa9459Szrj PUT_SCNHDR_SIZE (abfd, ss, 989*a9fa9459Szrj scnhdr_ext->s_size); 990*a9fa9459Szrj 991*a9fa9459Szrj /* s_paddr in PE is really the virtual size. */ 992*a9fa9459Szrj PUT_SCNHDR_PADDR (abfd, ps, scnhdr_ext->s_paddr); 993*a9fa9459Szrj 994*a9fa9459Szrj PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr, 995*a9fa9459Szrj scnhdr_ext->s_scnptr); 996*a9fa9459Szrj PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr, 997*a9fa9459Szrj scnhdr_ext->s_relptr); 998*a9fa9459Szrj PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr, 999*a9fa9459Szrj scnhdr_ext->s_lnnoptr); 1000*a9fa9459Szrj 1001*a9fa9459Szrj { 1002*a9fa9459Szrj /* Extra flags must be set when dealing with PE. All sections should also 1003*a9fa9459Szrj have the IMAGE_SCN_MEM_READ (0x40000000) flag set. In addition, the 1004*a9fa9459Szrj .text section must have IMAGE_SCN_MEM_EXECUTE (0x20000000) and the data 1005*a9fa9459Szrj sections (.idata, .data, .bss, .CRT) must have IMAGE_SCN_MEM_WRITE set 1006*a9fa9459Szrj (this is especially important when dealing with the .idata section since 1007*a9fa9459Szrj the addresses for routines from .dlls must be overwritten). If .reloc 1008*a9fa9459Szrj section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE 1009*a9fa9459Szrj (0x02000000). Also, the resource data should also be read and 1010*a9fa9459Szrj writable. */ 1011*a9fa9459Szrj 1012*a9fa9459Szrj /* FIXME: Alignment is also encoded in this field, at least on PPC and 1013*a9fa9459Szrj ARM-WINCE. Although - how do we get the original alignment field 1014*a9fa9459Szrj back ? */ 1015*a9fa9459Szrj 1016*a9fa9459Szrj typedef struct 1017*a9fa9459Szrj { 1018*a9fa9459Szrj const char * section_name; 1019*a9fa9459Szrj unsigned long must_have; 1020*a9fa9459Szrj } 1021*a9fa9459Szrj pe_required_section_flags; 1022*a9fa9459Szrj 1023*a9fa9459Szrj pe_required_section_flags known_sections [] = 1024*a9fa9459Szrj { 1025*a9fa9459Szrj { ".arch", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_ALIGN_8BYTES }, 1026*a9fa9459Szrj { ".bss", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 1027*a9fa9459Szrj { ".data", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 1028*a9fa9459Szrj { ".edata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA }, 1029*a9fa9459Szrj { ".idata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 1030*a9fa9459Szrj { ".pdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA }, 1031*a9fa9459Szrj { ".rdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA }, 1032*a9fa9459Szrj { ".reloc", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE }, 1033*a9fa9459Szrj { ".rsrc", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 1034*a9fa9459Szrj { ".text" , IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE }, 1035*a9fa9459Szrj { ".tls", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE }, 1036*a9fa9459Szrj { ".xdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA }, 1037*a9fa9459Szrj { NULL, 0} 1038*a9fa9459Szrj }; 1039*a9fa9459Szrj 1040*a9fa9459Szrj pe_required_section_flags * p; 1041*a9fa9459Szrj 1042*a9fa9459Szrj /* We have defaulted to adding the IMAGE_SCN_MEM_WRITE flag, but now 1043*a9fa9459Szrj we know exactly what this specific section wants so we remove it 1044*a9fa9459Szrj and then allow the must_have field to add it back in if necessary. 1045*a9fa9459Szrj However, we don't remove IMAGE_SCN_MEM_WRITE flag from .text if the 1046*a9fa9459Szrj default WP_TEXT file flag has been cleared. WP_TEXT may be cleared 1047*a9fa9459Szrj by ld --enable-auto-import (if auto-import is actually needed), 1048*a9fa9459Szrj by ld --omagic, or by obcopy --writable-text. */ 1049*a9fa9459Szrj 1050*a9fa9459Szrj for (p = known_sections; p->section_name; p++) 1051*a9fa9459Szrj if (strcmp (scnhdr_int->s_name, p->section_name) == 0) 1052*a9fa9459Szrj { 1053*a9fa9459Szrj if (strcmp (scnhdr_int->s_name, ".text") 1054*a9fa9459Szrj || (bfd_get_file_flags (abfd) & WP_TEXT)) 1055*a9fa9459Szrj scnhdr_int->s_flags &= ~IMAGE_SCN_MEM_WRITE; 1056*a9fa9459Szrj scnhdr_int->s_flags |= p->must_have; 1057*a9fa9459Szrj break; 1058*a9fa9459Szrj } 1059*a9fa9459Szrj 1060*a9fa9459Szrj H_PUT_32 (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags); 1061*a9fa9459Szrj } 1062*a9fa9459Szrj 1063*a9fa9459Szrj if (coff_data (abfd)->link_info 1064*a9fa9459Szrj && ! bfd_link_relocatable (coff_data (abfd)->link_info) 1065*a9fa9459Szrj && ! bfd_link_pic (coff_data (abfd)->link_info) 1066*a9fa9459Szrj && strcmp (scnhdr_int->s_name, ".text") == 0) 1067*a9fa9459Szrj { 1068*a9fa9459Szrj /* By inference from looking at MS output, the 32 bit field 1069*a9fa9459Szrj which is the combination of the number_of_relocs and 1070*a9fa9459Szrj number_of_linenos is used for the line number count in 1071*a9fa9459Szrj executables. A 16-bit field won't do for cc1. The MS 1072*a9fa9459Szrj document says that the number of relocs is zero for 1073*a9fa9459Szrj executables, but the 17-th bit has been observed to be there. 1074*a9fa9459Szrj Overflow is not an issue: a 4G-line program will overflow a 1075*a9fa9459Szrj bunch of other fields long before this! */ 1076*a9fa9459Szrj H_PUT_16 (abfd, (scnhdr_int->s_nlnno & 0xffff), scnhdr_ext->s_nlnno); 1077*a9fa9459Szrj H_PUT_16 (abfd, (scnhdr_int->s_nlnno >> 16), scnhdr_ext->s_nreloc); 1078*a9fa9459Szrj } 1079*a9fa9459Szrj else 1080*a9fa9459Szrj { 1081*a9fa9459Szrj if (scnhdr_int->s_nlnno <= 0xffff) 1082*a9fa9459Szrj H_PUT_16 (abfd, scnhdr_int->s_nlnno, scnhdr_ext->s_nlnno); 1083*a9fa9459Szrj else 1084*a9fa9459Szrj { 1085*a9fa9459Szrj (*_bfd_error_handler) (_("%s: line number overflow: 0x%lx > 0xffff"), 1086*a9fa9459Szrj bfd_get_filename (abfd), 1087*a9fa9459Szrj scnhdr_int->s_nlnno); 1088*a9fa9459Szrj bfd_set_error (bfd_error_file_truncated); 1089*a9fa9459Szrj H_PUT_16 (abfd, 0xffff, scnhdr_ext->s_nlnno); 1090*a9fa9459Szrj ret = 0; 1091*a9fa9459Szrj } 1092*a9fa9459Szrj 1093*a9fa9459Szrj /* Although we could encode 0xffff relocs here, we do not, to be 1094*a9fa9459Szrj consistent with other parts of bfd. Also it lets us warn, as 1095*a9fa9459Szrj we should never see 0xffff here w/o having the overflow flag 1096*a9fa9459Szrj set. */ 1097*a9fa9459Szrj if (scnhdr_int->s_nreloc < 0xffff) 1098*a9fa9459Szrj H_PUT_16 (abfd, scnhdr_int->s_nreloc, scnhdr_ext->s_nreloc); 1099*a9fa9459Szrj else 1100*a9fa9459Szrj { 1101*a9fa9459Szrj /* PE can deal with large #s of relocs, but not here. */ 1102*a9fa9459Szrj H_PUT_16 (abfd, 0xffff, scnhdr_ext->s_nreloc); 1103*a9fa9459Szrj scnhdr_int->s_flags |= IMAGE_SCN_LNK_NRELOC_OVFL; 1104*a9fa9459Szrj H_PUT_32 (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags); 1105*a9fa9459Szrj } 1106*a9fa9459Szrj } 1107*a9fa9459Szrj return ret; 1108*a9fa9459Szrj } 1109*a9fa9459Szrj 1110*a9fa9459Szrj void 1111*a9fa9459Szrj _bfd_XXi_swap_debugdir_in (bfd * abfd, void * ext1, void * in1) 1112*a9fa9459Szrj { 1113*a9fa9459Szrj struct external_IMAGE_DEBUG_DIRECTORY *ext = (struct external_IMAGE_DEBUG_DIRECTORY *) ext1; 1114*a9fa9459Szrj struct internal_IMAGE_DEBUG_DIRECTORY *in = (struct internal_IMAGE_DEBUG_DIRECTORY *) in1; 1115*a9fa9459Szrj 1116*a9fa9459Szrj in->Characteristics = H_GET_32(abfd, ext->Characteristics); 1117*a9fa9459Szrj in->TimeDateStamp = H_GET_32(abfd, ext->TimeDateStamp); 1118*a9fa9459Szrj in->MajorVersion = H_GET_16(abfd, ext->MajorVersion); 1119*a9fa9459Szrj in->MinorVersion = H_GET_16(abfd, ext->MinorVersion); 1120*a9fa9459Szrj in->Type = H_GET_32(abfd, ext->Type); 1121*a9fa9459Szrj in->SizeOfData = H_GET_32(abfd, ext->SizeOfData); 1122*a9fa9459Szrj in->AddressOfRawData = H_GET_32(abfd, ext->AddressOfRawData); 1123*a9fa9459Szrj in->PointerToRawData = H_GET_32(abfd, ext->PointerToRawData); 1124*a9fa9459Szrj } 1125*a9fa9459Szrj 1126*a9fa9459Szrj unsigned int 1127*a9fa9459Szrj _bfd_XXi_swap_debugdir_out (bfd * abfd, void * inp, void * extp) 1128*a9fa9459Szrj { 1129*a9fa9459Szrj struct external_IMAGE_DEBUG_DIRECTORY *ext = (struct external_IMAGE_DEBUG_DIRECTORY *) extp; 1130*a9fa9459Szrj struct internal_IMAGE_DEBUG_DIRECTORY *in = (struct internal_IMAGE_DEBUG_DIRECTORY *) inp; 1131*a9fa9459Szrj 1132*a9fa9459Szrj H_PUT_32(abfd, in->Characteristics, ext->Characteristics); 1133*a9fa9459Szrj H_PUT_32(abfd, in->TimeDateStamp, ext->TimeDateStamp); 1134*a9fa9459Szrj H_PUT_16(abfd, in->MajorVersion, ext->MajorVersion); 1135*a9fa9459Szrj H_PUT_16(abfd, in->MinorVersion, ext->MinorVersion); 1136*a9fa9459Szrj H_PUT_32(abfd, in->Type, ext->Type); 1137*a9fa9459Szrj H_PUT_32(abfd, in->SizeOfData, ext->SizeOfData); 1138*a9fa9459Szrj H_PUT_32(abfd, in->AddressOfRawData, ext->AddressOfRawData); 1139*a9fa9459Szrj H_PUT_32(abfd, in->PointerToRawData, ext->PointerToRawData); 1140*a9fa9459Szrj 1141*a9fa9459Szrj return sizeof (struct external_IMAGE_DEBUG_DIRECTORY); 1142*a9fa9459Szrj } 1143*a9fa9459Szrj 1144*a9fa9459Szrj CODEVIEW_INFO * 1145*a9fa9459Szrj _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length, CODEVIEW_INFO *cvinfo) 1146*a9fa9459Szrj { 1147*a9fa9459Szrj char buffer[256+1]; 1148*a9fa9459Szrj 1149*a9fa9459Szrj if (bfd_seek (abfd, where, SEEK_SET) != 0) 1150*a9fa9459Szrj return NULL; 1151*a9fa9459Szrj 1152*a9fa9459Szrj if (bfd_bread (buffer, 256, abfd) < 4) 1153*a9fa9459Szrj return NULL; 1154*a9fa9459Szrj 1155*a9fa9459Szrj /* Ensure null termination of filename. */ 1156*a9fa9459Szrj buffer[256] = '\0'; 1157*a9fa9459Szrj 1158*a9fa9459Szrj cvinfo->CVSignature = H_GET_32 (abfd, buffer); 1159*a9fa9459Szrj cvinfo->Age = 0; 1160*a9fa9459Szrj 1161*a9fa9459Szrj if ((cvinfo->CVSignature == CVINFO_PDB70_CVSIGNATURE) 1162*a9fa9459Szrj && (length > sizeof (CV_INFO_PDB70))) 1163*a9fa9459Szrj { 1164*a9fa9459Szrj CV_INFO_PDB70 *cvinfo70 = (CV_INFO_PDB70 *)(buffer); 1165*a9fa9459Szrj 1166*a9fa9459Szrj cvinfo->Age = H_GET_32(abfd, cvinfo70->Age); 1167*a9fa9459Szrj 1168*a9fa9459Szrj /* A GUID consists of 4,2,2 byte values in little-endian order, followed 1169*a9fa9459Szrj by 8 single bytes. Byte swap them so we can conveniently treat the GUID 1170*a9fa9459Szrj as 16 bytes in big-endian order. */ 1171*a9fa9459Szrj bfd_putb32 (bfd_getl32 (cvinfo70->Signature), cvinfo->Signature); 1172*a9fa9459Szrj bfd_putb16 (bfd_getl16 (&(cvinfo70->Signature[4])), &(cvinfo->Signature[4])); 1173*a9fa9459Szrj bfd_putb16 (bfd_getl16 (&(cvinfo70->Signature[6])), &(cvinfo->Signature[6])); 1174*a9fa9459Szrj memcpy (&(cvinfo->Signature[8]), &(cvinfo70->Signature[8]), 8); 1175*a9fa9459Szrj 1176*a9fa9459Szrj cvinfo->SignatureLength = CV_INFO_SIGNATURE_LENGTH; 1177*a9fa9459Szrj // cvinfo->PdbFileName = cvinfo70->PdbFileName; 1178*a9fa9459Szrj 1179*a9fa9459Szrj return cvinfo; 1180*a9fa9459Szrj } 1181*a9fa9459Szrj else if ((cvinfo->CVSignature == CVINFO_PDB20_CVSIGNATURE) 1182*a9fa9459Szrj && (length > sizeof (CV_INFO_PDB20))) 1183*a9fa9459Szrj { 1184*a9fa9459Szrj CV_INFO_PDB20 *cvinfo20 = (CV_INFO_PDB20 *)(buffer); 1185*a9fa9459Szrj cvinfo->Age = H_GET_32(abfd, cvinfo20->Age); 1186*a9fa9459Szrj memcpy (cvinfo->Signature, cvinfo20->Signature, 4); 1187*a9fa9459Szrj cvinfo->SignatureLength = 4; 1188*a9fa9459Szrj // cvinfo->PdbFileName = cvinfo20->PdbFileName; 1189*a9fa9459Szrj 1190*a9fa9459Szrj return cvinfo; 1191*a9fa9459Szrj } 1192*a9fa9459Szrj 1193*a9fa9459Szrj return NULL; 1194*a9fa9459Szrj } 1195*a9fa9459Szrj 1196*a9fa9459Szrj unsigned int 1197*a9fa9459Szrj _bfd_XXi_write_codeview_record (bfd * abfd, file_ptr where, CODEVIEW_INFO *cvinfo) 1198*a9fa9459Szrj { 1199*a9fa9459Szrj const bfd_size_type size = sizeof (CV_INFO_PDB70) + 1; 1200*a9fa9459Szrj bfd_size_type written; 1201*a9fa9459Szrj CV_INFO_PDB70 *cvinfo70; 1202*a9fa9459Szrj char * buffer; 1203*a9fa9459Szrj 1204*a9fa9459Szrj if (bfd_seek (abfd, where, SEEK_SET) != 0) 1205*a9fa9459Szrj return 0; 1206*a9fa9459Szrj 1207*a9fa9459Szrj buffer = xmalloc (size); 1208*a9fa9459Szrj cvinfo70 = (CV_INFO_PDB70 *) buffer; 1209*a9fa9459Szrj H_PUT_32 (abfd, CVINFO_PDB70_CVSIGNATURE, cvinfo70->CvSignature); 1210*a9fa9459Szrj 1211*a9fa9459Szrj /* Byte swap the GUID from 16 bytes in big-endian order to 4,2,2 byte values 1212*a9fa9459Szrj in little-endian order, followed by 8 single bytes. */ 1213*a9fa9459Szrj bfd_putl32 (bfd_getb32 (cvinfo->Signature), cvinfo70->Signature); 1214*a9fa9459Szrj bfd_putl16 (bfd_getb16 (&(cvinfo->Signature[4])), &(cvinfo70->Signature[4])); 1215*a9fa9459Szrj bfd_putl16 (bfd_getb16 (&(cvinfo->Signature[6])), &(cvinfo70->Signature[6])); 1216*a9fa9459Szrj memcpy (&(cvinfo70->Signature[8]), &(cvinfo->Signature[8]), 8); 1217*a9fa9459Szrj 1218*a9fa9459Szrj H_PUT_32 (abfd, cvinfo->Age, cvinfo70->Age); 1219*a9fa9459Szrj cvinfo70->PdbFileName[0] = '\0'; 1220*a9fa9459Szrj 1221*a9fa9459Szrj written = bfd_bwrite (buffer, size, abfd); 1222*a9fa9459Szrj 1223*a9fa9459Szrj free (buffer); 1224*a9fa9459Szrj 1225*a9fa9459Szrj return written == size ? size : 0; 1226*a9fa9459Szrj } 1227*a9fa9459Szrj 1228*a9fa9459Szrj static char * dir_names[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = 1229*a9fa9459Szrj { 1230*a9fa9459Szrj N_("Export Directory [.edata (or where ever we found it)]"), 1231*a9fa9459Szrj N_("Import Directory [parts of .idata]"), 1232*a9fa9459Szrj N_("Resource Directory [.rsrc]"), 1233*a9fa9459Szrj N_("Exception Directory [.pdata]"), 1234*a9fa9459Szrj N_("Security Directory"), 1235*a9fa9459Szrj N_("Base Relocation Directory [.reloc]"), 1236*a9fa9459Szrj N_("Debug Directory"), 1237*a9fa9459Szrj N_("Description Directory"), 1238*a9fa9459Szrj N_("Special Directory"), 1239*a9fa9459Szrj N_("Thread Storage Directory [.tls]"), 1240*a9fa9459Szrj N_("Load Configuration Directory"), 1241*a9fa9459Szrj N_("Bound Import Directory"), 1242*a9fa9459Szrj N_("Import Address Table Directory"), 1243*a9fa9459Szrj N_("Delay Import Directory"), 1244*a9fa9459Szrj N_("CLR Runtime Header"), 1245*a9fa9459Szrj N_("Reserved") 1246*a9fa9459Szrj }; 1247*a9fa9459Szrj 1248*a9fa9459Szrj #ifdef POWERPC_LE_PE 1249*a9fa9459Szrj /* The code for the PPC really falls in the "architecture dependent" 1250*a9fa9459Szrj category. However, it's not clear that anyone will ever care, so 1251*a9fa9459Szrj we're ignoring the issue for now; if/when PPC matters, some of this 1252*a9fa9459Szrj may need to go into peicode.h, or arguments passed to enable the 1253*a9fa9459Szrj PPC- specific code. */ 1254*a9fa9459Szrj #endif 1255*a9fa9459Szrj 1256*a9fa9459Szrj static bfd_boolean 1257*a9fa9459Szrj pe_print_idata (bfd * abfd, void * vfile) 1258*a9fa9459Szrj { 1259*a9fa9459Szrj FILE *file = (FILE *) vfile; 1260*a9fa9459Szrj bfd_byte *data; 1261*a9fa9459Szrj asection *section; 1262*a9fa9459Szrj bfd_signed_vma adj; 1263*a9fa9459Szrj 1264*a9fa9459Szrj #ifdef POWERPC_LE_PE 1265*a9fa9459Szrj asection *rel_section = bfd_get_section_by_name (abfd, ".reldata"); 1266*a9fa9459Szrj #endif 1267*a9fa9459Szrj 1268*a9fa9459Szrj bfd_size_type datasize = 0; 1269*a9fa9459Szrj bfd_size_type dataoff; 1270*a9fa9459Szrj bfd_size_type i; 1271*a9fa9459Szrj int onaline = 20; 1272*a9fa9459Szrj 1273*a9fa9459Szrj pe_data_type *pe = pe_data (abfd); 1274*a9fa9459Szrj struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; 1275*a9fa9459Szrj 1276*a9fa9459Szrj bfd_vma addr; 1277*a9fa9459Szrj 1278*a9fa9459Szrj addr = extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress; 1279*a9fa9459Szrj 1280*a9fa9459Szrj if (addr == 0 && extra->DataDirectory[PE_IMPORT_TABLE].Size == 0) 1281*a9fa9459Szrj { 1282*a9fa9459Szrj /* Maybe the extra header isn't there. Look for the section. */ 1283*a9fa9459Szrj section = bfd_get_section_by_name (abfd, ".idata"); 1284*a9fa9459Szrj if (section == NULL) 1285*a9fa9459Szrj return TRUE; 1286*a9fa9459Szrj 1287*a9fa9459Szrj addr = section->vma; 1288*a9fa9459Szrj datasize = section->size; 1289*a9fa9459Szrj if (datasize == 0) 1290*a9fa9459Szrj return TRUE; 1291*a9fa9459Szrj } 1292*a9fa9459Szrj else 1293*a9fa9459Szrj { 1294*a9fa9459Szrj addr += extra->ImageBase; 1295*a9fa9459Szrj for (section = abfd->sections; section != NULL; section = section->next) 1296*a9fa9459Szrj { 1297*a9fa9459Szrj datasize = section->size; 1298*a9fa9459Szrj if (addr >= section->vma && addr < section->vma + datasize) 1299*a9fa9459Szrj break; 1300*a9fa9459Szrj } 1301*a9fa9459Szrj 1302*a9fa9459Szrj if (section == NULL) 1303*a9fa9459Szrj { 1304*a9fa9459Szrj fprintf (file, 1305*a9fa9459Szrj _("\nThere is an import table, but the section containing it could not be found\n")); 1306*a9fa9459Szrj return TRUE; 1307*a9fa9459Szrj } 1308*a9fa9459Szrj else if (!(section->flags & SEC_HAS_CONTENTS)) 1309*a9fa9459Szrj { 1310*a9fa9459Szrj fprintf (file, 1311*a9fa9459Szrj _("\nThere is an import table in %s, but that section has no contents\n"), 1312*a9fa9459Szrj section->name); 1313*a9fa9459Szrj return TRUE; 1314*a9fa9459Szrj } 1315*a9fa9459Szrj } 1316*a9fa9459Szrj 1317*a9fa9459Szrj fprintf (file, _("\nThere is an import table in %s at 0x%lx\n"), 1318*a9fa9459Szrj section->name, (unsigned long) addr); 1319*a9fa9459Szrj 1320*a9fa9459Szrj dataoff = addr - section->vma; 1321*a9fa9459Szrj 1322*a9fa9459Szrj #ifdef POWERPC_LE_PE 1323*a9fa9459Szrj if (rel_section != 0 && rel_section->size != 0) 1324*a9fa9459Szrj { 1325*a9fa9459Szrj /* The toc address can be found by taking the starting address, 1326*a9fa9459Szrj which on the PPC locates a function descriptor. The 1327*a9fa9459Szrj descriptor consists of the function code starting address 1328*a9fa9459Szrj followed by the address of the toc. The starting address we 1329*a9fa9459Szrj get from the bfd, and the descriptor is supposed to be in the 1330*a9fa9459Szrj .reldata section. */ 1331*a9fa9459Szrj 1332*a9fa9459Szrj bfd_vma loadable_toc_address; 1333*a9fa9459Szrj bfd_vma toc_address; 1334*a9fa9459Szrj bfd_vma start_address; 1335*a9fa9459Szrj bfd_byte *data; 1336*a9fa9459Szrj bfd_vma offset; 1337*a9fa9459Szrj 1338*a9fa9459Szrj if (!bfd_malloc_and_get_section (abfd, rel_section, &data)) 1339*a9fa9459Szrj { 1340*a9fa9459Szrj if (data != NULL) 1341*a9fa9459Szrj free (data); 1342*a9fa9459Szrj return FALSE; 1343*a9fa9459Szrj } 1344*a9fa9459Szrj 1345*a9fa9459Szrj offset = abfd->start_address - rel_section->vma; 1346*a9fa9459Szrj 1347*a9fa9459Szrj if (offset >= rel_section->size || offset + 8 > rel_section->size) 1348*a9fa9459Szrj { 1349*a9fa9459Szrj if (data != NULL) 1350*a9fa9459Szrj free (data); 1351*a9fa9459Szrj return FALSE; 1352*a9fa9459Szrj } 1353*a9fa9459Szrj 1354*a9fa9459Szrj start_address = bfd_get_32 (abfd, data + offset); 1355*a9fa9459Szrj loadable_toc_address = bfd_get_32 (abfd, data + offset + 4); 1356*a9fa9459Szrj toc_address = loadable_toc_address - 32768; 1357*a9fa9459Szrj 1358*a9fa9459Szrj fprintf (file, 1359*a9fa9459Szrj _("\nFunction descriptor located at the start address: %04lx\n"), 1360*a9fa9459Szrj (unsigned long int) (abfd->start_address)); 1361*a9fa9459Szrj fprintf (file, 1362*a9fa9459Szrj _("\tcode-base %08lx toc (loadable/actual) %08lx/%08lx\n"), 1363*a9fa9459Szrj start_address, loadable_toc_address, toc_address); 1364*a9fa9459Szrj if (data != NULL) 1365*a9fa9459Szrj free (data); 1366*a9fa9459Szrj } 1367*a9fa9459Szrj else 1368*a9fa9459Szrj { 1369*a9fa9459Szrj fprintf (file, 1370*a9fa9459Szrj _("\nNo reldata section! Function descriptor not decoded.\n")); 1371*a9fa9459Szrj } 1372*a9fa9459Szrj #endif 1373*a9fa9459Szrj 1374*a9fa9459Szrj fprintf (file, 1375*a9fa9459Szrj _("\nThe Import Tables (interpreted %s section contents)\n"), 1376*a9fa9459Szrj section->name); 1377*a9fa9459Szrj fprintf (file, 1378*a9fa9459Szrj _("\ 1379*a9fa9459Szrj vma: Hint Time Forward DLL First\n\ 1380*a9fa9459Szrj Table Stamp Chain Name Thunk\n")); 1381*a9fa9459Szrj 1382*a9fa9459Szrj /* Read the whole section. Some of the fields might be before dataoff. */ 1383*a9fa9459Szrj if (!bfd_malloc_and_get_section (abfd, section, &data)) 1384*a9fa9459Szrj { 1385*a9fa9459Szrj if (data != NULL) 1386*a9fa9459Szrj free (data); 1387*a9fa9459Szrj return FALSE; 1388*a9fa9459Szrj } 1389*a9fa9459Szrj 1390*a9fa9459Szrj adj = section->vma - extra->ImageBase; 1391*a9fa9459Szrj 1392*a9fa9459Szrj /* Print all image import descriptors. */ 1393*a9fa9459Szrj for (i = dataoff; i + onaline <= datasize; i += onaline) 1394*a9fa9459Szrj { 1395*a9fa9459Szrj bfd_vma hint_addr; 1396*a9fa9459Szrj bfd_vma time_stamp; 1397*a9fa9459Szrj bfd_vma forward_chain; 1398*a9fa9459Szrj bfd_vma dll_name; 1399*a9fa9459Szrj bfd_vma first_thunk; 1400*a9fa9459Szrj int idx = 0; 1401*a9fa9459Szrj bfd_size_type j; 1402*a9fa9459Szrj char *dll; 1403*a9fa9459Szrj 1404*a9fa9459Szrj /* Print (i + extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress). */ 1405*a9fa9459Szrj fprintf (file, " %08lx\t", (unsigned long) (i + adj)); 1406*a9fa9459Szrj hint_addr = bfd_get_32 (abfd, data + i); 1407*a9fa9459Szrj time_stamp = bfd_get_32 (abfd, data + i + 4); 1408*a9fa9459Szrj forward_chain = bfd_get_32 (abfd, data + i + 8); 1409*a9fa9459Szrj dll_name = bfd_get_32 (abfd, data + i + 12); 1410*a9fa9459Szrj first_thunk = bfd_get_32 (abfd, data + i + 16); 1411*a9fa9459Szrj 1412*a9fa9459Szrj fprintf (file, "%08lx %08lx %08lx %08lx %08lx\n", 1413*a9fa9459Szrj (unsigned long) hint_addr, 1414*a9fa9459Szrj (unsigned long) time_stamp, 1415*a9fa9459Szrj (unsigned long) forward_chain, 1416*a9fa9459Szrj (unsigned long) dll_name, 1417*a9fa9459Szrj (unsigned long) first_thunk); 1418*a9fa9459Szrj 1419*a9fa9459Szrj if (hint_addr == 0 && first_thunk == 0) 1420*a9fa9459Szrj break; 1421*a9fa9459Szrj 1422*a9fa9459Szrj if (dll_name - adj >= section->size) 1423*a9fa9459Szrj break; 1424*a9fa9459Szrj 1425*a9fa9459Szrj dll = (char *) data + dll_name - adj; 1426*a9fa9459Szrj /* PR 17512 file: 078-12277-0.004. */ 1427*a9fa9459Szrj bfd_size_type maxlen = (char *)(data + datasize) - dll - 1; 1428*a9fa9459Szrj fprintf (file, _("\n\tDLL Name: %.*s\n"), (int) maxlen, dll); 1429*a9fa9459Szrj 1430*a9fa9459Szrj if (hint_addr != 0) 1431*a9fa9459Szrj { 1432*a9fa9459Szrj bfd_byte *ft_data; 1433*a9fa9459Szrj asection *ft_section; 1434*a9fa9459Szrj bfd_vma ft_addr; 1435*a9fa9459Szrj bfd_size_type ft_datasize; 1436*a9fa9459Szrj int ft_idx; 1437*a9fa9459Szrj int ft_allocated; 1438*a9fa9459Szrj 1439*a9fa9459Szrj fprintf (file, _("\tvma: Hint/Ord Member-Name Bound-To\n")); 1440*a9fa9459Szrj 1441*a9fa9459Szrj idx = hint_addr - adj; 1442*a9fa9459Szrj 1443*a9fa9459Szrj ft_addr = first_thunk + extra->ImageBase; 1444*a9fa9459Szrj ft_idx = first_thunk - adj; 1445*a9fa9459Szrj ft_data = data + ft_idx; 1446*a9fa9459Szrj ft_datasize = datasize - ft_idx; 1447*a9fa9459Szrj ft_allocated = 0; 1448*a9fa9459Szrj 1449*a9fa9459Szrj if (first_thunk != hint_addr) 1450*a9fa9459Szrj { 1451*a9fa9459Szrj /* Find the section which contains the first thunk. */ 1452*a9fa9459Szrj for (ft_section = abfd->sections; 1453*a9fa9459Szrj ft_section != NULL; 1454*a9fa9459Szrj ft_section = ft_section->next) 1455*a9fa9459Szrj { 1456*a9fa9459Szrj if (ft_addr >= ft_section->vma 1457*a9fa9459Szrj && ft_addr < ft_section->vma + ft_section->size) 1458*a9fa9459Szrj break; 1459*a9fa9459Szrj } 1460*a9fa9459Szrj 1461*a9fa9459Szrj if (ft_section == NULL) 1462*a9fa9459Szrj { 1463*a9fa9459Szrj fprintf (file, 1464*a9fa9459Szrj _("\nThere is a first thunk, but the section containing it could not be found\n")); 1465*a9fa9459Szrj continue; 1466*a9fa9459Szrj } 1467*a9fa9459Szrj 1468*a9fa9459Szrj /* Now check to see if this section is the same as our current 1469*a9fa9459Szrj section. If it is not then we will have to load its data in. */ 1470*a9fa9459Szrj if (ft_section != section) 1471*a9fa9459Szrj { 1472*a9fa9459Szrj ft_idx = first_thunk - (ft_section->vma - extra->ImageBase); 1473*a9fa9459Szrj ft_datasize = ft_section->size - ft_idx; 1474*a9fa9459Szrj ft_data = (bfd_byte *) bfd_malloc (ft_datasize); 1475*a9fa9459Szrj if (ft_data == NULL) 1476*a9fa9459Szrj continue; 1477*a9fa9459Szrj 1478*a9fa9459Szrj /* Read ft_datasize bytes starting at offset ft_idx. */ 1479*a9fa9459Szrj if (!bfd_get_section_contents (abfd, ft_section, ft_data, 1480*a9fa9459Szrj (bfd_vma) ft_idx, ft_datasize)) 1481*a9fa9459Szrj { 1482*a9fa9459Szrj free (ft_data); 1483*a9fa9459Szrj continue; 1484*a9fa9459Szrj } 1485*a9fa9459Szrj ft_allocated = 1; 1486*a9fa9459Szrj } 1487*a9fa9459Szrj } 1488*a9fa9459Szrj 1489*a9fa9459Szrj /* Print HintName vector entries. */ 1490*a9fa9459Szrj #ifdef COFF_WITH_pex64 1491*a9fa9459Szrj for (j = 0; idx + j + 8 <= datasize; j += 8) 1492*a9fa9459Szrj { 1493*a9fa9459Szrj bfd_size_type amt; 1494*a9fa9459Szrj unsigned long member = bfd_get_32 (abfd, data + idx + j); 1495*a9fa9459Szrj unsigned long member_high = bfd_get_32 (abfd, data + idx + j + 4); 1496*a9fa9459Szrj 1497*a9fa9459Szrj if (!member && !member_high) 1498*a9fa9459Szrj break; 1499*a9fa9459Szrj 1500*a9fa9459Szrj amt = member - adj; 1501*a9fa9459Szrj 1502*a9fa9459Szrj if (HighBitSet (member_high)) 1503*a9fa9459Szrj fprintf (file, "\t%lx%08lx\t %4lx%08lx <none>", 1504*a9fa9459Szrj member_high, member, 1505*a9fa9459Szrj WithoutHighBit (member_high), member); 1506*a9fa9459Szrj /* PR binutils/17512: Handle corrupt PE data. */ 1507*a9fa9459Szrj else if (amt + 2 >= datasize) 1508*a9fa9459Szrj fprintf (file, _("\t<corrupt: 0x%04lx>"), member); 1509*a9fa9459Szrj else 1510*a9fa9459Szrj { 1511*a9fa9459Szrj int ordinal; 1512*a9fa9459Szrj char *member_name; 1513*a9fa9459Szrj 1514*a9fa9459Szrj ordinal = bfd_get_16 (abfd, data + amt); 1515*a9fa9459Szrj member_name = (char *) data + amt + 2; 1516*a9fa9459Szrj fprintf (file, "\t%04lx\t %4d %.*s",member, ordinal, 1517*a9fa9459Szrj (int) (datasize - (amt + 2)), member_name); 1518*a9fa9459Szrj } 1519*a9fa9459Szrj 1520*a9fa9459Szrj /* If the time stamp is not zero, the import address 1521*a9fa9459Szrj table holds actual addresses. */ 1522*a9fa9459Szrj if (time_stamp != 0 1523*a9fa9459Szrj && first_thunk != 0 1524*a9fa9459Szrj && first_thunk != hint_addr 1525*a9fa9459Szrj && j + 4 <= ft_datasize) 1526*a9fa9459Szrj fprintf (file, "\t%04lx", 1527*a9fa9459Szrj (unsigned long) bfd_get_32 (abfd, ft_data + j)); 1528*a9fa9459Szrj fprintf (file, "\n"); 1529*a9fa9459Szrj } 1530*a9fa9459Szrj #else 1531*a9fa9459Szrj for (j = 0; idx + j + 4 <= datasize; j += 4) 1532*a9fa9459Szrj { 1533*a9fa9459Szrj bfd_size_type amt; 1534*a9fa9459Szrj unsigned long member = bfd_get_32 (abfd, data + idx + j); 1535*a9fa9459Szrj 1536*a9fa9459Szrj /* Print single IMAGE_IMPORT_BY_NAME vector. */ 1537*a9fa9459Szrj if (member == 0) 1538*a9fa9459Szrj break; 1539*a9fa9459Szrj 1540*a9fa9459Szrj amt = member - adj; 1541*a9fa9459Szrj if (HighBitSet (member)) 1542*a9fa9459Szrj fprintf (file, "\t%04lx\t %4lu <none>", 1543*a9fa9459Szrj member, WithoutHighBit (member)); 1544*a9fa9459Szrj /* PR binutils/17512: Handle corrupt PE data. */ 1545*a9fa9459Szrj else if (amt + 2 >= datasize) 1546*a9fa9459Szrj fprintf (file, _("\t<corrupt: 0x%04lx>"), member); 1547*a9fa9459Szrj else 1548*a9fa9459Szrj { 1549*a9fa9459Szrj int ordinal; 1550*a9fa9459Szrj char *member_name; 1551*a9fa9459Szrj 1552*a9fa9459Szrj ordinal = bfd_get_16 (abfd, data + amt); 1553*a9fa9459Szrj member_name = (char *) data + amt + 2; 1554*a9fa9459Szrj fprintf (file, "\t%04lx\t %4d %.*s", 1555*a9fa9459Szrj member, ordinal, 1556*a9fa9459Szrj (int) (datasize - (amt + 2)), member_name); 1557*a9fa9459Szrj } 1558*a9fa9459Szrj 1559*a9fa9459Szrj /* If the time stamp is not zero, the import address 1560*a9fa9459Szrj table holds actual addresses. */ 1561*a9fa9459Szrj if (time_stamp != 0 1562*a9fa9459Szrj && first_thunk != 0 1563*a9fa9459Szrj && first_thunk != hint_addr 1564*a9fa9459Szrj && j + 4 <= ft_datasize) 1565*a9fa9459Szrj fprintf (file, "\t%04lx", 1566*a9fa9459Szrj (unsigned long) bfd_get_32 (abfd, ft_data + j)); 1567*a9fa9459Szrj 1568*a9fa9459Szrj fprintf (file, "\n"); 1569*a9fa9459Szrj } 1570*a9fa9459Szrj #endif 1571*a9fa9459Szrj if (ft_allocated) 1572*a9fa9459Szrj free (ft_data); 1573*a9fa9459Szrj } 1574*a9fa9459Szrj 1575*a9fa9459Szrj fprintf (file, "\n"); 1576*a9fa9459Szrj } 1577*a9fa9459Szrj 1578*a9fa9459Szrj free (data); 1579*a9fa9459Szrj 1580*a9fa9459Szrj return TRUE; 1581*a9fa9459Szrj } 1582*a9fa9459Szrj 1583*a9fa9459Szrj static bfd_boolean 1584*a9fa9459Szrj pe_print_edata (bfd * abfd, void * vfile) 1585*a9fa9459Szrj { 1586*a9fa9459Szrj FILE *file = (FILE *) vfile; 1587*a9fa9459Szrj bfd_byte *data; 1588*a9fa9459Szrj asection *section; 1589*a9fa9459Szrj bfd_size_type datasize = 0; 1590*a9fa9459Szrj bfd_size_type dataoff; 1591*a9fa9459Szrj bfd_size_type i; 1592*a9fa9459Szrj bfd_vma adj; 1593*a9fa9459Szrj struct EDT_type 1594*a9fa9459Szrj { 1595*a9fa9459Szrj long export_flags; /* Reserved - should be zero. */ 1596*a9fa9459Szrj long time_stamp; 1597*a9fa9459Szrj short major_ver; 1598*a9fa9459Szrj short minor_ver; 1599*a9fa9459Szrj bfd_vma name; /* RVA - relative to image base. */ 1600*a9fa9459Szrj long base; /* Ordinal base. */ 1601*a9fa9459Szrj unsigned long num_functions;/* Number in the export address table. */ 1602*a9fa9459Szrj unsigned long num_names; /* Number in the name pointer table. */ 1603*a9fa9459Szrj bfd_vma eat_addr; /* RVA to the export address table. */ 1604*a9fa9459Szrj bfd_vma npt_addr; /* RVA to the Export Name Pointer Table. */ 1605*a9fa9459Szrj bfd_vma ot_addr; /* RVA to the Ordinal Table. */ 1606*a9fa9459Szrj } edt; 1607*a9fa9459Szrj 1608*a9fa9459Szrj pe_data_type *pe = pe_data (abfd); 1609*a9fa9459Szrj struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; 1610*a9fa9459Szrj 1611*a9fa9459Szrj bfd_vma addr; 1612*a9fa9459Szrj 1613*a9fa9459Szrj addr = extra->DataDirectory[PE_EXPORT_TABLE].VirtualAddress; 1614*a9fa9459Szrj 1615*a9fa9459Szrj if (addr == 0 && extra->DataDirectory[PE_EXPORT_TABLE].Size == 0) 1616*a9fa9459Szrj { 1617*a9fa9459Szrj /* Maybe the extra header isn't there. Look for the section. */ 1618*a9fa9459Szrj section = bfd_get_section_by_name (abfd, ".edata"); 1619*a9fa9459Szrj if (section == NULL) 1620*a9fa9459Szrj return TRUE; 1621*a9fa9459Szrj 1622*a9fa9459Szrj addr = section->vma; 1623*a9fa9459Szrj dataoff = 0; 1624*a9fa9459Szrj datasize = section->size; 1625*a9fa9459Szrj if (datasize == 0) 1626*a9fa9459Szrj return TRUE; 1627*a9fa9459Szrj } 1628*a9fa9459Szrj else 1629*a9fa9459Szrj { 1630*a9fa9459Szrj addr += extra->ImageBase; 1631*a9fa9459Szrj 1632*a9fa9459Szrj for (section = abfd->sections; section != NULL; section = section->next) 1633*a9fa9459Szrj if (addr >= section->vma && addr < section->vma + section->size) 1634*a9fa9459Szrj break; 1635*a9fa9459Szrj 1636*a9fa9459Szrj if (section == NULL) 1637*a9fa9459Szrj { 1638*a9fa9459Szrj fprintf (file, 1639*a9fa9459Szrj _("\nThere is an export table, but the section containing it could not be found\n")); 1640*a9fa9459Szrj return TRUE; 1641*a9fa9459Szrj } 1642*a9fa9459Szrj else if (!(section->flags & SEC_HAS_CONTENTS)) 1643*a9fa9459Szrj { 1644*a9fa9459Szrj fprintf (file, 1645*a9fa9459Szrj _("\nThere is an export table in %s, but that section has no contents\n"), 1646*a9fa9459Szrj section->name); 1647*a9fa9459Szrj return TRUE; 1648*a9fa9459Szrj } 1649*a9fa9459Szrj 1650*a9fa9459Szrj dataoff = addr - section->vma; 1651*a9fa9459Szrj datasize = extra->DataDirectory[PE_EXPORT_TABLE].Size; 1652*a9fa9459Szrj if (datasize > section->size - dataoff) 1653*a9fa9459Szrj { 1654*a9fa9459Szrj fprintf (file, 1655*a9fa9459Szrj _("\nThere is an export table in %s, but it does not fit into that section\n"), 1656*a9fa9459Szrj section->name); 1657*a9fa9459Szrj return TRUE; 1658*a9fa9459Szrj } 1659*a9fa9459Szrj } 1660*a9fa9459Szrj 1661*a9fa9459Szrj /* PR 17512: Handle corrupt PE binaries. */ 1662*a9fa9459Szrj if (datasize < 36) 1663*a9fa9459Szrj { 1664*a9fa9459Szrj fprintf (file, 1665*a9fa9459Szrj _("\nThere is an export table in %s, but it is too small (%d)\n"), 1666*a9fa9459Szrj section->name, (int) datasize); 1667*a9fa9459Szrj return TRUE; 1668*a9fa9459Szrj } 1669*a9fa9459Szrj 1670*a9fa9459Szrj fprintf (file, _("\nThere is an export table in %s at 0x%lx\n"), 1671*a9fa9459Szrj section->name, (unsigned long) addr); 1672*a9fa9459Szrj 1673*a9fa9459Szrj data = (bfd_byte *) bfd_malloc (datasize); 1674*a9fa9459Szrj if (data == NULL) 1675*a9fa9459Szrj return FALSE; 1676*a9fa9459Szrj 1677*a9fa9459Szrj if (! bfd_get_section_contents (abfd, section, data, 1678*a9fa9459Szrj (file_ptr) dataoff, datasize)) 1679*a9fa9459Szrj return FALSE; 1680*a9fa9459Szrj 1681*a9fa9459Szrj /* Go get Export Directory Table. */ 1682*a9fa9459Szrj edt.export_flags = bfd_get_32 (abfd, data + 0); 1683*a9fa9459Szrj edt.time_stamp = bfd_get_32 (abfd, data + 4); 1684*a9fa9459Szrj edt.major_ver = bfd_get_16 (abfd, data + 8); 1685*a9fa9459Szrj edt.minor_ver = bfd_get_16 (abfd, data + 10); 1686*a9fa9459Szrj edt.name = bfd_get_32 (abfd, data + 12); 1687*a9fa9459Szrj edt.base = bfd_get_32 (abfd, data + 16); 1688*a9fa9459Szrj edt.num_functions = bfd_get_32 (abfd, data + 20); 1689*a9fa9459Szrj edt.num_names = bfd_get_32 (abfd, data + 24); 1690*a9fa9459Szrj edt.eat_addr = bfd_get_32 (abfd, data + 28); 1691*a9fa9459Szrj edt.npt_addr = bfd_get_32 (abfd, data + 32); 1692*a9fa9459Szrj edt.ot_addr = bfd_get_32 (abfd, data + 36); 1693*a9fa9459Szrj 1694*a9fa9459Szrj adj = section->vma - extra->ImageBase + dataoff; 1695*a9fa9459Szrj 1696*a9fa9459Szrj /* Dump the EDT first. */ 1697*a9fa9459Szrj fprintf (file, 1698*a9fa9459Szrj _("\nThe Export Tables (interpreted %s section contents)\n\n"), 1699*a9fa9459Szrj section->name); 1700*a9fa9459Szrj 1701*a9fa9459Szrj fprintf (file, 1702*a9fa9459Szrj _("Export Flags \t\t\t%lx\n"), (unsigned long) edt.export_flags); 1703*a9fa9459Szrj 1704*a9fa9459Szrj fprintf (file, 1705*a9fa9459Szrj _("Time/Date stamp \t\t%lx\n"), (unsigned long) edt.time_stamp); 1706*a9fa9459Szrj 1707*a9fa9459Szrj fprintf (file, 1708*a9fa9459Szrj _("Major/Minor \t\t\t%d/%d\n"), edt.major_ver, edt.minor_ver); 1709*a9fa9459Szrj 1710*a9fa9459Szrj fprintf (file, 1711*a9fa9459Szrj _("Name \t\t\t\t")); 1712*a9fa9459Szrj bfd_fprintf_vma (abfd, file, edt.name); 1713*a9fa9459Szrj 1714*a9fa9459Szrj if ((edt.name >= adj) && (edt.name < adj + datasize)) 1715*a9fa9459Szrj fprintf (file, " %.*s\n", 1716*a9fa9459Szrj (int) (datasize - (edt.name - adj)), 1717*a9fa9459Szrj data + edt.name - adj); 1718*a9fa9459Szrj else 1719*a9fa9459Szrj fprintf (file, "(outside .edata section)\n"); 1720*a9fa9459Szrj 1721*a9fa9459Szrj fprintf (file, 1722*a9fa9459Szrj _("Ordinal Base \t\t\t%ld\n"), edt.base); 1723*a9fa9459Szrj 1724*a9fa9459Szrj fprintf (file, 1725*a9fa9459Szrj _("Number in:\n")); 1726*a9fa9459Szrj 1727*a9fa9459Szrj fprintf (file, 1728*a9fa9459Szrj _("\tExport Address Table \t\t%08lx\n"), 1729*a9fa9459Szrj edt.num_functions); 1730*a9fa9459Szrj 1731*a9fa9459Szrj fprintf (file, 1732*a9fa9459Szrj _("\t[Name Pointer/Ordinal] Table\t%08lx\n"), edt.num_names); 1733*a9fa9459Szrj 1734*a9fa9459Szrj fprintf (file, 1735*a9fa9459Szrj _("Table Addresses\n")); 1736*a9fa9459Szrj 1737*a9fa9459Szrj fprintf (file, 1738*a9fa9459Szrj _("\tExport Address Table \t\t")); 1739*a9fa9459Szrj bfd_fprintf_vma (abfd, file, edt.eat_addr); 1740*a9fa9459Szrj fprintf (file, "\n"); 1741*a9fa9459Szrj 1742*a9fa9459Szrj fprintf (file, 1743*a9fa9459Szrj _("\tName Pointer Table \t\t")); 1744*a9fa9459Szrj bfd_fprintf_vma (abfd, file, edt.npt_addr); 1745*a9fa9459Szrj fprintf (file, "\n"); 1746*a9fa9459Szrj 1747*a9fa9459Szrj fprintf (file, 1748*a9fa9459Szrj _("\tOrdinal Table \t\t\t")); 1749*a9fa9459Szrj bfd_fprintf_vma (abfd, file, edt.ot_addr); 1750*a9fa9459Szrj fprintf (file, "\n"); 1751*a9fa9459Szrj 1752*a9fa9459Szrj /* The next table to find is the Export Address Table. It's basically 1753*a9fa9459Szrj a list of pointers that either locate a function in this dll, or 1754*a9fa9459Szrj forward the call to another dll. Something like: 1755*a9fa9459Szrj typedef union 1756*a9fa9459Szrj { 1757*a9fa9459Szrj long export_rva; 1758*a9fa9459Szrj long forwarder_rva; 1759*a9fa9459Szrj } export_address_table_entry; */ 1760*a9fa9459Szrj 1761*a9fa9459Szrj fprintf (file, 1762*a9fa9459Szrj _("\nExport Address Table -- Ordinal Base %ld\n"), 1763*a9fa9459Szrj edt.base); 1764*a9fa9459Szrj 1765*a9fa9459Szrj /* PR 17512: Handle corrupt PE binaries. */ 1766*a9fa9459Szrj if (edt.eat_addr + (edt.num_functions * 4) - adj >= datasize 1767*a9fa9459Szrj /* PR 17512: file: 092b1829 */ 1768*a9fa9459Szrj || (edt.num_functions * 4) < edt.num_functions 1769*a9fa9459Szrj /* PR 17512 file: 140-165018-0.004. */ 1770*a9fa9459Szrj || data + edt.eat_addr - adj < data) 1771*a9fa9459Szrj fprintf (file, _("\tInvalid Export Address Table rva (0x%lx) or entry count (0x%lx)\n"), 1772*a9fa9459Szrj (long) edt.eat_addr, 1773*a9fa9459Szrj (long) edt.num_functions); 1774*a9fa9459Szrj else for (i = 0; i < edt.num_functions; ++i) 1775*a9fa9459Szrj { 1776*a9fa9459Szrj bfd_vma eat_member = bfd_get_32 (abfd, 1777*a9fa9459Szrj data + edt.eat_addr + (i * 4) - adj); 1778*a9fa9459Szrj if (eat_member == 0) 1779*a9fa9459Szrj continue; 1780*a9fa9459Szrj 1781*a9fa9459Szrj if (eat_member - adj <= datasize) 1782*a9fa9459Szrj { 1783*a9fa9459Szrj /* This rva is to a name (forwarding function) in our section. */ 1784*a9fa9459Szrj /* Should locate a function descriptor. */ 1785*a9fa9459Szrj fprintf (file, 1786*a9fa9459Szrj "\t[%4ld] +base[%4ld] %04lx %s -- %.*s\n", 1787*a9fa9459Szrj (long) i, 1788*a9fa9459Szrj (long) (i + edt.base), 1789*a9fa9459Szrj (unsigned long) eat_member, 1790*a9fa9459Szrj _("Forwarder RVA"), 1791*a9fa9459Szrj (int)(datasize - (eat_member - adj)), 1792*a9fa9459Szrj data + eat_member - adj); 1793*a9fa9459Szrj } 1794*a9fa9459Szrj else 1795*a9fa9459Szrj { 1796*a9fa9459Szrj /* Should locate a function descriptor in the reldata section. */ 1797*a9fa9459Szrj fprintf (file, 1798*a9fa9459Szrj "\t[%4ld] +base[%4ld] %04lx %s\n", 1799*a9fa9459Szrj (long) i, 1800*a9fa9459Szrj (long) (i + edt.base), 1801*a9fa9459Szrj (unsigned long) eat_member, 1802*a9fa9459Szrj _("Export RVA")); 1803*a9fa9459Szrj } 1804*a9fa9459Szrj } 1805*a9fa9459Szrj 1806*a9fa9459Szrj /* The Export Name Pointer Table is paired with the Export Ordinal Table. */ 1807*a9fa9459Szrj /* Dump them in parallel for clarity. */ 1808*a9fa9459Szrj fprintf (file, 1809*a9fa9459Szrj _("\n[Ordinal/Name Pointer] Table\n")); 1810*a9fa9459Szrj 1811*a9fa9459Szrj /* PR 17512: Handle corrupt PE binaries. */ 1812*a9fa9459Szrj if (edt.npt_addr + (edt.num_names * 4) - adj >= datasize 1813*a9fa9459Szrj /* PR 17512: file: bb68816e. */ 1814*a9fa9459Szrj || edt.num_names * 4 < edt.num_names 1815*a9fa9459Szrj || (data + edt.npt_addr - adj) < data) 1816*a9fa9459Szrj fprintf (file, _("\tInvalid Name Pointer Table rva (0x%lx) or entry count (0x%lx)\n"), 1817*a9fa9459Szrj (long) edt.npt_addr, 1818*a9fa9459Szrj (long) edt.num_names); 1819*a9fa9459Szrj /* PR 17512: file: 140-147171-0.004. */ 1820*a9fa9459Szrj else if (edt.ot_addr + (edt.num_names * 2) - adj >= datasize 1821*a9fa9459Szrj || data + edt.ot_addr - adj < data) 1822*a9fa9459Szrj fprintf (file, _("\tInvalid Ordinal Table rva (0x%lx) or entry count (0x%lx)\n"), 1823*a9fa9459Szrj (long) edt.ot_addr, 1824*a9fa9459Szrj (long) edt.num_names); 1825*a9fa9459Szrj else for (i = 0; i < edt.num_names; ++i) 1826*a9fa9459Szrj { 1827*a9fa9459Szrj bfd_vma name_ptr; 1828*a9fa9459Szrj bfd_vma ord; 1829*a9fa9459Szrj 1830*a9fa9459Szrj ord = bfd_get_16 (abfd, data + edt.ot_addr + (i * 2) - adj); 1831*a9fa9459Szrj name_ptr = bfd_get_32 (abfd, data + edt.npt_addr + (i * 4) - adj); 1832*a9fa9459Szrj 1833*a9fa9459Szrj if ((name_ptr - adj) >= datasize) 1834*a9fa9459Szrj { 1835*a9fa9459Szrj fprintf (file, _("\t[%4ld] <corrupt offset: %lx>\n"), 1836*a9fa9459Szrj (long) ord, (long) name_ptr); 1837*a9fa9459Szrj } 1838*a9fa9459Szrj else 1839*a9fa9459Szrj { 1840*a9fa9459Szrj char * name = (char *) data + name_ptr - adj; 1841*a9fa9459Szrj 1842*a9fa9459Szrj fprintf (file, "\t[%4ld] %.*s\n", (long) ord, 1843*a9fa9459Szrj (int)((char *)(data + datasize) - name), name); 1844*a9fa9459Szrj } 1845*a9fa9459Szrj } 1846*a9fa9459Szrj 1847*a9fa9459Szrj free (data); 1848*a9fa9459Szrj 1849*a9fa9459Szrj return TRUE; 1850*a9fa9459Szrj } 1851*a9fa9459Szrj 1852*a9fa9459Szrj /* This really is architecture dependent. On IA-64, a .pdata entry 1853*a9fa9459Szrj consists of three dwords containing relative virtual addresses that 1854*a9fa9459Szrj specify the start and end address of the code range the entry 1855*a9fa9459Szrj covers and the address of the corresponding unwind info data. 1856*a9fa9459Szrj 1857*a9fa9459Szrj On ARM and SH-4, a compressed PDATA structure is used : 1858*a9fa9459Szrj _IMAGE_CE_RUNTIME_FUNCTION_ENTRY, whereas MIPS is documented to use 1859*a9fa9459Szrj _IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY. 1860*a9fa9459Szrj See http://msdn2.microsoft.com/en-us/library/ms253988(VS.80).aspx . 1861*a9fa9459Szrj 1862*a9fa9459Szrj This is the version for uncompressed data. */ 1863*a9fa9459Szrj 1864*a9fa9459Szrj static bfd_boolean 1865*a9fa9459Szrj pe_print_pdata (bfd * abfd, void * vfile) 1866*a9fa9459Szrj { 1867*a9fa9459Szrj #if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 1868*a9fa9459Szrj # define PDATA_ROW_SIZE (3 * 8) 1869*a9fa9459Szrj #else 1870*a9fa9459Szrj # define PDATA_ROW_SIZE (5 * 4) 1871*a9fa9459Szrj #endif 1872*a9fa9459Szrj FILE *file = (FILE *) vfile; 1873*a9fa9459Szrj bfd_byte *data = 0; 1874*a9fa9459Szrj asection *section = bfd_get_section_by_name (abfd, ".pdata"); 1875*a9fa9459Szrj bfd_size_type datasize = 0; 1876*a9fa9459Szrj bfd_size_type i; 1877*a9fa9459Szrj bfd_size_type start, stop; 1878*a9fa9459Szrj int onaline = PDATA_ROW_SIZE; 1879*a9fa9459Szrj 1880*a9fa9459Szrj if (section == NULL 1881*a9fa9459Szrj || coff_section_data (abfd, section) == NULL 1882*a9fa9459Szrj || pei_section_data (abfd, section) == NULL) 1883*a9fa9459Szrj return TRUE; 1884*a9fa9459Szrj 1885*a9fa9459Szrj stop = pei_section_data (abfd, section)->virt_size; 1886*a9fa9459Szrj if ((stop % onaline) != 0) 1887*a9fa9459Szrj fprintf (file, 1888*a9fa9459Szrj _("Warning, .pdata section size (%ld) is not a multiple of %d\n"), 1889*a9fa9459Szrj (long) stop, onaline); 1890*a9fa9459Szrj 1891*a9fa9459Szrj fprintf (file, 1892*a9fa9459Szrj _("\nThe Function Table (interpreted .pdata section contents)\n")); 1893*a9fa9459Szrj #if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 1894*a9fa9459Szrj fprintf (file, 1895*a9fa9459Szrj _(" vma:\t\t\tBegin Address End Address Unwind Info\n")); 1896*a9fa9459Szrj #else 1897*a9fa9459Szrj fprintf (file, _("\ 1898*a9fa9459Szrj vma:\t\tBegin End EH EH PrologEnd Exception\n\ 1899*a9fa9459Szrj \t\tAddress Address Handler Data Address Mask\n")); 1900*a9fa9459Szrj #endif 1901*a9fa9459Szrj 1902*a9fa9459Szrj datasize = section->size; 1903*a9fa9459Szrj if (datasize == 0) 1904*a9fa9459Szrj return TRUE; 1905*a9fa9459Szrj 1906*a9fa9459Szrj /* PR 17512: file: 002-193900-0.004. */ 1907*a9fa9459Szrj if (datasize < stop) 1908*a9fa9459Szrj { 1909*a9fa9459Szrj fprintf (file, _("Virtual size of .pdata section (%ld) larger than real size (%ld)\n"), 1910*a9fa9459Szrj (long) stop, (long) datasize); 1911*a9fa9459Szrj return FALSE; 1912*a9fa9459Szrj } 1913*a9fa9459Szrj 1914*a9fa9459Szrj if (! bfd_malloc_and_get_section (abfd, section, &data)) 1915*a9fa9459Szrj { 1916*a9fa9459Szrj if (data != NULL) 1917*a9fa9459Szrj free (data); 1918*a9fa9459Szrj return FALSE; 1919*a9fa9459Szrj } 1920*a9fa9459Szrj 1921*a9fa9459Szrj start = 0; 1922*a9fa9459Szrj 1923*a9fa9459Szrj for (i = start; i < stop; i += onaline) 1924*a9fa9459Szrj { 1925*a9fa9459Szrj bfd_vma begin_addr; 1926*a9fa9459Szrj bfd_vma end_addr; 1927*a9fa9459Szrj bfd_vma eh_handler; 1928*a9fa9459Szrj bfd_vma eh_data; 1929*a9fa9459Szrj bfd_vma prolog_end_addr; 1930*a9fa9459Szrj #if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) 1931*a9fa9459Szrj int em_data; 1932*a9fa9459Szrj #endif 1933*a9fa9459Szrj 1934*a9fa9459Szrj if (i + PDATA_ROW_SIZE > stop) 1935*a9fa9459Szrj break; 1936*a9fa9459Szrj 1937*a9fa9459Szrj begin_addr = GET_PDATA_ENTRY (abfd, data + i ); 1938*a9fa9459Szrj end_addr = GET_PDATA_ENTRY (abfd, data + i + 4); 1939*a9fa9459Szrj eh_handler = GET_PDATA_ENTRY (abfd, data + i + 8); 1940*a9fa9459Szrj eh_data = GET_PDATA_ENTRY (abfd, data + i + 12); 1941*a9fa9459Szrj prolog_end_addr = GET_PDATA_ENTRY (abfd, data + i + 16); 1942*a9fa9459Szrj 1943*a9fa9459Szrj if (begin_addr == 0 && end_addr == 0 && eh_handler == 0 1944*a9fa9459Szrj && eh_data == 0 && prolog_end_addr == 0) 1945*a9fa9459Szrj /* We are probably into the padding of the section now. */ 1946*a9fa9459Szrj break; 1947*a9fa9459Szrj 1948*a9fa9459Szrj #if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) 1949*a9fa9459Szrj em_data = ((eh_handler & 0x1) << 2) | (prolog_end_addr & 0x3); 1950*a9fa9459Szrj #endif 1951*a9fa9459Szrj eh_handler &= ~(bfd_vma) 0x3; 1952*a9fa9459Szrj prolog_end_addr &= ~(bfd_vma) 0x3; 1953*a9fa9459Szrj 1954*a9fa9459Szrj fputc (' ', file); 1955*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i + section->vma); fputc ('\t', file); 1956*a9fa9459Szrj bfd_fprintf_vma (abfd, file, begin_addr); fputc (' ', file); 1957*a9fa9459Szrj bfd_fprintf_vma (abfd, file, end_addr); fputc (' ', file); 1958*a9fa9459Szrj bfd_fprintf_vma (abfd, file, eh_handler); 1959*a9fa9459Szrj #if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) 1960*a9fa9459Szrj fputc (' ', file); 1961*a9fa9459Szrj bfd_fprintf_vma (abfd, file, eh_data); fputc (' ', file); 1962*a9fa9459Szrj bfd_fprintf_vma (abfd, file, prolog_end_addr); 1963*a9fa9459Szrj fprintf (file, " %x", em_data); 1964*a9fa9459Szrj #endif 1965*a9fa9459Szrj 1966*a9fa9459Szrj #ifdef POWERPC_LE_PE 1967*a9fa9459Szrj if (eh_handler == 0 && eh_data != 0) 1968*a9fa9459Szrj { 1969*a9fa9459Szrj /* Special bits here, although the meaning may be a little 1970*a9fa9459Szrj mysterious. The only one I know for sure is 0x03 1971*a9fa9459Szrj Code Significance 1972*a9fa9459Szrj 0x00 None 1973*a9fa9459Szrj 0x01 Register Save Millicode 1974*a9fa9459Szrj 0x02 Register Restore Millicode 1975*a9fa9459Szrj 0x03 Glue Code Sequence. */ 1976*a9fa9459Szrj switch (eh_data) 1977*a9fa9459Szrj { 1978*a9fa9459Szrj case 0x01: 1979*a9fa9459Szrj fprintf (file, _(" Register save millicode")); 1980*a9fa9459Szrj break; 1981*a9fa9459Szrj case 0x02: 1982*a9fa9459Szrj fprintf (file, _(" Register restore millicode")); 1983*a9fa9459Szrj break; 1984*a9fa9459Szrj case 0x03: 1985*a9fa9459Szrj fprintf (file, _(" Glue code sequence")); 1986*a9fa9459Szrj break; 1987*a9fa9459Szrj default: 1988*a9fa9459Szrj break; 1989*a9fa9459Szrj } 1990*a9fa9459Szrj } 1991*a9fa9459Szrj #endif 1992*a9fa9459Szrj fprintf (file, "\n"); 1993*a9fa9459Szrj } 1994*a9fa9459Szrj 1995*a9fa9459Szrj free (data); 1996*a9fa9459Szrj 1997*a9fa9459Szrj return TRUE; 1998*a9fa9459Szrj #undef PDATA_ROW_SIZE 1999*a9fa9459Szrj } 2000*a9fa9459Szrj 2001*a9fa9459Szrj typedef struct sym_cache 2002*a9fa9459Szrj { 2003*a9fa9459Szrj int symcount; 2004*a9fa9459Szrj asymbol ** syms; 2005*a9fa9459Szrj } sym_cache; 2006*a9fa9459Szrj 2007*a9fa9459Szrj static asymbol ** 2008*a9fa9459Szrj slurp_symtab (bfd *abfd, sym_cache *psc) 2009*a9fa9459Szrj { 2010*a9fa9459Szrj asymbol ** sy = NULL; 2011*a9fa9459Szrj long storage; 2012*a9fa9459Szrj 2013*a9fa9459Szrj if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) 2014*a9fa9459Szrj { 2015*a9fa9459Szrj psc->symcount = 0; 2016*a9fa9459Szrj return NULL; 2017*a9fa9459Szrj } 2018*a9fa9459Szrj 2019*a9fa9459Szrj storage = bfd_get_symtab_upper_bound (abfd); 2020*a9fa9459Szrj if (storage < 0) 2021*a9fa9459Szrj return NULL; 2022*a9fa9459Szrj if (storage) 2023*a9fa9459Szrj { 2024*a9fa9459Szrj sy = (asymbol **) bfd_malloc (storage); 2025*a9fa9459Szrj if (sy == NULL) 2026*a9fa9459Szrj return NULL; 2027*a9fa9459Szrj } 2028*a9fa9459Szrj 2029*a9fa9459Szrj psc->symcount = bfd_canonicalize_symtab (abfd, sy); 2030*a9fa9459Szrj if (psc->symcount < 0) 2031*a9fa9459Szrj return NULL; 2032*a9fa9459Szrj return sy; 2033*a9fa9459Szrj } 2034*a9fa9459Szrj 2035*a9fa9459Szrj static const char * 2036*a9fa9459Szrj my_symbol_for_address (bfd *abfd, bfd_vma func, sym_cache *psc) 2037*a9fa9459Szrj { 2038*a9fa9459Szrj int i; 2039*a9fa9459Szrj 2040*a9fa9459Szrj if (psc->syms == 0) 2041*a9fa9459Szrj psc->syms = slurp_symtab (abfd, psc); 2042*a9fa9459Szrj 2043*a9fa9459Szrj for (i = 0; i < psc->symcount; i++) 2044*a9fa9459Szrj { 2045*a9fa9459Szrj if (psc->syms[i]->section->vma + psc->syms[i]->value == func) 2046*a9fa9459Szrj return psc->syms[i]->name; 2047*a9fa9459Szrj } 2048*a9fa9459Szrj 2049*a9fa9459Szrj return NULL; 2050*a9fa9459Szrj } 2051*a9fa9459Szrj 2052*a9fa9459Szrj static void 2053*a9fa9459Szrj cleanup_syms (sym_cache *psc) 2054*a9fa9459Szrj { 2055*a9fa9459Szrj psc->symcount = 0; 2056*a9fa9459Szrj free (psc->syms); 2057*a9fa9459Szrj psc->syms = NULL; 2058*a9fa9459Szrj } 2059*a9fa9459Szrj 2060*a9fa9459Szrj /* This is the version for "compressed" pdata. */ 2061*a9fa9459Szrj 2062*a9fa9459Szrj bfd_boolean 2063*a9fa9459Szrj _bfd_XX_print_ce_compressed_pdata (bfd * abfd, void * vfile) 2064*a9fa9459Szrj { 2065*a9fa9459Szrj # define PDATA_ROW_SIZE (2 * 4) 2066*a9fa9459Szrj FILE *file = (FILE *) vfile; 2067*a9fa9459Szrj bfd_byte *data = NULL; 2068*a9fa9459Szrj asection *section = bfd_get_section_by_name (abfd, ".pdata"); 2069*a9fa9459Szrj bfd_size_type datasize = 0; 2070*a9fa9459Szrj bfd_size_type i; 2071*a9fa9459Szrj bfd_size_type start, stop; 2072*a9fa9459Szrj int onaline = PDATA_ROW_SIZE; 2073*a9fa9459Szrj struct sym_cache cache = {0, 0} ; 2074*a9fa9459Szrj 2075*a9fa9459Szrj if (section == NULL 2076*a9fa9459Szrj || coff_section_data (abfd, section) == NULL 2077*a9fa9459Szrj || pei_section_data (abfd, section) == NULL) 2078*a9fa9459Szrj return TRUE; 2079*a9fa9459Szrj 2080*a9fa9459Szrj stop = pei_section_data (abfd, section)->virt_size; 2081*a9fa9459Szrj if ((stop % onaline) != 0) 2082*a9fa9459Szrj fprintf (file, 2083*a9fa9459Szrj _("Warning, .pdata section size (%ld) is not a multiple of %d\n"), 2084*a9fa9459Szrj (long) stop, onaline); 2085*a9fa9459Szrj 2086*a9fa9459Szrj fprintf (file, 2087*a9fa9459Szrj _("\nThe Function Table (interpreted .pdata section contents)\n")); 2088*a9fa9459Szrj 2089*a9fa9459Szrj fprintf (file, _("\ 2090*a9fa9459Szrj vma:\t\tBegin Prolog Function Flags Exception EH\n\ 2091*a9fa9459Szrj \t\tAddress Length Length 32b exc Handler Data\n")); 2092*a9fa9459Szrj 2093*a9fa9459Szrj datasize = section->size; 2094*a9fa9459Szrj if (datasize == 0) 2095*a9fa9459Szrj return TRUE; 2096*a9fa9459Szrj 2097*a9fa9459Szrj if (! bfd_malloc_and_get_section (abfd, section, &data)) 2098*a9fa9459Szrj { 2099*a9fa9459Szrj if (data != NULL) 2100*a9fa9459Szrj free (data); 2101*a9fa9459Szrj return FALSE; 2102*a9fa9459Szrj } 2103*a9fa9459Szrj 2104*a9fa9459Szrj start = 0; 2105*a9fa9459Szrj 2106*a9fa9459Szrj for (i = start; i < stop; i += onaline) 2107*a9fa9459Szrj { 2108*a9fa9459Szrj bfd_vma begin_addr; 2109*a9fa9459Szrj bfd_vma other_data; 2110*a9fa9459Szrj bfd_vma prolog_length, function_length; 2111*a9fa9459Szrj int flag32bit, exception_flag; 2112*a9fa9459Szrj asection *tsection; 2113*a9fa9459Szrj 2114*a9fa9459Szrj if (i + PDATA_ROW_SIZE > stop) 2115*a9fa9459Szrj break; 2116*a9fa9459Szrj 2117*a9fa9459Szrj begin_addr = GET_PDATA_ENTRY (abfd, data + i ); 2118*a9fa9459Szrj other_data = GET_PDATA_ENTRY (abfd, data + i + 4); 2119*a9fa9459Szrj 2120*a9fa9459Szrj if (begin_addr == 0 && other_data == 0) 2121*a9fa9459Szrj /* We are probably into the padding of the section now. */ 2122*a9fa9459Szrj break; 2123*a9fa9459Szrj 2124*a9fa9459Szrj prolog_length = (other_data & 0x000000FF); 2125*a9fa9459Szrj function_length = (other_data & 0x3FFFFF00) >> 8; 2126*a9fa9459Szrj flag32bit = (int)((other_data & 0x40000000) >> 30); 2127*a9fa9459Szrj exception_flag = (int)((other_data & 0x80000000) >> 31); 2128*a9fa9459Szrj 2129*a9fa9459Szrj fputc (' ', file); 2130*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i + section->vma); fputc ('\t', file); 2131*a9fa9459Szrj bfd_fprintf_vma (abfd, file, begin_addr); fputc (' ', file); 2132*a9fa9459Szrj bfd_fprintf_vma (abfd, file, prolog_length); fputc (' ', file); 2133*a9fa9459Szrj bfd_fprintf_vma (abfd, file, function_length); fputc (' ', file); 2134*a9fa9459Szrj fprintf (file, "%2d %2d ", flag32bit, exception_flag); 2135*a9fa9459Szrj 2136*a9fa9459Szrj /* Get the exception handler's address and the data passed from the 2137*a9fa9459Szrj .text section. This is really the data that belongs with the .pdata 2138*a9fa9459Szrj but got "compressed" out for the ARM and SH4 architectures. */ 2139*a9fa9459Szrj tsection = bfd_get_section_by_name (abfd, ".text"); 2140*a9fa9459Szrj if (tsection && coff_section_data (abfd, tsection) 2141*a9fa9459Szrj && pei_section_data (abfd, tsection)) 2142*a9fa9459Szrj { 2143*a9fa9459Szrj bfd_vma eh_off = (begin_addr - 8) - tsection->vma; 2144*a9fa9459Szrj bfd_byte *tdata; 2145*a9fa9459Szrj 2146*a9fa9459Szrj tdata = (bfd_byte *) bfd_malloc (8); 2147*a9fa9459Szrj if (tdata) 2148*a9fa9459Szrj { 2149*a9fa9459Szrj if (bfd_get_section_contents (abfd, tsection, tdata, eh_off, 8)) 2150*a9fa9459Szrj { 2151*a9fa9459Szrj bfd_vma eh, eh_data; 2152*a9fa9459Szrj 2153*a9fa9459Szrj eh = bfd_get_32 (abfd, tdata); 2154*a9fa9459Szrj eh_data = bfd_get_32 (abfd, tdata + 4); 2155*a9fa9459Szrj fprintf (file, "%08x ", (unsigned int) eh); 2156*a9fa9459Szrj fprintf (file, "%08x", (unsigned int) eh_data); 2157*a9fa9459Szrj if (eh != 0) 2158*a9fa9459Szrj { 2159*a9fa9459Szrj const char *s = my_symbol_for_address (abfd, eh, &cache); 2160*a9fa9459Szrj 2161*a9fa9459Szrj if (s) 2162*a9fa9459Szrj fprintf (file, " (%s) ", s); 2163*a9fa9459Szrj } 2164*a9fa9459Szrj } 2165*a9fa9459Szrj free (tdata); 2166*a9fa9459Szrj } 2167*a9fa9459Szrj } 2168*a9fa9459Szrj 2169*a9fa9459Szrj fprintf (file, "\n"); 2170*a9fa9459Szrj } 2171*a9fa9459Szrj 2172*a9fa9459Szrj free (data); 2173*a9fa9459Szrj 2174*a9fa9459Szrj cleanup_syms (& cache); 2175*a9fa9459Szrj 2176*a9fa9459Szrj return TRUE; 2177*a9fa9459Szrj #undef PDATA_ROW_SIZE 2178*a9fa9459Szrj } 2179*a9fa9459Szrj 2180*a9fa9459Szrj 2181*a9fa9459Szrj #define IMAGE_REL_BASED_HIGHADJ 4 2182*a9fa9459Szrj static const char * const tbl[] = 2183*a9fa9459Szrj { 2184*a9fa9459Szrj "ABSOLUTE", 2185*a9fa9459Szrj "HIGH", 2186*a9fa9459Szrj "LOW", 2187*a9fa9459Szrj "HIGHLOW", 2188*a9fa9459Szrj "HIGHADJ", 2189*a9fa9459Szrj "MIPS_JMPADDR", 2190*a9fa9459Szrj "SECTION", 2191*a9fa9459Szrj "REL32", 2192*a9fa9459Szrj "RESERVED1", 2193*a9fa9459Szrj "MIPS_JMPADDR16", 2194*a9fa9459Szrj "DIR64", 2195*a9fa9459Szrj "HIGH3ADJ", 2196*a9fa9459Szrj "UNKNOWN", /* MUST be last. */ 2197*a9fa9459Szrj }; 2198*a9fa9459Szrj 2199*a9fa9459Szrj static bfd_boolean 2200*a9fa9459Szrj pe_print_reloc (bfd * abfd, void * vfile) 2201*a9fa9459Szrj { 2202*a9fa9459Szrj FILE *file = (FILE *) vfile; 2203*a9fa9459Szrj bfd_byte *data = 0; 2204*a9fa9459Szrj asection *section = bfd_get_section_by_name (abfd, ".reloc"); 2205*a9fa9459Szrj bfd_byte *p, *end; 2206*a9fa9459Szrj 2207*a9fa9459Szrj if (section == NULL || section->size == 0 || !(section->flags & SEC_HAS_CONTENTS)) 2208*a9fa9459Szrj return TRUE; 2209*a9fa9459Szrj 2210*a9fa9459Szrj fprintf (file, 2211*a9fa9459Szrj _("\n\nPE File Base Relocations (interpreted .reloc section contents)\n")); 2212*a9fa9459Szrj 2213*a9fa9459Szrj if (! bfd_malloc_and_get_section (abfd, section, &data)) 2214*a9fa9459Szrj { 2215*a9fa9459Szrj if (data != NULL) 2216*a9fa9459Szrj free (data); 2217*a9fa9459Szrj return FALSE; 2218*a9fa9459Szrj } 2219*a9fa9459Szrj 2220*a9fa9459Szrj p = data; 2221*a9fa9459Szrj end = data + section->size; 2222*a9fa9459Szrj while (p + 8 <= end) 2223*a9fa9459Szrj { 2224*a9fa9459Szrj int j; 2225*a9fa9459Szrj bfd_vma virtual_address; 2226*a9fa9459Szrj unsigned long number, size; 2227*a9fa9459Szrj bfd_byte *chunk_end; 2228*a9fa9459Szrj 2229*a9fa9459Szrj /* The .reloc section is a sequence of blocks, with a header consisting 2230*a9fa9459Szrj of two 32 bit quantities, followed by a number of 16 bit entries. */ 2231*a9fa9459Szrj virtual_address = bfd_get_32 (abfd, p); 2232*a9fa9459Szrj size = bfd_get_32 (abfd, p + 4); 2233*a9fa9459Szrj p += 8; 2234*a9fa9459Szrj number = (size - 8) / 2; 2235*a9fa9459Szrj 2236*a9fa9459Szrj if (size == 0) 2237*a9fa9459Szrj break; 2238*a9fa9459Szrj 2239*a9fa9459Szrj fprintf (file, 2240*a9fa9459Szrj _("\nVirtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n"), 2241*a9fa9459Szrj (unsigned long) virtual_address, size, size, number); 2242*a9fa9459Szrj 2243*a9fa9459Szrj chunk_end = p + size; 2244*a9fa9459Szrj if (chunk_end > end) 2245*a9fa9459Szrj chunk_end = end; 2246*a9fa9459Szrj j = 0; 2247*a9fa9459Szrj while (p + 2 <= chunk_end) 2248*a9fa9459Szrj { 2249*a9fa9459Szrj unsigned short e = bfd_get_16 (abfd, p); 2250*a9fa9459Szrj unsigned int t = (e & 0xF000) >> 12; 2251*a9fa9459Szrj int off = e & 0x0FFF; 2252*a9fa9459Szrj 2253*a9fa9459Szrj if (t >= sizeof (tbl) / sizeof (tbl[0])) 2254*a9fa9459Szrj t = (sizeof (tbl) / sizeof (tbl[0])) - 1; 2255*a9fa9459Szrj 2256*a9fa9459Szrj fprintf (file, 2257*a9fa9459Szrj _("\treloc %4d offset %4x [%4lx] %s"), 2258*a9fa9459Szrj j, off, (unsigned long) (off + virtual_address), tbl[t]); 2259*a9fa9459Szrj 2260*a9fa9459Szrj p += 2; 2261*a9fa9459Szrj j++; 2262*a9fa9459Szrj 2263*a9fa9459Szrj /* HIGHADJ takes an argument, - the next record *is* the 2264*a9fa9459Szrj low 16 bits of addend. */ 2265*a9fa9459Szrj if (t == IMAGE_REL_BASED_HIGHADJ && p + 2 <= chunk_end) 2266*a9fa9459Szrj { 2267*a9fa9459Szrj fprintf (file, " (%4x)", (unsigned int) bfd_get_16 (abfd, p)); 2268*a9fa9459Szrj p += 2; 2269*a9fa9459Szrj j++; 2270*a9fa9459Szrj } 2271*a9fa9459Szrj 2272*a9fa9459Szrj fprintf (file, "\n"); 2273*a9fa9459Szrj } 2274*a9fa9459Szrj } 2275*a9fa9459Szrj 2276*a9fa9459Szrj free (data); 2277*a9fa9459Szrj 2278*a9fa9459Szrj return TRUE; 2279*a9fa9459Szrj } 2280*a9fa9459Szrj 2281*a9fa9459Szrj /* A data structure describing the regions of a .rsrc section. 2282*a9fa9459Szrj Some fields are filled in as the section is parsed. */ 2283*a9fa9459Szrj 2284*a9fa9459Szrj typedef struct rsrc_regions 2285*a9fa9459Szrj { 2286*a9fa9459Szrj bfd_byte * section_start; 2287*a9fa9459Szrj bfd_byte * section_end; 2288*a9fa9459Szrj bfd_byte * strings_start; 2289*a9fa9459Szrj bfd_byte * resource_start; 2290*a9fa9459Szrj } rsrc_regions; 2291*a9fa9459Szrj 2292*a9fa9459Szrj static bfd_byte * 2293*a9fa9459Szrj rsrc_print_resource_directory (FILE * , bfd *, unsigned int, bfd_byte *, 2294*a9fa9459Szrj rsrc_regions *, bfd_vma); 2295*a9fa9459Szrj 2296*a9fa9459Szrj /* Print the resource entry at DATA, with the text indented by INDENT. 2297*a9fa9459Szrj Recusively calls rsrc_print_resource_directory to print the contents 2298*a9fa9459Szrj of directory entries. 2299*a9fa9459Szrj Returns the address of the end of the data associated with the entry 2300*a9fa9459Szrj or section_end + 1 upon failure. */ 2301*a9fa9459Szrj 2302*a9fa9459Szrj static bfd_byte * 2303*a9fa9459Szrj rsrc_print_resource_entries (FILE * file, 2304*a9fa9459Szrj bfd * abfd, 2305*a9fa9459Szrj unsigned int indent, 2306*a9fa9459Szrj bfd_boolean is_name, 2307*a9fa9459Szrj bfd_byte * data, 2308*a9fa9459Szrj rsrc_regions * regions, 2309*a9fa9459Szrj bfd_vma rva_bias) 2310*a9fa9459Szrj { 2311*a9fa9459Szrj unsigned long entry, addr, size; 2312*a9fa9459Szrj bfd_byte * leaf; 2313*a9fa9459Szrj 2314*a9fa9459Szrj if (data + 8 >= regions->section_end) 2315*a9fa9459Szrj return regions->section_end + 1; 2316*a9fa9459Szrj 2317*a9fa9459Szrj fprintf (file, _("%03x %*.s Entry: "), (int)(data - regions->section_start), indent, " "); 2318*a9fa9459Szrj 2319*a9fa9459Szrj entry = (unsigned long) bfd_get_32 (abfd, data); 2320*a9fa9459Szrj if (is_name) 2321*a9fa9459Szrj { 2322*a9fa9459Szrj bfd_byte * name; 2323*a9fa9459Szrj 2324*a9fa9459Szrj /* Note - the documentation says that this field is an RVA value 2325*a9fa9459Szrj but windres appears to produce a section relative offset with 2326*a9fa9459Szrj the top bit set. Support both styles for now. */ 2327*a9fa9459Szrj if (HighBitSet (entry)) 2328*a9fa9459Szrj name = regions->section_start + WithoutHighBit (entry); 2329*a9fa9459Szrj else 2330*a9fa9459Szrj name = regions->section_start + entry - rva_bias; 2331*a9fa9459Szrj 2332*a9fa9459Szrj if (name + 2 < regions->section_end && name > regions->section_start) 2333*a9fa9459Szrj { 2334*a9fa9459Szrj unsigned int len; 2335*a9fa9459Szrj 2336*a9fa9459Szrj if (regions->strings_start == NULL) 2337*a9fa9459Szrj regions->strings_start = name; 2338*a9fa9459Szrj 2339*a9fa9459Szrj len = bfd_get_16 (abfd, name); 2340*a9fa9459Szrj 2341*a9fa9459Szrj fprintf (file, _("name: [val: %08lx len %d]: "), entry, len); 2342*a9fa9459Szrj 2343*a9fa9459Szrj if (name + 2 + len * 2 < regions->section_end) 2344*a9fa9459Szrj { 2345*a9fa9459Szrj /* This strange loop is to cope with multibyte characters. */ 2346*a9fa9459Szrj while (len --) 2347*a9fa9459Szrj { 2348*a9fa9459Szrj char c; 2349*a9fa9459Szrj 2350*a9fa9459Szrj name += 2; 2351*a9fa9459Szrj c = * name; 2352*a9fa9459Szrj /* Avoid printing control characters. */ 2353*a9fa9459Szrj if (c > 0 && c < 32) 2354*a9fa9459Szrj fprintf (file, "^%c", c + 64); 2355*a9fa9459Szrj else 2356*a9fa9459Szrj fprintf (file, "%.1s", name); 2357*a9fa9459Szrj } 2358*a9fa9459Szrj } 2359*a9fa9459Szrj else 2360*a9fa9459Szrj { 2361*a9fa9459Szrj fprintf (file, _("<corrupt string length: %#x>\n"), len); 2362*a9fa9459Szrj /* PR binutils/17512: Do not try to continue decoding a 2363*a9fa9459Szrj corrupted resource section. It is likely to end up with 2364*a9fa9459Szrj reams of extraneous output. FIXME: We could probably 2365*a9fa9459Szrj continue if we disable the printing of strings... */ 2366*a9fa9459Szrj return regions->section_end + 1; 2367*a9fa9459Szrj } 2368*a9fa9459Szrj } 2369*a9fa9459Szrj else 2370*a9fa9459Szrj { 2371*a9fa9459Szrj fprintf (file, _("<corrupt string offset: %#lx>\n"), entry); 2372*a9fa9459Szrj return regions->section_end + 1; 2373*a9fa9459Szrj } 2374*a9fa9459Szrj } 2375*a9fa9459Szrj else 2376*a9fa9459Szrj fprintf (file, _("ID: %#08lx"), entry); 2377*a9fa9459Szrj 2378*a9fa9459Szrj entry = (long) bfd_get_32 (abfd, data + 4); 2379*a9fa9459Szrj fprintf (file, _(", Value: %#08lx\n"), entry); 2380*a9fa9459Szrj 2381*a9fa9459Szrj if (HighBitSet (entry)) 2382*a9fa9459Szrj { 2383*a9fa9459Szrj data = regions->section_start + WithoutHighBit (entry); 2384*a9fa9459Szrj if (data <= regions->section_start || data > regions->section_end) 2385*a9fa9459Szrj return regions->section_end + 1; 2386*a9fa9459Szrj 2387*a9fa9459Szrj /* FIXME: PR binutils/17512: A corrupt file could contain a loop 2388*a9fa9459Szrj in the resource table. We need some way to detect this. */ 2389*a9fa9459Szrj return rsrc_print_resource_directory (file, abfd, indent + 1, data, 2390*a9fa9459Szrj regions, rva_bias); 2391*a9fa9459Szrj } 2392*a9fa9459Szrj 2393*a9fa9459Szrj leaf = regions->section_start + entry; 2394*a9fa9459Szrj 2395*a9fa9459Szrj if (leaf + 16 >= regions->section_end 2396*a9fa9459Szrj /* PR 17512: file: 055dff7e. */ 2397*a9fa9459Szrj || leaf < regions->section_start) 2398*a9fa9459Szrj return regions->section_end + 1; 2399*a9fa9459Szrj 2400*a9fa9459Szrj fprintf (file, _("%03x %*.s Leaf: Addr: %#08lx, Size: %#08lx, Codepage: %d\n"), 2401*a9fa9459Szrj (int) (entry), indent, " ", 2402*a9fa9459Szrj addr = (long) bfd_get_32 (abfd, leaf), 2403*a9fa9459Szrj size = (long) bfd_get_32 (abfd, leaf + 4), 2404*a9fa9459Szrj (int) bfd_get_32 (abfd, leaf + 8)); 2405*a9fa9459Szrj 2406*a9fa9459Szrj /* Check that the reserved entry is 0. */ 2407*a9fa9459Szrj if (bfd_get_32 (abfd, leaf + 12) != 0 2408*a9fa9459Szrj /* And that the data address/size is valid too. */ 2409*a9fa9459Szrj || (regions->section_start + (addr - rva_bias) + size > regions->section_end)) 2410*a9fa9459Szrj return regions->section_end + 1; 2411*a9fa9459Szrj 2412*a9fa9459Szrj if (regions->resource_start == NULL) 2413*a9fa9459Szrj regions->resource_start = regions->section_start + (addr - rva_bias); 2414*a9fa9459Szrj 2415*a9fa9459Szrj return regions->section_start + (addr - rva_bias) + size; 2416*a9fa9459Szrj } 2417*a9fa9459Szrj 2418*a9fa9459Szrj #define max(a,b) ((a) > (b) ? (a) : (b)) 2419*a9fa9459Szrj #define min(a,b) ((a) < (b) ? (a) : (b)) 2420*a9fa9459Szrj 2421*a9fa9459Szrj static bfd_byte * 2422*a9fa9459Szrj rsrc_print_resource_directory (FILE * file, 2423*a9fa9459Szrj bfd * abfd, 2424*a9fa9459Szrj unsigned int indent, 2425*a9fa9459Szrj bfd_byte * data, 2426*a9fa9459Szrj rsrc_regions * regions, 2427*a9fa9459Szrj bfd_vma rva_bias) 2428*a9fa9459Szrj { 2429*a9fa9459Szrj unsigned int num_names, num_ids; 2430*a9fa9459Szrj bfd_byte * highest_data = data; 2431*a9fa9459Szrj 2432*a9fa9459Szrj if (data + 16 >= regions->section_end) 2433*a9fa9459Szrj return regions->section_end + 1; 2434*a9fa9459Szrj 2435*a9fa9459Szrj fprintf (file, "%03x %*.s ", (int)(data - regions->section_start), indent, " "); 2436*a9fa9459Szrj switch (indent) 2437*a9fa9459Szrj { 2438*a9fa9459Szrj case 0: fprintf (file, "Type"); break; 2439*a9fa9459Szrj case 2: fprintf (file, "Name"); break; 2440*a9fa9459Szrj case 4: fprintf (file, "Language"); break; 2441*a9fa9459Szrj default: 2442*a9fa9459Szrj fprintf (file, _("<unknown directory type: %d>\n"), indent); 2443*a9fa9459Szrj /* FIXME: For now we end the printing here. If in the 2444*a9fa9459Szrj future more directory types are added to the RSRC spec 2445*a9fa9459Szrj then we will need to change this. */ 2446*a9fa9459Szrj return regions->section_end + 1; 2447*a9fa9459Szrj } 2448*a9fa9459Szrj 2449*a9fa9459Szrj fprintf (file, _(" Table: Char: %d, Time: %08lx, Ver: %d/%d, Num Names: %d, IDs: %d\n"), 2450*a9fa9459Szrj (int) bfd_get_32 (abfd, data), 2451*a9fa9459Szrj (long) bfd_get_32 (abfd, data + 4), 2452*a9fa9459Szrj (int) bfd_get_16 (abfd, data + 8), 2453*a9fa9459Szrj (int) bfd_get_16 (abfd, data + 10), 2454*a9fa9459Szrj num_names = (int) bfd_get_16 (abfd, data + 12), 2455*a9fa9459Szrj num_ids = (int) bfd_get_16 (abfd, data + 14)); 2456*a9fa9459Szrj data += 16; 2457*a9fa9459Szrj 2458*a9fa9459Szrj while (num_names --) 2459*a9fa9459Szrj { 2460*a9fa9459Szrj bfd_byte * entry_end; 2461*a9fa9459Szrj 2462*a9fa9459Szrj entry_end = rsrc_print_resource_entries (file, abfd, indent + 1, TRUE, 2463*a9fa9459Szrj data, regions, rva_bias); 2464*a9fa9459Szrj data += 8; 2465*a9fa9459Szrj highest_data = max (highest_data, entry_end); 2466*a9fa9459Szrj if (entry_end >= regions->section_end) 2467*a9fa9459Szrj return entry_end; 2468*a9fa9459Szrj } 2469*a9fa9459Szrj 2470*a9fa9459Szrj while (num_ids --) 2471*a9fa9459Szrj { 2472*a9fa9459Szrj bfd_byte * entry_end; 2473*a9fa9459Szrj 2474*a9fa9459Szrj entry_end = rsrc_print_resource_entries (file, abfd, indent + 1, FALSE, 2475*a9fa9459Szrj data, regions, rva_bias); 2476*a9fa9459Szrj data += 8; 2477*a9fa9459Szrj highest_data = max (highest_data, entry_end); 2478*a9fa9459Szrj if (entry_end >= regions->section_end) 2479*a9fa9459Szrj return entry_end; 2480*a9fa9459Szrj } 2481*a9fa9459Szrj 2482*a9fa9459Szrj return max (highest_data, data); 2483*a9fa9459Szrj } 2484*a9fa9459Szrj 2485*a9fa9459Szrj /* Display the contents of a .rsrc section. We do not try to 2486*a9fa9459Szrj reproduce the resources, windres does that. Instead we dump 2487*a9fa9459Szrj the tables in a human readable format. */ 2488*a9fa9459Szrj 2489*a9fa9459Szrj static bfd_boolean 2490*a9fa9459Szrj rsrc_print_section (bfd * abfd, void * vfile) 2491*a9fa9459Szrj { 2492*a9fa9459Szrj bfd_vma rva_bias; 2493*a9fa9459Szrj pe_data_type * pe; 2494*a9fa9459Szrj FILE * file = (FILE *) vfile; 2495*a9fa9459Szrj bfd_size_type datasize; 2496*a9fa9459Szrj asection * section; 2497*a9fa9459Szrj bfd_byte * data; 2498*a9fa9459Szrj rsrc_regions regions; 2499*a9fa9459Szrj 2500*a9fa9459Szrj pe = pe_data (abfd); 2501*a9fa9459Szrj if (pe == NULL) 2502*a9fa9459Szrj return TRUE; 2503*a9fa9459Szrj 2504*a9fa9459Szrj section = bfd_get_section_by_name (abfd, ".rsrc"); 2505*a9fa9459Szrj if (section == NULL) 2506*a9fa9459Szrj return TRUE; 2507*a9fa9459Szrj if (!(section->flags & SEC_HAS_CONTENTS)) 2508*a9fa9459Szrj return TRUE; 2509*a9fa9459Szrj 2510*a9fa9459Szrj datasize = section->size; 2511*a9fa9459Szrj if (datasize == 0) 2512*a9fa9459Szrj return TRUE; 2513*a9fa9459Szrj 2514*a9fa9459Szrj rva_bias = section->vma - pe->pe_opthdr.ImageBase; 2515*a9fa9459Szrj 2516*a9fa9459Szrj if (! bfd_malloc_and_get_section (abfd, section, & data)) 2517*a9fa9459Szrj { 2518*a9fa9459Szrj if (data != NULL) 2519*a9fa9459Szrj free (data); 2520*a9fa9459Szrj return FALSE; 2521*a9fa9459Szrj } 2522*a9fa9459Szrj 2523*a9fa9459Szrj regions.section_start = data; 2524*a9fa9459Szrj regions.section_end = data + datasize; 2525*a9fa9459Szrj regions.strings_start = NULL; 2526*a9fa9459Szrj regions.resource_start = NULL; 2527*a9fa9459Szrj 2528*a9fa9459Szrj fflush (file); 2529*a9fa9459Szrj fprintf (file, "\nThe .rsrc Resource Directory section:\n"); 2530*a9fa9459Szrj 2531*a9fa9459Szrj while (data < regions.section_end) 2532*a9fa9459Szrj { 2533*a9fa9459Szrj bfd_byte * p = data; 2534*a9fa9459Szrj 2535*a9fa9459Szrj data = rsrc_print_resource_directory (file, abfd, 0, data, & regions, rva_bias); 2536*a9fa9459Szrj 2537*a9fa9459Szrj if (data == regions.section_end + 1) 2538*a9fa9459Szrj fprintf (file, _("Corrupt .rsrc section detected!\n")); 2539*a9fa9459Szrj else 2540*a9fa9459Szrj { 2541*a9fa9459Szrj /* Align data before continuing. */ 2542*a9fa9459Szrj int align = (1 << section->alignment_power) - 1; 2543*a9fa9459Szrj 2544*a9fa9459Szrj data = (bfd_byte *) (((ptrdiff_t) (data + align)) & ~ align); 2545*a9fa9459Szrj rva_bias += data - p; 2546*a9fa9459Szrj 2547*a9fa9459Szrj /* For reasons that are unclear .rsrc sections are sometimes created 2548*a9fa9459Szrj aligned to a 1^3 boundary even when their alignment is set at 2549*a9fa9459Szrj 1^2. Catch that case here before we issue a spurious warning 2550*a9fa9459Szrj message. */ 2551*a9fa9459Szrj if (data == (regions.section_end - 4)) 2552*a9fa9459Szrj data = regions.section_end; 2553*a9fa9459Szrj else if (data < regions.section_end) 2554*a9fa9459Szrj { 2555*a9fa9459Szrj /* If the extra data is all zeros then do not complain. 2556*a9fa9459Szrj This is just padding so that the section meets the 2557*a9fa9459Szrj page size requirements. */ 2558*a9fa9459Szrj while (++ data < regions.section_end) 2559*a9fa9459Szrj if (*data != 0) 2560*a9fa9459Szrj break; 2561*a9fa9459Szrj if (data < regions.section_end) 2562*a9fa9459Szrj fprintf (file, _("\nWARNING: Extra data in .rsrc section - it will be ignored by Windows:\n")); 2563*a9fa9459Szrj } 2564*a9fa9459Szrj } 2565*a9fa9459Szrj } 2566*a9fa9459Szrj 2567*a9fa9459Szrj if (regions.strings_start != NULL) 2568*a9fa9459Szrj fprintf (file, " String table starts at offset: %#03x\n", 2569*a9fa9459Szrj (int) (regions.strings_start - regions.section_start)); 2570*a9fa9459Szrj if (regions.resource_start != NULL) 2571*a9fa9459Szrj fprintf (file, " Resources start at offset: %#03x\n", 2572*a9fa9459Szrj (int) (regions.resource_start - regions.section_start)); 2573*a9fa9459Szrj 2574*a9fa9459Szrj free (regions.section_start); 2575*a9fa9459Szrj return TRUE; 2576*a9fa9459Szrj } 2577*a9fa9459Szrj 2578*a9fa9459Szrj #define IMAGE_NUMBEROF_DEBUG_TYPES 12 2579*a9fa9459Szrj 2580*a9fa9459Szrj static char * debug_type_names[IMAGE_NUMBEROF_DEBUG_TYPES] = 2581*a9fa9459Szrj { 2582*a9fa9459Szrj "Unknown", 2583*a9fa9459Szrj "COFF", 2584*a9fa9459Szrj "CodeView", 2585*a9fa9459Szrj "FPO", 2586*a9fa9459Szrj "Misc", 2587*a9fa9459Szrj "Exception", 2588*a9fa9459Szrj "Fixup", 2589*a9fa9459Szrj "OMAP-to-SRC", 2590*a9fa9459Szrj "OMAP-from-SRC", 2591*a9fa9459Szrj "Borland", 2592*a9fa9459Szrj "Reserved", 2593*a9fa9459Szrj "CLSID", 2594*a9fa9459Szrj }; 2595*a9fa9459Szrj 2596*a9fa9459Szrj static bfd_boolean 2597*a9fa9459Szrj pe_print_debugdata (bfd * abfd, void * vfile) 2598*a9fa9459Szrj { 2599*a9fa9459Szrj FILE *file = (FILE *) vfile; 2600*a9fa9459Szrj pe_data_type *pe = pe_data (abfd); 2601*a9fa9459Szrj struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr; 2602*a9fa9459Szrj asection *section; 2603*a9fa9459Szrj bfd_byte *data = 0; 2604*a9fa9459Szrj bfd_size_type dataoff; 2605*a9fa9459Szrj unsigned int i; 2606*a9fa9459Szrj 2607*a9fa9459Szrj bfd_vma addr = extra->DataDirectory[PE_DEBUG_DATA].VirtualAddress; 2608*a9fa9459Szrj bfd_size_type size = extra->DataDirectory[PE_DEBUG_DATA].Size; 2609*a9fa9459Szrj 2610*a9fa9459Szrj if (size == 0) 2611*a9fa9459Szrj return TRUE; 2612*a9fa9459Szrj 2613*a9fa9459Szrj addr += extra->ImageBase; 2614*a9fa9459Szrj for (section = abfd->sections; section != NULL; section = section->next) 2615*a9fa9459Szrj { 2616*a9fa9459Szrj if ((addr >= section->vma) && (addr < (section->vma + section->size))) 2617*a9fa9459Szrj break; 2618*a9fa9459Szrj } 2619*a9fa9459Szrj 2620*a9fa9459Szrj if (section == NULL) 2621*a9fa9459Szrj { 2622*a9fa9459Szrj fprintf (file, 2623*a9fa9459Szrj _("\nThere is a debug directory, but the section containing it could not be found\n")); 2624*a9fa9459Szrj return TRUE; 2625*a9fa9459Szrj } 2626*a9fa9459Szrj else if (!(section->flags & SEC_HAS_CONTENTS)) 2627*a9fa9459Szrj { 2628*a9fa9459Szrj fprintf (file, 2629*a9fa9459Szrj _("\nThere is a debug directory in %s, but that section has no contents\n"), 2630*a9fa9459Szrj section->name); 2631*a9fa9459Szrj return TRUE; 2632*a9fa9459Szrj } 2633*a9fa9459Szrj else if (section->size < size) 2634*a9fa9459Szrj { 2635*a9fa9459Szrj fprintf (file, 2636*a9fa9459Szrj _("\nError: section %s contains the debug data starting address but it is too small\n"), 2637*a9fa9459Szrj section->name); 2638*a9fa9459Szrj return FALSE; 2639*a9fa9459Szrj } 2640*a9fa9459Szrj 2641*a9fa9459Szrj fprintf (file, _("\nThere is a debug directory in %s at 0x%lx\n\n"), 2642*a9fa9459Szrj section->name, (unsigned long) addr); 2643*a9fa9459Szrj 2644*a9fa9459Szrj dataoff = addr - section->vma; 2645*a9fa9459Szrj 2646*a9fa9459Szrj if (size > (section->size - dataoff)) 2647*a9fa9459Szrj { 2648*a9fa9459Szrj fprintf (file, _("The debug data size field in the data directory is too big for the section")); 2649*a9fa9459Szrj return FALSE; 2650*a9fa9459Szrj } 2651*a9fa9459Szrj 2652*a9fa9459Szrj fprintf (file, 2653*a9fa9459Szrj _("Type Size Rva Offset\n")); 2654*a9fa9459Szrj 2655*a9fa9459Szrj /* Read the whole section. */ 2656*a9fa9459Szrj if (!bfd_malloc_and_get_section (abfd, section, &data)) 2657*a9fa9459Szrj { 2658*a9fa9459Szrj if (data != NULL) 2659*a9fa9459Szrj free (data); 2660*a9fa9459Szrj return FALSE; 2661*a9fa9459Szrj } 2662*a9fa9459Szrj 2663*a9fa9459Szrj for (i = 0; i < size / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++) 2664*a9fa9459Szrj { 2665*a9fa9459Szrj const char *type_name; 2666*a9fa9459Szrj struct external_IMAGE_DEBUG_DIRECTORY *ext 2667*a9fa9459Szrj = &((struct external_IMAGE_DEBUG_DIRECTORY *)(data + dataoff))[i]; 2668*a9fa9459Szrj struct internal_IMAGE_DEBUG_DIRECTORY idd; 2669*a9fa9459Szrj 2670*a9fa9459Szrj _bfd_XXi_swap_debugdir_in (abfd, ext, &idd); 2671*a9fa9459Szrj 2672*a9fa9459Szrj if ((idd.Type) >= IMAGE_NUMBEROF_DEBUG_TYPES) 2673*a9fa9459Szrj type_name = debug_type_names[0]; 2674*a9fa9459Szrj else 2675*a9fa9459Szrj type_name = debug_type_names[idd.Type]; 2676*a9fa9459Szrj 2677*a9fa9459Szrj fprintf (file, " %2ld %14s %08lx %08lx %08lx\n", 2678*a9fa9459Szrj idd.Type, type_name, idd.SizeOfData, 2679*a9fa9459Szrj idd.AddressOfRawData, idd.PointerToRawData); 2680*a9fa9459Szrj 2681*a9fa9459Szrj if (idd.Type == PE_IMAGE_DEBUG_TYPE_CODEVIEW) 2682*a9fa9459Szrj { 2683*a9fa9459Szrj char signature[CV_INFO_SIGNATURE_LENGTH * 2 + 1]; 2684*a9fa9459Szrj /* PR 17512: file: 065-29434-0.001:0.1 2685*a9fa9459Szrj We need to use a 32-bit aligned buffer 2686*a9fa9459Szrj to safely read in a codeview record. */ 2687*a9fa9459Szrj char buffer[256 + 1] ATTRIBUTE_ALIGNED_ALIGNOF (CODEVIEW_INFO); 2688*a9fa9459Szrj 2689*a9fa9459Szrj CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer; 2690*a9fa9459Szrj 2691*a9fa9459Szrj /* The debug entry doesn't have to have to be in a section, 2692*a9fa9459Szrj in which case AddressOfRawData is 0, so always use PointerToRawData. */ 2693*a9fa9459Szrj if (!_bfd_XXi_slurp_codeview_record (abfd, (file_ptr) idd.PointerToRawData, 2694*a9fa9459Szrj idd.SizeOfData, cvinfo)) 2695*a9fa9459Szrj continue; 2696*a9fa9459Szrj 2697*a9fa9459Szrj for (i = 0; i < cvinfo->SignatureLength; i++) 2698*a9fa9459Szrj sprintf (&signature[i*2], "%02x", cvinfo->Signature[i] & 0xff); 2699*a9fa9459Szrj 2700*a9fa9459Szrj fprintf (file, "(format %c%c%c%c signature %s age %ld)\n", 2701*a9fa9459Szrj buffer[0], buffer[1], buffer[2], buffer[3], 2702*a9fa9459Szrj signature, cvinfo->Age); 2703*a9fa9459Szrj } 2704*a9fa9459Szrj } 2705*a9fa9459Szrj 2706*a9fa9459Szrj if (size % sizeof (struct external_IMAGE_DEBUG_DIRECTORY) != 0) 2707*a9fa9459Szrj fprintf (file, 2708*a9fa9459Szrj _("The debug directory size is not a multiple of the debug directory entry size\n")); 2709*a9fa9459Szrj 2710*a9fa9459Szrj return TRUE; 2711*a9fa9459Szrj } 2712*a9fa9459Szrj 2713*a9fa9459Szrj /* Print out the program headers. */ 2714*a9fa9459Szrj 2715*a9fa9459Szrj bfd_boolean 2716*a9fa9459Szrj _bfd_XX_print_private_bfd_data_common (bfd * abfd, void * vfile) 2717*a9fa9459Szrj { 2718*a9fa9459Szrj FILE *file = (FILE *) vfile; 2719*a9fa9459Szrj int j; 2720*a9fa9459Szrj pe_data_type *pe = pe_data (abfd); 2721*a9fa9459Szrj struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr; 2722*a9fa9459Szrj const char *subsystem_name = NULL; 2723*a9fa9459Szrj const char *name; 2724*a9fa9459Szrj 2725*a9fa9459Szrj /* The MS dumpbin program reportedly ands with 0xff0f before 2726*a9fa9459Szrj printing the characteristics field. Not sure why. No reason to 2727*a9fa9459Szrj emulate it here. */ 2728*a9fa9459Szrj fprintf (file, _("\nCharacteristics 0x%x\n"), pe->real_flags); 2729*a9fa9459Szrj #undef PF 2730*a9fa9459Szrj #define PF(x, y) if (pe->real_flags & x) { fprintf (file, "\t%s\n", y); } 2731*a9fa9459Szrj PF (IMAGE_FILE_RELOCS_STRIPPED, "relocations stripped"); 2732*a9fa9459Szrj PF (IMAGE_FILE_EXECUTABLE_IMAGE, "executable"); 2733*a9fa9459Szrj PF (IMAGE_FILE_LINE_NUMS_STRIPPED, "line numbers stripped"); 2734*a9fa9459Szrj PF (IMAGE_FILE_LOCAL_SYMS_STRIPPED, "symbols stripped"); 2735*a9fa9459Szrj PF (IMAGE_FILE_LARGE_ADDRESS_AWARE, "large address aware"); 2736*a9fa9459Szrj PF (IMAGE_FILE_BYTES_REVERSED_LO, "little endian"); 2737*a9fa9459Szrj PF (IMAGE_FILE_32BIT_MACHINE, "32 bit words"); 2738*a9fa9459Szrj PF (IMAGE_FILE_DEBUG_STRIPPED, "debugging information removed"); 2739*a9fa9459Szrj PF (IMAGE_FILE_SYSTEM, "system file"); 2740*a9fa9459Szrj PF (IMAGE_FILE_DLL, "DLL"); 2741*a9fa9459Szrj PF (IMAGE_FILE_BYTES_REVERSED_HI, "big endian"); 2742*a9fa9459Szrj #undef PF 2743*a9fa9459Szrj 2744*a9fa9459Szrj /* ctime implies '\n'. */ 2745*a9fa9459Szrj { 2746*a9fa9459Szrj time_t t = pe->coff.timestamp; 2747*a9fa9459Szrj fprintf (file, "\nTime/Date\t\t%s", ctime (&t)); 2748*a9fa9459Szrj } 2749*a9fa9459Szrj 2750*a9fa9459Szrj #ifndef IMAGE_NT_OPTIONAL_HDR_MAGIC 2751*a9fa9459Szrj # define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b 2752*a9fa9459Szrj #endif 2753*a9fa9459Szrj #ifndef IMAGE_NT_OPTIONAL_HDR64_MAGIC 2754*a9fa9459Szrj # define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b 2755*a9fa9459Szrj #endif 2756*a9fa9459Szrj #ifndef IMAGE_NT_OPTIONAL_HDRROM_MAGIC 2757*a9fa9459Szrj # define IMAGE_NT_OPTIONAL_HDRROM_MAGIC 0x107 2758*a9fa9459Szrj #endif 2759*a9fa9459Szrj 2760*a9fa9459Szrj switch (i->Magic) 2761*a9fa9459Szrj { 2762*a9fa9459Szrj case IMAGE_NT_OPTIONAL_HDR_MAGIC: 2763*a9fa9459Szrj name = "PE32"; 2764*a9fa9459Szrj break; 2765*a9fa9459Szrj case IMAGE_NT_OPTIONAL_HDR64_MAGIC: 2766*a9fa9459Szrj name = "PE32+"; 2767*a9fa9459Szrj break; 2768*a9fa9459Szrj case IMAGE_NT_OPTIONAL_HDRROM_MAGIC: 2769*a9fa9459Szrj name = "ROM"; 2770*a9fa9459Szrj break; 2771*a9fa9459Szrj default: 2772*a9fa9459Szrj name = NULL; 2773*a9fa9459Szrj break; 2774*a9fa9459Szrj } 2775*a9fa9459Szrj fprintf (file, "Magic\t\t\t%04x", i->Magic); 2776*a9fa9459Szrj if (name) 2777*a9fa9459Szrj fprintf (file, "\t(%s)",name); 2778*a9fa9459Szrj fprintf (file, "\nMajorLinkerVersion\t%d\n", i->MajorLinkerVersion); 2779*a9fa9459Szrj fprintf (file, "MinorLinkerVersion\t%d\n", i->MinorLinkerVersion); 2780*a9fa9459Szrj fprintf (file, "SizeOfCode\t\t%08lx\n", (unsigned long) i->SizeOfCode); 2781*a9fa9459Szrj fprintf (file, "SizeOfInitializedData\t%08lx\n", 2782*a9fa9459Szrj (unsigned long) i->SizeOfInitializedData); 2783*a9fa9459Szrj fprintf (file, "SizeOfUninitializedData\t%08lx\n", 2784*a9fa9459Szrj (unsigned long) i->SizeOfUninitializedData); 2785*a9fa9459Szrj fprintf (file, "AddressOfEntryPoint\t"); 2786*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->AddressOfEntryPoint); 2787*a9fa9459Szrj fprintf (file, "\nBaseOfCode\t\t"); 2788*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->BaseOfCode); 2789*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 2790*a9fa9459Szrj /* PE32+ does not have BaseOfData member! */ 2791*a9fa9459Szrj fprintf (file, "\nBaseOfData\t\t"); 2792*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->BaseOfData); 2793*a9fa9459Szrj #endif 2794*a9fa9459Szrj 2795*a9fa9459Szrj fprintf (file, "\nImageBase\t\t"); 2796*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->ImageBase); 2797*a9fa9459Szrj fprintf (file, "\nSectionAlignment\t"); 2798*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->SectionAlignment); 2799*a9fa9459Szrj fprintf (file, "\nFileAlignment\t\t"); 2800*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->FileAlignment); 2801*a9fa9459Szrj fprintf (file, "\nMajorOSystemVersion\t%d\n", i->MajorOperatingSystemVersion); 2802*a9fa9459Szrj fprintf (file, "MinorOSystemVersion\t%d\n", i->MinorOperatingSystemVersion); 2803*a9fa9459Szrj fprintf (file, "MajorImageVersion\t%d\n", i->MajorImageVersion); 2804*a9fa9459Szrj fprintf (file, "MinorImageVersion\t%d\n", i->MinorImageVersion); 2805*a9fa9459Szrj fprintf (file, "MajorSubsystemVersion\t%d\n", i->MajorSubsystemVersion); 2806*a9fa9459Szrj fprintf (file, "MinorSubsystemVersion\t%d\n", i->MinorSubsystemVersion); 2807*a9fa9459Szrj fprintf (file, "Win32Version\t\t%08lx\n", (unsigned long) i->Reserved1); 2808*a9fa9459Szrj fprintf (file, "SizeOfImage\t\t%08lx\n", (unsigned long) i->SizeOfImage); 2809*a9fa9459Szrj fprintf (file, "SizeOfHeaders\t\t%08lx\n", (unsigned long) i->SizeOfHeaders); 2810*a9fa9459Szrj fprintf (file, "CheckSum\t\t%08lx\n", (unsigned long) i->CheckSum); 2811*a9fa9459Szrj 2812*a9fa9459Szrj switch (i->Subsystem) 2813*a9fa9459Szrj { 2814*a9fa9459Szrj case IMAGE_SUBSYSTEM_UNKNOWN: 2815*a9fa9459Szrj subsystem_name = "unspecified"; 2816*a9fa9459Szrj break; 2817*a9fa9459Szrj case IMAGE_SUBSYSTEM_NATIVE: 2818*a9fa9459Szrj subsystem_name = "NT native"; 2819*a9fa9459Szrj break; 2820*a9fa9459Szrj case IMAGE_SUBSYSTEM_WINDOWS_GUI: 2821*a9fa9459Szrj subsystem_name = "Windows GUI"; 2822*a9fa9459Szrj break; 2823*a9fa9459Szrj case IMAGE_SUBSYSTEM_WINDOWS_CUI: 2824*a9fa9459Szrj subsystem_name = "Windows CUI"; 2825*a9fa9459Szrj break; 2826*a9fa9459Szrj case IMAGE_SUBSYSTEM_POSIX_CUI: 2827*a9fa9459Szrj subsystem_name = "POSIX CUI"; 2828*a9fa9459Szrj break; 2829*a9fa9459Szrj case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: 2830*a9fa9459Szrj subsystem_name = "Wince CUI"; 2831*a9fa9459Szrj break; 2832*a9fa9459Szrj // These are from UEFI Platform Initialization Specification 1.1. 2833*a9fa9459Szrj case IMAGE_SUBSYSTEM_EFI_APPLICATION: 2834*a9fa9459Szrj subsystem_name = "EFI application"; 2835*a9fa9459Szrj break; 2836*a9fa9459Szrj case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: 2837*a9fa9459Szrj subsystem_name = "EFI boot service driver"; 2838*a9fa9459Szrj break; 2839*a9fa9459Szrj case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: 2840*a9fa9459Szrj subsystem_name = "EFI runtime driver"; 2841*a9fa9459Szrj break; 2842*a9fa9459Szrj case IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER: 2843*a9fa9459Szrj subsystem_name = "SAL runtime driver"; 2844*a9fa9459Szrj break; 2845*a9fa9459Szrj // This is from revision 8.0 of the MS PE/COFF spec 2846*a9fa9459Szrj case IMAGE_SUBSYSTEM_XBOX: 2847*a9fa9459Szrj subsystem_name = "XBOX"; 2848*a9fa9459Szrj break; 2849*a9fa9459Szrj // Added default case for clarity - subsystem_name is NULL anyway. 2850*a9fa9459Szrj default: 2851*a9fa9459Szrj subsystem_name = NULL; 2852*a9fa9459Szrj } 2853*a9fa9459Szrj 2854*a9fa9459Szrj fprintf (file, "Subsystem\t\t%08x", i->Subsystem); 2855*a9fa9459Szrj if (subsystem_name) 2856*a9fa9459Szrj fprintf (file, "\t(%s)", subsystem_name); 2857*a9fa9459Szrj fprintf (file, "\nDllCharacteristics\t%08x\n", i->DllCharacteristics); 2858*a9fa9459Szrj fprintf (file, "SizeOfStackReserve\t"); 2859*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->SizeOfStackReserve); 2860*a9fa9459Szrj fprintf (file, "\nSizeOfStackCommit\t"); 2861*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->SizeOfStackCommit); 2862*a9fa9459Szrj fprintf (file, "\nSizeOfHeapReserve\t"); 2863*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->SizeOfHeapReserve); 2864*a9fa9459Szrj fprintf (file, "\nSizeOfHeapCommit\t"); 2865*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->SizeOfHeapCommit); 2866*a9fa9459Szrj fprintf (file, "\nLoaderFlags\t\t%08lx\n", (unsigned long) i->LoaderFlags); 2867*a9fa9459Szrj fprintf (file, "NumberOfRvaAndSizes\t%08lx\n", 2868*a9fa9459Szrj (unsigned long) i->NumberOfRvaAndSizes); 2869*a9fa9459Szrj 2870*a9fa9459Szrj fprintf (file, "\nThe Data Directory\n"); 2871*a9fa9459Szrj for (j = 0; j < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; j++) 2872*a9fa9459Szrj { 2873*a9fa9459Szrj fprintf (file, "Entry %1x ", j); 2874*a9fa9459Szrj bfd_fprintf_vma (abfd, file, i->DataDirectory[j].VirtualAddress); 2875*a9fa9459Szrj fprintf (file, " %08lx ", (unsigned long) i->DataDirectory[j].Size); 2876*a9fa9459Szrj fprintf (file, "%s\n", dir_names[j]); 2877*a9fa9459Szrj } 2878*a9fa9459Szrj 2879*a9fa9459Szrj pe_print_idata (abfd, vfile); 2880*a9fa9459Szrj pe_print_edata (abfd, vfile); 2881*a9fa9459Szrj if (bfd_coff_have_print_pdata (abfd)) 2882*a9fa9459Szrj bfd_coff_print_pdata (abfd, vfile); 2883*a9fa9459Szrj else 2884*a9fa9459Szrj pe_print_pdata (abfd, vfile); 2885*a9fa9459Szrj pe_print_reloc (abfd, vfile); 2886*a9fa9459Szrj pe_print_debugdata (abfd, file); 2887*a9fa9459Szrj 2888*a9fa9459Szrj rsrc_print_section (abfd, vfile); 2889*a9fa9459Szrj 2890*a9fa9459Szrj return TRUE; 2891*a9fa9459Szrj } 2892*a9fa9459Szrj 2893*a9fa9459Szrj static bfd_boolean 2894*a9fa9459Szrj is_vma_in_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj) 2895*a9fa9459Szrj { 2896*a9fa9459Szrj bfd_vma addr = * (bfd_vma *) obj; 2897*a9fa9459Szrj return (addr >= sect->vma) && (addr < (sect->vma + sect->size)); 2898*a9fa9459Szrj } 2899*a9fa9459Szrj 2900*a9fa9459Szrj static asection * 2901*a9fa9459Szrj find_section_by_vma (bfd *abfd, bfd_vma addr) 2902*a9fa9459Szrj { 2903*a9fa9459Szrj return bfd_sections_find_if (abfd, is_vma_in_section, (void *) & addr); 2904*a9fa9459Szrj } 2905*a9fa9459Szrj 2906*a9fa9459Szrj /* Copy any private info we understand from the input bfd 2907*a9fa9459Szrj to the output bfd. */ 2908*a9fa9459Szrj 2909*a9fa9459Szrj bfd_boolean 2910*a9fa9459Szrj _bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd) 2911*a9fa9459Szrj { 2912*a9fa9459Szrj pe_data_type *ipe, *ope; 2913*a9fa9459Szrj 2914*a9fa9459Szrj /* One day we may try to grok other private data. */ 2915*a9fa9459Szrj if (ibfd->xvec->flavour != bfd_target_coff_flavour 2916*a9fa9459Szrj || obfd->xvec->flavour != bfd_target_coff_flavour) 2917*a9fa9459Szrj return TRUE; 2918*a9fa9459Szrj 2919*a9fa9459Szrj ipe = pe_data (ibfd); 2920*a9fa9459Szrj ope = pe_data (obfd); 2921*a9fa9459Szrj 2922*a9fa9459Szrj /* pe_opthdr is copied in copy_object. */ 2923*a9fa9459Szrj ope->dll = ipe->dll; 2924*a9fa9459Szrj 2925*a9fa9459Szrj /* Don't copy input subsystem if output is different from input. */ 2926*a9fa9459Szrj if (obfd->xvec != ibfd->xvec) 2927*a9fa9459Szrj ope->pe_opthdr.Subsystem = IMAGE_SUBSYSTEM_UNKNOWN; 2928*a9fa9459Szrj 2929*a9fa9459Szrj /* For strip: if we removed .reloc, we'll make a real mess of things 2930*a9fa9459Szrj if we don't remove this entry as well. */ 2931*a9fa9459Szrj if (! pe_data (obfd)->has_reloc_section) 2932*a9fa9459Szrj { 2933*a9fa9459Szrj pe_data (obfd)->pe_opthdr.DataDirectory[PE_BASE_RELOCATION_TABLE].VirtualAddress = 0; 2934*a9fa9459Szrj pe_data (obfd)->pe_opthdr.DataDirectory[PE_BASE_RELOCATION_TABLE].Size = 0; 2935*a9fa9459Szrj } 2936*a9fa9459Szrj 2937*a9fa9459Szrj /* For PIE, if there is .reloc, we won't add IMAGE_FILE_RELOCS_STRIPPED. 2938*a9fa9459Szrj But there is no .reloc, we make sure that IMAGE_FILE_RELOCS_STRIPPED 2939*a9fa9459Szrj won't be added. */ 2940*a9fa9459Szrj if (! pe_data (ibfd)->has_reloc_section 2941*a9fa9459Szrj && ! (pe_data (ibfd)->real_flags & IMAGE_FILE_RELOCS_STRIPPED)) 2942*a9fa9459Szrj pe_data (obfd)->dont_strip_reloc = 1; 2943*a9fa9459Szrj 2944*a9fa9459Szrj /* The file offsets contained in the debug directory need rewriting. */ 2945*a9fa9459Szrj if (ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size != 0) 2946*a9fa9459Szrj { 2947*a9fa9459Szrj bfd_vma addr = ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].VirtualAddress 2948*a9fa9459Szrj + ope->pe_opthdr.ImageBase; 2949*a9fa9459Szrj asection *section = find_section_by_vma (obfd, addr); 2950*a9fa9459Szrj bfd_byte *data; 2951*a9fa9459Szrj 2952*a9fa9459Szrj if (section && bfd_malloc_and_get_section (obfd, section, &data)) 2953*a9fa9459Szrj { 2954*a9fa9459Szrj unsigned int i; 2955*a9fa9459Szrj struct external_IMAGE_DEBUG_DIRECTORY *dd = 2956*a9fa9459Szrj (struct external_IMAGE_DEBUG_DIRECTORY *)(data + (addr - section->vma)); 2957*a9fa9459Szrj 2958*a9fa9459Szrj /* PR 17512: file: 0f15796a. */ 2959*a9fa9459Szrj if (ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size + (addr - section->vma) 2960*a9fa9459Szrj > bfd_get_section_size (section)) 2961*a9fa9459Szrj { 2962*a9fa9459Szrj _bfd_error_handler (_("%B: Data Directory size (%lx) exceeds space left in section (%lx)"), 2963*a9fa9459Szrj obfd, ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size, 2964*a9fa9459Szrj bfd_get_section_size (section) - (addr - section->vma)); 2965*a9fa9459Szrj return FALSE; 2966*a9fa9459Szrj } 2967*a9fa9459Szrj 2968*a9fa9459Szrj for (i = 0; i < ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size 2969*a9fa9459Szrj / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++) 2970*a9fa9459Szrj { 2971*a9fa9459Szrj asection *ddsection; 2972*a9fa9459Szrj struct external_IMAGE_DEBUG_DIRECTORY *edd = &(dd[i]); 2973*a9fa9459Szrj struct internal_IMAGE_DEBUG_DIRECTORY idd; 2974*a9fa9459Szrj 2975*a9fa9459Szrj _bfd_XXi_swap_debugdir_in (obfd, edd, &idd); 2976*a9fa9459Szrj 2977*a9fa9459Szrj if (idd.AddressOfRawData == 0) 2978*a9fa9459Szrj continue; /* RVA 0 means only offset is valid, not handled yet. */ 2979*a9fa9459Szrj 2980*a9fa9459Szrj ddsection = find_section_by_vma (obfd, idd.AddressOfRawData + ope->pe_opthdr.ImageBase); 2981*a9fa9459Szrj if (!ddsection) 2982*a9fa9459Szrj continue; /* Not in a section! */ 2983*a9fa9459Szrj 2984*a9fa9459Szrj idd.PointerToRawData = ddsection->filepos + (idd.AddressOfRawData 2985*a9fa9459Szrj + ope->pe_opthdr.ImageBase) - ddsection->vma; 2986*a9fa9459Szrj 2987*a9fa9459Szrj _bfd_XXi_swap_debugdir_out (obfd, &idd, edd); 2988*a9fa9459Szrj } 2989*a9fa9459Szrj 2990*a9fa9459Szrj if (!bfd_set_section_contents (obfd, section, data, 0, section->size)) 2991*a9fa9459Szrj { 2992*a9fa9459Szrj _bfd_error_handler (_("Failed to update file offsets in debug directory")); 2993*a9fa9459Szrj return FALSE; 2994*a9fa9459Szrj } 2995*a9fa9459Szrj } 2996*a9fa9459Szrj else if (section) 2997*a9fa9459Szrj { 2998*a9fa9459Szrj _bfd_error_handler (_("%B: Failed to read debug data section"), obfd); 2999*a9fa9459Szrj return FALSE; 3000*a9fa9459Szrj } 3001*a9fa9459Szrj } 3002*a9fa9459Szrj 3003*a9fa9459Szrj return TRUE; 3004*a9fa9459Szrj } 3005*a9fa9459Szrj 3006*a9fa9459Szrj /* Copy private section data. */ 3007*a9fa9459Szrj 3008*a9fa9459Szrj bfd_boolean 3009*a9fa9459Szrj _bfd_XX_bfd_copy_private_section_data (bfd *ibfd, 3010*a9fa9459Szrj asection *isec, 3011*a9fa9459Szrj bfd *obfd, 3012*a9fa9459Szrj asection *osec) 3013*a9fa9459Szrj { 3014*a9fa9459Szrj if (bfd_get_flavour (ibfd) != bfd_target_coff_flavour 3015*a9fa9459Szrj || bfd_get_flavour (obfd) != bfd_target_coff_flavour) 3016*a9fa9459Szrj return TRUE; 3017*a9fa9459Szrj 3018*a9fa9459Szrj if (coff_section_data (ibfd, isec) != NULL 3019*a9fa9459Szrj && pei_section_data (ibfd, isec) != NULL) 3020*a9fa9459Szrj { 3021*a9fa9459Szrj if (coff_section_data (obfd, osec) == NULL) 3022*a9fa9459Szrj { 3023*a9fa9459Szrj bfd_size_type amt = sizeof (struct coff_section_tdata); 3024*a9fa9459Szrj osec->used_by_bfd = bfd_zalloc (obfd, amt); 3025*a9fa9459Szrj if (osec->used_by_bfd == NULL) 3026*a9fa9459Szrj return FALSE; 3027*a9fa9459Szrj } 3028*a9fa9459Szrj 3029*a9fa9459Szrj if (pei_section_data (obfd, osec) == NULL) 3030*a9fa9459Szrj { 3031*a9fa9459Szrj bfd_size_type amt = sizeof (struct pei_section_tdata); 3032*a9fa9459Szrj coff_section_data (obfd, osec)->tdata = bfd_zalloc (obfd, amt); 3033*a9fa9459Szrj if (coff_section_data (obfd, osec)->tdata == NULL) 3034*a9fa9459Szrj return FALSE; 3035*a9fa9459Szrj } 3036*a9fa9459Szrj 3037*a9fa9459Szrj pei_section_data (obfd, osec)->virt_size = 3038*a9fa9459Szrj pei_section_data (ibfd, isec)->virt_size; 3039*a9fa9459Szrj pei_section_data (obfd, osec)->pe_flags = 3040*a9fa9459Szrj pei_section_data (ibfd, isec)->pe_flags; 3041*a9fa9459Szrj } 3042*a9fa9459Szrj 3043*a9fa9459Szrj return TRUE; 3044*a9fa9459Szrj } 3045*a9fa9459Szrj 3046*a9fa9459Szrj void 3047*a9fa9459Szrj _bfd_XX_get_symbol_info (bfd * abfd, asymbol *symbol, symbol_info *ret) 3048*a9fa9459Szrj { 3049*a9fa9459Szrj coff_get_symbol_info (abfd, symbol, ret); 3050*a9fa9459Szrj } 3051*a9fa9459Szrj 3052*a9fa9459Szrj #if !defined(COFF_WITH_pep) && defined(COFF_WITH_pex64) 3053*a9fa9459Szrj static int 3054*a9fa9459Szrj sort_x64_pdata (const void *l, const void *r) 3055*a9fa9459Szrj { 3056*a9fa9459Szrj const char *lp = (const char *) l; 3057*a9fa9459Szrj const char *rp = (const char *) r; 3058*a9fa9459Szrj bfd_vma vl, vr; 3059*a9fa9459Szrj vl = bfd_getl32 (lp); vr = bfd_getl32 (rp); 3060*a9fa9459Szrj if (vl != vr) 3061*a9fa9459Szrj return (vl < vr ? -1 : 1); 3062*a9fa9459Szrj /* We compare just begin address. */ 3063*a9fa9459Szrj return 0; 3064*a9fa9459Szrj } 3065*a9fa9459Szrj #endif 3066*a9fa9459Szrj 3067*a9fa9459Szrj /* Functions to process a .rsrc section. */ 3068*a9fa9459Szrj 3069*a9fa9459Szrj static unsigned int sizeof_leaves; 3070*a9fa9459Szrj static unsigned int sizeof_strings; 3071*a9fa9459Szrj static unsigned int sizeof_tables_and_entries; 3072*a9fa9459Szrj 3073*a9fa9459Szrj static bfd_byte * 3074*a9fa9459Szrj rsrc_count_directory (bfd *, bfd_byte *, bfd_byte *, bfd_byte *, bfd_vma); 3075*a9fa9459Szrj 3076*a9fa9459Szrj static bfd_byte * 3077*a9fa9459Szrj rsrc_count_entries (bfd * abfd, 3078*a9fa9459Szrj bfd_boolean is_name, 3079*a9fa9459Szrj bfd_byte * datastart, 3080*a9fa9459Szrj bfd_byte * data, 3081*a9fa9459Szrj bfd_byte * dataend, 3082*a9fa9459Szrj bfd_vma rva_bias) 3083*a9fa9459Szrj { 3084*a9fa9459Szrj unsigned long entry, addr, size; 3085*a9fa9459Szrj 3086*a9fa9459Szrj if (data + 8 >= dataend) 3087*a9fa9459Szrj return dataend + 1; 3088*a9fa9459Szrj 3089*a9fa9459Szrj if (is_name) 3090*a9fa9459Szrj { 3091*a9fa9459Szrj bfd_byte * name; 3092*a9fa9459Szrj 3093*a9fa9459Szrj entry = (long) bfd_get_32 (abfd, data); 3094*a9fa9459Szrj 3095*a9fa9459Szrj if (HighBitSet (entry)) 3096*a9fa9459Szrj name = datastart + WithoutHighBit (entry); 3097*a9fa9459Szrj else 3098*a9fa9459Szrj name = datastart + entry - rva_bias; 3099*a9fa9459Szrj 3100*a9fa9459Szrj if (name + 2 >= dataend || name < datastart) 3101*a9fa9459Szrj return dataend + 1; 3102*a9fa9459Szrj 3103*a9fa9459Szrj unsigned int len = bfd_get_16 (abfd, name); 3104*a9fa9459Szrj if (len == 0 || len > 256) 3105*a9fa9459Szrj return dataend + 1; 3106*a9fa9459Szrj } 3107*a9fa9459Szrj 3108*a9fa9459Szrj entry = (long) bfd_get_32 (abfd, data + 4); 3109*a9fa9459Szrj 3110*a9fa9459Szrj if (HighBitSet (entry)) 3111*a9fa9459Szrj { 3112*a9fa9459Szrj data = datastart + WithoutHighBit (entry); 3113*a9fa9459Szrj 3114*a9fa9459Szrj if (data <= datastart || data >= dataend) 3115*a9fa9459Szrj return dataend + 1; 3116*a9fa9459Szrj 3117*a9fa9459Szrj return rsrc_count_directory (abfd, datastart, data, dataend, rva_bias); 3118*a9fa9459Szrj } 3119*a9fa9459Szrj 3120*a9fa9459Szrj if (datastart + entry + 16 >= dataend) 3121*a9fa9459Szrj return dataend + 1; 3122*a9fa9459Szrj 3123*a9fa9459Szrj addr = (long) bfd_get_32 (abfd, datastart + entry); 3124*a9fa9459Szrj size = (long) bfd_get_32 (abfd, datastart + entry + 4); 3125*a9fa9459Szrj 3126*a9fa9459Szrj return datastart + addr - rva_bias + size; 3127*a9fa9459Szrj } 3128*a9fa9459Szrj 3129*a9fa9459Szrj static bfd_byte * 3130*a9fa9459Szrj rsrc_count_directory (bfd * abfd, 3131*a9fa9459Szrj bfd_byte * datastart, 3132*a9fa9459Szrj bfd_byte * data, 3133*a9fa9459Szrj bfd_byte * dataend, 3134*a9fa9459Szrj bfd_vma rva_bias) 3135*a9fa9459Szrj { 3136*a9fa9459Szrj unsigned int num_entries, num_ids; 3137*a9fa9459Szrj bfd_byte * highest_data = data; 3138*a9fa9459Szrj 3139*a9fa9459Szrj if (data + 16 >= dataend) 3140*a9fa9459Szrj return dataend + 1; 3141*a9fa9459Szrj 3142*a9fa9459Szrj num_entries = (int) bfd_get_16 (abfd, data + 12); 3143*a9fa9459Szrj num_ids = (int) bfd_get_16 (abfd, data + 14); 3144*a9fa9459Szrj 3145*a9fa9459Szrj num_entries += num_ids; 3146*a9fa9459Szrj 3147*a9fa9459Szrj data += 16; 3148*a9fa9459Szrj 3149*a9fa9459Szrj while (num_entries --) 3150*a9fa9459Szrj { 3151*a9fa9459Szrj bfd_byte * entry_end; 3152*a9fa9459Szrj 3153*a9fa9459Szrj entry_end = rsrc_count_entries (abfd, num_entries >= num_ids, 3154*a9fa9459Szrj datastart, data, dataend, rva_bias); 3155*a9fa9459Szrj data += 8; 3156*a9fa9459Szrj highest_data = max (highest_data, entry_end); 3157*a9fa9459Szrj if (entry_end >= dataend) 3158*a9fa9459Szrj break; 3159*a9fa9459Szrj } 3160*a9fa9459Szrj 3161*a9fa9459Szrj return max (highest_data, data); 3162*a9fa9459Szrj } 3163*a9fa9459Szrj 3164*a9fa9459Szrj typedef struct rsrc_dir_chain 3165*a9fa9459Szrj { 3166*a9fa9459Szrj unsigned int num_entries; 3167*a9fa9459Szrj struct rsrc_entry * first_entry; 3168*a9fa9459Szrj struct rsrc_entry * last_entry; 3169*a9fa9459Szrj } rsrc_dir_chain; 3170*a9fa9459Szrj 3171*a9fa9459Szrj typedef struct rsrc_directory 3172*a9fa9459Szrj { 3173*a9fa9459Szrj unsigned int characteristics; 3174*a9fa9459Szrj unsigned int time; 3175*a9fa9459Szrj unsigned int major; 3176*a9fa9459Szrj unsigned int minor; 3177*a9fa9459Szrj 3178*a9fa9459Szrj rsrc_dir_chain names; 3179*a9fa9459Szrj rsrc_dir_chain ids; 3180*a9fa9459Szrj 3181*a9fa9459Szrj struct rsrc_entry * entry; 3182*a9fa9459Szrj } rsrc_directory; 3183*a9fa9459Szrj 3184*a9fa9459Szrj typedef struct rsrc_string 3185*a9fa9459Szrj { 3186*a9fa9459Szrj unsigned int len; 3187*a9fa9459Szrj bfd_byte * string; 3188*a9fa9459Szrj } rsrc_string; 3189*a9fa9459Szrj 3190*a9fa9459Szrj typedef struct rsrc_leaf 3191*a9fa9459Szrj { 3192*a9fa9459Szrj unsigned int size; 3193*a9fa9459Szrj unsigned int codepage; 3194*a9fa9459Szrj bfd_byte * data; 3195*a9fa9459Szrj } rsrc_leaf; 3196*a9fa9459Szrj 3197*a9fa9459Szrj typedef struct rsrc_entry 3198*a9fa9459Szrj { 3199*a9fa9459Szrj bfd_boolean is_name; 3200*a9fa9459Szrj union 3201*a9fa9459Szrj { 3202*a9fa9459Szrj unsigned int id; 3203*a9fa9459Szrj struct rsrc_string name; 3204*a9fa9459Szrj } name_id; 3205*a9fa9459Szrj 3206*a9fa9459Szrj bfd_boolean is_dir; 3207*a9fa9459Szrj union 3208*a9fa9459Szrj { 3209*a9fa9459Szrj struct rsrc_directory * directory; 3210*a9fa9459Szrj struct rsrc_leaf * leaf; 3211*a9fa9459Szrj } value; 3212*a9fa9459Szrj 3213*a9fa9459Szrj struct rsrc_entry * next_entry; 3214*a9fa9459Szrj struct rsrc_directory * parent; 3215*a9fa9459Szrj } rsrc_entry; 3216*a9fa9459Szrj 3217*a9fa9459Szrj static bfd_byte * 3218*a9fa9459Szrj rsrc_parse_directory (bfd *, rsrc_directory *, bfd_byte *, 3219*a9fa9459Szrj bfd_byte *, bfd_byte *, bfd_vma, rsrc_entry *); 3220*a9fa9459Szrj 3221*a9fa9459Szrj static bfd_byte * 3222*a9fa9459Szrj rsrc_parse_entry (bfd * abfd, 3223*a9fa9459Szrj bfd_boolean is_name, 3224*a9fa9459Szrj rsrc_entry * entry, 3225*a9fa9459Szrj bfd_byte * datastart, 3226*a9fa9459Szrj bfd_byte * data, 3227*a9fa9459Szrj bfd_byte * dataend, 3228*a9fa9459Szrj bfd_vma rva_bias, 3229*a9fa9459Szrj rsrc_directory * parent) 3230*a9fa9459Szrj { 3231*a9fa9459Szrj unsigned long val, addr, size; 3232*a9fa9459Szrj 3233*a9fa9459Szrj val = bfd_get_32 (abfd, data); 3234*a9fa9459Szrj 3235*a9fa9459Szrj entry->parent = parent; 3236*a9fa9459Szrj entry->is_name = is_name; 3237*a9fa9459Szrj 3238*a9fa9459Szrj if (is_name) 3239*a9fa9459Szrj { 3240*a9fa9459Szrj bfd_byte * address; 3241*a9fa9459Szrj 3242*a9fa9459Szrj if (HighBitSet (val)) 3243*a9fa9459Szrj { 3244*a9fa9459Szrj val = WithoutHighBit (val); 3245*a9fa9459Szrj 3246*a9fa9459Szrj address = datastart + val; 3247*a9fa9459Szrj } 3248*a9fa9459Szrj else 3249*a9fa9459Szrj { 3250*a9fa9459Szrj address = datastart + val - rva_bias; 3251*a9fa9459Szrj } 3252*a9fa9459Szrj 3253*a9fa9459Szrj if (address + 3 > dataend) 3254*a9fa9459Szrj return dataend; 3255*a9fa9459Szrj 3256*a9fa9459Szrj entry->name_id.name.len = bfd_get_16 (abfd, address); 3257*a9fa9459Szrj entry->name_id.name.string = address + 2; 3258*a9fa9459Szrj } 3259*a9fa9459Szrj else 3260*a9fa9459Szrj entry->name_id.id = val; 3261*a9fa9459Szrj 3262*a9fa9459Szrj val = bfd_get_32 (abfd, data + 4); 3263*a9fa9459Szrj 3264*a9fa9459Szrj if (HighBitSet (val)) 3265*a9fa9459Szrj { 3266*a9fa9459Szrj entry->is_dir = TRUE; 3267*a9fa9459Szrj entry->value.directory = bfd_malloc (sizeof * entry->value.directory); 3268*a9fa9459Szrj if (entry->value.directory == NULL) 3269*a9fa9459Szrj return dataend; 3270*a9fa9459Szrj 3271*a9fa9459Szrj return rsrc_parse_directory (abfd, entry->value.directory, 3272*a9fa9459Szrj datastart, 3273*a9fa9459Szrj datastart + WithoutHighBit (val), 3274*a9fa9459Szrj dataend, rva_bias, entry); 3275*a9fa9459Szrj } 3276*a9fa9459Szrj 3277*a9fa9459Szrj entry->is_dir = FALSE; 3278*a9fa9459Szrj entry->value.leaf = bfd_malloc (sizeof * entry->value.leaf); 3279*a9fa9459Szrj if (entry->value.leaf == NULL) 3280*a9fa9459Szrj return dataend; 3281*a9fa9459Szrj 3282*a9fa9459Szrj data = datastart + val; 3283*a9fa9459Szrj if (data < datastart || data >= dataend) 3284*a9fa9459Szrj return dataend; 3285*a9fa9459Szrj 3286*a9fa9459Szrj addr = bfd_get_32 (abfd, data); 3287*a9fa9459Szrj size = entry->value.leaf->size = bfd_get_32 (abfd, data + 4); 3288*a9fa9459Szrj entry->value.leaf->codepage = bfd_get_32 (abfd, data + 8); 3289*a9fa9459Szrj /* FIXME: We assume that the reserved field (data + 12) is OK. */ 3290*a9fa9459Szrj 3291*a9fa9459Szrj entry->value.leaf->data = bfd_malloc (size); 3292*a9fa9459Szrj if (entry->value.leaf->data == NULL) 3293*a9fa9459Szrj return dataend; 3294*a9fa9459Szrj 3295*a9fa9459Szrj memcpy (entry->value.leaf->data, datastart + addr - rva_bias, size); 3296*a9fa9459Szrj return datastart + (addr - rva_bias) + size; 3297*a9fa9459Szrj } 3298*a9fa9459Szrj 3299*a9fa9459Szrj static bfd_byte * 3300*a9fa9459Szrj rsrc_parse_entries (bfd * abfd, 3301*a9fa9459Szrj rsrc_dir_chain * chain, 3302*a9fa9459Szrj bfd_boolean is_name, 3303*a9fa9459Szrj bfd_byte * highest_data, 3304*a9fa9459Szrj bfd_byte * datastart, 3305*a9fa9459Szrj bfd_byte * data, 3306*a9fa9459Szrj bfd_byte * dataend, 3307*a9fa9459Szrj bfd_vma rva_bias, 3308*a9fa9459Szrj rsrc_directory * parent) 3309*a9fa9459Szrj { 3310*a9fa9459Szrj unsigned int i; 3311*a9fa9459Szrj rsrc_entry * entry; 3312*a9fa9459Szrj 3313*a9fa9459Szrj if (chain->num_entries == 0) 3314*a9fa9459Szrj { 3315*a9fa9459Szrj chain->first_entry = chain->last_entry = NULL; 3316*a9fa9459Szrj return highest_data; 3317*a9fa9459Szrj } 3318*a9fa9459Szrj 3319*a9fa9459Szrj entry = bfd_malloc (sizeof * entry); 3320*a9fa9459Szrj if (entry == NULL) 3321*a9fa9459Szrj return dataend; 3322*a9fa9459Szrj 3323*a9fa9459Szrj chain->first_entry = entry; 3324*a9fa9459Szrj 3325*a9fa9459Szrj for (i = chain->num_entries; i--;) 3326*a9fa9459Szrj { 3327*a9fa9459Szrj bfd_byte * entry_end; 3328*a9fa9459Szrj 3329*a9fa9459Szrj entry_end = rsrc_parse_entry (abfd, is_name, entry, datastart, 3330*a9fa9459Szrj data, dataend, rva_bias, parent); 3331*a9fa9459Szrj data += 8; 3332*a9fa9459Szrj highest_data = max (entry_end, highest_data); 3333*a9fa9459Szrj if (entry_end > dataend) 3334*a9fa9459Szrj return dataend; 3335*a9fa9459Szrj 3336*a9fa9459Szrj if (i) 3337*a9fa9459Szrj { 3338*a9fa9459Szrj entry->next_entry = bfd_malloc (sizeof * entry); 3339*a9fa9459Szrj entry = entry->next_entry; 3340*a9fa9459Szrj if (entry == NULL) 3341*a9fa9459Szrj return dataend; 3342*a9fa9459Szrj } 3343*a9fa9459Szrj else 3344*a9fa9459Szrj entry->next_entry = NULL; 3345*a9fa9459Szrj } 3346*a9fa9459Szrj 3347*a9fa9459Szrj chain->last_entry = entry; 3348*a9fa9459Szrj 3349*a9fa9459Szrj return highest_data; 3350*a9fa9459Szrj } 3351*a9fa9459Szrj 3352*a9fa9459Szrj static bfd_byte * 3353*a9fa9459Szrj rsrc_parse_directory (bfd * abfd, 3354*a9fa9459Szrj rsrc_directory * table, 3355*a9fa9459Szrj bfd_byte * datastart, 3356*a9fa9459Szrj bfd_byte * data, 3357*a9fa9459Szrj bfd_byte * dataend, 3358*a9fa9459Szrj bfd_vma rva_bias, 3359*a9fa9459Szrj rsrc_entry * entry) 3360*a9fa9459Szrj { 3361*a9fa9459Szrj bfd_byte * highest_data = data; 3362*a9fa9459Szrj 3363*a9fa9459Szrj if (table == NULL) 3364*a9fa9459Szrj return dataend; 3365*a9fa9459Szrj 3366*a9fa9459Szrj table->characteristics = bfd_get_32 (abfd, data); 3367*a9fa9459Szrj table->time = bfd_get_32 (abfd, data + 4); 3368*a9fa9459Szrj table->major = bfd_get_16 (abfd, data + 8); 3369*a9fa9459Szrj table->minor = bfd_get_16 (abfd, data + 10); 3370*a9fa9459Szrj table->names.num_entries = bfd_get_16 (abfd, data + 12); 3371*a9fa9459Szrj table->ids.num_entries = bfd_get_16 (abfd, data + 14); 3372*a9fa9459Szrj table->entry = entry; 3373*a9fa9459Szrj 3374*a9fa9459Szrj data += 16; 3375*a9fa9459Szrj 3376*a9fa9459Szrj highest_data = rsrc_parse_entries (abfd, & table->names, TRUE, data, 3377*a9fa9459Szrj datastart, data, dataend, rva_bias, table); 3378*a9fa9459Szrj data += table->names.num_entries * 8; 3379*a9fa9459Szrj 3380*a9fa9459Szrj highest_data = rsrc_parse_entries (abfd, & table->ids, FALSE, highest_data, 3381*a9fa9459Szrj datastart, data, dataend, rva_bias, table); 3382*a9fa9459Szrj data += table->ids.num_entries * 8; 3383*a9fa9459Szrj 3384*a9fa9459Szrj return max (highest_data, data); 3385*a9fa9459Szrj } 3386*a9fa9459Szrj 3387*a9fa9459Szrj typedef struct rsrc_write_data 3388*a9fa9459Szrj { 3389*a9fa9459Szrj bfd * abfd; 3390*a9fa9459Szrj bfd_byte * datastart; 3391*a9fa9459Szrj bfd_byte * next_table; 3392*a9fa9459Szrj bfd_byte * next_leaf; 3393*a9fa9459Szrj bfd_byte * next_string; 3394*a9fa9459Szrj bfd_byte * next_data; 3395*a9fa9459Szrj bfd_vma rva_bias; 3396*a9fa9459Szrj } rsrc_write_data; 3397*a9fa9459Szrj 3398*a9fa9459Szrj static void 3399*a9fa9459Szrj rsrc_write_string (rsrc_write_data * data, 3400*a9fa9459Szrj rsrc_string * string) 3401*a9fa9459Szrj { 3402*a9fa9459Szrj bfd_put_16 (data->abfd, string->len, data->next_string); 3403*a9fa9459Szrj memcpy (data->next_string + 2, string->string, string->len * 2); 3404*a9fa9459Szrj data->next_string += (string->len + 1) * 2; 3405*a9fa9459Szrj } 3406*a9fa9459Szrj 3407*a9fa9459Szrj static inline unsigned int 3408*a9fa9459Szrj rsrc_compute_rva (rsrc_write_data * data, 3409*a9fa9459Szrj bfd_byte * addr) 3410*a9fa9459Szrj { 3411*a9fa9459Szrj return (addr - data->datastart) + data->rva_bias; 3412*a9fa9459Szrj } 3413*a9fa9459Szrj 3414*a9fa9459Szrj static void 3415*a9fa9459Szrj rsrc_write_leaf (rsrc_write_data * data, 3416*a9fa9459Szrj rsrc_leaf * leaf) 3417*a9fa9459Szrj { 3418*a9fa9459Szrj bfd_put_32 (data->abfd, rsrc_compute_rva (data, data->next_data), 3419*a9fa9459Szrj data->next_leaf); 3420*a9fa9459Szrj bfd_put_32 (data->abfd, leaf->size, data->next_leaf + 4); 3421*a9fa9459Szrj bfd_put_32 (data->abfd, leaf->codepage, data->next_leaf + 8); 3422*a9fa9459Szrj bfd_put_32 (data->abfd, 0 /*reserved*/, data->next_leaf + 12); 3423*a9fa9459Szrj data->next_leaf += 16; 3424*a9fa9459Szrj 3425*a9fa9459Szrj memcpy (data->next_data, leaf->data, leaf->size); 3426*a9fa9459Szrj /* An undocumented feature of Windows resources is that each unit 3427*a9fa9459Szrj of raw data is 8-byte aligned... */ 3428*a9fa9459Szrj data->next_data += ((leaf->size + 7) & ~7); 3429*a9fa9459Szrj } 3430*a9fa9459Szrj 3431*a9fa9459Szrj static void rsrc_write_directory (rsrc_write_data *, rsrc_directory *); 3432*a9fa9459Szrj 3433*a9fa9459Szrj static void 3434*a9fa9459Szrj rsrc_write_entry (rsrc_write_data * data, 3435*a9fa9459Szrj bfd_byte * where, 3436*a9fa9459Szrj rsrc_entry * entry) 3437*a9fa9459Szrj { 3438*a9fa9459Szrj if (entry->is_name) 3439*a9fa9459Szrj { 3440*a9fa9459Szrj bfd_put_32 (data->abfd, 3441*a9fa9459Szrj SetHighBit (data->next_string - data->datastart), 3442*a9fa9459Szrj where); 3443*a9fa9459Szrj rsrc_write_string (data, & entry->name_id.name); 3444*a9fa9459Szrj } 3445*a9fa9459Szrj else 3446*a9fa9459Szrj bfd_put_32 (data->abfd, entry->name_id.id, where); 3447*a9fa9459Szrj 3448*a9fa9459Szrj if (entry->is_dir) 3449*a9fa9459Szrj { 3450*a9fa9459Szrj bfd_put_32 (data->abfd, 3451*a9fa9459Szrj SetHighBit (data->next_table - data->datastart), 3452*a9fa9459Szrj where + 4); 3453*a9fa9459Szrj rsrc_write_directory (data, entry->value.directory); 3454*a9fa9459Szrj } 3455*a9fa9459Szrj else 3456*a9fa9459Szrj { 3457*a9fa9459Szrj bfd_put_32 (data->abfd, data->next_leaf - data->datastart, where + 4); 3458*a9fa9459Szrj rsrc_write_leaf (data, entry->value.leaf); 3459*a9fa9459Szrj } 3460*a9fa9459Szrj } 3461*a9fa9459Szrj 3462*a9fa9459Szrj static void 3463*a9fa9459Szrj rsrc_compute_region_sizes (rsrc_directory * dir) 3464*a9fa9459Szrj { 3465*a9fa9459Szrj struct rsrc_entry * entry; 3466*a9fa9459Szrj 3467*a9fa9459Szrj if (dir == NULL) 3468*a9fa9459Szrj return; 3469*a9fa9459Szrj 3470*a9fa9459Szrj sizeof_tables_and_entries += 16; 3471*a9fa9459Szrj 3472*a9fa9459Szrj for (entry = dir->names.first_entry; entry != NULL; entry = entry->next_entry) 3473*a9fa9459Szrj { 3474*a9fa9459Szrj sizeof_tables_and_entries += 8; 3475*a9fa9459Szrj 3476*a9fa9459Szrj sizeof_strings += (entry->name_id.name.len + 1) * 2; 3477*a9fa9459Szrj 3478*a9fa9459Szrj if (entry->is_dir) 3479*a9fa9459Szrj rsrc_compute_region_sizes (entry->value.directory); 3480*a9fa9459Szrj else 3481*a9fa9459Szrj sizeof_leaves += 16; 3482*a9fa9459Szrj } 3483*a9fa9459Szrj 3484*a9fa9459Szrj for (entry = dir->ids.first_entry; entry != NULL; entry = entry->next_entry) 3485*a9fa9459Szrj { 3486*a9fa9459Szrj sizeof_tables_and_entries += 8; 3487*a9fa9459Szrj 3488*a9fa9459Szrj if (entry->is_dir) 3489*a9fa9459Szrj rsrc_compute_region_sizes (entry->value.directory); 3490*a9fa9459Szrj else 3491*a9fa9459Szrj sizeof_leaves += 16; 3492*a9fa9459Szrj } 3493*a9fa9459Szrj } 3494*a9fa9459Szrj 3495*a9fa9459Szrj static void 3496*a9fa9459Szrj rsrc_write_directory (rsrc_write_data * data, 3497*a9fa9459Szrj rsrc_directory * dir) 3498*a9fa9459Szrj { 3499*a9fa9459Szrj rsrc_entry * entry; 3500*a9fa9459Szrj unsigned int i; 3501*a9fa9459Szrj bfd_byte * next_entry; 3502*a9fa9459Szrj bfd_byte * nt; 3503*a9fa9459Szrj 3504*a9fa9459Szrj bfd_put_32 (data->abfd, dir->characteristics, data->next_table); 3505*a9fa9459Szrj bfd_put_32 (data->abfd, 0 /*dir->time*/, data->next_table + 4); 3506*a9fa9459Szrj bfd_put_16 (data->abfd, dir->major, data->next_table + 8); 3507*a9fa9459Szrj bfd_put_16 (data->abfd, dir->minor, data->next_table + 10); 3508*a9fa9459Szrj bfd_put_16 (data->abfd, dir->names.num_entries, data->next_table + 12); 3509*a9fa9459Szrj bfd_put_16 (data->abfd, dir->ids.num_entries, data->next_table + 14); 3510*a9fa9459Szrj 3511*a9fa9459Szrj /* Compute where the entries and the next table will be placed. */ 3512*a9fa9459Szrj next_entry = data->next_table + 16; 3513*a9fa9459Szrj data->next_table = next_entry + (dir->names.num_entries * 8) 3514*a9fa9459Szrj + (dir->ids.num_entries * 8); 3515*a9fa9459Szrj nt = data->next_table; 3516*a9fa9459Szrj 3517*a9fa9459Szrj /* Write the entries. */ 3518*a9fa9459Szrj for (i = dir->names.num_entries, entry = dir->names.first_entry; 3519*a9fa9459Szrj i > 0 && entry != NULL; 3520*a9fa9459Szrj i--, entry = entry->next_entry) 3521*a9fa9459Szrj { 3522*a9fa9459Szrj BFD_ASSERT (entry->is_name); 3523*a9fa9459Szrj rsrc_write_entry (data, next_entry, entry); 3524*a9fa9459Szrj next_entry += 8; 3525*a9fa9459Szrj } 3526*a9fa9459Szrj BFD_ASSERT (i == 0); 3527*a9fa9459Szrj BFD_ASSERT (entry == NULL); 3528*a9fa9459Szrj 3529*a9fa9459Szrj for (i = dir->ids.num_entries, entry = dir->ids.first_entry; 3530*a9fa9459Szrj i > 0 && entry != NULL; 3531*a9fa9459Szrj i--, entry = entry->next_entry) 3532*a9fa9459Szrj { 3533*a9fa9459Szrj BFD_ASSERT (! entry->is_name); 3534*a9fa9459Szrj rsrc_write_entry (data, next_entry, entry); 3535*a9fa9459Szrj next_entry += 8; 3536*a9fa9459Szrj } 3537*a9fa9459Szrj BFD_ASSERT (i == 0); 3538*a9fa9459Szrj BFD_ASSERT (entry == NULL); 3539*a9fa9459Szrj BFD_ASSERT (nt == next_entry); 3540*a9fa9459Szrj } 3541*a9fa9459Szrj 3542*a9fa9459Szrj #if defined HAVE_WCHAR_H && ! defined __CYGWIN__ && ! defined __MINGW32__ 3543*a9fa9459Szrj /* Return the length (number of units) of the first character in S, 3544*a9fa9459Szrj putting its 'ucs4_t' representation in *PUC. */ 3545*a9fa9459Szrj 3546*a9fa9459Szrj static unsigned int 3547*a9fa9459Szrj #if defined HAVE_WCTYPE_H 3548*a9fa9459Szrj u16_mbtouc (wint_t * puc, const unsigned short * s, unsigned int n) 3549*a9fa9459Szrj #else 3550*a9fa9459Szrj u16_mbtouc (wchar_t * puc, const unsigned short * s, unsigned int n) 3551*a9fa9459Szrj #endif 3552*a9fa9459Szrj { 3553*a9fa9459Szrj unsigned short c = * s; 3554*a9fa9459Szrj 3555*a9fa9459Szrj if (c < 0xd800 || c >= 0xe000) 3556*a9fa9459Szrj { 3557*a9fa9459Szrj *puc = c; 3558*a9fa9459Szrj return 1; 3559*a9fa9459Szrj } 3560*a9fa9459Szrj 3561*a9fa9459Szrj if (c < 0xdc00) 3562*a9fa9459Szrj { 3563*a9fa9459Szrj if (n >= 2) 3564*a9fa9459Szrj { 3565*a9fa9459Szrj if (s[1] >= 0xdc00 && s[1] < 0xe000) 3566*a9fa9459Szrj { 3567*a9fa9459Szrj *puc = 0x10000 + ((c - 0xd800) << 10) + (s[1] - 0xdc00); 3568*a9fa9459Szrj return 2; 3569*a9fa9459Szrj } 3570*a9fa9459Szrj } 3571*a9fa9459Szrj else 3572*a9fa9459Szrj { 3573*a9fa9459Szrj /* Incomplete multibyte character. */ 3574*a9fa9459Szrj *puc = 0xfffd; 3575*a9fa9459Szrj return n; 3576*a9fa9459Szrj } 3577*a9fa9459Szrj } 3578*a9fa9459Szrj 3579*a9fa9459Szrj /* Invalid multibyte character. */ 3580*a9fa9459Szrj *puc = 0xfffd; 3581*a9fa9459Szrj return 1; 3582*a9fa9459Szrj } 3583*a9fa9459Szrj #endif /* HAVE_WCHAR_H and not Cygwin/Mingw */ 3584*a9fa9459Szrj 3585*a9fa9459Szrj /* Perform a comparison of two entries. */ 3586*a9fa9459Szrj static signed int 3587*a9fa9459Szrj rsrc_cmp (bfd_boolean is_name, rsrc_entry * a, rsrc_entry * b) 3588*a9fa9459Szrj { 3589*a9fa9459Szrj signed int res; 3590*a9fa9459Szrj bfd_byte * astring; 3591*a9fa9459Szrj unsigned int alen; 3592*a9fa9459Szrj bfd_byte * bstring; 3593*a9fa9459Szrj unsigned int blen; 3594*a9fa9459Szrj 3595*a9fa9459Szrj if (! is_name) 3596*a9fa9459Szrj return a->name_id.id - b->name_id.id; 3597*a9fa9459Szrj 3598*a9fa9459Szrj /* We have to perform a case insenstive, unicode string comparison... */ 3599*a9fa9459Szrj astring = a->name_id.name.string; 3600*a9fa9459Szrj alen = a->name_id.name.len; 3601*a9fa9459Szrj bstring = b->name_id.name.string; 3602*a9fa9459Szrj blen = b->name_id.name.len; 3603*a9fa9459Szrj 3604*a9fa9459Szrj #if defined __CYGWIN__ || defined __MINGW32__ 3605*a9fa9459Szrj /* Under Windows hosts (both Cygwin and Mingw types), 3606*a9fa9459Szrj unicode == UTF-16 == wchar_t. The case insensitive string comparison 3607*a9fa9459Szrj function however goes by different names in the two environments... */ 3608*a9fa9459Szrj 3609*a9fa9459Szrj #undef rscpcmp 3610*a9fa9459Szrj #ifdef __CYGWIN__ 3611*a9fa9459Szrj #define rscpcmp wcsncasecmp 3612*a9fa9459Szrj #endif 3613*a9fa9459Szrj #ifdef __MINGW32__ 3614*a9fa9459Szrj #define rscpcmp wcsnicmp 3615*a9fa9459Szrj #endif 3616*a9fa9459Szrj 3617*a9fa9459Szrj res = rscpcmp ((const wchar_t *) astring, (const wchar_t *) bstring, 3618*a9fa9459Szrj min (alen, blen)); 3619*a9fa9459Szrj 3620*a9fa9459Szrj #elif defined HAVE_WCHAR_H 3621*a9fa9459Szrj { 3622*a9fa9459Szrj unsigned int i; 3623*a9fa9459Szrj 3624*a9fa9459Szrj res = 0; 3625*a9fa9459Szrj for (i = min (alen, blen); i--; astring += 2, bstring += 2) 3626*a9fa9459Szrj { 3627*a9fa9459Szrj #if defined HAVE_WCTYPE_H 3628*a9fa9459Szrj wint_t awc; 3629*a9fa9459Szrj wint_t bwc; 3630*a9fa9459Szrj #else 3631*a9fa9459Szrj wchar_t awc; 3632*a9fa9459Szrj wchar_t bwc; 3633*a9fa9459Szrj #endif 3634*a9fa9459Szrj 3635*a9fa9459Szrj /* Convert UTF-16 unicode characters into wchar_t characters 3636*a9fa9459Szrj so that we can then perform a case insensitive comparison. */ 3637*a9fa9459Szrj unsigned int Alen = u16_mbtouc (& awc, (const unsigned short *) astring, 2); 3638*a9fa9459Szrj unsigned int Blen = u16_mbtouc (& bwc, (const unsigned short *) bstring, 2); 3639*a9fa9459Szrj 3640*a9fa9459Szrj if (Alen != Blen) 3641*a9fa9459Szrj return Alen - Blen; 3642*a9fa9459Szrj 3643*a9fa9459Szrj #ifdef HAVE_WCTYPE_H 3644*a9fa9459Szrj awc = towlower (awc); 3645*a9fa9459Szrj bwc = towlower (bwc); 3646*a9fa9459Szrj 3647*a9fa9459Szrj res = awc - bwc; 3648*a9fa9459Szrj #else 3649*a9fa9459Szrj res = wcsncasecmp (& awc, & bwc, 1); 3650*a9fa9459Szrj #endif 3651*a9fa9459Szrj if (res) 3652*a9fa9459Szrj break; 3653*a9fa9459Szrj } 3654*a9fa9459Szrj } 3655*a9fa9459Szrj #else 3656*a9fa9459Szrj /* Do the best we can - a case sensitive, untranslated comparison. */ 3657*a9fa9459Szrj res = memcmp (astring, bstring, min (alen, blen) * 2); 3658*a9fa9459Szrj #endif 3659*a9fa9459Szrj 3660*a9fa9459Szrj if (res == 0) 3661*a9fa9459Szrj res = alen - blen; 3662*a9fa9459Szrj 3663*a9fa9459Szrj return res; 3664*a9fa9459Szrj } 3665*a9fa9459Szrj 3666*a9fa9459Szrj static void 3667*a9fa9459Szrj rsrc_print_name (char * buffer, rsrc_string string) 3668*a9fa9459Szrj { 3669*a9fa9459Szrj unsigned int i; 3670*a9fa9459Szrj bfd_byte * name = string.string; 3671*a9fa9459Szrj 3672*a9fa9459Szrj for (i = string.len; i--; name += 2) 3673*a9fa9459Szrj sprintf (buffer + strlen (buffer), "%.1s", name); 3674*a9fa9459Szrj } 3675*a9fa9459Szrj 3676*a9fa9459Szrj static const char * 3677*a9fa9459Szrj rsrc_resource_name (rsrc_entry * entry, rsrc_directory * dir) 3678*a9fa9459Szrj { 3679*a9fa9459Szrj static char buffer [256]; 3680*a9fa9459Szrj bfd_boolean is_string = FALSE; 3681*a9fa9459Szrj 3682*a9fa9459Szrj buffer[0] = 0; 3683*a9fa9459Szrj 3684*a9fa9459Szrj if (dir != NULL && dir->entry != NULL && dir->entry->parent != NULL 3685*a9fa9459Szrj && dir->entry->parent->entry != NULL) 3686*a9fa9459Szrj { 3687*a9fa9459Szrj strcpy (buffer, "type: "); 3688*a9fa9459Szrj if (dir->entry->parent->entry->is_name) 3689*a9fa9459Szrj rsrc_print_name (buffer + strlen (buffer), 3690*a9fa9459Szrj dir->entry->parent->entry->name_id.name); 3691*a9fa9459Szrj else 3692*a9fa9459Szrj { 3693*a9fa9459Szrj unsigned int id = dir->entry->parent->entry->name_id.id; 3694*a9fa9459Szrj 3695*a9fa9459Szrj sprintf (buffer + strlen (buffer), "%x", id); 3696*a9fa9459Szrj switch (id) 3697*a9fa9459Szrj { 3698*a9fa9459Szrj case 1: strcat (buffer, " (CURSOR)"); break; 3699*a9fa9459Szrj case 2: strcat (buffer, " (BITMAP)"); break; 3700*a9fa9459Szrj case 3: strcat (buffer, " (ICON)"); break; 3701*a9fa9459Szrj case 4: strcat (buffer, " (MENU)"); break; 3702*a9fa9459Szrj case 5: strcat (buffer, " (DIALOG)"); break; 3703*a9fa9459Szrj case 6: strcat (buffer, " (STRING)"); is_string = TRUE; break; 3704*a9fa9459Szrj case 7: strcat (buffer, " (FONTDIR)"); break; 3705*a9fa9459Szrj case 8: strcat (buffer, " (FONT)"); break; 3706*a9fa9459Szrj case 9: strcat (buffer, " (ACCELERATOR)"); break; 3707*a9fa9459Szrj case 10: strcat (buffer, " (RCDATA)"); break; 3708*a9fa9459Szrj case 11: strcat (buffer, " (MESSAGETABLE)"); break; 3709*a9fa9459Szrj case 12: strcat (buffer, " (GROUP_CURSOR)"); break; 3710*a9fa9459Szrj case 14: strcat (buffer, " (GROUP_ICON)"); break; 3711*a9fa9459Szrj case 16: strcat (buffer, " (VERSION)"); break; 3712*a9fa9459Szrj case 17: strcat (buffer, " (DLGINCLUDE)"); break; 3713*a9fa9459Szrj case 19: strcat (buffer, " (PLUGPLAY)"); break; 3714*a9fa9459Szrj case 20: strcat (buffer, " (VXD)"); break; 3715*a9fa9459Szrj case 21: strcat (buffer, " (ANICURSOR)"); break; 3716*a9fa9459Szrj case 22: strcat (buffer, " (ANIICON)"); break; 3717*a9fa9459Szrj case 23: strcat (buffer, " (HTML)"); break; 3718*a9fa9459Szrj case 24: strcat (buffer, " (MANIFEST)"); break; 3719*a9fa9459Szrj case 240: strcat (buffer, " (DLGINIT)"); break; 3720*a9fa9459Szrj case 241: strcat (buffer, " (TOOLBAR)"); break; 3721*a9fa9459Szrj } 3722*a9fa9459Szrj } 3723*a9fa9459Szrj } 3724*a9fa9459Szrj 3725*a9fa9459Szrj if (dir != NULL && dir->entry != NULL) 3726*a9fa9459Szrj { 3727*a9fa9459Szrj strcat (buffer, " name: "); 3728*a9fa9459Szrj if (dir->entry->is_name) 3729*a9fa9459Szrj rsrc_print_name (buffer + strlen (buffer), dir->entry->name_id.name); 3730*a9fa9459Szrj else 3731*a9fa9459Szrj { 3732*a9fa9459Szrj unsigned int id = dir->entry->name_id.id; 3733*a9fa9459Szrj 3734*a9fa9459Szrj sprintf (buffer + strlen (buffer), "%x", id); 3735*a9fa9459Szrj 3736*a9fa9459Szrj if (is_string) 3737*a9fa9459Szrj sprintf (buffer + strlen (buffer), " (resource id range: %d - %d)", 3738*a9fa9459Szrj (id - 1) << 4, (id << 4) - 1); 3739*a9fa9459Szrj } 3740*a9fa9459Szrj } 3741*a9fa9459Szrj 3742*a9fa9459Szrj if (entry != NULL) 3743*a9fa9459Szrj { 3744*a9fa9459Szrj strcat (buffer, " lang: "); 3745*a9fa9459Szrj 3746*a9fa9459Szrj if (entry->is_name) 3747*a9fa9459Szrj rsrc_print_name (buffer + strlen (buffer), entry->name_id.name); 3748*a9fa9459Szrj else 3749*a9fa9459Szrj sprintf (buffer + strlen (buffer), "%x", entry->name_id.id); 3750*a9fa9459Szrj } 3751*a9fa9459Szrj 3752*a9fa9459Szrj return buffer; 3753*a9fa9459Szrj } 3754*a9fa9459Szrj 3755*a9fa9459Szrj /* *sigh* Windows resource strings are special. Only the top 28-bits of 3756*a9fa9459Szrj their ID is stored in the NAME entry. The bottom four bits are used as 3757*a9fa9459Szrj an index into unicode string table that makes up the data of the leaf. 3758*a9fa9459Szrj So identical type-name-lang string resources may not actually be 3759*a9fa9459Szrj identical at all. 3760*a9fa9459Szrj 3761*a9fa9459Szrj This function is called when we have detected two string resources with 3762*a9fa9459Szrj match top-28-bit IDs. We have to scan the string tables inside the leaves 3763*a9fa9459Szrj and discover if there are any real collisions. If there are then we report 3764*a9fa9459Szrj them and return FALSE. Otherwise we copy any strings from B into A and 3765*a9fa9459Szrj then return TRUE. */ 3766*a9fa9459Szrj 3767*a9fa9459Szrj static bfd_boolean 3768*a9fa9459Szrj rsrc_merge_string_entries (rsrc_entry * a ATTRIBUTE_UNUSED, 3769*a9fa9459Szrj rsrc_entry * b ATTRIBUTE_UNUSED) 3770*a9fa9459Szrj { 3771*a9fa9459Szrj unsigned int copy_needed = 0; 3772*a9fa9459Szrj unsigned int i; 3773*a9fa9459Szrj bfd_byte * astring; 3774*a9fa9459Szrj bfd_byte * bstring; 3775*a9fa9459Szrj bfd_byte * new_data; 3776*a9fa9459Szrj bfd_byte * nstring; 3777*a9fa9459Szrj 3778*a9fa9459Szrj /* Step one: Find out what we have to do. */ 3779*a9fa9459Szrj BFD_ASSERT (! a->is_dir); 3780*a9fa9459Szrj astring = a->value.leaf->data; 3781*a9fa9459Szrj 3782*a9fa9459Szrj BFD_ASSERT (! b->is_dir); 3783*a9fa9459Szrj bstring = b->value.leaf->data; 3784*a9fa9459Szrj 3785*a9fa9459Szrj for (i = 0; i < 16; i++) 3786*a9fa9459Szrj { 3787*a9fa9459Szrj unsigned int alen = astring[0] + (astring[1] << 8); 3788*a9fa9459Szrj unsigned int blen = bstring[0] + (bstring[1] << 8); 3789*a9fa9459Szrj 3790*a9fa9459Szrj if (alen == 0) 3791*a9fa9459Szrj { 3792*a9fa9459Szrj copy_needed += blen * 2; 3793*a9fa9459Szrj } 3794*a9fa9459Szrj else if (blen == 0) 3795*a9fa9459Szrj ; 3796*a9fa9459Szrj else if (alen != blen) 3797*a9fa9459Szrj /* FIXME: Should we continue the loop in order to report other duplicates ? */ 3798*a9fa9459Szrj break; 3799*a9fa9459Szrj /* alen == blen != 0. We might have two identical strings. If so we 3800*a9fa9459Szrj can ignore the second one. There is no need for wchar_t vs UTF-16 3801*a9fa9459Szrj theatrics here - we are only interested in (case sensitive) equality. */ 3802*a9fa9459Szrj else if (memcmp (astring + 2, bstring + 2, alen * 2) != 0) 3803*a9fa9459Szrj break; 3804*a9fa9459Szrj 3805*a9fa9459Szrj astring += (alen + 1) * 2; 3806*a9fa9459Szrj bstring += (blen + 1) * 2; 3807*a9fa9459Szrj } 3808*a9fa9459Szrj 3809*a9fa9459Szrj if (i != 16) 3810*a9fa9459Szrj { 3811*a9fa9459Szrj if (a->parent != NULL 3812*a9fa9459Szrj && a->parent->entry != NULL 3813*a9fa9459Szrj && a->parent->entry->is_name == FALSE) 3814*a9fa9459Szrj _bfd_error_handler (_(".rsrc merge failure: duplicate string resource: %d"), 3815*a9fa9459Szrj ((a->parent->entry->name_id.id - 1) << 4) + i); 3816*a9fa9459Szrj return FALSE; 3817*a9fa9459Szrj } 3818*a9fa9459Szrj 3819*a9fa9459Szrj if (copy_needed == 0) 3820*a9fa9459Szrj return TRUE; 3821*a9fa9459Szrj 3822*a9fa9459Szrj /* If we reach here then A and B must both have non-colliding strings. 3823*a9fa9459Szrj (We never get string resources with fully empty string tables). 3824*a9fa9459Szrj We need to allocate an extra COPY_NEEDED bytes in A and then bring 3825*a9fa9459Szrj in B's strings. */ 3826*a9fa9459Szrj new_data = bfd_malloc (a->value.leaf->size + copy_needed); 3827*a9fa9459Szrj if (new_data == NULL) 3828*a9fa9459Szrj return FALSE; 3829*a9fa9459Szrj 3830*a9fa9459Szrj nstring = new_data; 3831*a9fa9459Szrj astring = a->value.leaf->data; 3832*a9fa9459Szrj bstring = b->value.leaf->data; 3833*a9fa9459Szrj 3834*a9fa9459Szrj for (i = 0; i < 16; i++) 3835*a9fa9459Szrj { 3836*a9fa9459Szrj unsigned int alen = astring[0] + (astring[1] << 8); 3837*a9fa9459Szrj unsigned int blen = bstring[0] + (bstring[1] << 8); 3838*a9fa9459Szrj 3839*a9fa9459Szrj if (alen != 0) 3840*a9fa9459Szrj { 3841*a9fa9459Szrj memcpy (nstring, astring, (alen + 1) * 2); 3842*a9fa9459Szrj nstring += (alen + 1) * 2; 3843*a9fa9459Szrj } 3844*a9fa9459Szrj else if (blen != 0) 3845*a9fa9459Szrj { 3846*a9fa9459Szrj memcpy (nstring, bstring, (blen + 1) * 2); 3847*a9fa9459Szrj nstring += (blen + 1) * 2; 3848*a9fa9459Szrj } 3849*a9fa9459Szrj else 3850*a9fa9459Szrj { 3851*a9fa9459Szrj * nstring++ = 0; 3852*a9fa9459Szrj * nstring++ = 0; 3853*a9fa9459Szrj } 3854*a9fa9459Szrj 3855*a9fa9459Szrj astring += (alen + 1) * 2; 3856*a9fa9459Szrj bstring += (blen + 1) * 2; 3857*a9fa9459Szrj } 3858*a9fa9459Szrj 3859*a9fa9459Szrj BFD_ASSERT (nstring - new_data == (signed) (a->value.leaf->size + copy_needed)); 3860*a9fa9459Szrj 3861*a9fa9459Szrj free (a->value.leaf->data); 3862*a9fa9459Szrj a->value.leaf->data = new_data; 3863*a9fa9459Szrj a->value.leaf->size += copy_needed; 3864*a9fa9459Szrj 3865*a9fa9459Szrj return TRUE; 3866*a9fa9459Szrj } 3867*a9fa9459Szrj 3868*a9fa9459Szrj static void rsrc_merge (rsrc_entry *, rsrc_entry *); 3869*a9fa9459Szrj 3870*a9fa9459Szrj /* Sort the entries in given part of the directory. 3871*a9fa9459Szrj We use an old fashioned bubble sort because we are dealing 3872*a9fa9459Szrj with lists and we want to handle matches specially. */ 3873*a9fa9459Szrj 3874*a9fa9459Szrj static void 3875*a9fa9459Szrj rsrc_sort_entries (rsrc_dir_chain * chain, 3876*a9fa9459Szrj bfd_boolean is_name, 3877*a9fa9459Szrj rsrc_directory * dir) 3878*a9fa9459Szrj { 3879*a9fa9459Szrj rsrc_entry * entry; 3880*a9fa9459Szrj rsrc_entry * next; 3881*a9fa9459Szrj rsrc_entry ** points_to_entry; 3882*a9fa9459Szrj bfd_boolean swapped; 3883*a9fa9459Szrj 3884*a9fa9459Szrj if (chain->num_entries < 2) 3885*a9fa9459Szrj return; 3886*a9fa9459Szrj 3887*a9fa9459Szrj do 3888*a9fa9459Szrj { 3889*a9fa9459Szrj swapped = FALSE; 3890*a9fa9459Szrj points_to_entry = & chain->first_entry; 3891*a9fa9459Szrj entry = * points_to_entry; 3892*a9fa9459Szrj next = entry->next_entry; 3893*a9fa9459Szrj 3894*a9fa9459Szrj do 3895*a9fa9459Szrj { 3896*a9fa9459Szrj signed int cmp = rsrc_cmp (is_name, entry, next); 3897*a9fa9459Szrj 3898*a9fa9459Szrj if (cmp > 0) 3899*a9fa9459Szrj { 3900*a9fa9459Szrj entry->next_entry = next->next_entry; 3901*a9fa9459Szrj next->next_entry = entry; 3902*a9fa9459Szrj * points_to_entry = next; 3903*a9fa9459Szrj points_to_entry = & next->next_entry; 3904*a9fa9459Szrj next = entry->next_entry; 3905*a9fa9459Szrj swapped = TRUE; 3906*a9fa9459Szrj } 3907*a9fa9459Szrj else if (cmp == 0) 3908*a9fa9459Szrj { 3909*a9fa9459Szrj if (entry->is_dir && next->is_dir) 3910*a9fa9459Szrj { 3911*a9fa9459Szrj /* When we encounter identical directory entries we have to 3912*a9fa9459Szrj merge them together. The exception to this rule is for 3913*a9fa9459Szrj resource manifests - there can only be one of these, 3914*a9fa9459Szrj even if they differ in language. Zero-language manifests 3915*a9fa9459Szrj are assumed to be default manifests (provided by the 3916*a9fa9459Szrj Cygwin/MinGW build system) and these can be silently dropped, 3917*a9fa9459Szrj unless that would reduce the number of manifests to zero. 3918*a9fa9459Szrj There should only ever be one non-zero lang manifest - 3919*a9fa9459Szrj if there are more it is an error. A non-zero lang 3920*a9fa9459Szrj manifest takes precedence over a default manifest. */ 3921*a9fa9459Szrj if (entry->is_name == FALSE 3922*a9fa9459Szrj && entry->name_id.id == 1 3923*a9fa9459Szrj && dir != NULL 3924*a9fa9459Szrj && dir->entry != NULL 3925*a9fa9459Szrj && dir->entry->is_name == FALSE 3926*a9fa9459Szrj && dir->entry->name_id.id == 0x18) 3927*a9fa9459Szrj { 3928*a9fa9459Szrj if (next->value.directory->names.num_entries == 0 3929*a9fa9459Szrj && next->value.directory->ids.num_entries == 1 3930*a9fa9459Szrj && next->value.directory->ids.first_entry->is_name == FALSE 3931*a9fa9459Szrj && next->value.directory->ids.first_entry->name_id.id == 0) 3932*a9fa9459Szrj /* Fall through so that NEXT is dropped. */ 3933*a9fa9459Szrj ; 3934*a9fa9459Szrj else if (entry->value.directory->names.num_entries == 0 3935*a9fa9459Szrj && entry->value.directory->ids.num_entries == 1 3936*a9fa9459Szrj && entry->value.directory->ids.first_entry->is_name == FALSE 3937*a9fa9459Szrj && entry->value.directory->ids.first_entry->name_id.id == 0) 3938*a9fa9459Szrj { 3939*a9fa9459Szrj /* Swap ENTRY and NEXT. Then fall through so that the old ENTRY is dropped. */ 3940*a9fa9459Szrj entry->next_entry = next->next_entry; 3941*a9fa9459Szrj next->next_entry = entry; 3942*a9fa9459Szrj * points_to_entry = next; 3943*a9fa9459Szrj points_to_entry = & next->next_entry; 3944*a9fa9459Szrj next = entry->next_entry; 3945*a9fa9459Szrj swapped = TRUE; 3946*a9fa9459Szrj } 3947*a9fa9459Szrj else 3948*a9fa9459Szrj { 3949*a9fa9459Szrj _bfd_error_handler (_(".rsrc merge failure: multiple non-default manifests")); 3950*a9fa9459Szrj bfd_set_error (bfd_error_file_truncated); 3951*a9fa9459Szrj return; 3952*a9fa9459Szrj } 3953*a9fa9459Szrj 3954*a9fa9459Szrj /* Unhook NEXT from the chain. */ 3955*a9fa9459Szrj /* FIXME: memory loss here. */ 3956*a9fa9459Szrj entry->next_entry = next->next_entry; 3957*a9fa9459Szrj chain->num_entries --; 3958*a9fa9459Szrj if (chain->num_entries < 2) 3959*a9fa9459Szrj return; 3960*a9fa9459Szrj next = next->next_entry; 3961*a9fa9459Szrj } 3962*a9fa9459Szrj else 3963*a9fa9459Szrj rsrc_merge (entry, next); 3964*a9fa9459Szrj } 3965*a9fa9459Szrj else if (entry->is_dir != next->is_dir) 3966*a9fa9459Szrj { 3967*a9fa9459Szrj _bfd_error_handler (_(".rsrc merge failure: a directory matches a leaf")); 3968*a9fa9459Szrj bfd_set_error (bfd_error_file_truncated); 3969*a9fa9459Szrj return; 3970*a9fa9459Szrj } 3971*a9fa9459Szrj else 3972*a9fa9459Szrj { 3973*a9fa9459Szrj /* Otherwise with identical leaves we issue an error 3974*a9fa9459Szrj message - because there should never be duplicates. 3975*a9fa9459Szrj The exception is Type 18/Name 1/Lang 0 which is the 3976*a9fa9459Szrj defaul manifest - this can just be dropped. */ 3977*a9fa9459Szrj if (entry->is_name == FALSE 3978*a9fa9459Szrj && entry->name_id.id == 0 3979*a9fa9459Szrj && dir != NULL 3980*a9fa9459Szrj && dir->entry != NULL 3981*a9fa9459Szrj && dir->entry->is_name == FALSE 3982*a9fa9459Szrj && dir->entry->name_id.id == 1 3983*a9fa9459Szrj && dir->entry->parent != NULL 3984*a9fa9459Szrj && dir->entry->parent->entry != NULL 3985*a9fa9459Szrj && dir->entry->parent->entry->is_name == FALSE 3986*a9fa9459Szrj && dir->entry->parent->entry->name_id.id == 0x18 /* RT_MANIFEST */) 3987*a9fa9459Szrj ; 3988*a9fa9459Szrj else if (dir != NULL 3989*a9fa9459Szrj && dir->entry != NULL 3990*a9fa9459Szrj && dir->entry->parent != NULL 3991*a9fa9459Szrj && dir->entry->parent->entry != NULL 3992*a9fa9459Szrj && dir->entry->parent->entry->is_name == FALSE 3993*a9fa9459Szrj && dir->entry->parent->entry->name_id.id == 0x6 /* RT_STRING */) 3994*a9fa9459Szrj { 3995*a9fa9459Szrj /* Strings need special handling. */ 3996*a9fa9459Szrj if (! rsrc_merge_string_entries (entry, next)) 3997*a9fa9459Szrj { 3998*a9fa9459Szrj /* _bfd_error_handler should have been called inside merge_strings. */ 3999*a9fa9459Szrj bfd_set_error (bfd_error_file_truncated); 4000*a9fa9459Szrj return; 4001*a9fa9459Szrj } 4002*a9fa9459Szrj } 4003*a9fa9459Szrj else 4004*a9fa9459Szrj { 4005*a9fa9459Szrj if (dir == NULL 4006*a9fa9459Szrj || dir->entry == NULL 4007*a9fa9459Szrj || dir->entry->parent == NULL 4008*a9fa9459Szrj || dir->entry->parent->entry == NULL) 4009*a9fa9459Szrj _bfd_error_handler (_(".rsrc merge failure: duplicate leaf")); 4010*a9fa9459Szrj else 4011*a9fa9459Szrj _bfd_error_handler (_(".rsrc merge failure: duplicate leaf: %s"), 4012*a9fa9459Szrj rsrc_resource_name (entry, dir)); 4013*a9fa9459Szrj bfd_set_error (bfd_error_file_truncated); 4014*a9fa9459Szrj return; 4015*a9fa9459Szrj } 4016*a9fa9459Szrj } 4017*a9fa9459Szrj 4018*a9fa9459Szrj /* Unhook NEXT from the chain. */ 4019*a9fa9459Szrj entry->next_entry = next->next_entry; 4020*a9fa9459Szrj chain->num_entries --; 4021*a9fa9459Szrj if (chain->num_entries < 2) 4022*a9fa9459Szrj return; 4023*a9fa9459Szrj next = next->next_entry; 4024*a9fa9459Szrj } 4025*a9fa9459Szrj else 4026*a9fa9459Szrj { 4027*a9fa9459Szrj points_to_entry = & entry->next_entry; 4028*a9fa9459Szrj entry = next; 4029*a9fa9459Szrj next = next->next_entry; 4030*a9fa9459Szrj } 4031*a9fa9459Szrj } 4032*a9fa9459Szrj while (next); 4033*a9fa9459Szrj 4034*a9fa9459Szrj chain->last_entry = entry; 4035*a9fa9459Szrj } 4036*a9fa9459Szrj while (swapped); 4037*a9fa9459Szrj } 4038*a9fa9459Szrj 4039*a9fa9459Szrj /* Attach B's chain onto A. */ 4040*a9fa9459Szrj static void 4041*a9fa9459Szrj rsrc_attach_chain (rsrc_dir_chain * achain, rsrc_dir_chain * bchain) 4042*a9fa9459Szrj { 4043*a9fa9459Szrj if (bchain->num_entries == 0) 4044*a9fa9459Szrj return; 4045*a9fa9459Szrj 4046*a9fa9459Szrj achain->num_entries += bchain->num_entries; 4047*a9fa9459Szrj 4048*a9fa9459Szrj if (achain->first_entry == NULL) 4049*a9fa9459Szrj { 4050*a9fa9459Szrj achain->first_entry = bchain->first_entry; 4051*a9fa9459Szrj achain->last_entry = bchain->last_entry; 4052*a9fa9459Szrj } 4053*a9fa9459Szrj else 4054*a9fa9459Szrj { 4055*a9fa9459Szrj achain->last_entry->next_entry = bchain->first_entry; 4056*a9fa9459Szrj achain->last_entry = bchain->last_entry; 4057*a9fa9459Szrj } 4058*a9fa9459Szrj 4059*a9fa9459Szrj bchain->num_entries = 0; 4060*a9fa9459Szrj bchain->first_entry = bchain->last_entry = NULL; 4061*a9fa9459Szrj } 4062*a9fa9459Szrj 4063*a9fa9459Szrj static void 4064*a9fa9459Szrj rsrc_merge (struct rsrc_entry * a, struct rsrc_entry * b) 4065*a9fa9459Szrj { 4066*a9fa9459Szrj rsrc_directory * adir; 4067*a9fa9459Szrj rsrc_directory * bdir; 4068*a9fa9459Szrj 4069*a9fa9459Szrj BFD_ASSERT (a->is_dir); 4070*a9fa9459Szrj BFD_ASSERT (b->is_dir); 4071*a9fa9459Szrj 4072*a9fa9459Szrj adir = a->value.directory; 4073*a9fa9459Szrj bdir = b->value.directory; 4074*a9fa9459Szrj 4075*a9fa9459Szrj if (adir->characteristics != bdir->characteristics) 4076*a9fa9459Szrj { 4077*a9fa9459Szrj _bfd_error_handler (_(".rsrc merge failure: dirs with differing characteristics\n")); 4078*a9fa9459Szrj bfd_set_error (bfd_error_file_truncated); 4079*a9fa9459Szrj return; 4080*a9fa9459Szrj } 4081*a9fa9459Szrj 4082*a9fa9459Szrj if (adir->major != bdir->major || adir->minor != bdir->minor) 4083*a9fa9459Szrj { 4084*a9fa9459Szrj _bfd_error_handler (_(".rsrc merge failure: differing directory versions\n")); 4085*a9fa9459Szrj bfd_set_error (bfd_error_file_truncated); 4086*a9fa9459Szrj return; 4087*a9fa9459Szrj } 4088*a9fa9459Szrj 4089*a9fa9459Szrj /* Attach B's name chain to A. */ 4090*a9fa9459Szrj rsrc_attach_chain (& adir->names, & bdir->names); 4091*a9fa9459Szrj 4092*a9fa9459Szrj /* Attach B's ID chain to A. */ 4093*a9fa9459Szrj rsrc_attach_chain (& adir->ids, & bdir->ids); 4094*a9fa9459Szrj 4095*a9fa9459Szrj /* Now sort A's entries. */ 4096*a9fa9459Szrj rsrc_sort_entries (& adir->names, TRUE, adir); 4097*a9fa9459Szrj rsrc_sort_entries (& adir->ids, FALSE, adir); 4098*a9fa9459Szrj } 4099*a9fa9459Szrj 4100*a9fa9459Szrj /* Check the .rsrc section. If it contains multiple concatenated 4101*a9fa9459Szrj resources then we must merge them properly. Otherwise Windows 4102*a9fa9459Szrj will ignore all but the first set. */ 4103*a9fa9459Szrj 4104*a9fa9459Szrj static void 4105*a9fa9459Szrj rsrc_process_section (bfd * abfd, 4106*a9fa9459Szrj struct coff_final_link_info * pfinfo) 4107*a9fa9459Szrj { 4108*a9fa9459Szrj rsrc_directory new_table; 4109*a9fa9459Szrj bfd_size_type size; 4110*a9fa9459Szrj asection * sec; 4111*a9fa9459Szrj pe_data_type * pe; 4112*a9fa9459Szrj bfd_vma rva_bias; 4113*a9fa9459Szrj bfd_byte * data; 4114*a9fa9459Szrj bfd_byte * datastart; 4115*a9fa9459Szrj bfd_byte * dataend; 4116*a9fa9459Szrj bfd_byte * new_data; 4117*a9fa9459Szrj unsigned int num_resource_sets; 4118*a9fa9459Szrj rsrc_directory * type_tables; 4119*a9fa9459Szrj rsrc_write_data write_data; 4120*a9fa9459Szrj unsigned int indx; 4121*a9fa9459Szrj bfd * input; 4122*a9fa9459Szrj unsigned int num_input_rsrc = 0; 4123*a9fa9459Szrj unsigned int max_num_input_rsrc = 4; 4124*a9fa9459Szrj ptrdiff_t * rsrc_sizes = NULL; 4125*a9fa9459Szrj 4126*a9fa9459Szrj new_table.names.num_entries = 0; 4127*a9fa9459Szrj new_table.ids.num_entries = 0; 4128*a9fa9459Szrj 4129*a9fa9459Szrj sec = bfd_get_section_by_name (abfd, ".rsrc"); 4130*a9fa9459Szrj if (sec == NULL || (size = sec->rawsize) == 0) 4131*a9fa9459Szrj return; 4132*a9fa9459Szrj 4133*a9fa9459Szrj pe = pe_data (abfd); 4134*a9fa9459Szrj if (pe == NULL) 4135*a9fa9459Szrj return; 4136*a9fa9459Szrj 4137*a9fa9459Szrj rva_bias = sec->vma - pe->pe_opthdr.ImageBase; 4138*a9fa9459Szrj 4139*a9fa9459Szrj data = bfd_malloc (size); 4140*a9fa9459Szrj if (data == NULL) 4141*a9fa9459Szrj return; 4142*a9fa9459Szrj 4143*a9fa9459Szrj datastart = data; 4144*a9fa9459Szrj 4145*a9fa9459Szrj if (! bfd_get_section_contents (abfd, sec, data, 0, size)) 4146*a9fa9459Szrj goto end; 4147*a9fa9459Szrj 4148*a9fa9459Szrj /* Step zero: Scan the input bfds looking for .rsrc sections and record 4149*a9fa9459Szrj their lengths. Note - we rely upon the fact that the linker script 4150*a9fa9459Szrj does *not* sort the input .rsrc sections, so that the order in the 4151*a9fa9459Szrj linkinfo list matches the order in the output .rsrc section. 4152*a9fa9459Szrj 4153*a9fa9459Szrj We need to know the lengths because each input .rsrc section has padding 4154*a9fa9459Szrj at the end of a variable amount. (It does not appear to be based upon 4155*a9fa9459Szrj the section alignment or the file alignment). We need to skip any 4156*a9fa9459Szrj padding bytes when parsing the input .rsrc sections. */ 4157*a9fa9459Szrj rsrc_sizes = bfd_malloc (max_num_input_rsrc * sizeof * rsrc_sizes); 4158*a9fa9459Szrj if (rsrc_sizes == NULL) 4159*a9fa9459Szrj goto end; 4160*a9fa9459Szrj 4161*a9fa9459Szrj for (input = pfinfo->info->input_bfds; 4162*a9fa9459Szrj input != NULL; 4163*a9fa9459Szrj input = input->link.next) 4164*a9fa9459Szrj { 4165*a9fa9459Szrj asection * rsrc_sec = bfd_get_section_by_name (input, ".rsrc"); 4166*a9fa9459Szrj 4167*a9fa9459Szrj /* PR 18372 - skip discarded .rsrc sections. */ 4168*a9fa9459Szrj if (rsrc_sec != NULL && !discarded_section (rsrc_sec)) 4169*a9fa9459Szrj { 4170*a9fa9459Szrj if (num_input_rsrc == max_num_input_rsrc) 4171*a9fa9459Szrj { 4172*a9fa9459Szrj max_num_input_rsrc += 10; 4173*a9fa9459Szrj rsrc_sizes = bfd_realloc (rsrc_sizes, max_num_input_rsrc 4174*a9fa9459Szrj * sizeof * rsrc_sizes); 4175*a9fa9459Szrj if (rsrc_sizes == NULL) 4176*a9fa9459Szrj goto end; 4177*a9fa9459Szrj } 4178*a9fa9459Szrj 4179*a9fa9459Szrj BFD_ASSERT (rsrc_sec->size > 0); 4180*a9fa9459Szrj rsrc_sizes [num_input_rsrc ++] = rsrc_sec->size; 4181*a9fa9459Szrj } 4182*a9fa9459Szrj } 4183*a9fa9459Szrj 4184*a9fa9459Szrj if (num_input_rsrc < 2) 4185*a9fa9459Szrj goto end; 4186*a9fa9459Szrj 4187*a9fa9459Szrj /* Step one: Walk the section, computing the size of the tables, 4188*a9fa9459Szrj leaves and data and decide if we need to do anything. */ 4189*a9fa9459Szrj dataend = data + size; 4190*a9fa9459Szrj num_resource_sets = 0; 4191*a9fa9459Szrj 4192*a9fa9459Szrj while (data < dataend) 4193*a9fa9459Szrj { 4194*a9fa9459Szrj bfd_byte * p = data; 4195*a9fa9459Szrj 4196*a9fa9459Szrj data = rsrc_count_directory (abfd, data, data, dataend, rva_bias); 4197*a9fa9459Szrj 4198*a9fa9459Szrj if (data > dataend) 4199*a9fa9459Szrj { 4200*a9fa9459Szrj /* Corrupted .rsrc section - cannot merge. */ 4201*a9fa9459Szrj _bfd_error_handler (_("%s: .rsrc merge failure: corrupt .rsrc section"), 4202*a9fa9459Szrj bfd_get_filename (abfd)); 4203*a9fa9459Szrj bfd_set_error (bfd_error_file_truncated); 4204*a9fa9459Szrj goto end; 4205*a9fa9459Szrj } 4206*a9fa9459Szrj 4207*a9fa9459Szrj if ((data - p) > rsrc_sizes [num_resource_sets]) 4208*a9fa9459Szrj { 4209*a9fa9459Szrj _bfd_error_handler (_("%s: .rsrc merge failure: unexpected .rsrc size"), 4210*a9fa9459Szrj bfd_get_filename (abfd)); 4211*a9fa9459Szrj bfd_set_error (bfd_error_file_truncated); 4212*a9fa9459Szrj goto end; 4213*a9fa9459Szrj } 4214*a9fa9459Szrj /* FIXME: Should we add a check for "data - p" being much smaller 4215*a9fa9459Szrj than rsrc_sizes[num_resource_sets] ? */ 4216*a9fa9459Szrj 4217*a9fa9459Szrj data = p + rsrc_sizes[num_resource_sets]; 4218*a9fa9459Szrj rva_bias += data - p; 4219*a9fa9459Szrj ++ num_resource_sets; 4220*a9fa9459Szrj } 4221*a9fa9459Szrj BFD_ASSERT (num_resource_sets == num_input_rsrc); 4222*a9fa9459Szrj 4223*a9fa9459Szrj /* Step two: Walk the data again, building trees of the resources. */ 4224*a9fa9459Szrj data = datastart; 4225*a9fa9459Szrj rva_bias = sec->vma - pe->pe_opthdr.ImageBase; 4226*a9fa9459Szrj 4227*a9fa9459Szrj type_tables = bfd_malloc (num_resource_sets * sizeof * type_tables); 4228*a9fa9459Szrj if (type_tables == NULL) 4229*a9fa9459Szrj goto end; 4230*a9fa9459Szrj 4231*a9fa9459Szrj indx = 0; 4232*a9fa9459Szrj while (data < dataend) 4233*a9fa9459Szrj { 4234*a9fa9459Szrj bfd_byte * p = data; 4235*a9fa9459Szrj 4236*a9fa9459Szrj (void) rsrc_parse_directory (abfd, type_tables + indx, data, data, 4237*a9fa9459Szrj dataend, rva_bias, NULL); 4238*a9fa9459Szrj data = p + rsrc_sizes[indx]; 4239*a9fa9459Szrj rva_bias += data - p; 4240*a9fa9459Szrj ++ indx; 4241*a9fa9459Szrj } 4242*a9fa9459Szrj BFD_ASSERT (indx == num_resource_sets); 4243*a9fa9459Szrj 4244*a9fa9459Szrj /* Step three: Merge the top level tables (there can be only one). 4245*a9fa9459Szrj 4246*a9fa9459Szrj We must ensure that the merged entries are in ascending order. 4247*a9fa9459Szrj 4248*a9fa9459Szrj We also thread the top level table entries from the old tree onto 4249*a9fa9459Szrj the new table, so that they can be pulled off later. */ 4250*a9fa9459Szrj 4251*a9fa9459Szrj /* FIXME: Should we verify that all type tables are the same ? */ 4252*a9fa9459Szrj new_table.characteristics = type_tables[0].characteristics; 4253*a9fa9459Szrj new_table.time = type_tables[0].time; 4254*a9fa9459Szrj new_table.major = type_tables[0].major; 4255*a9fa9459Szrj new_table.minor = type_tables[0].minor; 4256*a9fa9459Szrj 4257*a9fa9459Szrj /* Chain the NAME entries onto the table. */ 4258*a9fa9459Szrj new_table.names.first_entry = NULL; 4259*a9fa9459Szrj new_table.names.last_entry = NULL; 4260*a9fa9459Szrj 4261*a9fa9459Szrj for (indx = 0; indx < num_resource_sets; indx++) 4262*a9fa9459Szrj rsrc_attach_chain (& new_table.names, & type_tables[indx].names); 4263*a9fa9459Szrj 4264*a9fa9459Szrj rsrc_sort_entries (& new_table.names, TRUE, & new_table); 4265*a9fa9459Szrj 4266*a9fa9459Szrj /* Chain the ID entries onto the table. */ 4267*a9fa9459Szrj new_table.ids.first_entry = NULL; 4268*a9fa9459Szrj new_table.ids.last_entry = NULL; 4269*a9fa9459Szrj 4270*a9fa9459Szrj for (indx = 0; indx < num_resource_sets; indx++) 4271*a9fa9459Szrj rsrc_attach_chain (& new_table.ids, & type_tables[indx].ids); 4272*a9fa9459Szrj 4273*a9fa9459Szrj rsrc_sort_entries (& new_table.ids, FALSE, & new_table); 4274*a9fa9459Szrj 4275*a9fa9459Szrj /* Step four: Create new contents for the .rsrc section. */ 4276*a9fa9459Szrj /* Step four point one: Compute the size of each region of the .rsrc section. 4277*a9fa9459Szrj We do this now, rather than earlier, as the merging above may have dropped 4278*a9fa9459Szrj some entries. */ 4279*a9fa9459Szrj sizeof_leaves = sizeof_strings = sizeof_tables_and_entries = 0; 4280*a9fa9459Szrj rsrc_compute_region_sizes (& new_table); 4281*a9fa9459Szrj /* We increment sizeof_strings to make sure that resource data 4282*a9fa9459Szrj starts on an 8-byte boundary. FIXME: Is this correct ? */ 4283*a9fa9459Szrj sizeof_strings = (sizeof_strings + 7) & ~ 7; 4284*a9fa9459Szrj 4285*a9fa9459Szrj new_data = bfd_zalloc (abfd, size); 4286*a9fa9459Szrj if (new_data == NULL) 4287*a9fa9459Szrj goto end; 4288*a9fa9459Szrj 4289*a9fa9459Szrj write_data.abfd = abfd; 4290*a9fa9459Szrj write_data.datastart = new_data; 4291*a9fa9459Szrj write_data.next_table = new_data; 4292*a9fa9459Szrj write_data.next_leaf = new_data + sizeof_tables_and_entries; 4293*a9fa9459Szrj write_data.next_string = write_data.next_leaf + sizeof_leaves; 4294*a9fa9459Szrj write_data.next_data = write_data.next_string + sizeof_strings; 4295*a9fa9459Szrj write_data.rva_bias = sec->vma - pe->pe_opthdr.ImageBase; 4296*a9fa9459Szrj 4297*a9fa9459Szrj rsrc_write_directory (& write_data, & new_table); 4298*a9fa9459Szrj 4299*a9fa9459Szrj /* Step five: Replace the old contents with the new. 4300*a9fa9459Szrj We recompute the size as we may have lost entries due to mergeing. */ 4301*a9fa9459Szrj size = ((write_data.next_data - new_data) + 3) & ~ 3; 4302*a9fa9459Szrj 4303*a9fa9459Szrj { 4304*a9fa9459Szrj int page_size; 4305*a9fa9459Szrj 4306*a9fa9459Szrj if (coff_data (abfd)->link_info) 4307*a9fa9459Szrj { 4308*a9fa9459Szrj page_size = pe_data (abfd)->pe_opthdr.FileAlignment; 4309*a9fa9459Szrj 4310*a9fa9459Szrj /* If no file alignment has been set, default to one. 4311*a9fa9459Szrj This repairs 'ld -r' for arm-wince-pe target. */ 4312*a9fa9459Szrj if (page_size == 0) 4313*a9fa9459Szrj page_size = 1; 4314*a9fa9459Szrj } 4315*a9fa9459Szrj else 4316*a9fa9459Szrj page_size = PE_DEF_FILE_ALIGNMENT; 4317*a9fa9459Szrj size = (size + page_size - 1) & - page_size; 4318*a9fa9459Szrj } 4319*a9fa9459Szrj 4320*a9fa9459Szrj bfd_set_section_contents (pfinfo->output_bfd, sec, new_data, 0, size); 4321*a9fa9459Szrj sec->size = sec->rawsize = size; 4322*a9fa9459Szrj 4323*a9fa9459Szrj end: 4324*a9fa9459Szrj /* Step six: Free all the memory that we have used. */ 4325*a9fa9459Szrj /* FIXME: Free the resource tree, if we have one. */ 4326*a9fa9459Szrj free (datastart); 4327*a9fa9459Szrj free (rsrc_sizes); 4328*a9fa9459Szrj } 4329*a9fa9459Szrj 4330*a9fa9459Szrj /* Handle the .idata section and other things that need symbol table 4331*a9fa9459Szrj access. */ 4332*a9fa9459Szrj 4333*a9fa9459Szrj bfd_boolean 4334*a9fa9459Szrj _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo) 4335*a9fa9459Szrj { 4336*a9fa9459Szrj struct coff_link_hash_entry *h1; 4337*a9fa9459Szrj struct bfd_link_info *info = pfinfo->info; 4338*a9fa9459Szrj bfd_boolean result = TRUE; 4339*a9fa9459Szrj 4340*a9fa9459Szrj /* There are a few fields that need to be filled in now while we 4341*a9fa9459Szrj have symbol table access. 4342*a9fa9459Szrj 4343*a9fa9459Szrj The .idata subsections aren't directly available as sections, but 4344*a9fa9459Szrj they are in the symbol table, so get them from there. */ 4345*a9fa9459Szrj 4346*a9fa9459Szrj /* The import directory. This is the address of .idata$2, with size 4347*a9fa9459Szrj of .idata$2 + .idata$3. */ 4348*a9fa9459Szrj h1 = coff_link_hash_lookup (coff_hash_table (info), 4349*a9fa9459Szrj ".idata$2", FALSE, FALSE, TRUE); 4350*a9fa9459Szrj if (h1 != NULL) 4351*a9fa9459Szrj { 4352*a9fa9459Szrj /* PR ld/2729: We cannot rely upon all the output sections having been 4353*a9fa9459Szrj created properly, so check before referencing them. Issue a warning 4354*a9fa9459Szrj message for any sections tht could not be found. */ 4355*a9fa9459Szrj if ((h1->root.type == bfd_link_hash_defined 4356*a9fa9459Szrj || h1->root.type == bfd_link_hash_defweak) 4357*a9fa9459Szrj && h1->root.u.def.section != NULL 4358*a9fa9459Szrj && h1->root.u.def.section->output_section != NULL) 4359*a9fa9459Szrj pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress = 4360*a9fa9459Szrj (h1->root.u.def.value 4361*a9fa9459Szrj + h1->root.u.def.section->output_section->vma 4362*a9fa9459Szrj + h1->root.u.def.section->output_offset); 4363*a9fa9459Szrj else 4364*a9fa9459Szrj { 4365*a9fa9459Szrj _bfd_error_handler 4366*a9fa9459Szrj (_("%B: unable to fill in DataDictionary[1] because .idata$2 is missing"), 4367*a9fa9459Szrj abfd); 4368*a9fa9459Szrj result = FALSE; 4369*a9fa9459Szrj } 4370*a9fa9459Szrj 4371*a9fa9459Szrj h1 = coff_link_hash_lookup (coff_hash_table (info), 4372*a9fa9459Szrj ".idata$4", FALSE, FALSE, TRUE); 4373*a9fa9459Szrj if (h1 != NULL 4374*a9fa9459Szrj && (h1->root.type == bfd_link_hash_defined 4375*a9fa9459Szrj || h1->root.type == bfd_link_hash_defweak) 4376*a9fa9459Szrj && h1->root.u.def.section != NULL 4377*a9fa9459Szrj && h1->root.u.def.section->output_section != NULL) 4378*a9fa9459Szrj pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].Size = 4379*a9fa9459Szrj ((h1->root.u.def.value 4380*a9fa9459Szrj + h1->root.u.def.section->output_section->vma 4381*a9fa9459Szrj + h1->root.u.def.section->output_offset) 4382*a9fa9459Szrj - pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress); 4383*a9fa9459Szrj else 4384*a9fa9459Szrj { 4385*a9fa9459Szrj _bfd_error_handler 4386*a9fa9459Szrj (_("%B: unable to fill in DataDictionary[1] because .idata$4 is missing"), 4387*a9fa9459Szrj abfd); 4388*a9fa9459Szrj result = FALSE; 4389*a9fa9459Szrj } 4390*a9fa9459Szrj 4391*a9fa9459Szrj /* The import address table. This is the size/address of 4392*a9fa9459Szrj .idata$5. */ 4393*a9fa9459Szrj h1 = coff_link_hash_lookup (coff_hash_table (info), 4394*a9fa9459Szrj ".idata$5", FALSE, FALSE, TRUE); 4395*a9fa9459Szrj if (h1 != NULL 4396*a9fa9459Szrj && (h1->root.type == bfd_link_hash_defined 4397*a9fa9459Szrj || h1->root.type == bfd_link_hash_defweak) 4398*a9fa9459Szrj && h1->root.u.def.section != NULL 4399*a9fa9459Szrj && h1->root.u.def.section->output_section != NULL) 4400*a9fa9459Szrj pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress = 4401*a9fa9459Szrj (h1->root.u.def.value 4402*a9fa9459Szrj + h1->root.u.def.section->output_section->vma 4403*a9fa9459Szrj + h1->root.u.def.section->output_offset); 4404*a9fa9459Szrj else 4405*a9fa9459Szrj { 4406*a9fa9459Szrj _bfd_error_handler 4407*a9fa9459Szrj (_("%B: unable to fill in DataDictionary[12] because .idata$5 is missing"), 4408*a9fa9459Szrj abfd); 4409*a9fa9459Szrj result = FALSE; 4410*a9fa9459Szrj } 4411*a9fa9459Szrj 4412*a9fa9459Szrj h1 = coff_link_hash_lookup (coff_hash_table (info), 4413*a9fa9459Szrj ".idata$6", FALSE, FALSE, TRUE); 4414*a9fa9459Szrj if (h1 != NULL 4415*a9fa9459Szrj && (h1->root.type == bfd_link_hash_defined 4416*a9fa9459Szrj || h1->root.type == bfd_link_hash_defweak) 4417*a9fa9459Szrj && h1->root.u.def.section != NULL 4418*a9fa9459Szrj && h1->root.u.def.section->output_section != NULL) 4419*a9fa9459Szrj pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size = 4420*a9fa9459Szrj ((h1->root.u.def.value 4421*a9fa9459Szrj + h1->root.u.def.section->output_section->vma 4422*a9fa9459Szrj + h1->root.u.def.section->output_offset) 4423*a9fa9459Szrj - pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress); 4424*a9fa9459Szrj else 4425*a9fa9459Szrj { 4426*a9fa9459Szrj _bfd_error_handler 4427*a9fa9459Szrj (_("%B: unable to fill in DataDictionary[PE_IMPORT_ADDRESS_TABLE (12)] because .idata$6 is missing"), 4428*a9fa9459Szrj abfd); 4429*a9fa9459Szrj result = FALSE; 4430*a9fa9459Szrj } 4431*a9fa9459Szrj } 4432*a9fa9459Szrj else 4433*a9fa9459Szrj { 4434*a9fa9459Szrj h1 = coff_link_hash_lookup (coff_hash_table (info), 4435*a9fa9459Szrj "__IAT_start__", FALSE, FALSE, TRUE); 4436*a9fa9459Szrj if (h1 != NULL 4437*a9fa9459Szrj && (h1->root.type == bfd_link_hash_defined 4438*a9fa9459Szrj || h1->root.type == bfd_link_hash_defweak) 4439*a9fa9459Szrj && h1->root.u.def.section != NULL 4440*a9fa9459Szrj && h1->root.u.def.section->output_section != NULL) 4441*a9fa9459Szrj { 4442*a9fa9459Szrj bfd_vma iat_va; 4443*a9fa9459Szrj 4444*a9fa9459Szrj iat_va = 4445*a9fa9459Szrj (h1->root.u.def.value 4446*a9fa9459Szrj + h1->root.u.def.section->output_section->vma 4447*a9fa9459Szrj + h1->root.u.def.section->output_offset); 4448*a9fa9459Szrj 4449*a9fa9459Szrj h1 = coff_link_hash_lookup (coff_hash_table (info), 4450*a9fa9459Szrj "__IAT_end__", FALSE, FALSE, TRUE); 4451*a9fa9459Szrj if (h1 != NULL 4452*a9fa9459Szrj && (h1->root.type == bfd_link_hash_defined 4453*a9fa9459Szrj || h1->root.type == bfd_link_hash_defweak) 4454*a9fa9459Szrj && h1->root.u.def.section != NULL 4455*a9fa9459Szrj && h1->root.u.def.section->output_section != NULL) 4456*a9fa9459Szrj { 4457*a9fa9459Szrj pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size = 4458*a9fa9459Szrj ((h1->root.u.def.value 4459*a9fa9459Szrj + h1->root.u.def.section->output_section->vma 4460*a9fa9459Szrj + h1->root.u.def.section->output_offset) 4461*a9fa9459Szrj - iat_va); 4462*a9fa9459Szrj if (pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size != 0) 4463*a9fa9459Szrj pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress = 4464*a9fa9459Szrj iat_va - pe_data (abfd)->pe_opthdr.ImageBase; 4465*a9fa9459Szrj } 4466*a9fa9459Szrj else 4467*a9fa9459Szrj { 4468*a9fa9459Szrj _bfd_error_handler 4469*a9fa9459Szrj (_("%B: unable to fill in DataDictionary[PE_IMPORT_ADDRESS_TABLE(12)]" 4470*a9fa9459Szrj " because .idata$6 is missing"), abfd); 4471*a9fa9459Szrj result = FALSE; 4472*a9fa9459Szrj } 4473*a9fa9459Szrj } 4474*a9fa9459Szrj } 4475*a9fa9459Szrj 4476*a9fa9459Szrj h1 = coff_link_hash_lookup (coff_hash_table (info), 4477*a9fa9459Szrj (bfd_get_symbol_leading_char (abfd) != 0 4478*a9fa9459Szrj ? "__tls_used" : "_tls_used"), 4479*a9fa9459Szrj FALSE, FALSE, TRUE); 4480*a9fa9459Szrj if (h1 != NULL) 4481*a9fa9459Szrj { 4482*a9fa9459Szrj if ((h1->root.type == bfd_link_hash_defined 4483*a9fa9459Szrj || h1->root.type == bfd_link_hash_defweak) 4484*a9fa9459Szrj && h1->root.u.def.section != NULL 4485*a9fa9459Szrj && h1->root.u.def.section->output_section != NULL) 4486*a9fa9459Szrj pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].VirtualAddress = 4487*a9fa9459Szrj (h1->root.u.def.value 4488*a9fa9459Szrj + h1->root.u.def.section->output_section->vma 4489*a9fa9459Szrj + h1->root.u.def.section->output_offset 4490*a9fa9459Szrj - pe_data (abfd)->pe_opthdr.ImageBase); 4491*a9fa9459Szrj else 4492*a9fa9459Szrj { 4493*a9fa9459Szrj _bfd_error_handler 4494*a9fa9459Szrj (_("%B: unable to fill in DataDictionary[9] because __tls_used is missing"), 4495*a9fa9459Szrj abfd); 4496*a9fa9459Szrj result = FALSE; 4497*a9fa9459Szrj } 4498*a9fa9459Szrj /* According to PECOFF sepcifications by Microsoft version 8.2 4499*a9fa9459Szrj the TLS data directory consists of 4 pointers, followed 4500*a9fa9459Szrj by two 4-byte integer. This implies that the total size 4501*a9fa9459Szrj is different for 32-bit and 64-bit executables. */ 4502*a9fa9459Szrj #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) 4503*a9fa9459Szrj pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x18; 4504*a9fa9459Szrj #else 4505*a9fa9459Szrj pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x28; 4506*a9fa9459Szrj #endif 4507*a9fa9459Szrj } 4508*a9fa9459Szrj 4509*a9fa9459Szrj /* If there is a .pdata section and we have linked pdata finally, we 4510*a9fa9459Szrj need to sort the entries ascending. */ 4511*a9fa9459Szrj #if !defined(COFF_WITH_pep) && defined(COFF_WITH_pex64) 4512*a9fa9459Szrj { 4513*a9fa9459Szrj asection *sec = bfd_get_section_by_name (abfd, ".pdata"); 4514*a9fa9459Szrj 4515*a9fa9459Szrj if (sec) 4516*a9fa9459Szrj { 4517*a9fa9459Szrj bfd_size_type x = sec->rawsize; 4518*a9fa9459Szrj bfd_byte *tmp_data = NULL; 4519*a9fa9459Szrj 4520*a9fa9459Szrj if (x) 4521*a9fa9459Szrj tmp_data = bfd_malloc (x); 4522*a9fa9459Szrj 4523*a9fa9459Szrj if (tmp_data != NULL) 4524*a9fa9459Szrj { 4525*a9fa9459Szrj if (bfd_get_section_contents (abfd, sec, tmp_data, 0, x)) 4526*a9fa9459Szrj { 4527*a9fa9459Szrj qsort (tmp_data, 4528*a9fa9459Szrj (size_t) (x / 12), 4529*a9fa9459Szrj 12, sort_x64_pdata); 4530*a9fa9459Szrj bfd_set_section_contents (pfinfo->output_bfd, sec, 4531*a9fa9459Szrj tmp_data, 0, x); 4532*a9fa9459Szrj } 4533*a9fa9459Szrj free (tmp_data); 4534*a9fa9459Szrj } 4535*a9fa9459Szrj else 4536*a9fa9459Szrj result = FALSE; 4537*a9fa9459Szrj } 4538*a9fa9459Szrj } 4539*a9fa9459Szrj #endif 4540*a9fa9459Szrj 4541*a9fa9459Szrj rsrc_process_section (abfd, pfinfo); 4542*a9fa9459Szrj 4543*a9fa9459Szrj /* If we couldn't find idata$2, we either have an excessively 4544*a9fa9459Szrj trivial program or are in DEEP trouble; we have to assume trivial 4545*a9fa9459Szrj program.... */ 4546*a9fa9459Szrj return result; 4547*a9fa9459Szrj } 4548