static void pe_build_imports(struct pe_info *pe) { int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i; DWORD rva_base = pe->thunk->sh_addr - pe->imagebase; int ndlls = pe->imp_count; for (sym_cnt = i = 0; i < ndlls; ++i) { sym_cnt += pe->imp_info[i]->sym_count; } if (sym_cnt == 0) return; pe_align_section(pe->thunk, 16); pe->imp_offs = dll_ptr = pe->thunk->data_offset; pe->imp_size = (ndlls + 1) * sizeof(struct pe_import_header); pe->iat_offs = dll_ptr + pe->imp_size; pe->iat_size = (sym_cnt + ndlls) * sizeof(DWORD); section_ptr_add(pe->thunk, pe->imp_size + 2 * pe->iat_size); thk_ptr = pe->iat_offs; ent_ptr = pe->iat_offs + pe->iat_size; for (i = 0; i < pe->imp_count; ++i) { struct pe_import_header *hdr; int k, n, v; struct pe_import_info *p = pe->imp_info[i]; const char *name = pe->s1->loaded_dlls[p->dll_index - 1]->name; // Put the DLL name into the import header v = put_elf_str(pe->thunk, name); hdr = (struct pe_import_header *) (pe->thunk->data + dll_ptr); hdr->first_thunk = thk_ptr + rva_base; hdr->first_entry = ent_ptr + rva_base; hdr->lib_name_offset = v + rva_base; for (k = 0, n = p->sym_count; k <= n; ++k) { if (k < n) { DWORD iat_index = p->symbols[k]->iat_index; int sym_index = p->symbols[k]->sym_index; Elf32_Sym *imp_sym = (Elf32_Sym *) pe->s1->dynsymtab_section->data + sym_index; Elf32_Sym *org_sym = (Elf32_Sym *) symtab_section->data + iat_index; const char *name = pe->s1->dynsymtab_section->link->data + imp_sym->st_name; org_sym->st_value = thk_ptr; org_sym->st_shndx = pe->thunk->sh_num; v = pe->thunk->data_offset + rva_base; *(WORD *) section_ptr_add(pe->thunk, sizeof(WORD)) = imp_sym->st_other; // Hint put_elf_str(pe->thunk, name); } else { v = 0; // Last entry is zero } *(DWORD *)(pe->thunk->data + thk_ptr) = v; *(DWORD *)(pe->thunk->data + ent_ptr) = v; thk_ptr += sizeof(DWORD); ent_ptr += sizeof(DWORD); } dll_ptr += sizeof(struct pe_import_header); dynarray_reset(&p->symbols, &p->sym_count); } dynarray_reset(&pe->imp_info, &pe->imp_count); }
static void pe_build_exports(struct pe_info *pe) { Elf32_Sym *sym; int sym_index, sym_end; DWORD rva_base, func_o, name_o, ord_o, str_o; struct pe_export_header *hdr; int sym_count, n, ord, *sorted, *sp; FILE *op; char buf[260]; const char *dllname; const char *name; rva_base = pe->thunk->sh_addr - pe->imagebase; sym_count = 0; n = 1; sorted = NULL; op = NULL; sym_end = symtab_section->data_offset / sizeof(Elf32_Sym); for (sym_index = 1; sym_index < sym_end; ++sym_index) { sym = (Elf32_Sym *) symtab_section->data + sym_index; name = symtab_section->link->data + sym->st_name; // Only export symbols from actually written sections if ((sym->st_other & 1) && pe->s1->sections[sym->st_shndx]->sh_addr) { dynarray_add((void ***) &sorted, &sym_count, (void *) n); dynarray_add((void ***) &sorted, &sym_count, (void *) name); } ++n; } if (sym_count == 0) return; sym_count /= 2; qsort(sorted, sym_count, 2 * sizeof(sorted[0]), sym_cmp); pe_align_section(pe->thunk, 16); dllname = tcc_basename(pe->filename); pe->exp_offs = pe->thunk->data_offset; func_o = pe->exp_offs + sizeof(struct pe_export_header); name_o = func_o + sym_count * sizeof(DWORD); ord_o = name_o + sym_count * sizeof(DWORD); str_o = ord_o + sym_count * sizeof(WORD); hdr = section_ptr_add(pe->thunk, str_o - pe->exp_offs); hdr->Characteristics = 0; hdr->Base = 1; hdr->NumberOfFunctions = sym_count; hdr->NumberOfNames = sym_count; hdr->AddressOfFunctions = func_o + rva_base; hdr->AddressOfNames = name_o + rva_base; hdr->AddressOfNameOrdinals = ord_o + rva_base; hdr->Name = str_o + rva_base; put_elf_str(pe->thunk, dllname); if (pe->def != NULL) { // Write exports to .def file op = fopen(pe->def, "w"); if (op == NULL) { error_noabort("could not create '%s': %s", pe->def, strerror(errno)); } else { fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname); if (verbose) { printf("<- %s (%d symbols)\n", buf, sym_count); } } } for (sp = sorted, ord = 0; ord < sym_count; ++ord, sp += 2) { sym_index = sp[0]; name = (const char *) sp[1]; // Insert actual address later in pe_relocate_rva put_elf_reloc(symtab_section, pe->thunk, func_o, R_386_RELATIVE, sym_index); *(DWORD *)(pe->thunk->data + name_o) = pe->thunk->data_offset + rva_base; *(WORD *)(pe->thunk->data + ord_o) = ord; put_elf_str(pe->thunk, name); func_o += sizeof(DWORD); name_o += sizeof(DWORD); ord_o += sizeof(WORD); if (op) fprintf(op, "%s@%d\n", name, ord); } pe->exp_size = pe->thunk->data_offset - pe->exp_offs; tcc_free(sorted); if (op) fclose(op); }
ST_FN void pe_build_exports(struct pe_info *pe) { Elf32_Sym *sym; int sym_index, sym_end; DWORD rva_base, func_o, name_o, ord_o, str_o; struct pe_export_header *hdr; int sym_count, n, ord, *sorted, *sp; FILE *op; char buf[MAX_PATH]; const char *dllname; const char *name; rva_base = pe->thunk->sh_addr - pe->imagebase; sym_count = 0, n = 1, sorted = NULL, op = NULL; sym_end = symtab_section->data_offset / sizeof(Elf32_Sym); for (sym_index = 1; sym_index < sym_end; ++sym_index) { sym = (Elf32_Sym*)symtab_section->data + sym_index; name = symtab_section->link->data + sym->st_name; if ((sym->st_other & 1) /* export only symbols from actually written sections */ && pe->s1->sections[sym->st_shndx]->sh_addr) { dynarray_add((void***)&sorted, &sym_count, (void*)n); dynarray_add((void***)&sorted, &sym_count, (void*)name); } ++n; #if 0 if (sym->st_other & 1) printf("export: %s\n", name); if (sym->st_other & 2) printf("stdcall: %s\n", name); #endif } if (0 == sym_count) return; sym_count /= 2; qsort (sorted, sym_count, 2 * sizeof sorted[0], sym_cmp); pe_align_section(pe->thunk, 16); dllname = tcc_basename(pe->filename); pe->exp_offs = pe->thunk->data_offset; func_o = pe->exp_offs + sizeof(struct pe_export_header); name_o = func_o + sym_count * sizeof (DWORD); ord_o = name_o + sym_count * sizeof (DWORD); str_o = ord_o + sym_count * sizeof(WORD); hdr = section_ptr_add(pe->thunk, str_o - pe->exp_offs); hdr->Characteristics = 0; hdr->Base = 1; hdr->NumberOfFunctions = sym_count; hdr->NumberOfNames = sym_count; hdr->AddressOfFunctions = func_o + rva_base; hdr->AddressOfNames = name_o + rva_base; hdr->AddressOfNameOrdinals = ord_o + rva_base; hdr->Name = str_o + rva_base; put_elf_str(pe->thunk, dllname); #if 1 /* automatically write exports to <output-filename>.def */ strcpy(buf, pe->filename); strcpy(tcc_fileextension(buf), ".def"); op = fopen(buf, "w"); if (NULL == op) { error_noabort("could not create '%s': %s", buf, strerror(errno)); } else { fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname); if (pe->s1->verbose) printf("<- %s (%d symbols)\n", buf, sym_count); } #endif for (sp = sorted, ord = 0; ord < sym_count; ++ord, sp += 2) { sym_index = sp[0], name = (const char *)sp[1]; /* insert actual address later in pe_relocate_rva */ put_elf_reloc(symtab_section, pe->thunk, func_o, R_386_RELATIVE, sym_index); *(DWORD*)(pe->thunk->data + name_o) = pe->thunk->data_offset + rva_base; *(WORD*)(pe->thunk->data + ord_o) = ord; put_elf_str(pe->thunk, name); func_o += sizeof (DWORD); name_o += sizeof (DWORD); ord_o += sizeof (WORD); if (op) fprintf(op, "%s\n", name); } pe->exp_size = pe->thunk->data_offset - pe->exp_offs; tcc_free(sorted); }