mirror of
https://github.com/TinyCC/tinycc.git
synced 2025-11-16 04:24:45 +00:00
tccpe: add COFF symbol table for GDB
wanted by gdb to have global variables info on windows Also: tcc.h: - move dwarf inline fns - use dwarf as default for 64-bit platforms. GDB can't handle locals info from stabs on 64-bit correctly (also not from gcc). tccpe.c: - use 's1' instead of 'pe->s1' tccdbg.c: - fix locals info problem on Windows where (unsigned long) s->value is uint32_t and would not cast to long long correctly. - tweak dwarf to have line info at begin of functions, otherwise "gdb b main, r, n" would say "no line number info, single step..." (see also objdump --dwarf=decodedline ...)
This commit is contained in:
8
configure
vendored
8
configure
vendored
@@ -234,8 +234,8 @@ Advanced options (experts only):
|
|||||||
Cross build options (experimental):
|
Cross build options (experimental):
|
||||||
--cpu=CPU target CPU [$cpu]
|
--cpu=CPU target CPU [$cpu]
|
||||||
--targetos=... target OS (Darwin,WIN32,Android/Termux) [$targetos]
|
--targetos=... target OS (Darwin,WIN32,Android/Termux) [$targetos]
|
||||||
|
--os-release=x.y.z target os release x.y.z [$os_release] (with BSD systems)
|
||||||
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
|
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
|
||||||
--os-release=x.y.z use os release x.y.z [$os_release]
|
|
||||||
EOF
|
EOF
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@@ -260,6 +260,7 @@ fi
|
|||||||
# OS specific
|
# OS specific
|
||||||
buildos=$(uname)
|
buildos=$(uname)
|
||||||
cpu_sys=$(uname -m)
|
cpu_sys=$(uname -m)
|
||||||
|
default os_release "$(uname -r)"
|
||||||
|
|
||||||
case $buildos in
|
case $buildos in
|
||||||
Windows_NT|MINGW*|MSYS*|CYGWIN*)
|
Windows_NT|MINGW*|MSYS*|CYGWIN*)
|
||||||
@@ -294,11 +295,6 @@ then
|
|||||||
ar="${cross_prefix}${ar}"
|
ar="${cross_prefix}${ar}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test -z "$os_release"
|
|
||||||
then
|
|
||||||
os_release=$(uname -r)
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$cpu" in
|
case "$cpu" in
|
||||||
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
||||||
cpu="i386"
|
cpu="i386"
|
||||||
|
|||||||
95
tcc.h
95
tcc.h
@@ -1656,54 +1656,6 @@ static inline void write64le(unsigned char *p, uint64_t x) {
|
|||||||
static inline void add64le(unsigned char *p, int64_t x) {
|
static inline void add64le(unsigned char *p, int64_t x) {
|
||||||
write64le(p, read64le(p) + x);
|
write64le(p, read64le(p) + x);
|
||||||
}
|
}
|
||||||
#define DWARF_MAX_128 ((8 * sizeof (int64_t) + 6) / 7)
|
|
||||||
#define dwarf_read_1(ln,end) \
|
|
||||||
((ln) < (end) ? *(ln)++ : 0)
|
|
||||||
#define dwarf_read_2(ln,end) \
|
|
||||||
((ln) + 1 < (end) ? (ln) += 2, read16le((ln) - 2) : 0)
|
|
||||||
#define dwarf_read_4(ln,end) \
|
|
||||||
((ln) + 3 < (end) ? (ln) += 4, read32le((ln) - 4) : 0)
|
|
||||||
#define dwarf_read_8(ln,end) \
|
|
||||||
((ln) + 7 < (end) ? (ln) += 8, read64le((ln) - 8) : 0)
|
|
||||||
static inline uint64_t
|
|
||||||
dwarf_read_uleb128(unsigned char **ln, unsigned char *end)
|
|
||||||
{
|
|
||||||
unsigned char *cp = *ln;
|
|
||||||
uint64_t retval = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < DWARF_MAX_128; i++) {
|
|
||||||
uint64_t byte = dwarf_read_1(cp, end);
|
|
||||||
|
|
||||||
retval |= (byte & 0x7f) << (i * 7);
|
|
||||||
if ((byte & 0x80) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*ln = cp;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
static inline int64_t
|
|
||||||
dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
|
|
||||||
{
|
|
||||||
unsigned char *cp = *ln;
|
|
||||||
int64_t retval = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < DWARF_MAX_128; i++) {
|
|
||||||
uint64_t byte = dwarf_read_1(cp, end);
|
|
||||||
|
|
||||||
retval |= (byte & 0x7f) << (i * 7);
|
|
||||||
if ((byte & 0x80) == 0) {
|
|
||||||
if ((byte & 0x40) && (i + 1) * 7 < 64)
|
|
||||||
retval |= (uint64_t)-1LL << ((i + 1) * 7);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*ln = cp;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------ i386-gen.c ------------ */
|
/* ------------ i386-gen.c ------------ */
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
|
||||||
ST_FUNC void g(int c);
|
ST_FUNC void g(int c);
|
||||||
@@ -1892,6 +1844,49 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
|
|||||||
#define dwarf_str_section s1->dwarf_str_section
|
#define dwarf_str_section s1->dwarf_str_section
|
||||||
#define dwarf_line_str_section s1->dwarf_line_str_section
|
#define dwarf_line_str_section s1->dwarf_line_str_section
|
||||||
|
|
||||||
|
#define DWARF_MAX_128 ((8 * sizeof (int64_t) + 6) / 7)
|
||||||
|
#define dwarf_read_1(ln,end) \
|
||||||
|
((ln) < (end) ? *(ln)++ : 0)
|
||||||
|
#define dwarf_read_2(ln,end) \
|
||||||
|
((ln) + 1 < (end) ? read16le(((ln)+=2) - 2) : 0)
|
||||||
|
#define dwarf_read_4(ln,end) \
|
||||||
|
((ln) + 3 < (end) ? read32le(((ln)+=4) - 4) : 0)
|
||||||
|
#define dwarf_read_8(ln,end) \
|
||||||
|
((ln) + 7 < (end) ? read64le(((ln)+=8) - 8) : 0)
|
||||||
|
static inline uint64_t
|
||||||
|
dwarf_read_uleb128(unsigned char **ln, unsigned char *end)
|
||||||
|
{
|
||||||
|
unsigned char *cp = *ln;
|
||||||
|
uint64_t retval = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < DWARF_MAX_128; i++) {
|
||||||
|
uint64_t byte = dwarf_read_1(cp, end);
|
||||||
|
retval |= (byte & 0x7f) << (i * 7);
|
||||||
|
if ((byte & 0x80) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*ln = cp;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
static inline int64_t
|
||||||
|
dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
|
||||||
|
{
|
||||||
|
unsigned char *cp = *ln;
|
||||||
|
int64_t retval = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < DWARF_MAX_128; i++) {
|
||||||
|
uint64_t byte = dwarf_read_1(cp, end);
|
||||||
|
retval |= (byte & 0x7f) << (i * 7);
|
||||||
|
if ((byte & 0x80) == 0) {
|
||||||
|
if ((byte & 0x40) && (i + 1) * 7 < 64)
|
||||||
|
retval |= (uint64_t)-1LL << ((i + 1) * 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ln = cp;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/* default dwarf version for "-gdwarf" */
|
/* default dwarf version for "-gdwarf" */
|
||||||
#ifdef TCC_TARGET_MACHO
|
#ifdef TCC_TARGET_MACHO
|
||||||
# define DEFAULT_DWARF_VERSION 2
|
# define DEFAULT_DWARF_VERSION 2
|
||||||
@@ -1904,9 +1899,7 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
|
|||||||
# define CONFIG_DWARF_VERSION 0
|
# define CONFIG_DWARF_VERSION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined TCC_TARGET_PE
|
#if defined TCC_TARGET_X86_64
|
||||||
# define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */
|
|
||||||
#elif defined TCC_TARGET_X86_64
|
|
||||||
# define R_DATA_32DW R_X86_64_32
|
# define R_DATA_32DW R_X86_64_32
|
||||||
#else
|
#else
|
||||||
# define R_DATA_32DW R_DATA_32
|
# define R_DATA_32DW R_DATA_32
|
||||||
|
|||||||
6
tccdbg.c
6
tccdbg.c
@@ -1500,6 +1500,8 @@ ST_FUNC void tcc_debug_line(TCCState *s1)
|
|||||||
else {
|
else {
|
||||||
dwarf_line_op(s1, DW_LNS_advance_line);
|
dwarf_line_op(s1, DW_LNS_advance_line);
|
||||||
dwarf_sleb128_op(s1, len_line);
|
dwarf_sleb128_op(s1, len_line);
|
||||||
|
/* advance by nothing */
|
||||||
|
dwarf_line_op(s1, DWARF_OPCODE_BASE - DWARF_LINE_BASE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2209,9 +2211,9 @@ static void tcc_debug_finish (TCCState *s1, struct _debug_info *cur)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* param/local */
|
/* param/local */
|
||||||
dwarf_data1(dwarf_info_section, dwarf_sleb128_size(s->value) + 1);
|
dwarf_data1(dwarf_info_section, dwarf_sleb128_size((long)s->value) + 1);
|
||||||
dwarf_data1(dwarf_info_section, DW_OP_fbreg);
|
dwarf_data1(dwarf_info_section, DW_OP_fbreg);
|
||||||
dwarf_sleb128(dwarf_info_section, s->value);
|
dwarf_sleb128(dwarf_info_section, (long)s->value);
|
||||||
}
|
}
|
||||||
tcc_free (s->str);
|
tcc_free (s->str);
|
||||||
}
|
}
|
||||||
|
|||||||
206
tccpe.c
206
tccpe.c
@@ -347,6 +347,8 @@ struct pe_info {
|
|||||||
TCCState *s1;
|
TCCState *s1;
|
||||||
Section *reloc;
|
Section *reloc;
|
||||||
Section *thunk;
|
Section *thunk;
|
||||||
|
Section *coffsym;
|
||||||
|
Section *coffstr;
|
||||||
const char *filename;
|
const char *filename;
|
||||||
int type;
|
int type;
|
||||||
DWORD sizeofheaders;
|
DWORD sizeofheaders;
|
||||||
@@ -366,6 +368,10 @@ struct pe_info {
|
|||||||
int sec_count;
|
int sec_count;
|
||||||
struct pe_import_info **imp_info;
|
struct pe_import_info **imp_info;
|
||||||
int imp_count;
|
int imp_count;
|
||||||
|
/* output */
|
||||||
|
FILE *op;
|
||||||
|
DWORD sum;
|
||||||
|
unsigned pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PE_NUL 0
|
#define PE_NUL 0
|
||||||
@@ -427,71 +433,110 @@ static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD siz
|
|||||||
hdr->opthdr.DataDirectory[dir].Size = size;
|
hdr->opthdr.DataDirectory[dir].Size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pe_file {
|
static int pe_fwrite(struct pe_info *pe, const void *data, int len)
|
||||||
FILE *op;
|
|
||||||
DWORD sum;
|
|
||||||
unsigned pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int pe_fwrite(const void *data, int len, struct pe_file *pf)
|
|
||||||
{
|
{
|
||||||
const WORD *p = data;
|
const WORD *p = data;
|
||||||
DWORD sum;
|
DWORD sum;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
pf->pos += (ret = fwrite(data, 1, len, pf->op));
|
pe->pos += (ret = fwrite(data, 1, len, pe->op));
|
||||||
sum = pf->sum;
|
sum = pe->sum;
|
||||||
for (i = len; i > 0; i -= 2) {
|
for (i = len; i > 0; i -= 2) {
|
||||||
sum += (i >= 2) ? *p++ : *(BYTE*)p;
|
sum += (i >= 2) ? *p++ : *(BYTE*)p;
|
||||||
sum = (sum + (sum >> 16)) & 0xFFFF;
|
sum = (sum + (sum >> 16)) & 0xFFFF;
|
||||||
}
|
}
|
||||||
pf->sum = sum;
|
pe->sum = sum;
|
||||||
return len == ret ? 0 : -1;
|
return len == ret ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pe_fpad(struct pe_file *pf, DWORD new_pos)
|
static void pe_fpad(struct pe_info *pe, DWORD new_pos)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
int n, diff = new_pos - pf->pos;
|
int n, diff = new_pos - pe->pos;
|
||||||
memset(buf, 0, sizeof buf);
|
memset(buf, 0, sizeof buf);
|
||||||
while (diff > 0) {
|
while (diff > 0) {
|
||||||
diff -= n = umin(diff, sizeof buf);
|
diff -= n = umin(diff, sizeof buf);
|
||||||
fwrite(buf, n, 1, pf->op);
|
fwrite(buf, n, 1, pe->op);
|
||||||
}
|
}
|
||||||
pf->pos = new_pos;
|
pe->pos = new_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
/* PE-DWARF/COFF support
|
/* some DWARF support with COFF symbol/string table for gdb */
|
||||||
does not work with a mingw-gdb really but works with cv2pdb
|
|
||||||
(https://github.com/rainers/cv2pdb) */
|
|
||||||
|
|
||||||
#define N_COFF_SYMS 0
|
#pragma pack(push, 1)
|
||||||
|
struct syment
|
||||||
static const char dwarf_secs[] =
|
|
||||||
{
|
{
|
||||||
".debug_info\0"
|
union {
|
||||||
".debug_abbrev\0"
|
char n_name[8]; /* old COFF version */
|
||||||
".debug_line\0"
|
struct {
|
||||||
".debug_aranges\0"
|
int32_t n_zeroes; /* new == 0 */
|
||||||
".debug_str\0"
|
int32_t n_offset; /* offset into string table */
|
||||||
".debug_line_str\0"
|
};
|
||||||
|
};
|
||||||
|
int32_t n_value; /* value of symbol */
|
||||||
|
short n_scnum; /* section number */
|
||||||
|
unsigned short n_type; /* type and derived type */
|
||||||
|
char n_sclass; /* storage class */
|
||||||
|
char n_numaux; /* number of aux. entries */
|
||||||
};
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
static const unsigned coff_strtab_size = 4 + sizeof dwarf_secs - 1;
|
#define SHF_PRIVATE 0x80000000
|
||||||
|
|
||||||
static int pe_put_long_secname(char *secname, const char *name)
|
static void pe_add_coffsym(struct pe_info *pe)
|
||||||
{
|
{
|
||||||
const char *d = dwarf_secs;
|
TCCState *s1 = pe->s1;
|
||||||
do {
|
ElfSym *esym;
|
||||||
if (0 == strcmp(d, name)) {
|
struct syment *se;
|
||||||
snprintf(secname, 8, "/%d", (int)(d - dwarf_secs + 4));
|
int n;
|
||||||
return 1;
|
|
||||||
|
if (NULL == pe->coffsym) {
|
||||||
|
pe->coffsym = new_section(s1, ".coffsym", SHT_PROGBITS, SHF_PRIVATE);
|
||||||
|
pe->coffstr = new_section(s1, ".coffstr", SHT_PROGBITS, SHF_PRIVATE);
|
||||||
|
section_ptr_add(pe->coffstr, 4); /* coff string table size */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
se = section_ptr_add(pe->coffsym, sizeof *se);
|
||||||
|
strcpy(se->n_name, ".file");
|
||||||
|
se->n_scnum = -2;
|
||||||
|
se->n_sclass = 0x67;
|
||||||
|
se->n_numaux = 1;
|
||||||
|
se = section_ptr_add(pe->coffsym, sizeof *se);
|
||||||
|
strcpy((char*)se, "no-file");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
esym = (ElfSym*)s1->symtab->data;
|
||||||
|
for (n = s1->symtab->data_offset / sizeof *esym; ++esym, --n;) {
|
||||||
|
int sym_bind = ELFW(ST_BIND)(esym->st_info);
|
||||||
|
if (sym_bind == STB_GLOBAL) {
|
||||||
|
char *name = esym->st_name + (char*)s1->symtab->link->data;
|
||||||
|
int nl = strlen(name);
|
||||||
|
addr_t value = esym->st_value;
|
||||||
|
int shnum = esym->st_shndx;
|
||||||
|
if (shnum != SHN_UNDEF && shnum < s1->nb_sections) {
|
||||||
|
Section *s = s1->sections[shnum];
|
||||||
|
shnum = s->sh_info;
|
||||||
|
value = value - s->sh_addr;
|
||||||
|
}
|
||||||
|
se = section_ptr_add(pe->coffsym, sizeof *se);
|
||||||
|
se->n_value = value;
|
||||||
|
se->n_scnum = shnum;
|
||||||
|
se->n_sclass = 2; // C_EXT
|
||||||
|
if (nl <= 8)
|
||||||
|
memcpy(se->n_name, name, nl);
|
||||||
|
else
|
||||||
|
se->n_offset = put_elf_str(pe->coffstr, name);
|
||||||
}
|
}
|
||||||
d = strchr(d, 0) + 1;
|
}
|
||||||
} while (*d);
|
#endif
|
||||||
return 0;
|
write32le(pe->coffstr->data, pe->coffstr->data_offset); /* coff string table size */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Run cv2pdb, available at https://github.com/rainers/cv2pdb. It reads
|
||||||
|
and strips the dwarf info and creates a <exename>.pdb file instead */
|
||||||
static void pe_create_pdb(TCCState *s1, const char *exename)
|
static void pe_create_pdb(TCCState *s1, const char *exename)
|
||||||
{
|
{
|
||||||
char buf[300]; int r;
|
char buf[300]; int r;
|
||||||
@@ -614,15 +659,16 @@ static int pe_write(struct pe_info *pe)
|
|||||||
struct pe_header pe_header = pe_template;
|
struct pe_header pe_header = pe_template;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
struct pe_file pf = {0};
|
|
||||||
DWORD file_offset;
|
DWORD file_offset;
|
||||||
struct section_info *si;
|
struct section_info *si;
|
||||||
IMAGE_SECTION_HEADER *psh;
|
IMAGE_SECTION_HEADER *psh;
|
||||||
TCCState *s1 = pe->s1;
|
TCCState *s1 = pe->s1;
|
||||||
int need_strtab = 0;
|
|
||||||
|
|
||||||
pf.op = fopen(pe->filename, "wb");
|
if (s1->do_debug)
|
||||||
if (NULL == pf.op)
|
pe_add_coffsym(pe);
|
||||||
|
|
||||||
|
pe->op = fopen(pe->filename, "wb");
|
||||||
|
if (NULL == pe->op)
|
||||||
return tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
|
return tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
|
||||||
|
|
||||||
pe->sizeofheaders = pe_file_align(pe,
|
pe->sizeofheaders = pe_file_align(pe,
|
||||||
@@ -632,7 +678,7 @@ static int pe_write(struct pe_info *pe)
|
|||||||
|
|
||||||
file_offset = pe->sizeofheaders;
|
file_offset = pe->sizeofheaders;
|
||||||
|
|
||||||
if (2 == pe->s1->verbose)
|
if (2 == s1->verbose)
|
||||||
printf("-------------------------------"
|
printf("-------------------------------"
|
||||||
"\n virt file size section" "\n");
|
"\n virt file size section" "\n");
|
||||||
for (i = 0; i < pe->sec_count; ++i) {
|
for (i = 0; i < pe->sec_count; ++i) {
|
||||||
@@ -645,7 +691,7 @@ static int pe_write(struct pe_info *pe)
|
|||||||
size = si->sh_size;
|
size = si->sh_size;
|
||||||
psh = &si->ish;
|
psh = &si->ish;
|
||||||
|
|
||||||
if (2 == pe->s1->verbose)
|
if (2 == s1->verbose)
|
||||||
printf("%6x %6x %6x %s\n",
|
printf("%6x %6x %6x %s\n",
|
||||||
(unsigned)addr, (unsigned)file_offset, (unsigned)size, sh_name);
|
(unsigned)addr, (unsigned)file_offset, (unsigned)size, sh_name);
|
||||||
|
|
||||||
@@ -690,8 +736,10 @@ static int pe_write(struct pe_info *pe)
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(psh->Name, sh_name, umin(strlen(sh_name), sizeof psh->Name));
|
memcpy(psh->Name, sh_name, umin(strlen(sh_name), sizeof psh->Name));
|
||||||
if (si->cls == sec_debug)
|
if (pe->coffstr && strlen(sh_name) > 8) {
|
||||||
need_strtab += pe_put_long_secname((char*)psh->Name, sh_name);
|
/* long section name, for example ".debug_info" */
|
||||||
|
snprintf((char*)psh->Name, 8, "/%d", put_elf_str(pe->coffstr, sh_name));
|
||||||
|
}
|
||||||
|
|
||||||
psh->Characteristics = si->pe_flags;
|
psh->Characteristics = si->pe_flags;
|
||||||
psh->VirtualAddress = addr;
|
psh->VirtualAddress = addr;
|
||||||
@@ -716,18 +764,22 @@ static int pe_write(struct pe_info *pe)
|
|||||||
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
|
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
|
||||||
pe_header.opthdr.ImageBase = pe->imagebase;
|
pe_header.opthdr.ImageBase = pe->imagebase;
|
||||||
pe_header.opthdr.Subsystem = pe->subsystem;
|
pe_header.opthdr.Subsystem = pe->subsystem;
|
||||||
if (pe->s1->pe_stack_size)
|
if (s1->pe_stack_size)
|
||||||
pe_header.opthdr.SizeOfStackReserve = pe->s1->pe_stack_size;
|
pe_header.opthdr.SizeOfStackReserve = s1->pe_stack_size;
|
||||||
if (PE_DLL == pe->type)
|
if (PE_DLL == pe->type)
|
||||||
pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
|
pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
|
||||||
pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics;
|
pe_header.filehdr.Characteristics |= s1->pe_characteristics;
|
||||||
if (need_strtab) {
|
|
||||||
|
if (pe->coffsym) {
|
||||||
|
pe_add_coffsym(pe);
|
||||||
pe_header.filehdr.PointerToSymbolTable = file_offset;
|
pe_header.filehdr.PointerToSymbolTable = file_offset;
|
||||||
pe_header.filehdr.NumberOfSymbols = N_COFF_SYMS;
|
pe_header.filehdr.NumberOfSymbols
|
||||||
|
= pe->coffsym->data_offset / sizeof (struct syment);
|
||||||
}
|
}
|
||||||
pe_fwrite(&pe_header, sizeof pe_header, &pf);
|
|
||||||
|
pe_fwrite(pe, &pe_header, sizeof pe_header);
|
||||||
for (i = 0; i < pe->sec_count; ++i)
|
for (i = 0; i < pe->sec_count; ++i)
|
||||||
pe_fwrite(&pe->sec_info[i]->ish, sizeof(IMAGE_SECTION_HEADER), &pf);
|
pe_fwrite(pe, &pe->sec_info[i]->ish, sizeof(IMAGE_SECTION_HEADER));
|
||||||
|
|
||||||
file_offset = pe->sizeofheaders;
|
file_offset = pe->sizeofheaders;
|
||||||
for (i = 0; i < pe->sec_count; ++i) {
|
for (i = 0; i < pe->sec_count; ++i) {
|
||||||
@@ -736,34 +788,33 @@ static int pe_write(struct pe_info *pe)
|
|||||||
if (!si->data_size)
|
if (!si->data_size)
|
||||||
continue;
|
continue;
|
||||||
for (s = si->sec; s; s = s->prev) {
|
for (s = si->sec; s; s = s->prev) {
|
||||||
pe_fpad(&pf, file_offset);
|
pe_fpad(pe, file_offset);
|
||||||
pe_fwrite(s->data, s->data_offset, &pf);
|
pe_fwrite(pe, s->data, s->data_offset);
|
||||||
if (s->prev)
|
if (s->prev)
|
||||||
file_offset += s->prev->sh_addr - s->sh_addr;
|
file_offset += s->prev->sh_addr - s->sh_addr;
|
||||||
}
|
}
|
||||||
file_offset = si->ish.PointerToRawData + si->ish.SizeOfRawData;
|
file_offset = si->ish.PointerToRawData + si->ish.SizeOfRawData;
|
||||||
pe_fpad(&pf, file_offset);
|
pe_fpad(pe, file_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_strtab) {
|
if (pe->coffsym) {
|
||||||
/* create a tiny COFF string table with the long section names */
|
pe_fwrite(pe, pe->coffsym->data, pe->coffsym->data_offset);
|
||||||
pe_fwrite(&coff_strtab_size, sizeof coff_strtab_size, &pf);
|
pe_fwrite(pe, pe->coffstr->data, pe->coffstr->data_offset);
|
||||||
pe_fwrite(dwarf_secs, sizeof dwarf_secs - 1, &pf);
|
file_offset = pe->pos;
|
||||||
file_offset = pf.pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pf.sum += file_offset;
|
pe->sum += file_offset;
|
||||||
fseek(pf.op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET);
|
fseek(pe->op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET);
|
||||||
pe_fwrite(&pf.sum, sizeof (DWORD), &pf);
|
pe_fwrite(pe, &pe->sum, sizeof (DWORD));
|
||||||
|
|
||||||
fclose (pf.op);
|
fclose (pe->op);
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
chmod(pe->filename, 0777);
|
chmod(pe->filename, 0777);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (2 == pe->s1->verbose)
|
if (2 == s1->verbose)
|
||||||
printf("-------------------------------\n");
|
printf("-------------------------------\n");
|
||||||
if (pe->s1->verbose)
|
if (s1->verbose)
|
||||||
printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset);
|
printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset);
|
||||||
|
|
||||||
if (s1->do_debug & 16)
|
if (s1->do_debug & 16)
|
||||||
@@ -848,7 +899,7 @@ static void pe_build_imports(struct pe_info *pe)
|
|||||||
|
|
||||||
dllindex = p->dll_index;
|
dllindex = p->dll_index;
|
||||||
if (dllindex)
|
if (dllindex)
|
||||||
name = tcc_basename((dllref = pe->s1->loaded_dlls[dllindex-1])->name);
|
name = tcc_basename((dllref = s1->loaded_dlls[dllindex-1])->name);
|
||||||
else
|
else
|
||||||
name = "", dllref = NULL;
|
name = "", dllref = NULL;
|
||||||
|
|
||||||
@@ -863,8 +914,8 @@ static void pe_build_imports(struct pe_info *pe)
|
|||||||
if (k < n) {
|
if (k < n) {
|
||||||
int iat_index = p->symbols[k]->iat_index;
|
int iat_index = p->symbols[k]->iat_index;
|
||||||
int sym_index = p->symbols[k]->sym_index;
|
int sym_index = p->symbols[k]->sym_index;
|
||||||
ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
|
ElfW(Sym) *imp_sym = (ElfW(Sym) *)s1->dynsymtab_section->data + sym_index;
|
||||||
const char *name = (char*)pe->s1->dynsymtab_section->link->data + imp_sym->st_name;
|
const char *name = (char*)s1->dynsymtab_section->link->data + imp_sym->st_name;
|
||||||
int ordinal;
|
int ordinal;
|
||||||
|
|
||||||
/* patch symbol (and possibly its underscored alias) */
|
/* patch symbol (and possibly its underscored alias) */
|
||||||
@@ -948,7 +999,7 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
|
sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
|
||||||
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
||||||
sym = (ElfW(Sym)*)symtab_section->data + sym_index;
|
sym = (ElfW(Sym)*)symtab_section->data + sym_index;
|
||||||
name = pe_export_name(pe->s1, sym);
|
name = pe_export_name(s1, sym);
|
||||||
if (sym->st_other & ST_PE_EXPORT) {
|
if (sym->st_other & ST_PE_EXPORT) {
|
||||||
p = tcc_malloc(sizeof *p);
|
p = tcc_malloc(sizeof *p);
|
||||||
p->index = sym_index;
|
p->index = sym_index;
|
||||||
@@ -997,7 +1048,7 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
tcc_error_noabort("could not create '%s': %s", buf, strerror(errno));
|
tcc_error_noabort("could not create '%s': %s", buf, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
|
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
|
||||||
if (pe->s1->verbose)
|
if (s1->verbose)
|
||||||
printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]);
|
printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1035,6 +1086,8 @@ static void pe_build_reloc (struct pe_info *pe)
|
|||||||
ElfW_Rel *rel, *rel_end;
|
ElfW_Rel *rel, *rel_end;
|
||||||
Section *s = NULL, *sr;
|
Section *s = NULL, *sr;
|
||||||
struct pe_reloc_header *hdr;
|
struct pe_reloc_header *hdr;
|
||||||
|
TCCState *s1 = pe->s1;
|
||||||
|
int dwarf = 0, n;
|
||||||
|
|
||||||
sh_addr = offset = block_ptr = count = i = 0;
|
sh_addr = offset = block_ptr = count = i = 0;
|
||||||
rel = rel_end = NULL;
|
rel = rel_end = NULL;
|
||||||
@@ -1046,6 +1099,11 @@ static void pe_build_reloc (struct pe_info *pe)
|
|||||||
++ rel;
|
++ rel;
|
||||||
if (type != REL_TYPE_DIRECT)
|
if (type != REL_TYPE_DIRECT)
|
||||||
continue;
|
continue;
|
||||||
|
if (dwarf) { /* don't runtime-relocate dwarf-to-dwarf */
|
||||||
|
n = ((ElfSym *)s1->symtab->data + ELFW(R_SYM)(rel[-1].r_info))->st_shndx;
|
||||||
|
if (n >= s1->dwlo && n < s1->dwhi)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (count == 0) { /* new block */
|
if (count == 0) { /* new block */
|
||||||
block_ptr = pe->reloc->data_offset;
|
block_ptr = pe->reloc->data_offset;
|
||||||
section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
|
section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
|
||||||
@@ -1065,6 +1123,7 @@ static void pe_build_reloc (struct pe_info *pe)
|
|||||||
rel = (ElfW_Rel *)sr->data;
|
rel = (ElfW_Rel *)sr->data;
|
||||||
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
|
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
|
||||||
sh_addr = s->sh_addr;
|
sh_addr = s->sh_addr;
|
||||||
|
dwarf = s->sh_num >= s1->dwlo && s->sh_num < s1->dwhi;
|
||||||
}
|
}
|
||||||
s = s->prev;
|
s = s->prev;
|
||||||
continue;
|
continue;
|
||||||
@@ -1133,8 +1192,8 @@ static int pe_assign_addresses (struct pe_info *pe)
|
|||||||
TCCState *s1 = pe->s1;
|
TCCState *s1 = pe->s1;
|
||||||
|
|
||||||
if (PE_DLL == pe->type)
|
if (PE_DLL == pe->type)
|
||||||
pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
|
pe->reloc = new_section(s1, ".reloc", SHT_PROGBITS, 0);
|
||||||
//pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
|
//pe->thunk = new_section(s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
|
||||||
|
|
||||||
nbs = s1->nb_sections;
|
nbs = s1->nb_sections;
|
||||||
sec_order = tcc_mallocz(2 * sizeof (int) * nbs);
|
sec_order = tcc_mallocz(2 * sizeof (int) * nbs);
|
||||||
@@ -1200,6 +1259,7 @@ static int pe_assign_addresses (struct pe_info *pe)
|
|||||||
si->pe_flags |= IMAGE_SCN_MEM_DISCARDABLE;
|
si->pe_flags |= IMAGE_SCN_MEM_DISCARDABLE;
|
||||||
|
|
||||||
add_section:
|
add_section:
|
||||||
|
s->sh_info = pe->sec_count; /* section number for coff syms */
|
||||||
addr += s->data_offset;
|
addr += s->data_offset;
|
||||||
si->sh_size = addr - si->sh_addr;
|
si->sh_size = addr - si->sh_addr;
|
||||||
if (s->sh_type != SHT_NOBITS) {
|
if (s->sh_type != SHT_NOBITS) {
|
||||||
@@ -1345,7 +1405,7 @@ static int pe_check_symbols(struct pe_info *pe)
|
|||||||
is->iat_index = sym_index;
|
is->iat_index = sym_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (pe->s1->rdynamic
|
} else if (s1->rdynamic
|
||||||
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
|
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
|
||||||
/* if -rdynamic option, then export all non local symbols */
|
/* if -rdynamic option, then export all non local symbols */
|
||||||
sym->st_other |= ST_PE_EXPORT;
|
sym->st_other |= ST_PE_EXPORT;
|
||||||
|
|||||||
Reference in New Issue
Block a user