Changeset 331 for EcnlProtoTool/trunk/tcc-0.9.27/tccpe.c
- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/tcc-0.9.27
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/tcc-0.9.27/tccpe.c
r321 r331 21 21 #include "tcc.h" 22 22 23 #define PE_MERGE_DATA 24 /* #define PE_PRINT_SECTIONS */ 25 23 26 #ifndef _WIN32 24 27 #define stricmp strcasecmp 25 28 #define strnicmp strncasecmp 26 #endif 27 28 #ifndef MAX_PATH 29 #define MAX_PATH 260 30 #endif 31 32 #define PE_MERGE_DATA 33 // #define PE_PRINT_SECTIONS 29 #include <sys/stat.h> /* chmod() */ 30 #endif 34 31 35 32 #ifdef TCC_TARGET_X86_64 36 33 # define ADDR3264 ULONGLONG 37 #else 34 # define PE_IMAGE_REL IMAGE_REL_BASED_DIR64 35 # define REL_TYPE_DIRECT R_X86_64_64 36 # define R_XXX_THUNKFIX R_X86_64_PC32 37 # define R_XXX_RELATIVE R_X86_64_RELATIVE 38 # define IMAGE_FILE_MACHINE 0x8664 39 # define RSRC_RELTYPE 3 40 41 #elif defined TCC_TARGET_ARM 38 42 # define ADDR3264 DWORD 39 #endif 40 41 #ifdef _WIN32 42 void dbg_printf (const char *fmt, ...) 43 { 44 char buffer[4000]; 45 va_list arg; 46 int x; 47 va_start(arg, fmt); 48 x = vsprintf (buffer, fmt, arg); 49 strcpy(buffer+x, "\n"); 50 OutputDebugString(buffer); 51 } 52 #endif 53 54 /* ----------------------------------------------------------- */ 43 # define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW 44 # define REL_TYPE_DIRECT R_ARM_ABS32 45 # define R_XXX_THUNKFIX R_ARM_ABS32 46 # define R_XXX_RELATIVE R_ARM_RELATIVE 47 # define IMAGE_FILE_MACHINE 0x01C0 48 # define RSRC_RELTYPE 7 /* ??? (not tested) */ 49 50 #elif defined TCC_TARGET_I386 51 # define ADDR3264 DWORD 52 # define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW 53 # define REL_TYPE_DIRECT R_386_32 54 # define R_XXX_THUNKFIX R_386_32 55 # define R_XXX_RELATIVE R_386_RELATIVE 56 # define IMAGE_FILE_MACHINE 0x014C 57 # define RSRC_RELTYPE 7 /* DIR32NB */ 58 59 #endif 60 55 61 #ifndef IMAGE_NT_SIGNATURE 56 62 /* ----------------------------------------------------------- */ … … 224 230 #define IMAGE_REL_BASED_SECTION 6 225 231 #define IMAGE_REL_BASED_REL32 7 232 #define IMAGE_REL_BASED_DIR64 10 226 233 227 234 #pragma pack(pop) … … 230 237 #endif /* ndef IMAGE_NT_SIGNATURE */ 231 238 /* ----------------------------------------------------------- */ 239 240 #ifndef IMAGE_REL_BASED_DIR64 241 # define IMAGE_REL_BASED_DIR64 10 242 #endif 243 232 244 #pragma pack(push, 1) 233 234 245 struct pe_header 235 246 { … … 264 275 WORD type; 265 276 }; 266 267 277 #pragma pack(pop) 268 278 … … 337 347 DWORD sizeofheaders; 338 348 ADDR3264 imagebase; 349 const char *start_symbol; 339 350 DWORD start_addr; 340 351 DWORD imp_offs; … … 363 374 static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym) 364 375 { 365 const char *name = symtab_section->link->data + sym->st_name;366 if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & 2))376 const char *name = (char*)symtab_section->link->data + sym->st_name; 377 if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL)) 367 378 return name + 1; 368 379 return name; … … 374 385 const char *s, *p; 375 386 int sym_index = 0, n = 0; 387 int a, err = 0; 376 388 377 389 do { 378 390 s = pe_export_name(s1, sym); 391 a = 0; 379 392 if (n) { 380 393 /* second try: */ 381 if (sym->st_other & 2) {394 if (sym->st_other & ST_PE_STDCALL) { 382 395 /* try w/0 stdcall deco (windows API convention) */ 383 396 p = strrchr(s, '@'); … … 387 400 } else if (s[0] != '_') { /* try non-ansi function */ 388 401 buffer[0] = '_', strcpy(buffer + 1, s); 389 } else if (0 == memcmp(s, "__imp_ _", 7)) { /* mingw 2.0 */390 strcpy(buffer, s + 6) ;391 } else if (0 == memcmp(s, "_imp__ _", 7)) { /* mingw 3.7 */392 strcpy(buffer, s + 6) ;402 } else if (0 == memcmp(s, "__imp_", 6)) { /* mingw 2.0 */ 403 strcpy(buffer, s + 6), a = 1; 404 } else if (0 == memcmp(s, "_imp__", 6)) { /* mingw 3.7 */ 405 strcpy(buffer, s + 6), a = 1; 393 406 } else { 394 break;407 continue; 395 408 } 396 409 s = buffer; … … 398 411 sym_index = find_elf_sym(s1->dynsymtab_section, s); 399 412 // printf("find (%d) %d %s\n", n, sym_index, s); 413 if (sym_index 414 && ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT 415 && 0 == (sym->st_other & ST_PE_IMPORT) 416 && 0 == a 417 ) err = -1, sym_index = 0; 400 418 } while (0 == sym_index && ++n < 2); 401 return sym_index;419 return n == 2 ? err : sym_index; 402 420 } 403 421 … … 508 526 { 509 527 /* IMAGE_FILE_HEADER filehdr */ 510 #if defined(TCC_TARGET_I386) 511 0x014C, /*WORD Machine; */ 512 #elif defined(TCC_TARGET_X86_64) 513 0x8664, /*WORD Machine; */ 514 #elif defined(TCC_TARGET_ARM) 515 0x01C0, /*WORD Machine; */ 516 #endif 528 IMAGE_FILE_MACHINE, /*WORD Machine; */ 517 529 0x0003, /*WORD NumberOfSections; */ 518 530 0x00000000, /*DWORD TimeDateStamp; */ … … 623 635 case sec_text: 624 636 pe_header.opthdr.BaseOfCode = addr; 625 pe_header.opthdr.AddressOfEntryPoint = addr + pe->start_addr;626 637 break; 627 638 … … 664 675 } 665 676 666 pstrcpy((char*)psh->Name, sizeof psh->Name, sh_name);677 strncpy((char*)psh->Name, sh_name, sizeof psh->Name); 667 678 668 679 psh->Characteristics = pe_sec_flags[si->cls]; … … 676 687 file_offset = pe_file_align(pe, file_offset + si->data_size); 677 688 psh->SizeOfRawData = file_offset - psh->PointerToRawData; 689 if (si->cls == sec_text) 690 pe_header.opthdr.SizeOfCode += psh->SizeOfRawData; 691 else 692 pe_header.opthdr.SizeOfInitializedData += psh->SizeOfRawData; 678 693 } 679 694 } … … 681 696 //pe_header.filehdr.TimeDateStamp = time(NULL); 682 697 pe_header.filehdr.NumberOfSections = pe->sec_count; 698 pe_header.opthdr.AddressOfEntryPoint = pe->start_addr; 683 699 pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders; 684 700 pe_header.opthdr.ImageBase = pe->imagebase; … … 688 704 if (PE_DLL == pe->type) 689 705 pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL; 706 pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics; 690 707 691 708 sum = 0; … … 708 725 pe_fwrite(&pe_header.opthdr.CheckSum, sizeof pe_header.opthdr.CheckSum, op, NULL); 709 726 fclose (op); 727 #ifndef _WIN32 728 chmod(pe->filename, 0777); 729 #endif 710 730 711 731 if (2 == pe->s1->verbose) … … 717 737 } 718 738 719 /*----------------------------------------------------------------------------*/720 721 #if defined(TCC_TARGET_X86_64)722 #define REL_TYPE_DIRECT R_X86_64_64723 #define R_XXX_THUNKFIX R_X86_64_PC32724 #define R_XXX_RELATIVE R_X86_64_RELATIVE725 726 #elif defined(TCC_TARGET_I386)727 #define REL_TYPE_DIRECT R_386_32728 #define R_XXX_THUNKFIX R_386_32729 #define R_XXX_RELATIVE R_386_RELATIVE730 731 #elif defined(TCC_TARGET_ARM)732 #define REL_TYPE_DIRECT R_ARM_ABS32733 #define R_XXX_THUNKFIX R_ARM_ABS32734 #define R_XXX_RELATIVE R_ARM_RELATIVE735 736 #endif737 739 /*----------------------------------------------------------------------------*/ 738 740 … … 755 757 p = tcc_mallocz(sizeof *p); 756 758 p->dll_index = dll_index; 757 dynarray_add( (void***)&pe->imp_info, &pe->imp_count, p);759 dynarray_add(&pe->imp_info, &pe->imp_count, p); 758 760 759 761 found_dll: … … 763 765 764 766 s = tcc_mallocz(sizeof *s); 765 dynarray_add( (void***)&p->symbols, &p->sym_count, s);767 dynarray_add(&p->symbols, &p->sym_count, s); 766 768 s->sym_index = sym_index; 767 769 return s; 770 } 771 772 void pe_free_imports(struct pe_info *pe) 773 { 774 int i; 775 for (i = 0; i < pe->imp_count; ++i) { 776 struct pe_import_info *p = pe->imp_info[i]; 777 dynarray_reset(&p->symbols, &p->sym_count); 778 } 779 dynarray_reset(&pe->imp_info, &pe->imp_count); 768 780 } 769 781 … … 819 831 ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index; 820 832 ElfW(Sym) *org_sym = (ElfW(Sym) *)symtab_section->data + iat_index; 821 const char *name = pe->s1->dynsymtab_section->link->data + imp_sym->st_name; 833 const char *name = (char*)pe->s1->dynsymtab_section->link->data + imp_sym->st_name; 834 int ordinal; 822 835 823 836 org_sym->st_value = thk_ptr; 824 837 org_sym->st_shndx = pe->thunk->sh_num; 825 v = pe->thunk->data_offset + rva_base; 826 section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */ 827 put_elf_str(pe->thunk, name); 838 839 if (dllref) 840 v = 0, ordinal = imp_sym->st_value; /* ordinal from pe_load_def */ 841 else 842 ordinal = 0, v = imp_sym->st_value; /* address from tcc_add_symbol() */ 843 828 844 #ifdef TCC_IS_NATIVE 829 845 if (pe->type == PE_RUN) { 830 v = imp_sym->st_value;831 846 if (dllref) { 832 847 if ( !dllref->handle ) 833 848 dllref->handle = LoadLibrary(dllref->name); 834 v = (ADDR3264)GetProcAddress(dllref->handle, name);849 v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(char*)0+ordinal:name); 835 850 } 836 851 if (!v) 837 tcc_error_noabort("undefined symbol '%s'", name); 852 tcc_error_noabort("can't build symbol '%s'", name); 853 } else 854 #endif 855 if (ordinal) { 856 v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1); 857 } else { 858 v = pe->thunk->data_offset + rva_base; 859 section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */ 860 put_elf_str(pe->thunk, name); 838 861 } 839 #endif 862 840 863 } else { 841 864 v = 0; /* last entry is zero */ 842 865 } 866 843 867 *(ADDR3264*)(pe->thunk->data+thk_ptr) = 844 868 *(ADDR3264*)(pe->thunk->data+ent_ptr) = v; … … 847 871 } 848 872 dll_ptr += sizeof(IMAGE_IMPORT_DESCRIPTOR); 849 dynarray_reset(&p->symbols, &p->sym_count); 850 } 851 dynarray_reset(&pe->imp_info, &pe->imp_count); 873 } 852 874 } 853 875 … … 877 899 878 900 FILE *op; 879 char buf[ MAX_PATH];901 char buf[260]; 880 902 const char *dllname; 881 903 const char *name; … … 888 910 sym = (ElfW(Sym)*)symtab_section->data + sym_index; 889 911 name = pe_export_name(pe->s1, sym); 890 if ((sym->st_other & 1)912 if ((sym->st_other & ST_PE_EXPORT) 891 913 /* export only symbols from actually written sections */ 892 914 && pe->s1->sections[sym->st_shndx]->sh_addr) { … … 894 916 p->index = sym_index; 895 917 p->name = name; 896 dynarray_add( (void***)&sorted, &sym_count, p);918 dynarray_add(&sorted, &sym_count, p); 897 919 } 898 920 #if 0 899 if (sym->st_other & 1)921 if (sym->st_other & ST_PE_EXPORT) 900 922 printf("export: %s\n", name); 901 if (sym->st_other & 2)923 if (sym->st_other & ST_PE_STDCALL) 902 924 printf("stdcall: %s\n", name); 903 925 #endif … … 933 955 pstrcpy(buf, sizeof buf, pe->filename); 934 956 strcpy(tcc_fileextension(buf), ".def"); 935 op = fopen(buf, "w ");957 op = fopen(buf, "wb"); 936 958 if (NULL == op) { 937 959 tcc_error_noabort("could not create '%s': %s", buf, strerror(errno)); … … 939 961 fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname); 940 962 if (pe->s1->verbose) 941 printf("<- %s (%d symbol s)\n", buf, sym_count);963 printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]); 942 964 } 943 965 #endif … … 946 968 { 947 969 p = sorted[ord], sym_index = p->index, name = p->name; 948 /* insert actual address later in pe_relocate_rva*/970 /* insert actual address later in relocate_section() */ 949 971 put_elf_reloc(symtab_section, pe->thunk, 950 972 func_o, R_XXX_RELATIVE, sym_index); … … 991 1013 if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */ 992 1014 WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD)); 993 *wp = addr | IMAGE_REL_BASED_HIGHLOW<<12;1015 *wp = addr | PE_IMAGE_REL<<12; 994 1016 ++count; 995 1017 continue; … … 1065 1087 Section *s; 1066 1088 1089 if (PE_DLL == pe->type) 1090 pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0); 1091 1067 1092 // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC); 1068 1093 … … 1157 1182 } 1158 1183 1159 /* ------------------------------------------------------------- */1160 static void pe_relocate_rva (struct pe_info *pe, Section *s)1161 {1162 Section *sr = s->reloc;1163 ElfW_Rel *rel, *rel_end;1164 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);1165 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {1166 if (ELFW(R_TYPE)(rel->r_info) == R_XXX_RELATIVE) {1167 int sym_index = ELFW(R_SYM)(rel->r_info);1168 DWORD addr = s->sh_addr;1169 if (sym_index) {1170 ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;1171 addr = sym->st_value;1172 }1173 // printf("reloc rva %08x %08x %s\n", (DWORD)rel->r_offset, addr, s->name);1174 *(DWORD*)(s->data + rel->r_offset) += addr - pe->imagebase;1175 }1176 }1177 }1178 1179 1184 /*----------------------------------------------------------------------------*/ 1180 1185 … … 1208 1213 if (sym->st_shndx == SHN_UNDEF) { 1209 1214 1210 const char *name = symtab_section->link->data + sym->st_name;1215 const char *name = (char*)symtab_section->link->data + sym->st_name; 1211 1216 unsigned type = ELFW(ST_TYPE)(sym->st_info); 1212 1217 int imp_sym = pe_find_import(pe->s1, sym); 1213 1218 struct import_symbol *is; 1214 1219 1215 if ( 0 == imp_sym)1220 if (imp_sym <= 0) 1216 1221 goto not_found; 1217 1222 … … 1271 1276 sym->st_value = offset; 1272 1277 sym->st_shndx = text_section->sh_num; 1273 sym->st_other &= ~ 1; /* do not export */1278 sym->st_other &= ~ST_PE_EXPORT; /* do not export */ 1274 1279 continue; 1275 1280 } … … 1284 1289 1285 1290 not_found: 1286 tcc_error_noabort("undefined symbol '%s'", name); 1291 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) 1292 /* STB_WEAK undefined symbols are accepted */ 1293 continue; 1294 tcc_error_noabort("undefined symbol '%s'%s", name, 1295 imp_sym < 0 ? ", missing __declspec(dllimport)?":""); 1287 1296 ret = -1; 1288 1297 … … 1290 1299 && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { 1291 1300 /* if -rdynamic option, then export all non local symbols */ 1292 sym->st_other |= 1;1301 sym->st_other |= ST_PE_EXPORT; 1293 1302 } 1294 1303 } … … 1300 1309 static void pe_print_section(FILE * f, Section * s) 1301 1310 { 1302 /* just if you'r curious */1311 /* just if you're curious */ 1303 1312 BYTE *p, *e, b; 1304 1313 int i, n, l, m; … … 1438 1447 /* helper function for load/store to insert one more indirection */ 1439 1448 1449 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 1440 1450 ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2) 1441 1451 { 1442 Sym *sym;1443 ElfW(Sym) *esym;1444 1452 int r2; 1445 1446 1453 if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST)) 1447 1454 return sv; 1448 sym = sv->sym; 1449 if ((sym->type.t & (VT_EXTERN|VT_STATIC)) != VT_EXTERN) 1455 if (!sv->sym->a.dllimport) 1450 1456 return sv; 1451 if (!sym->c) 1452 put_extern_sym(sym, NULL, 0, 0); 1453 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; 1454 if (!(esym->st_other & 4)) 1455 return sv; 1456 1457 // printf("import %04x %04x %04x %s\n", sv->type.t, sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL)); 1458 1457 // printf("import %04x %04x %04x %s\n", sv->type.t, sv->sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL)); 1459 1458 memset(v2, 0, sizeof *v2); 1460 1459 v2->type.t = VT_PTR; … … 1465 1464 load(r2, v2); 1466 1465 v2->r = r2; 1467 1468 if (sv->c.ui) { 1466 if ((uint32_t)sv->c.i) { 1469 1467 vpushv(v2); 1470 vpushi(sv->c. ui);1468 vpushi(sv->c.i); 1471 1469 gen_opi('+'); 1472 1470 *v2 = *vtop--; 1473 1471 } 1474 1475 1472 v2->type.t = sv->type.t; 1476 1473 v2->r |= sv->r & VT_LVAL; 1477 1474 return v2; 1478 1475 } 1476 #endif 1479 1477 1480 1478 ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value) 1481 1479 { 1482 return add_elf_sym(1480 return set_elf_sym( 1483 1481 s1->dynsymtab_section, 1484 1482 value, … … 1500 1498 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname)); 1501 1499 strcpy(dllref->name, dllname); 1502 dynarray_add( (void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);1500 dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); 1503 1501 return s1->nb_loaded_dlls; 1504 1502 } … … 1510 1508 lseek(fd, offset, SEEK_SET); 1511 1509 return len == read(fd, buffer, len); 1510 } 1511 1512 /* ------------------------------------------------------------- */ 1513 1514 PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) 1515 { 1516 int l, i, n, n0, ret; 1517 char *p; 1518 int fd; 1519 1520 IMAGE_SECTION_HEADER ish; 1521 IMAGE_EXPORT_DIRECTORY ied; 1522 IMAGE_DOS_HEADER dh; 1523 IMAGE_FILE_HEADER ih; 1524 DWORD sig, ref, addr, ptr, namep; 1525 1526 int pef_hdroffset, opt_hdroffset, sec_hdroffset; 1527 1528 n = n0 = 0; 1529 p = NULL; 1530 ret = -1; 1531 1532 fd = open(filename, O_RDONLY | O_BINARY); 1533 if (fd < 0) 1534 goto the_end_1; 1535 ret = 1; 1536 if (!read_mem(fd, 0, &dh, sizeof dh)) 1537 goto the_end; 1538 if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig)) 1539 goto the_end; 1540 if (sig != 0x00004550) 1541 goto the_end; 1542 pef_hdroffset = dh.e_lfanew + sizeof sig; 1543 if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) 1544 goto the_end; 1545 opt_hdroffset = pef_hdroffset + sizeof ih; 1546 if (ih.Machine == 0x014C) { 1547 IMAGE_OPTIONAL_HEADER32 oh; 1548 sec_hdroffset = opt_hdroffset + sizeof oh; 1549 if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) 1550 goto the_end; 1551 if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) 1552 goto the_end_0; 1553 addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 1554 } else if (ih.Machine == 0x8664) { 1555 IMAGE_OPTIONAL_HEADER64 oh; 1556 sec_hdroffset = opt_hdroffset + sizeof oh; 1557 if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) 1558 goto the_end; 1559 if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) 1560 goto the_end_0; 1561 addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 1562 } else 1563 goto the_end; 1564 1565 //printf("addr: %08x\n", addr); 1566 for (i = 0; i < ih.NumberOfSections; ++i) { 1567 if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) 1568 goto the_end; 1569 //printf("vaddr: %08x\n", ish.VirtualAddress); 1570 if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData) 1571 goto found; 1572 } 1573 goto the_end_0; 1574 1575 found: 1576 ref = ish.VirtualAddress - ish.PointerToRawData; 1577 if (!read_mem(fd, addr - ref, &ied, sizeof ied)) 1578 goto the_end; 1579 1580 namep = ied.AddressOfNames - ref; 1581 for (i = 0; i < ied.NumberOfNames; ++i) { 1582 if (!read_mem(fd, namep, &ptr, sizeof ptr)) 1583 goto the_end; 1584 namep += sizeof ptr; 1585 for (l = 0;;) { 1586 if (n+1 >= n0) 1587 p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256); 1588 if (!read_mem(fd, ptr - ref + l++, p + n, 1)) { 1589 tcc_free(p), p = NULL; 1590 goto the_end; 1591 } 1592 if (p[n++] == 0) 1593 break; 1594 } 1595 } 1596 if (p) 1597 p[n] = 0; 1598 the_end_0: 1599 ret = 0; 1600 the_end: 1601 close(fd); 1602 the_end_1: 1603 *pp = p; 1604 return ret; 1512 1605 } 1513 1606 … … 1521 1614 struct pe_rsrc_header hdr; 1522 1615 Section *rsrc_section; 1523 int i, ret = -1 ;1616 int i, ret = -1, sym_index; 1524 1617 BYTE *ptr; 1525 1618 unsigned offs; … … 1528 1621 goto quit; 1529 1622 1530 if (hdr.filehdr.Machine != 0x014C1623 if (hdr.filehdr.Machine != IMAGE_FILE_MACHINE 1531 1624 || hdr.filehdr.NumberOfSections != 1 1532 || strcmp( hdr.sectionhdr.Name, ".rsrc") != 0)1625 || strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0) 1533 1626 goto quit; 1534 1627 … … 1539 1632 goto quit; 1540 1633 offs = hdr.sectionhdr.PointerToRelocations; 1541 for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)1542 {1634 sym_index = put_elf_sym(symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc"); 1635 for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) { 1543 1636 struct pe_rsrc_reloc rel; 1544 1637 if (!read_mem(fd, offs, &rel, sizeof rel)) 1545 1638 goto quit; 1546 1639 // printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type); 1547 if (rel.type != 7) /* DIR32NB */1640 if (rel.type != RSRC_RELTYPE) 1548 1641 goto quit; 1549 1642 put_elf_reloc(symtab_section, rsrc_section, 1550 rel.offset, R_XXX_RELATIVE, 0);1643 rel.offset, R_XXX_RELATIVE, sym_index); 1551 1644 offs += sizeof rel; 1552 1645 } … … 1557 1650 1558 1651 /* ------------------------------------------------------------- */ 1652 1559 1653 static char *trimfront(char *p) 1560 1654 { 1561 1655 while (*p && (unsigned char)*p <= ' ') 1562 1656 ++p; 1563 1657 return p; 1564 1658 } … … 1567 1661 { 1568 1662 while (e > a && (unsigned char)e[-1] <= ' ') 1569 1663 --e; 1570 1664 *e = 0;; 1571 1665 return a; 1572 1666 } 1573 1667 1574 static char *get_line(char *line, int size, int fd)1575 {1576 int n;1577 for (n = 0; n < size - 1; )1578 if (read(fd, line + n, 1) < 1 || line[n++] == '\n')1579 break;1580 if (0 == n)1581 return NULL;1582 trimback(line, line + n);1583 return trimfront(line);1584 }1585 1586 1668 /* ------------------------------------------------------------- */ 1587 1669 static int pe_load_def(TCCState *s1, int fd) 1588 1670 { 1589 int state = 0, ret = -1, dllindex = 0; 1590 char line[400], dllname[80], *p; 1591 1592 for (;;) { 1593 p = get_line(line, sizeof line, fd); 1594 if (NULL == p) 1595 break; 1671 int state = 0, ret = -1, dllindex = 0, ord; 1672 char line[400], dllname[80], *p, *x; 1673 FILE *fp; 1674 1675 fp = fdopen(dup(fd), "rb"); 1676 while (fgets(line, sizeof line, fp)) 1677 { 1678 p = trimfront(trimback(line, strchr(line, 0))); 1596 1679 if (0 == *p || ';' == *p) 1597 1680 continue; 1681 1598 1682 switch (state) { 1599 1683 case 0: … … 1613 1697 dllindex = add_dllref(s1, dllname); 1614 1698 ++state; 1615 1699 /* fall through */ 1616 1700 default: 1617 pe_putimport(s1, dllindex, p, 0); 1701 /* get ordinal and will store in sym->st_value */ 1702 ord = 0; 1703 x = strchr(p, ' '); 1704 if (x) { 1705 *x = 0, x = strrchr(x + 1, '@'); 1706 if (x) { 1707 char *d; 1708 ord = (int)strtol(x + 1, &d, 10); 1709 if (*d) 1710 ord = 0; 1711 } 1712 } 1713 pe_putimport(s1, dllindex, p, ord); 1618 1714 continue; 1619 1715 } … … 1621 1717 ret = 0; 1622 1718 quit: 1719 fclose(fp); 1623 1720 return ret; 1624 1721 } 1625 1722 1626 1723 /* ------------------------------------------------------------- */ 1627 #define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY 1628 #include "win32/tools/tiny_impdef.c" 1629 1630 static int pe_load_dll(TCCState *s1, const char *dllname, int fd) 1724 static int pe_load_dll(TCCState *s1, const char *filename) 1631 1725 { 1632 1726 char *p, *q; 1633 int index; 1634 p = get_export_names(fd); 1635 if (!p) 1727 int index, ret; 1728 1729 ret = tcc_get_dllexports(filename, &p); 1730 if (ret) { 1636 1731 return -1; 1637 index = add_dllref(s1, dllname); 1638 for (q = p; *q; q += 1 + strlen(q)) 1639 pe_putimport(s1, index, q, 0); 1640 tcc_free(p); 1732 } else if (p) { 1733 index = add_dllref(s1, tcc_basename(filename)); 1734 for (q = p; *q; q += 1 + strlen(q)) 1735 pe_putimport(s1, index, q, 0); 1736 tcc_free(p); 1737 } 1641 1738 return 0; 1642 1739 } … … 1651 1748 else if (pe_load_res(s1, fd) == 0) 1652 1749 ret = 0; 1653 else if (read_mem(fd, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))1654 ret = pe_load_dll(s1, tcc_basename(filename), fd);1750 else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4)) 1751 ret = pe_load_dll(s1, filename); 1655 1752 return ret; 1656 1753 } … … 1663 1760 s1->uw_pdata = find_section(tcc_state, ".pdata"); 1664 1761 s1->uw_pdata->sh_addralign = 4; 1665 s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);1666 }1667 1762 } 1763 if (0 == s1->uw_sym) 1764 s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base"); 1668 1765 if (0 == s1->uw_offs) { 1669 1766 /* As our functions all have the same stackframe, we use one entry for all */ … … 1714 1811 /* put relocations on it */ 1715 1812 for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress) 1716 put_elf_reloc(symtab_section, pd, o, R_X86_64_RELATIVE, s1->uw_sym);1813 put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym); 1717 1814 } 1718 1815 #endif … … 1727 1824 { 1728 1825 const char *start_symbol; 1729 ADDR3264 addr = 0;1730 1826 int pe_type = 0; 1827 int unicode_entry = 0; 1731 1828 1732 1829 if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16"))) 1733 1830 pe_type = PE_GUI; 1831 else 1832 if (find_elf_sym(symtab_section, PE_STDSYM("wWinMain","@16"))) { 1833 pe_type = PE_GUI; 1834 unicode_entry = PE_GUI; 1835 } 1734 1836 else 1735 1837 if (TCC_OUTPUT_DLL == s1->output_type) { … … 1738 1840 s1->output_type = TCC_OUTPUT_EXE; 1739 1841 } 1740 else 1842 else { 1741 1843 pe_type = PE_EXE; 1844 if (find_elf_sym(symtab_section, "wmain")) 1845 unicode_entry = PE_EXE; 1846 } 1742 1847 1743 1848 start_symbol = 1744 1849 TCC_OUTPUT_MEMORY == s1->output_type 1745 ? PE_GUI == pe_type ? "__runwinmain" : "_main" 1850 ? PE_GUI == pe_type ? (unicode_entry ? "__runwwinmain" : "__runwinmain") 1851 : (unicode_entry ? "__runwmain" : "__runmain") 1746 1852 : PE_DLL == pe_type ? PE_STDSYM("__dllstart","@12") 1747 : PE_GUI == pe_type ? "__winstart" : "__start" 1853 : PE_GUI == pe_type ? (unicode_entry ? "__wwinstart": "__winstart") 1854 : (unicode_entry ? "__wstart" : "__start") 1748 1855 ; 1749 1856 1750 if (!s1->leading_underscore || strchr(start_symbol, '@')) {1857 if (!s1->leading_underscore || strchr(start_symbol, '@')) 1751 1858 ++start_symbol; 1752 if (start_symbol[0] != '_')1753 start_symbol = NULL;1754 }1755 1859 1756 1860 /* grab the startup code from libtcc1 */ 1757 if (start_symbol) 1758 add_elf_sym(symtab_section, 1759 0, 0, 1760 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1761 SHN_UNDEF, start_symbol); 1861 #ifdef TCC_IS_NATIVE 1862 if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main) 1863 #endif 1864 set_elf_sym(symtab_section, 1865 0, 0, 1866 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1867 SHN_UNDEF, start_symbol); 1868 1869 tcc_add_pragma_libs(s1); 1762 1870 1763 1871 if (0 == s1->nostdlib) { 1764 1872 static const char *libs[] = { 1765 "libtcc1.a", "msvcrt", "kernel32", "", "user32", "gdi32", NULL1873 TCC_LIBTCC1, "msvcrt", "kernel32", "", "user32", "gdi32", NULL 1766 1874 }; 1767 1875 const char **pp, *p; … … 1770 1878 if (PE_DLL != pe_type && PE_GUI != pe_type) 1771 1879 break; 1772 } else if (pp == libs ? tcc_add_dll(s1, p, 0) : tcc_add_library(s1, p)) { 1773 tcc_error_noabort("cannot find library: %s", p); 1774 break; 1880 } else if (pp == libs && tcc_add_dll(s1, p, 0) >= 0) { 1881 continue; 1882 } else { 1883 tcc_add_library_err(s1, p); 1775 1884 } 1776 1885 } … … 1779 1888 if (TCC_OUTPUT_MEMORY == s1->output_type) 1780 1889 pe_type = PE_RUN; 1781 1782 if (start_symbol) {1783 addr = get_elf_sym_addr(s1, start_symbol, 1);1784 if (PE_RUN == pe_type && addr)1785 /* for -run GUI's, put '_runwinmain' instead of 'main' */1786 add_elf_sym(symtab_section,1787 addr, 0,1788 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,1789 text_section->sh_num, "main");1790 }1791 1792 1890 pe->type = pe_type; 1793 pe->start_addr = addr; 1794 } 1795 1796 ST_FUNC int pe_output_file(TCCState * s1, const char *filename) 1891 pe->start_symbol = start_symbol; 1892 } 1893 1894 static void pe_set_options(TCCState * s1, struct pe_info *pe) 1895 { 1896 if (PE_DLL == pe->type) { 1897 /* XXX: check if is correct for arm-pe target */ 1898 pe->imagebase = 0x10000000; 1899 } else { 1900 #if defined(TCC_TARGET_ARM) 1901 pe->imagebase = 0x00010000; 1902 #else 1903 pe->imagebase = 0x00400000; 1904 #endif 1905 } 1906 1907 #if defined(TCC_TARGET_ARM) 1908 /* we use "console" subsystem by default */ 1909 pe->subsystem = 9; 1910 #else 1911 if (PE_DLL == pe->type || PE_GUI == pe->type) 1912 pe->subsystem = 2; 1913 else 1914 pe->subsystem = 3; 1915 #endif 1916 /* Allow override via -Wl,-subsystem=... option */ 1917 if (s1->pe_subsystem != 0) 1918 pe->subsystem = s1->pe_subsystem; 1919 1920 /* set default file/section alignment */ 1921 if (pe->subsystem == 1) { 1922 pe->section_align = 0x20; 1923 pe->file_align = 0x20; 1924 } else { 1925 pe->section_align = 0x1000; 1926 pe->file_align = 0x200; 1927 } 1928 1929 if (s1->section_align != 0) 1930 pe->section_align = s1->section_align; 1931 if (s1->pe_file_align != 0) 1932 pe->file_align = s1->pe_file_align; 1933 1934 if ((pe->subsystem >= 10) && (pe->subsystem <= 12)) 1935 pe->imagebase = 0; 1936 1937 if (s1->has_text_addr) 1938 pe->imagebase = s1->text_addr; 1939 } 1940 1941 ST_FUNC int pe_output_file(TCCState *s1, const char *filename) 1797 1942 { 1798 1943 int ret; … … 1806 1951 tcc_add_bcheck(s1); 1807 1952 pe_add_runtime(s1, &pe); 1808 re locate_common_syms(); /* assign bss adresses */1809 tcc_add_linker_symbols(s1);1953 resolve_common_syms(s1); 1954 pe_set_options(s1, &pe); 1810 1955 1811 1956 ret = pe_check_symbols(&pe); … … 1813 1958 ; 1814 1959 else if (filename) { 1815 if (PE_DLL == pe.type) {1816 pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);1817 /* XXX: check if is correct for arm-pe target */1818 pe.imagebase = 0x10000000;1819 } else {1820 #if defined(TCC_TARGET_ARM)1821 pe.imagebase = 0x00010000;1822 #else1823 pe.imagebase = 0x00400000;1824 #endif1825 }1826 1827 #if defined(TCC_TARGET_ARM)1828 /* we use "console" subsystem by default */1829 pe.subsystem = 9;1830 #else1831 if (PE_DLL == pe.type || PE_GUI == pe.type)1832 pe.subsystem = 2;1833 else1834 pe.subsystem = 3;1835 #endif1836 /* Allow override via -Wl,-subsystem=... option */1837 if (s1->pe_subsystem != 0)1838 pe.subsystem = s1->pe_subsystem;1839 1840 /* set default file/section alignment */1841 if (pe.subsystem == 1) {1842 pe.section_align = 0x20;1843 pe.file_align = 0x20;1844 } else {1845 pe.section_align = 0x1000;1846 pe.file_align = 0x200;1847 }1848 1849 if (s1->section_align != 0)1850 pe.section_align = s1->section_align;1851 if (s1->pe_file_align != 0)1852 pe.file_align = s1->pe_file_align;1853 1854 if ((pe.subsystem >= 10) && (pe.subsystem <= 12))1855 pe.imagebase = 0;1856 1857 if (s1->has_text_addr)1858 pe.imagebase = s1->text_addr;1859 1860 1960 pe_assign_addresses(&pe); 1861 relocate_syms(s1, 0); 1961 relocate_syms(s1, s1->symtab, 0); 1962 s1->pe_imagebase = pe.imagebase; 1862 1963 for (i = 1; i < s1->nb_sections; ++i) { 1863 1964 Section *s = s1->sections[i]; 1864 1965 if (s->reloc) { 1865 1966 relocate_section(s1, s); 1866 pe_relocate_rva(&pe, s);1867 1967 } 1868 1968 } 1969 pe.start_addr = (DWORD) 1970 ((uintptr_t)tcc_get_symbol_err(s1, pe.start_symbol) 1971 - pe.imagebase); 1869 1972 if (s1->nb_errors) 1870 1973 ret = -1; … … 1876 1979 pe.thunk = data_section; 1877 1980 pe_build_imports(&pe); 1878 #endif 1879 } 1981 s1->runtime_main = pe.start_symbol; 1982 #ifdef TCC_TARGET_X86_64 1983 s1->uw_pdata = find_section(s1, ".pdata"); 1984 #endif 1985 #endif 1986 } 1987 1988 pe_free_imports(&pe); 1880 1989 1881 1990 #ifdef PE_PRINT_SECTIONS
Note:
See TracChangeset
for help on using the changeset viewer.