mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
Fix bound checking dlcose problem
The main problem is that an application called dlclose and then had a bound checking problem. The list of dll's in tccrun was not updated an caused a crash. Also fixed some minor other things. tccdbg.c: - Allow filenames like ../file.c - Rewrite DWARF_ABBREV_MEMBER_BF/DWARF_ABBREV_MEMBER a bit tccelf.c: - Add call to __bt_exit. This solves problem when dlclose is called tccrun.c: - Rewrite rt_printline_dwarf a litlle to use opcode_length correctly - Do not stop at DW_LNE_end_sequence - Fix DW_LNE_set_address again. Works now in *bsd. lib/bt-exe.c lib/bt-dll.c: - Add __bt_exit/__bound_exit_dll lib/bcheck.c: - Add __bound_exit_dll
This commit is contained in:
parent
4c82b00342
commit
aaec564a82
20
lib/bcheck.c
20
lib/bcheck.c
@ -270,6 +270,7 @@ DLL_EXPORT void FASTCALL __bound_local_delete(void *p1);
|
||||
void __bound_init(size_t *, int);
|
||||
void __bound_main_arg(int argc, char **argv, char **envp);
|
||||
void __bound_exit(void);
|
||||
void __bound_exit_dll(size_t *);
|
||||
#if !defined(_WIN32)
|
||||
void *__bound_mmap (void *start, size_t size, int prot, int flags, int fd,
|
||||
off_t offset);
|
||||
@ -1255,6 +1256,25 @@ void __attribute__((destructor)) __bound_exit(void)
|
||||
}
|
||||
}
|
||||
|
||||
void __bound_exit_dll(size_t *p)
|
||||
{
|
||||
dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
|
||||
|
||||
if (p) {
|
||||
while (p[0] != 0) {
|
||||
tree = splay_delete(p[0], tree);
|
||||
#if BOUND_DEBUG
|
||||
if (print_calls) {
|
||||
dprintf(stderr, "%s, %s(): remove static var %p 0x%lx\n",
|
||||
__FILE__, __FUNCTION__,
|
||||
(void *) p[0], (unsigned long) p[1]);
|
||||
}
|
||||
#endif
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_PTHREAD_CREATE
|
||||
typedef struct {
|
||||
void *(*start_routine) (void *);
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#define REDIR_ALL \
|
||||
REDIR(__bt_init) \
|
||||
REDIR(__bt_exit) \
|
||||
REDIR(__bound_exit_dll) \
|
||||
REDIR(tcc_backtrace) \
|
||||
\
|
||||
REDIR(__bound_ptr_add) \
|
||||
|
18
lib/bt-exe.c
18
lib/bt-exe.c
@ -30,11 +30,27 @@ void __bt_init(rt_context *p, int num_callers)
|
||||
__rt_error = _rt_error;
|
||||
set_exception_handler();
|
||||
} else {
|
||||
p->num_callers = -1;
|
||||
p->next = rc->next, rc->next = p;
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(dllexport)
|
||||
void __bt_exit(rt_context *p)
|
||||
{
|
||||
__attribute__((weak)) void __bound_exit_dll(void*);
|
||||
struct rt_context *rc = &g_rtctxt;
|
||||
|
||||
if (__bound_exit_dll && p->bounds_start)
|
||||
__bound_exit_dll(p->bounds_start);
|
||||
while (rc) {
|
||||
if (rc->next == p) {
|
||||
rc->next = rc->next->next;
|
||||
break;
|
||||
}
|
||||
rc = rc->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy a string and truncate it. */
|
||||
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s)
|
||||
{
|
||||
|
60
tccdbg.c
60
tccdbg.c
@ -541,7 +541,7 @@ static void dwarf_file(TCCState *s1)
|
||||
|
||||
filename = strrchr(file->filename, '/');
|
||||
if (filename == NULL) {
|
||||
for (i = 1; i < dwarf_line.filename_size; i++)
|
||||
for (i = 0; i < dwarf_line.filename_size; i++)
|
||||
if (dwarf_line.filename_table[i].dir_entry == 0 &&
|
||||
strcmp(dwarf_line.filename_table[i].name,
|
||||
file->filename) == 0) {
|
||||
@ -685,6 +685,7 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
|
||||
if (s1->dwarf) {
|
||||
int start_abbrev;
|
||||
unsigned char *ptr;
|
||||
char *undo;
|
||||
|
||||
/* dwarf_abbrev */
|
||||
start_abbrev = dwarf_abbrev_section->data_offset;
|
||||
@ -775,18 +776,32 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
|
||||
dwarf_data1(dwarf_line_section, DWARF_OPCODE_BASE);
|
||||
ptr = section_ptr_add(dwarf_line_section, sizeof(dwarf_line_opcodes));
|
||||
memcpy(ptr, dwarf_line_opcodes, sizeof(dwarf_line_opcodes));
|
||||
dwarf_line.dir_size = 1;
|
||||
dwarf_line.dir_table = (char **) tcc_malloc(sizeof (char *));
|
||||
undo = strrchr(filename, '/');
|
||||
if (undo)
|
||||
*undo = 0;
|
||||
dwarf_line.dir_size = 1 + (undo != NULL);
|
||||
dwarf_line.dir_table = (char **) tcc_malloc(sizeof (char *) *
|
||||
dwarf_line.dir_size);
|
||||
dwarf_line.dir_table[0] = tcc_strdup(buf);
|
||||
/* line state machine starts with file 1 instead of 0 */
|
||||
if (undo)
|
||||
dwarf_line.dir_table[1] = tcc_strdup(filename);
|
||||
dwarf_line.filename_size = 2;
|
||||
dwarf_line.filename_table =
|
||||
(struct dwarf_filename_struct *)
|
||||
tcc_malloc(2*sizeof (struct dwarf_filename_struct));
|
||||
dwarf_line.filename_table[0].dir_entry = 0;
|
||||
if (undo) {
|
||||
dwarf_line.filename_table[0].name = tcc_strdup(filename);
|
||||
dwarf_line.filename_table[1].dir_entry = 1;
|
||||
dwarf_line.filename_table[1].name = tcc_strdup(undo + 1);
|
||||
*undo = '/';
|
||||
dwarf_line.filename_table[0].name = tcc_strdup(filename);
|
||||
}
|
||||
else {
|
||||
dwarf_line.filename_table[0].name = tcc_strdup(filename);
|
||||
dwarf_line.filename_table[1].dir_entry = 0;
|
||||
dwarf_line.filename_table[1].name = tcc_strdup(filename);
|
||||
}
|
||||
dwarf_line.line_size = dwarf_line.line_max_size = 0;
|
||||
dwarf_line.line_data = NULL;
|
||||
dwarf_line.cur_file = 1;
|
||||
@ -1020,7 +1035,8 @@ ST_FUNC void tcc_debug_bincl(TCCState *s1)
|
||||
}
|
||||
if (strcmp(filename, "<command line>")) {
|
||||
for (j = 0; j < dwarf_line.filename_size; j++)
|
||||
if (strcmp (dwarf_line.filename_table[j].name, filename) == 0)
|
||||
if (dwarf_line.filename_table[j].dir_entry == i &&
|
||||
strcmp (dwarf_line.filename_table[j].name, filename) == 0)
|
||||
break;
|
||||
if (j == dwarf_line.filename_size) {
|
||||
dwarf_line.filename_table =
|
||||
@ -1428,33 +1444,26 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
||||
i = 0;
|
||||
while (e->next) {
|
||||
e = e->next;
|
||||
dwarf_data1(dwarf_info_section,
|
||||
e->type.t & VT_BITFIELD ? DWARF_ABBREV_MEMBER_BF
|
||||
: DWARF_ABBREV_MEMBER);
|
||||
dwarf_strp(dwarf_info_section,
|
||||
(e->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
|
||||
? "" : get_tok_str(e->v & ~SYM_FIELD, NULL));
|
||||
dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
|
||||
dwarf_uleb128(dwarf_info_section, file->line_num);
|
||||
pos_type[i++] = dwarf_info_section->data_offset;
|
||||
dwarf_data4(dwarf_info_section, 0);
|
||||
if (e->type.t & VT_BITFIELD) {
|
||||
int pos = e->c * 8 + BIT_POS(e->type.t);
|
||||
int size = BIT_SIZE(e->type.t);
|
||||
|
||||
dwarf_data1(dwarf_info_section, DWARF_ABBREV_MEMBER_BF);
|
||||
dwarf_strp(dwarf_info_section,
|
||||
(e->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
|
||||
? "" : get_tok_str(e->v & ~SYM_FIELD, NULL));
|
||||
dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
|
||||
dwarf_uleb128(dwarf_info_section, file->line_num);
|
||||
pos_type[i++] = dwarf_info_section->data_offset;
|
||||
dwarf_data4(dwarf_info_section, 0);
|
||||
dwarf_uleb128(dwarf_info_section, size);
|
||||
dwarf_uleb128(dwarf_info_section, pos);
|
||||
}
|
||||
else {
|
||||
dwarf_data1(dwarf_info_section, DWARF_ABBREV_MEMBER);
|
||||
dwarf_strp(dwarf_info_section,
|
||||
(e->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
|
||||
? "" : get_tok_str(e->v & ~SYM_FIELD, NULL));
|
||||
dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
|
||||
dwarf_uleb128(dwarf_info_section, file->line_num);
|
||||
pos_type[i++] = dwarf_info_section->data_offset;
|
||||
dwarf_data4(dwarf_info_section, 0);
|
||||
else
|
||||
dwarf_uleb128(dwarf_info_section, e->c);
|
||||
}
|
||||
}
|
||||
dwarf_data1(dwarf_info_section, 0);
|
||||
write32le(dwarf_info_section->data + pos_sib,
|
||||
dwarf_info_section->data_offset - dwarf_info.start);
|
||||
@ -1785,12 +1794,13 @@ ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym)
|
||||
dwarf_info.func = sym;
|
||||
dwarf_info.line = file->line_num;
|
||||
if (s1->do_backtrace) {
|
||||
int i;
|
||||
int i, len;
|
||||
|
||||
dwarf_line_op(s1, 0); // extended
|
||||
dwarf_uleb128_op(s1, strlen(funcname) + 2);
|
||||
dwarf_line_op(s1, DW_LNE_hi_user - 1);
|
||||
for (i = 0; i < strlen(funcname) + 1; i++)
|
||||
len = strlen(funcname) + 1;
|
||||
for (i = 0; i < len; i++)
|
||||
dwarf_line_op(s1, funcname[i]);
|
||||
}
|
||||
}
|
||||
|
9
tccelf.c
9
tccelf.c
@ -1389,15 +1389,14 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
||||
put_ptr(s1, dwarf_line_str_section, 0);
|
||||
else
|
||||
put_ptr(s1, dwarf_str_section, 0);
|
||||
put_ptr(s1, text_section, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
put_ptr(s1, stab_section, 0);
|
||||
put_ptr(s1, stab_section, -1);
|
||||
put_ptr(s1, stab_section->link, 0);
|
||||
section_ptr_add(s, PTR_SIZE);
|
||||
}
|
||||
*(addr_t *)section_ptr_add(s, PTR_SIZE) = s1->dwarf;
|
||||
/* skip esym_start/esym_end/elf_str (not loaded) */
|
||||
section_ptr_add(s, 3 * PTR_SIZE);
|
||||
/* prog_base : local nameless symbol with offset 0 at SHN_ABS */
|
||||
@ -1412,7 +1411,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
||||
section_ptr_add(s, n);
|
||||
cstr_new(&cstr);
|
||||
cstr_printf(&cstr,
|
||||
"extern void __bt_init(),__bt_init_dll();"
|
||||
"extern void __bt_init(),__bt_exit(),__bt_init_dll();"
|
||||
"static void *__rt_info[];"
|
||||
"__attribute__((constructor)) static void __bt_init_rt(){");
|
||||
#ifdef TCC_TARGET_PE
|
||||
@ -1425,6 +1424,10 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
||||
#endif
|
||||
cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
|
||||
s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1);
|
||||
/* In case dlcose is called by application */
|
||||
cstr_printf(&cstr,
|
||||
"__attribute__((destructor)) static void __bt_exit_rt(){"
|
||||
"__bt_exit(__rt_info);}");
|
||||
tcc_compile_string_no_debug(s1, cstr.data);
|
||||
cstr_free(&cstr);
|
||||
set_local_sym(s1, &"___rt_info"[!s1->leading_underscore], s, o);
|
||||
|
94
tccrun.c
94
tccrun.c
@ -34,9 +34,9 @@ typedef struct rt_context
|
||||
};
|
||||
struct {
|
||||
unsigned char *dwarf_line, *dwarf_line_end, *dwarf_line_str;
|
||||
addr_t dwarf_text;
|
||||
};
|
||||
};
|
||||
addr_t dwarf;
|
||||
ElfW(Sym) *esym_start, *esym_end;
|
||||
char *elf_str;
|
||||
addr_t prog_base;
|
||||
@ -182,15 +182,14 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
rc->dwarf_line_end = dwarf_line_section->data + dwarf_line_section->data_offset;
|
||||
if (dwarf_line_str_section)
|
||||
rc->dwarf_line_str = dwarf_line_str_section->data;
|
||||
rc->dwarf_text = text_section->sh_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc->stab_sym = (Stab_Sym *)stab_section->data;
|
||||
rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
|
||||
rc->stab_str = (char *)stab_section->link->data;
|
||||
rc->dwarf_text = 0;
|
||||
}
|
||||
rc->dwarf = s1->dwarf;
|
||||
rc->esym_start = (ElfW(Sym) *)(symtab_section->data);
|
||||
rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
||||
rc->elf_str = (char *)symtab_section->link->data;
|
||||
@ -666,7 +665,9 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
|
||||
unsigned char *ln;
|
||||
unsigned char *cp;
|
||||
unsigned char *end;
|
||||
unsigned int size;
|
||||
unsigned char *opcode_length;
|
||||
unsigned long long size;
|
||||
unsigned int length;
|
||||
unsigned char version;
|
||||
unsigned int min_insn_length;
|
||||
unsigned int max_ops_per_insn;
|
||||
@ -678,7 +679,7 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
unsigned int len;
|
||||
unsigned int value;
|
||||
unsigned long long value;
|
||||
struct {
|
||||
unsigned int type;
|
||||
unsigned int form;
|
||||
@ -695,13 +696,11 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
|
||||
addr_t last_pc;
|
||||
addr_t pc;
|
||||
addr_t func_addr;
|
||||
addr_t offset_dll;
|
||||
int line;
|
||||
char *filename;
|
||||
char *function;
|
||||
|
||||
next:
|
||||
offset_dll = 0;
|
||||
ln = rc->dwarf_line;
|
||||
while (ln < rc->dwarf_line_end) {
|
||||
dir_size = 0;
|
||||
@ -712,13 +711,18 @@ next:
|
||||
line = 1;
|
||||
filename = NULL;
|
||||
function = NULL;
|
||||
length = 4;
|
||||
size = dwarf_read_4(ln, rc->dwarf_line_end);
|
||||
if (size == 0xffffffffu) // dwarf 64
|
||||
length = 8, size = dwarf_read_8(ln, rc->dwarf_line_end);
|
||||
end = ln + size;
|
||||
if (end < ln || end > rc->dwarf_line_end)
|
||||
break;
|
||||
version = dwarf_read_2(ln, end);
|
||||
if (version >= 5)
|
||||
ln += 6; // address size, segment selector, prologue Length
|
||||
ln += length + 2; // address size, segment selector, prologue Length
|
||||
else
|
||||
ln += 4; // prologue Length
|
||||
ln += length; // prologue Length
|
||||
min_insn_length = dwarf_read_1(ln, end);
|
||||
if (version >= 4)
|
||||
max_ops_per_insn = dwarf_read_1(ln, end);
|
||||
@ -729,8 +733,9 @@ next:
|
||||
line_base |= line_base >= 0x80 ? ~0xff : 0;
|
||||
line_range = dwarf_read_1(ln, end);
|
||||
opcode_base = dwarf_read_1(ln, end);
|
||||
opcode_length = ln;
|
||||
ln += opcode_base - 1;
|
||||
opindex = 0;
|
||||
ln += 12;
|
||||
if (version >= 5) {
|
||||
col = dwarf_read_1(ln, end);
|
||||
for (i = 0; i < col; i++) {
|
||||
@ -744,11 +749,13 @@ next:
|
||||
if (entry_format[j].form != DW_FORM_line_strp)
|
||||
goto next_line;
|
||||
#if 0
|
||||
value = dwarf_read_4(ln, end);
|
||||
value = length == 4 ? dwarf_read_4(ln, end)
|
||||
: dwarf_read_8(ln, end);
|
||||
if (i < DIR_TABLE_SIZE)
|
||||
dirs[i] = (char *)rc->dwarf_line_str + value;
|
||||
#else
|
||||
dwarf_read_4(ln, end);
|
||||
length == 4 ? dwarf_read_4(ln, end)
|
||||
: dwarf_read_8(ln, end);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@ -766,7 +773,8 @@ next:
|
||||
if (entry_format[j].type == DW_LNCT_path) {
|
||||
if (entry_format[j].form != DW_FORM_line_strp)
|
||||
goto next_line;
|
||||
value = dwarf_read_4(ln, end);
|
||||
value = length == 4 ? dwarf_read_4(ln, end)
|
||||
: dwarf_read_8(ln, end);
|
||||
if (i < FILE_TABLE_SIZE)
|
||||
filename_table[i].name =
|
||||
(char *)rc->dwarf_line_str + value;
|
||||
@ -813,7 +821,24 @@ next:
|
||||
filename = filename_table[0].name;
|
||||
while (ln < end) {
|
||||
last_pc = pc;
|
||||
switch (dwarf_read_1(ln, end)) {
|
||||
i = dwarf_read_1(ln, end);
|
||||
if (i >= opcode_base) {
|
||||
if (max_ops_per_insn == 1)
|
||||
pc += ((i - opcode_base) / line_range) * min_insn_length;
|
||||
else {
|
||||
pc += (opindex + (i - opcode_base) / line_range) /
|
||||
max_ops_per_insn * min_insn_length;
|
||||
opindex = (opindex + (i - opcode_base) / line_range) %
|
||||
max_ops_per_insn;
|
||||
}
|
||||
i = (int)((i - opcode_base) % line_range) + line_base;
|
||||
check_pc:
|
||||
if (pc >= wanted_pc && wanted_pc >= last_pc)
|
||||
goto found;
|
||||
line += i;
|
||||
}
|
||||
else {
|
||||
switch (i) {
|
||||
case 0:
|
||||
len = dwarf_read_uleb128(&ln, end);
|
||||
cp = ln;
|
||||
@ -822,19 +847,13 @@ next:
|
||||
goto next_line;
|
||||
switch (dwarf_read_1(cp, end)) {
|
||||
case DW_LNE_end_sequence:
|
||||
goto next_line;
|
||||
break;
|
||||
case DW_LNE_set_address:
|
||||
#if PTR_SIZE == 4
|
||||
pc = dwarf_read_4(cp, end);
|
||||
#else
|
||||
pc = dwarf_read_8(cp, end);
|
||||
#endif
|
||||
if (rc->num_callers < 0) {
|
||||
/* dll */
|
||||
if (!offset_dll)
|
||||
offset_dll = pc;
|
||||
pc = rc->dwarf_text + (pc - offset_dll);
|
||||
}
|
||||
opindex = 0;
|
||||
break;
|
||||
case DW_LNE_define_file: /* deprecated */
|
||||
@ -859,8 +878,6 @@ next:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DW_LNS_copy:
|
||||
break;
|
||||
case DW_LNS_advance_pc:
|
||||
if (max_ops_per_insn == 1)
|
||||
pc += dwarf_read_uleb128(&ln, end) * min_insn_length;
|
||||
@ -881,13 +898,6 @@ next:
|
||||
if (i < FILE_TABLE_SIZE && i < filename_size)
|
||||
filename = filename_table[i].name;
|
||||
break;
|
||||
case DW_LNS_set_column:
|
||||
dwarf_read_uleb128(&ln, end);
|
||||
break;
|
||||
case DW_LNS_negate_stmt:
|
||||
break;
|
||||
case DW_LNS_set_basic_block:
|
||||
break;
|
||||
case DW_LNS_const_add_pc:
|
||||
if (max_ops_per_insn == 1)
|
||||
pc += ((255 - opcode_base) / line_range) * min_insn_length;
|
||||
@ -906,29 +916,11 @@ next:
|
||||
opindex = 0;
|
||||
i = 0;
|
||||
goto check_pc;
|
||||
case DW_LNS_set_prologue_end:
|
||||
break;
|
||||
case DW_LNS_set_epilogue_begin:
|
||||
break;
|
||||
case DW_LNS_set_isa:
|
||||
default:
|
||||
for (j = 0; j < opcode_length[i - 1]; j++)
|
||||
dwarf_read_uleb128 (&ln, end);
|
||||
break;
|
||||
default:
|
||||
i = ln[-1];
|
||||
if (max_ops_per_insn == 1)
|
||||
pc += ((i - opcode_base) / line_range) * min_insn_length;
|
||||
else {
|
||||
pc += (opindex + (i - opcode_base) / line_range) /
|
||||
max_ops_per_insn * min_insn_length;
|
||||
opindex = (opindex + (i - opcode_base) / line_range) %
|
||||
max_ops_per_insn;
|
||||
}
|
||||
i = (int)((i - opcode_base) % line_range) + line_base;
|
||||
check_pc:
|
||||
if (pc >= wanted_pc && wanted_pc >= last_pc)
|
||||
goto found;
|
||||
line += i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
next_line:
|
||||
@ -988,7 +980,7 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
|
||||
ret = rt_get_caller_pc(&pc, rc, i);
|
||||
a = "%s";
|
||||
if (ret != -1) {
|
||||
if ((addr_t)rc->dwarf_text)
|
||||
if (rc->dwarf)
|
||||
pc = rt_printline_dwarf(rc, pc, level ? "by" : "at", skip);
|
||||
else
|
||||
pc = rt_printline(rc, pc, level ? "by" : "at", skip);
|
||||
|
Loading…
Reference in New Issue
Block a user