tccpe: load dll on the fly
This commit is contained in:
143
tccpe.c
143
tccpe.c
@ -46,6 +46,19 @@
|
||||
#define TCC_IS_NATIVE
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
void dbg_printf (const char *fmt, ...)
|
||||
{
|
||||
char buffer[4000];
|
||||
va_list arg;
|
||||
int x;
|
||||
va_start(arg, fmt);
|
||||
x = vsprintf (buffer, fmt, arg);
|
||||
strcpy(buffer+x, "\n");
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
#ifndef IMAGE_NT_SIGNATURE
|
||||
/* ----------------------------------------------------------- */
|
||||
@ -442,29 +455,12 @@ struct pe_info {
|
||||
int imp_count;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
#define PE_NUL 0
|
||||
#define PE_DLL 1
|
||||
#define PE_GUI 2
|
||||
#define PE_EXE 3
|
||||
#define PE_RUN 4
|
||||
|
||||
void error_noabort(const char *, ...);
|
||||
|
||||
#ifdef _WIN32
|
||||
void dbg_printf (const char *fmt, ...)
|
||||
{
|
||||
char buffer[4000];
|
||||
va_list arg;
|
||||
int x;
|
||||
va_start(arg, fmt);
|
||||
x = vsprintf (buffer, fmt, arg);
|
||||
strcpy(buffer+x, "\n");
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------*/
|
||||
|
||||
ST_FN const char* get_alt_symbol(char *buffer, const char *symbol)
|
||||
@ -1355,62 +1351,55 @@ ST_FN void pe_print_sections(TCCState *s1, const char *fname)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
ST_FN int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
|
||||
{
|
||||
fseek(fp, offset, 0);
|
||||
return len == fread(buffer, 1, len, fp);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* This is for compiled windows resources in 'coff' format
|
||||
* as generated by 'windres.exe -O coff ...'.
|
||||
*/
|
||||
|
||||
PUB_FN int pe_test_res_file(void *v, int size)
|
||||
{
|
||||
struct pe_rsrc_header *p = (struct pe_rsrc_header *)v;
|
||||
return
|
||||
size >= IMAGE_SIZEOF_FILE_HEADER + IMAGE_SIZEOF_SHORT_NAME /* = 28 */
|
||||
&& p->filehdr.Machine == 0x014C
|
||||
&& 1 == p->filehdr.NumberOfSections
|
||||
&& 0 == strcmp(p->sectionhdr.Name, ".rsrc")
|
||||
;
|
||||
}
|
||||
|
||||
ST_FN int read_n(int fd, void *ptr, unsigned size)
|
||||
{
|
||||
return size == read(fd, ptr, size);
|
||||
}
|
||||
|
||||
PUB_FN int pe_load_res_file(TCCState *s1, int fd)
|
||||
ST_FN int pe_load_res(TCCState *s1, FILE *fp)
|
||||
{
|
||||
struct pe_rsrc_header hdr;
|
||||
Section *rsrc_section;
|
||||
int i, ret = -1;
|
||||
BYTE *ptr;
|
||||
unsigned offs;
|
||||
|
||||
lseek (fd, 0, SEEK_SET);
|
||||
if (!read_n(fd, &hdr, sizeof hdr))
|
||||
if (!read_mem(fp, 0, &hdr, sizeof hdr))
|
||||
goto quit;
|
||||
if (!pe_test_res_file(&hdr, sizeof hdr))
|
||||
|
||||
if (hdr.filehdr.Machine != 0x014C
|
||||
|| hdr.filehdr.NumberOfSections != 1
|
||||
|| strcmp(hdr.sectionhdr.Name, ".rsrc") != 0)
|
||||
goto quit;
|
||||
|
||||
rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
|
||||
ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
|
||||
lseek (fd, hdr.sectionhdr.PointerToRawData, SEEK_SET);
|
||||
if (!read_n(fd, ptr, hdr.sectionhdr.SizeOfRawData))
|
||||
offs = hdr.sectionhdr.PointerToRawData;
|
||||
if (!read_mem(fp, offs, ptr, hdr.sectionhdr.SizeOfRawData))
|
||||
goto quit;
|
||||
|
||||
lseek (fd, hdr.sectionhdr.PointerToRelocations, SEEK_SET);
|
||||
offs = hdr.sectionhdr.PointerToRelocations;
|
||||
for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)
|
||||
{
|
||||
struct pe_rsrc_reloc rel;
|
||||
if (!read_n(fd, &rel, sizeof rel))
|
||||
if (!read_mem(fp, offs, &rel, sizeof rel))
|
||||
goto quit;
|
||||
// printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
|
||||
if (rel.type != 7) /* DIR32NB */
|
||||
goto quit;
|
||||
put_elf_reloc(symtab_section, rsrc_section,
|
||||
rel.offset, R_XXX_RELATIVE, 0);
|
||||
offs += sizeof rel;
|
||||
}
|
||||
ret = 0;
|
||||
quit:
|
||||
if (ret)
|
||||
error_noabort("unrecognized resource file format");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1439,15 +1428,11 @@ ST_FN char *get_line(char *line, int size, FILE *fp)
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
PUB_FN int pe_load_def_file(TCCState *s1, int fd)
|
||||
ST_FN int pe_load_def(TCCState *s1, FILE *fp)
|
||||
{
|
||||
DLLReference *dllref;
|
||||
int state = 0, ret = -1;
|
||||
char line[400], dllname[80], *p;
|
||||
FILE *fp = fdopen(dup(fd), "rb");
|
||||
|
||||
if (NULL == fp)
|
||||
goto quit;
|
||||
|
||||
for (;;) {
|
||||
p = get_line(line, sizeof line, fp);
|
||||
@ -1485,13 +1470,65 @@ PUB_FN int pe_load_def_file(TCCState *s1, int fd)
|
||||
}
|
||||
ret = 0;
|
||||
quit:
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
if (ret)
|
||||
error_noabort("unrecognized export definition file format");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
|
||||
#include "win32/tools/tiny_impdef.c"
|
||||
|
||||
ST_FN int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
|
||||
{
|
||||
int i = 0;
|
||||
char *p, *q;
|
||||
p = get_export_names(fp);
|
||||
if (p) {
|
||||
DLLReference *dllref;
|
||||
dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
|
||||
strcpy(dllref->name, dllname);
|
||||
dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
|
||||
for (q = p, i = 0; *q; ++i) {
|
||||
add_elf_sym(s1->dynsymtab_section,
|
||||
s1->nb_loaded_dlls, 0,
|
||||
ELFW_ST_INFO(STB_GLOBAL, STT_FUNC), 0,
|
||||
text_section->sh_num, q);
|
||||
q += 1 + strlen(q);
|
||||
}
|
||||
tcc_free(p);
|
||||
}
|
||||
return i ? 0 : -1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
PUB_FN int pe_load_file(struct TCCState *s1, const char *filename, int fd)
|
||||
{
|
||||
FILE *fp = fdopen(dup(fd), "rb");
|
||||
int ret = -1;
|
||||
char buf[10];
|
||||
if (fp) {
|
||||
if (0 == strcmp(tcc_fileextension(filename), ".def"))
|
||||
ret = pe_load_def(s1, fp);
|
||||
else if (pe_load_res(s1, fp) == 0)
|
||||
ret = 0;
|
||||
else if (read_mem(fp, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))
|
||||
ret = pe_load_dll(s1, filename, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pe_add_dll(struct TCCState *s, const char *libraryname)
|
||||
{
|
||||
char buf[MAX_PATH];
|
||||
snprintf(buf, sizeof(buf), "%s.def", libraryname);
|
||||
if (tcc_add_dll(s, buf, 0) == 0)
|
||||
return 0;
|
||||
snprintf(buf, sizeof(buf), "%s.dll", libraryname);
|
||||
if (tcc_add_dll(s, buf, 0) == 0)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
#define PE_STDSYM(n,s) n
|
||||
|
||||
Reference in New Issue
Block a user