1 /* 2 Copyright (c) 2019, David Anderson All rights reserved. 3 4 Redistribution and use in source and binary forms, with 5 or without modification, are permitted provided that the 6 following conditions are met: 7 8 Redistributions of source code must retain the above 9 copyright notice, this list of conditions and the following 10 disclaimer. 11 12 Redistributions in binary form must reproduce the above 13 copyright notice, this list of conditions and the following 14 disclaimer in the documentation and/or other materials 15 provided with the distribution. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 18 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 22 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 29 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 33 /* This file reads the parts of a Windows PE 34 file appropriate to reading DWARF debugging data. 35 */ 36 37 #ifdef _WIN32 38 #define _CRT_SECURE_NO_WARNINGS 39 #endif /* _WIN32 */ 40 41 #include "config.h" 42 #include <stdio.h> 43 #ifdef HAVE_MALLOC_H 44 /* Useful include for some Windows compilers. */ 45 #include <malloc.h> 46 #endif /* HAVE_MALLOC_H */ 47 #ifdef HAVE_STDLIB_H 48 #include <stdlib.h> 49 #endif /* HAVE_STDLIB_H */ 50 #include <string.h> /* memcpy */ 51 #include <sys/types.h> /* open() */ 52 #include <sys/stat.h> /* open() */ 53 #include <fcntl.h> /* open() */ 54 #include <time.h> 55 #ifdef HAVE_UNISTD_H 56 #include <unistd.h> /* lseek read close */ 57 #elif defined(_WIN32) && defined(_MSC_VER) 58 #include <io.h> 59 #endif /* HAVE_UNISTD_H */ 60 61 /* Windows specific header files */ 62 #if defined(_WIN32) && defined(HAVE_STDAFX_H) 63 #include "stdafx.h" 64 #endif /* HAVE_STDAFX_H */ 65 66 #include "libdwarf.h" 67 #include "libdwarfdefs.h" 68 #include "dwarf_base_types.h" 69 #include "dwarf_opaque.h" 70 #include "memcpy_swap.h" 71 #include "dwarf_error.h" /* for _dwarf_error() declaration */ 72 #include "dwarf_reading.h" 73 #include "dwarf_object_read_common.h" 74 #include "dwarf_object_detector.h" 75 #include "dwarf_pe_descr.h" 76 #include "dwarf_peread.h" 77 78 #ifdef HAVE_UNUSED_ATTRIBUTE 79 #define UNUSEDARG __attribute__ ((unused)) 80 #else 81 #define UNUSEDARG 82 #endif 83 84 #define DOS_HEADER_LEN 64 85 86 #ifndef TYP 87 #define TYP(n,l) char n[l] 88 #endif /* TYP */ 89 90 91 #ifndef SIZEOFT32 92 #define SIZEOFT32 4 93 #endif /* SIZEOFT32 */ 94 95 static int _dwarf_pe_object_access_init( 96 int fd, 97 unsigned ftype, 98 unsigned endian, 99 unsigned offsetsize, 100 size_t filesize, 101 Dwarf_Unsigned access, 102 Dwarf_Obj_Access_Interface **binary_interface, 103 int *localerrnum); 104 105 static unsigned long 106 magic_copy(char *d, unsigned len) 107 { 108 unsigned i = 0; 109 unsigned long v = 0; 110 111 v = d[0]; 112 for(i = 1 ; i < len; ++i) { 113 v <<= 8; 114 v |= 0xff&d[i]; 115 } 116 return v; 117 } 118 119 #ifdef WORDS_BIGENDIAN 120 #define ASNAR(func,t,s) \ 121 do { \ 122 unsigned tbyte = sizeof(t) - sizeof(s); \ 123 t = 0; \ 124 func(((char *)&t)+tbyte ,&s[0],sizeof(s)); \ 125 } while (0) 126 #else /* LITTLE ENDIAN */ 127 #define ASNAR(func,t,s) \ 128 do { \ 129 t = 0; \ 130 func(&t,&s[0],sizeof(s)); \ 131 } while (0) 132 #endif /* end LITTLE- BIG-ENDIAN */ 133 134 /* name_array is 8 byte string */ 135 static int 136 pe_section_name_get(dwarf_pe_object_access_internals_t *pep, 137 const char *name_array, 138 const char ** name_out, 139 int *errcode) 140 { 141 142 if (name_array[0] == '/') { 143 long v = 0; 144 unsigned long u = 0; 145 const char *s = 0; 146 char temp_array[9]; 147 148 memcpy(temp_array,name_array+1,7); 149 temp_array[7] = 0; 150 v = atoi(temp_array); 151 if (v < 0) { 152 *errcode = DW_DLE_STRING_OFFSET_BAD; 153 return DW_DLV_ERROR; 154 } 155 u = v; 156 if (u > pep->pe_string_table_size) { 157 *errcode = DW_DLE_STRING_OFFSET_BAD; 158 return DW_DLV_ERROR; 159 } 160 s = pep->pe_string_table +u; 161 *name_out = s; 162 return DW_DLV_OK; 163 } 164 *name_out = name_array; 165 return DW_DLV_OK; 166 } 167 168 169 static Dwarf_Endianness 170 pe_get_byte_order (void *obj) 171 { 172 dwarf_pe_object_access_internals_t *pep = 173 (dwarf_pe_object_access_internals_t*)(obj); 174 return pep->pe_endian; 175 } 176 177 178 static Dwarf_Small 179 pe_get_length_size (void *obj) 180 { 181 dwarf_pe_object_access_internals_t *pep = 182 (dwarf_pe_object_access_internals_t*)(obj); 183 return pep->pe_offsetsize/8; 184 } 185 186 static Dwarf_Small 187 pe_get_pointer_size (void *obj) 188 { 189 dwarf_pe_object_access_internals_t *pep = 190 (dwarf_pe_object_access_internals_t*)(obj); 191 return pep->pe_pointersize/8; 192 } 193 194 195 static Dwarf_Unsigned 196 pe_get_section_count (void *obj) 197 { 198 dwarf_pe_object_access_internals_t *pep = 199 (dwarf_pe_object_access_internals_t*)(obj); 200 return pep->pe_section_count; 201 } 202 203 static int 204 pe_get_section_info (void *obj, 205 Dwarf_Half section_index, 206 Dwarf_Obj_Access_Section *return_section, 207 UNUSEDARG int *error) 208 { 209 dwarf_pe_object_access_internals_t *pep = 210 (dwarf_pe_object_access_internals_t*)(obj); 211 212 213 if (section_index < pep->pe_section_count) { 214 struct dwarf_pe_generic_image_section_header *sp = 0; 215 sp = pep->pe_sectionptr + section_index; 216 return_section->addr = pep->pe_OptionalHeader.ImageBase + 217 sp->VirtualAddress; ; 218 return_section->type = 0; 219 /* SizeOfRawData can be rounded or truncated, 220 use VirtualSize for the real analog of Elf 221 section size. */ 222 return_section->size = sp->VirtualSize; 223 return_section->name = sp->dwarfsectname; 224 return_section->link = 0; 225 return_section->info = 0; 226 return_section->entrysize = 0; 227 return DW_DLV_OK; 228 } 229 return DW_DLV_NO_ENTRY; 230 } 231 232 233 static int 234 load_optional_header32(dwarf_pe_object_access_internals_t *pep, 235 Dwarf_Unsigned offset, int*errcode) 236 { 237 int res = 0; 238 IMAGE_OPTIONAL_HEADER32_dw hdr; 239 240 pep->pe_optional_header_size = sizeof(IMAGE_OPTIONAL_HEADER32_dw); 241 242 if ((pep->pe_optional_header_size + offset) > 243 pep->pe_filesize) { 244 *errcode = DW_DLE_FILE_TOO_SMALL; 245 return DW_DLV_ERROR; 246 } 247 248 res = _dwarf_object_read_random(pep->pe_fd, 249 (char *)&hdr, 250 (off_t)offset, sizeof(IMAGE_OPTIONAL_HEADER32_dw), 251 (off_t)pep->pe_filesize, 252 errcode); 253 if (res != DW_DLV_OK) { 254 return res; 255 } 256 257 /* This is a subset of fields. */ 258 ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.Magic, 259 hdr.Magic); 260 pep->pe_OptionalHeader.MajorLinkerVersion= hdr.MajorLinkerVersion; 261 pep->pe_OptionalHeader.MinorLinkerVersion= hdr.MinorLinkerVersion; 262 ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.ImageBase, 263 hdr.ImageBase); 264 ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfCode, 265 hdr.SizeOfCode); 266 ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfImage, 267 hdr.SizeOfImage); 268 ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfHeaders, 269 hdr.SizeOfHeaders); 270 pep->pe_OptionalHeader.SizeOfDataDirEntry = 271 sizeof(IMAGE_DATA_DIRECTORY_dw); 272 return DW_DLV_OK; 273 } 274 static int 275 load_optional_header64(dwarf_pe_object_access_internals_t *pep, 276 Dwarf_Unsigned offset, int*errcode ) 277 { 278 IMAGE_OPTIONAL_HEADER64_dw hdr; 279 int res = 0; 280 281 pep->pe_optional_header_size = sizeof(IMAGE_OPTIONAL_HEADER64_dw); 282 if ((pep->pe_optional_header_size + offset) > 283 pep->pe_filesize) { 284 *errcode = DW_DLE_FILE_TOO_SMALL; 285 return DW_DLV_ERROR; 286 } 287 res = _dwarf_object_read_random(pep->pe_fd, 288 (char *)&hdr, 289 (off_t)offset, sizeof(IMAGE_OPTIONAL_HEADER64_dw), 290 (off_t)pep->pe_filesize, 291 errcode); 292 if (res != DW_DLV_OK) { 293 return res; 294 } 295 296 /* This is a subset of fields. */ 297 ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.Magic, 298 hdr.Magic); 299 pep->pe_OptionalHeader.MajorLinkerVersion= hdr.MajorLinkerVersion; 300 pep->pe_OptionalHeader.MinorLinkerVersion= hdr.MinorLinkerVersion; 301 ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfCode, 302 hdr.SizeOfCode); 303 ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfImage, 304 hdr.SizeOfImage); 305 ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfHeaders, 306 hdr.SizeOfHeaders); 307 pep->pe_OptionalHeader.SizeOfDataDirEntry = 308 sizeof(IMAGE_DATA_DIRECTORY_dw); 309 return DW_DLV_OK; 310 } 311 312 static int 313 pe_load_section (void *obj, Dwarf_Half section_index, 314 Dwarf_Small **return_data, int *error) 315 { 316 dwarf_pe_object_access_internals_t *pep = 317 (dwarf_pe_object_access_internals_t*)(obj); 318 319 if (0 < section_index && 320 section_index < pep->pe_section_count) { 321 int res = 0; 322 struct dwarf_pe_generic_image_section_header *sp = 323 pep->pe_sectionptr + section_index; 324 Dwarf_Unsigned read_length = 0; 325 326 if(sp->loaded_data) { 327 *return_data = sp->loaded_data; 328 return DW_DLV_OK; 329 } 330 if (!sp->VirtualSize) { 331 return DW_DLV_NO_ENTRY; 332 } 333 read_length = sp->SizeOfRawData; 334 if(sp->VirtualSize < read_length) { 335 /* Don't read padding that wasn't allocated in memory */ 336 read_length = sp->VirtualSize; 337 } 338 if ((read_length + sp->PointerToRawData) > 339 pep->pe_filesize) { 340 *error = DW_DLE_FILE_TOO_SMALL; 341 return DW_DLV_ERROR; 342 } 343 sp->loaded_data = malloc((size_t)sp->SizeOfRawData); 344 if(!sp->loaded_data) { 345 *error = DW_DLE_ALLOC_FAIL; 346 return DW_DLV_ERROR; 347 } 348 res = _dwarf_object_read_random(pep->pe_fd, 349 (char *)sp->loaded_data, 350 (off_t)sp->PointerToRawData, (size_t)read_length, 351 (off_t)pep->pe_filesize, 352 error); 353 if (res != DW_DLV_OK) { 354 free(sp->loaded_data); 355 sp->loaded_data = 0; 356 return res; 357 } 358 if(sp->VirtualSize > read_length) { 359 /* Zero space that was allocated but 360 truncated from the file */ 361 memset(sp->loaded_data + read_length, 0, 362 (size_t)(sp->VirtualSize - read_length)); 363 } 364 *return_data = sp->loaded_data; 365 return DW_DLV_OK; 366 } 367 return DW_DLV_NO_ENTRY; 368 } 369 370 void 371 _dwarf_destruct_pe_access( 372 struct Dwarf_Obj_Access_Interface_s *aip) 373 { 374 dwarf_pe_object_access_internals_t *pep = 0; 375 Dwarf_Unsigned i = 0; 376 377 if (!aip) { 378 return; 379 } 380 pep = (dwarf_pe_object_access_internals_t*)(aip->object); 381 if (pep->pe_destruct_close_fd) { 382 close(pep->pe_fd); 383 pep->pe_fd = -1; 384 } 385 free((char *)pep->pe_path); 386 pep->pe_path = 0; 387 if (pep->pe_sectionptr) { 388 struct dwarf_pe_generic_image_section_header *sp = 0; 389 390 sp = pep->pe_sectionptr; 391 for( i=0; i < pep->pe_section_count; ++i,++sp) { 392 if (sp->loaded_data) { 393 free(sp->loaded_data); 394 sp->loaded_data = 0; 395 } 396 free(sp->name); 397 sp->name = 0; 398 free(sp->dwarfsectname); 399 sp->dwarfsectname = 0; 400 } 401 free(pep->pe_sectionptr); 402 pep->pe_section_count = 0; 403 } 404 free(pep->pe_string_table); 405 pep->pe_string_table = 0; 406 free(pep); 407 free(aip); 408 return; 409 } 410 411 412 static int 413 dwarf_pe_load_dwarf_section_headers( 414 dwarf_pe_object_access_internals_t *pep,int *errcode) 415 { 416 Dwarf_Unsigned i = 0; 417 Dwarf_Unsigned input_count = 418 pep->pe_FileHeader.NumberOfSections; 419 Dwarf_Unsigned offset_in_input = pep->pe_section_table_offset; 420 Dwarf_Unsigned section_hdr_size = sizeof(IMAGE_SECTION_HEADER_dw); 421 struct dwarf_pe_generic_image_section_header *sec_outp = 0; 422 Dwarf_Unsigned cur_offset = offset_in_input; 423 Dwarf_Unsigned past_end_hdrs = offset_in_input + 424 section_hdr_size*input_count; 425 426 /* internal sections include null initial section */ 427 pep->pe_section_count = input_count+1; 428 429 if (past_end_hdrs > pep->pe_filesize) { 430 *errcode = DW_DLE_FILE_TOO_SMALL; 431 return DW_DLV_ERROR; 432 } 433 434 if (!offset_in_input) { 435 *errcode = DW_DLE_PE_OFFSET_BAD; 436 return DW_DLV_ERROR; 437 } 438 pep->pe_sectionptr = 439 (struct dwarf_pe_generic_image_section_header * ) 440 calloc((size_t)pep->pe_section_count, 441 sizeof(struct dwarf_pe_generic_image_section_header)); 442 443 444 445 if (!pep->pe_sectionptr) { 446 *errcode = DW_DLE_ALLOC_FAIL; 447 return DW_DLV_ERROR; 448 } 449 sec_outp = pep->pe_sectionptr; 450 sec_outp->name = strdup(""); 451 sec_outp->dwarfsectname = strdup(""); 452 sec_outp++; 453 for ( ; i < input_count; 454 ++i, cur_offset += section_hdr_size, sec_outp++) { 455 456 int res = 0; 457 IMAGE_SECTION_HEADER_dw filesect; 458 char safe_name[IMAGE_SIZEOF_SHORT_NAME +1]; 459 const char *expname = 0; 460 461 res = _dwarf_object_read_random(pep->pe_fd, 462 (char *)&filesect,(off_t)cur_offset, 463 sizeof(filesect), 464 (off_t)pep->pe_filesize, 465 errcode); 466 if (res != DW_DLV_OK) { 467 return res; 468 } 469 /* The following is safe. filesect.Name is 470 IMAGE_SIZEOF_SHORT_NAME bytes long and may 471 not (not sure) have a NUL terminator. */ 472 strncpy(safe_name,filesect.Name,IMAGE_SIZEOF_SHORT_NAME); 473 /* Then add NUL terminator. */ 474 safe_name[IMAGE_SIZEOF_SHORT_NAME] = 0; 475 sec_outp->name = strdup(safe_name); 476 res = pe_section_name_get(pep, 477 safe_name,&expname,errcode); 478 if (res != DW_DLV_OK) { 479 return res; 480 } 481 sec_outp->dwarfsectname = strdup(expname); 482 483 if ( !sec_outp->name || !sec_outp->dwarfsectname) { 484 *errcode = DW_DLE_ALLOC_FAIL; 485 return DW_DLV_ERROR; 486 } 487 sec_outp->SecHeaderOffset = cur_offset; 488 ASNAR(pep->pe_copy_word,sec_outp->VirtualSize, 489 filesect.Misc.VirtualSize); 490 ASNAR(pep->pe_copy_word,sec_outp->VirtualAddress, 491 filesect.VirtualAddress); 492 ASNAR(pep->pe_copy_word,sec_outp->SizeOfRawData, 493 filesect.SizeOfRawData); 494 ASNAR(pep->pe_copy_word,sec_outp->PointerToRawData, 495 filesect.PointerToRawData); 496 if(sec_outp->SizeOfRawData > pep->pe_filesize || 497 sec_outp->PointerToRawData > pep->pe_filesize || 498 (sec_outp->SizeOfRawData+ 499 sec_outp->PointerToRawData > pep->pe_filesize)) { 500 *errcode = DW_DLE_FILE_TOO_SMALL; 501 return DW_DLV_ERROR; 502 } 503 ASNAR(pep->pe_copy_word,sec_outp->PointerToRelocations, 504 filesect.PointerToRelocations); 505 ASNAR(pep->pe_copy_word,sec_outp->PointerToLinenumbers, 506 filesect.PointerToLinenumbers); 507 ASNAR(pep->pe_copy_word,sec_outp->NumberOfRelocations, 508 filesect.NumberOfRelocations); 509 ASNAR(pep->pe_copy_word,sec_outp->NumberOfLinenumbers, 510 filesect.NumberOfLinenumbers); 511 ASNAR(pep->pe_copy_word,sec_outp->Characteristics, 512 filesect.Characteristics); 513 /* sec_outp->loaded data set when we load a section */ 514 } 515 return DW_DLV_OK; 516 } 517 518 519 static int 520 dwarf_load_pe_sections( 521 dwarf_pe_object_access_internals_t *pep,int *errcode) 522 { 523 struct dos_header_dw dhinmem; 524 IMAGE_FILE_HEADER_dw ifh; 525 void (*word_swap) (void *, const void *, unsigned long); 526 unsigned locendian = 0; 527 int res = 0; 528 Dwarf_Unsigned dos_sig = 0; 529 Dwarf_Unsigned nt_address = 0; 530 char nt_sig_array[4]; 531 unsigned long nt_signature = 0; 532 533 if ( (sizeof(ifh) + sizeof(dhinmem)) >= pep->pe_filesize) { 534 /* corrupt object. */ 535 *errcode = DW_DLE_PE_SIZE_SMALL; 536 return DW_DLV_ERROR; 537 } 538 res = _dwarf_object_read_random(pep->pe_fd,(char *)&dhinmem, 539 0, sizeof(dhinmem),(off_t)pep->pe_filesize, errcode); 540 if (res != DW_DLV_OK) { 541 return res; 542 } 543 dos_sig = magic_copy((char *)dhinmem.dh_mz, 544 sizeof(dhinmem.dh_mz)); 545 if (dos_sig == IMAGE_DOS_SIGNATURE_dw) { 546 /* IMAGE_DOS_SIGNATURE_dw assumes bytes reversed by little-endian 547 load, so we intrepet a match the other way. */ 548 /* BIG ENDIAN. From looking at hex characters in object */ 549 #ifdef WORDS_BIGENDIAN 550 word_swap = _dwarf_memcpy_noswap_bytes; 551 #else /* LITTLE ENDIAN */ 552 word_swap = _dwarf_memcpy_swap_bytes; 553 #endif /* LITTLE- BIG-ENDIAN */ 554 locendian = DW_OBJECT_MSB; 555 } else if (dos_sig == IMAGE_DOS_REVSIGNATURE_dw) { 556 /* raw load, so intrepet a match the other way. */ 557 /* LITTLE ENDIAN */ 558 #ifdef WORDS_BIGENDIAN 559 word_swap = _dwarf_memcpy_swap_bytes; 560 #else /* LITTLE ENDIAN */ 561 word_swap = _dwarf_memcpy_noswap_bytes; 562 #endif /* LITTLE- BIG-ENDIAN */ 563 locendian = DW_OBJECT_LSB; 564 } else { 565 /* Not dos header not a PE file we recognize */ 566 *errcode = DW_DLE_FILE_WRONG_TYPE; 567 return DW_DLV_ERROR; 568 } 569 if (locendian != pep->pe_endian) { 570 /* Really this is a coding botch somewhere here, 571 not an object corruption. */ 572 *errcode = DW_DLE_FILE_WRONG_TYPE; 573 return DW_DLV_ERROR; 574 } 575 pep->pe_copy_word = word_swap; 576 ASNAR(word_swap,nt_address,dhinmem.dh_image_offset); 577 if (pep->pe_filesize < (nt_address + sizeof(nt_sig_array))) { 578 /* The nt_address is really a file offset. */ 579 *errcode = DW_DLE_FILE_TOO_SMALL; 580 /* Not dos header not a PE file we recognize */ 581 return DW_DLV_ERROR; 582 } 583 584 res = _dwarf_object_read_random(pep->pe_fd, 585 (char *)&nt_sig_array[0], 586 (off_t)nt_address, sizeof(nt_sig_array), 587 (off_t)pep->pe_filesize,errcode); 588 if (res != DW_DLV_OK) { 589 return res; 590 } 591 { unsigned long lsig = 0; 592 593 ASNAR(word_swap,lsig,nt_sig_array); 594 nt_signature = lsig; 595 } 596 if (nt_signature != IMAGE_NT_SIGNATURE_dw) { 597 *errcode = DW_DLE_FILE_WRONG_TYPE; 598 return DW_DLV_ERROR; 599 } 600 601 pep->pe_nt_header_offset = nt_address + SIZEOFT32; 602 if (pep->pe_filesize < (pep->pe_nt_header_offset + 603 sizeof(ifh))) { 604 *errcode = DW_DLE_FILE_TOO_SMALL; 605 /* Not image header not a PE file we recognize */ 606 return DW_DLV_ERROR; 607 } 608 res = _dwarf_object_read_random(pep->pe_fd,(char *)&ifh, 609 (off_t)pep->pe_nt_header_offset, sizeof(ifh), 610 (off_t)pep->pe_filesize,errcode); 611 if (res != DW_DLV_OK) { 612 return res; 613 } 614 ASNAR(word_swap,pep->pe_FileHeader.Machine,ifh.Machine); 615 ASNAR(word_swap,pep->pe_FileHeader.NumberOfSections, 616 ifh.NumberOfSections); 617 ASNAR(word_swap,pep->pe_FileHeader.TimeDateStamp, 618 ifh.TimeDateStamp); 619 ASNAR(word_swap,pep->pe_FileHeader.PointerToSymbolTable, 620 ifh.PointerToSymbolTable); 621 ASNAR(word_swap,pep->pe_FileHeader.NumberOfSymbols, 622 ifh.NumberOfSymbols); 623 ASNAR(word_swap,pep->pe_FileHeader.SizeOfOptionalHeader, 624 ifh.SizeOfOptionalHeader); 625 ASNAR(word_swap,pep->pe_FileHeader.Characteristics, 626 ifh.Characteristics); 627 628 pep->pe_optional_header_offset = pep->pe_nt_header_offset+ 629 sizeof(ifh); 630 if (pep->pe_offsetsize == 32) { 631 res = load_optional_header32(pep, 632 pep->pe_optional_header_offset,errcode); 633 pep->pe_optional_header_size = sizeof(IMAGE_OPTIONAL_HEADER32_dw); 634 } else if (pep->pe_offsetsize == 64) { 635 res = load_optional_header64(pep, 636 pep->pe_optional_header_offset,errcode); 637 pep->pe_optional_header_size = sizeof(IMAGE_OPTIONAL_HEADER64_dw); 638 } else { 639 *errcode = DW_DLE_OFFSET_SIZE; 640 return DW_DLV_ERROR; 641 } 642 if (res != DW_DLV_OK) { 643 return res; 644 } 645 646 pep->pe_section_table_offset = pep->pe_optional_header_offset 647 + pep->pe_optional_header_size; 648 pep->pe_symbol_table_offset = 649 pep->pe_FileHeader.PointerToSymbolTable; 650 if (pep->pe_symbol_table_offset >= pep->pe_filesize) { 651 *errcode = DW_DLE_OFFSET_SIZE; 652 return DW_DLV_ERROR; 653 } 654 if (pep->pe_symbol_table_offset) { 655 pep->pe_string_table_offset = 656 pep->pe_symbol_table_offset + 657 (pep->pe_FileHeader.NumberOfSymbols * 658 IMAGE_SIZEOF_SYMBOL); 659 } 660 661 if (pep->pe_string_table_offset >= pep->pe_filesize) { 662 *errcode = DW_DLE_OFFSET_SIZE; 663 pep->pe_string_table_size = 0; 664 return DW_DLV_ERROR; 665 } 666 if (pep->pe_string_table_offset) { 667 /* https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#coff-string-table */ 668 /* The first 4 bytes of the string table contain 669 the size of the string table. */ 670 char size_field[4]; 671 672 if ((pep->pe_string_table_offset+sizeof(size_field)) > 673 pep->pe_filesize) { 674 *errcode = DW_DLE_FILE_TOO_SMALL; 675 return DW_DLV_ERROR; 676 } 677 memset(size_field,0,sizeof(size_field)); 678 res = _dwarf_object_read_random(pep->pe_fd, 679 (char *)size_field, (off_t)pep->pe_string_table_offset, 680 sizeof(size_field), 681 (off_t)pep->pe_filesize,errcode); 682 if (res != DW_DLV_OK) { 683 return res; 684 } 685 ASNAR(pep->pe_copy_word,pep->pe_string_table_size, 686 size_field); 687 if( pep->pe_string_table_size >= pep->pe_filesize ) { 688 *errcode = DW_DLE_PE_OFFSET_BAD; 689 return DW_DLV_ERROR; 690 } 691 if ((pep->pe_string_table_offset+pep->pe_string_table_size) > 692 pep->pe_filesize) { 693 *errcode = DW_DLE_FILE_TOO_SMALL; 694 return DW_DLV_ERROR; 695 } 696 pep->pe_string_table = 697 (char *)malloc((size_t)pep->pe_string_table_size); 698 if (!pep->pe_string_table) { 699 *errcode = DW_DLE_ALLOC_FAIL; 700 return DW_DLV_ERROR; 701 } 702 res = _dwarf_object_read_random(pep->pe_fd, 703 (char *)pep->pe_string_table, (off_t)pep->pe_string_table_offset, 704 (size_t)pep->pe_string_table_size, 705 (off_t)pep->pe_filesize,errcode); 706 if (res != DW_DLV_OK) { 707 return res; 708 } 709 } 710 res = dwarf_pe_load_dwarf_section_headers(pep,errcode); 711 return res; 712 } 713 714 int 715 _dwarf_pe_setup(int fd, 716 char *true_path, 717 unsigned ftype, 718 unsigned endian, 719 unsigned offsetsize, 720 size_t filesize, 721 Dwarf_Unsigned access, 722 unsigned groupnumber, 723 Dwarf_Handler errhand, 724 Dwarf_Ptr errarg, 725 Dwarf_Debug *dbg,Dwarf_Error *error) 726 { 727 Dwarf_Obj_Access_Interface *binary_interface = 0; 728 dwarf_pe_object_access_internals_t *pep = 0; 729 int res = DW_DLV_OK; 730 int localerrnum = 0; 731 732 res = _dwarf_pe_object_access_init( 733 fd, 734 ftype,endian,offsetsize,filesize,access, 735 &binary_interface, 736 &localerrnum); 737 if (res != DW_DLV_OK) { 738 if (res == DW_DLV_NO_ENTRY) { 739 return res; 740 } 741 _dwarf_error(NULL, error, localerrnum); 742 return DW_DLV_ERROR; 743 } 744 /* allocates and initializes Dwarf_Debug, 745 generic code */ 746 res = dwarf_object_init_b(binary_interface, errhand, errarg, 747 groupnumber, dbg, error); 748 if (res != DW_DLV_OK){ 749 _dwarf_destruct_pe_access(binary_interface); 750 return res; 751 } 752 pep = binary_interface->object; 753 pep->pe_path = strdup(true_path); 754 return res; 755 } 756 757 static Dwarf_Obj_Access_Methods pe_methods = { 758 pe_get_section_info, 759 pe_get_byte_order, 760 pe_get_length_size, 761 pe_get_pointer_size, 762 pe_get_section_count, 763 pe_load_section, 764 0 /* ignore pe relocations. */ 765 }; 766 767 /* On any error this frees internals. */ 768 static int 769 _dwarf_pe_object_access_internals_init( 770 dwarf_pe_object_access_internals_t * internals, 771 int fd, 772 unsigned ftype, 773 unsigned endian, 774 unsigned offsetsize, 775 size_t filesize, 776 UNUSEDARG Dwarf_Unsigned access, 777 int *errcode) 778 { 779 dwarf_pe_object_access_internals_t * intfc = internals; 780 struct Dwarf_Obj_Access_Interface_s *localdoas = 0; 781 int res = 0; 782 783 /* Must malloc as _dwarf_destruct_pe_access() 784 forces that due to other uses. */ 785 localdoas = (struct Dwarf_Obj_Access_Interface_s *) 786 malloc(sizeof(struct Dwarf_Obj_Access_Interface_s)); 787 if (!localdoas) { 788 free(internals); 789 *errcode = DW_DLE_ALLOC_FAIL; 790 return DW_DLV_ERROR; 791 } 792 memset(localdoas,0,sizeof(struct Dwarf_Obj_Access_Interface_s)); 793 intfc->pe_ident[0] = 'P'; 794 intfc->pe_ident[1] = '1'; 795 intfc->pe_fd = fd; 796 intfc->pe_is_64bit = ((offsetsize==64)?TRUE:FALSE); 797 intfc->pe_offsetsize = offsetsize; 798 intfc->pe_pointersize = offsetsize; 799 intfc->pe_filesize = filesize; 800 intfc->pe_ftype = ftype; 801 /* pe_path set by caller */ 802 803 #ifdef WORDS_BIGENDIAN 804 if (endian == DW_ENDIAN_LITTLE ) { 805 intfc->pe_copy_word = _dwarf_memcpy_swap_bytes; 806 intfc->pe_endian = DW_OBJECT_LSB; 807 } else { 808 intfc->pe_copy_word = _dwarf_memcpy_noswap_bytes; 809 intfc->pe_endian = DW_OBJECT_MSB; 810 } 811 #else /* LITTLE ENDIAN */ 812 if (endian == DW_ENDIAN_LITTLE ) { 813 intfc->pe_copy_word = _dwarf_memcpy_noswap_bytes; 814 intfc->pe_endian = DW_OBJECT_LSB; 815 } else { 816 intfc->pe_copy_word = _dwarf_memcpy_swap_bytes; 817 intfc->pe_endian = DW_OBJECT_MSB; 818 } 819 #endif /* LITTLE- BIG-ENDIAN */ 820 res = dwarf_load_pe_sections(intfc,errcode); 821 if (res != DW_DLV_OK) { 822 localdoas->object = intfc; 823 localdoas->methods = 0; 824 _dwarf_destruct_pe_access(localdoas); 825 localdoas = 0; 826 return res; 827 } 828 free(localdoas); 829 localdoas = 0; 830 return DW_DLV_OK; 831 } 832 833 834 static int 835 _dwarf_pe_object_access_init( 836 int fd, 837 unsigned ftype, 838 unsigned endian, 839 unsigned offsetsize, 840 size_t filesize, 841 Dwarf_Unsigned access, 842 Dwarf_Obj_Access_Interface **binary_interface, 843 int *localerrnum) 844 { 845 846 int res = 0; 847 dwarf_pe_object_access_internals_t *internals = 0; 848 Dwarf_Obj_Access_Interface *intfc = 0; 849 850 internals = malloc(sizeof(dwarf_pe_object_access_internals_t)); 851 if (!internals) { 852 *localerrnum = DW_DLE_ALLOC_FAIL; 853 /* Impossible case, we hope. Give up. */ 854 return DW_DLV_ERROR; 855 } 856 memset(internals,0,sizeof(*internals)); 857 res = _dwarf_pe_object_access_internals_init(internals, 858 fd, 859 ftype, endian, offsetsize, filesize, 860 access, 861 localerrnum); 862 if (res != DW_DLV_OK){ 863 /* *err is already set. and the call freed internals */ 864 return DW_DLV_ERROR; 865 } 866 867 intfc = malloc(sizeof(Dwarf_Obj_Access_Interface)); 868 if (!intfc) { 869 /* Impossible case, we hope. Give up. */ 870 free(internals); 871 *localerrnum = DW_DLE_ALLOC_FAIL; 872 return DW_DLV_ERROR; 873 } 874 /* Initialize the interface struct */ 875 intfc->object = internals; 876 intfc->methods = &pe_methods; 877 *binary_interface = intfc; 878 return DW_DLV_OK; 879 } 880