Add dwarf support
The new gcc12 release does not support stabs any more. This was a good reason to add support for dwarf. The stabs code still works and is used if configure option --dwarf is not used. Tested on x86_64, i386, arm, arm64, riscv64 with dwarf-5. Some debuggers may not support dwarf-5. Try using older dwarf versions i that case. The tccmacho.c code probably need some support for dwarf. arm-gen.c, arm64-gen.c, i386-gen.c, riscv64-gen.c, x86_64-gen. - fix get_sym_ref symbol size arm-link.c, arm64-link.c, i386-link.c, riscv64-link.c, x86_64-link.c - add R_DATA_32U libtcc.c: - parse -gdwarf option tcc.c: - add dwarf option tcc.h: - add dwarf option and sections tccelf.c: - init dwarf sections - avoid adding sh_addr for dwarf sections - remove dwarf relocs for output dll - add dwarf sections for tccrun tccgen.c: - add dwarf defines + global data - add dwarf_* functions - mix dwarf code with stabs code - a trick is used to emit function name in .debug_line section so only this section has to be parsed instead of .debug_info and .debug_abbrev. - fix init debug_modes tccrun.c: - add dwarf sections in rt_context - init them in tcc_run - add new dwarf code rt_printline_dwarf to find file/function dwarf.h: - New file tcc-doc.texi: - document dwarf configure: - add dwarf option lib/Makefile - change -gstabs into -gdwarf lib/bt-exe.c, tests/tests2/Makefile, tests/tests2/126_bound_global: - Add __bound_init call - Add new testcase to test it
This commit is contained in:
parent
d3e940c71c
commit
2f2708a769
26 changed files with 2754 additions and 144 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -24,6 +24,7 @@ config*.h
|
||||||
config*.mak
|
config*.mak
|
||||||
config.texi
|
config.texi
|
||||||
conftest*
|
conftest*
|
||||||
|
c2str
|
||||||
tags
|
tags
|
||||||
TAGS
|
TAGS
|
||||||
tcc.1
|
tcc.1
|
||||||
|
|
|
@ -866,7 +866,7 @@ static void gen_bounds_epilog(void)
|
||||||
*bounds_ptr = 0;
|
*bounds_ptr = 0;
|
||||||
|
|
||||||
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
||||||
func_bound_offset, lbounds_section->data_offset);
|
func_bound_offset, PTR_SIZE);
|
||||||
|
|
||||||
/* generate bound local allocation */
|
/* generate bound local allocation */
|
||||||
if (offset_modified) {
|
if (offset_modified) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
/* relocation type for 32 bit data relocation */
|
/* relocation type for 32 bit data relocation */
|
||||||
#define R_DATA_32 R_ARM_ABS32
|
#define R_DATA_32 R_ARM_ABS32
|
||||||
|
#define R_DATA_32U R_ARM_ABS32
|
||||||
#define R_DATA_PTR R_ARM_ABS32
|
#define R_DATA_PTR R_ARM_ABS32
|
||||||
#define R_JMP_SLOT R_ARM_JUMP_SLOT
|
#define R_JMP_SLOT R_ARM_JUMP_SLOT
|
||||||
#define R_GLOB_DAT R_ARM_GLOB_DAT
|
#define R_GLOB_DAT R_ARM_GLOB_DAT
|
||||||
|
|
|
@ -710,7 +710,7 @@ static void gen_bounds_epilog(void)
|
||||||
*bounds_ptr = 0;
|
*bounds_ptr = 0;
|
||||||
|
|
||||||
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
||||||
func_bound_offset, lbounds_section->data_offset);
|
func_bound_offset, PTR_SIZE);
|
||||||
|
|
||||||
/* generate bound local allocation */
|
/* generate bound local allocation */
|
||||||
if (offset_modified) {
|
if (offset_modified) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#define EM_TCC_TARGET EM_AARCH64
|
#define EM_TCC_TARGET EM_AARCH64
|
||||||
|
|
||||||
#define R_DATA_32 R_AARCH64_ABS32
|
#define R_DATA_32 R_AARCH64_ABS32
|
||||||
|
#define R_DATA_32U R_AARCH64_ABS32
|
||||||
#define R_DATA_PTR R_AARCH64_ABS64
|
#define R_DATA_PTR R_AARCH64_ABS64
|
||||||
#define R_JMP_SLOT R_AARCH64_JUMP_SLOT
|
#define R_JMP_SLOT R_AARCH64_JUMP_SLOT
|
||||||
#define R_GLOB_DAT R_AARCH64_GLOB_DAT
|
#define R_GLOB_DAT R_AARCH64_GLOB_DAT
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
/* relocation type for 32 bit data relocation */
|
/* relocation type for 32 bit data relocation */
|
||||||
#define R_DATA_32 R_C60_32
|
#define R_DATA_32 R_C60_32
|
||||||
|
#define R_DATA_32U R_C60_32
|
||||||
#define R_DATA_PTR R_C60_32
|
#define R_DATA_PTR R_C60_32
|
||||||
#define R_JMP_SLOT R_C60_JMP_SLOT
|
#define R_JMP_SLOT R_C60_JMP_SLOT
|
||||||
#define R_GLOB_DAT R_C60_GLOB_DAT
|
#define R_GLOB_DAT R_C60_GLOB_DAT
|
||||||
|
|
5
configure
vendored
5
configure
vendored
|
@ -51,6 +51,7 @@ ar_set=
|
||||||
darwin=
|
darwin=
|
||||||
cpu=
|
cpu=
|
||||||
cpuver=
|
cpuver=
|
||||||
|
dwarf=
|
||||||
|
|
||||||
# OS specific
|
# OS specific
|
||||||
cpu_sys=`uname -m`
|
cpu_sys=`uname -m`
|
||||||
|
@ -136,6 +137,8 @@ for opt do
|
||||||
;;
|
;;
|
||||||
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2-`
|
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2-`
|
||||||
;;
|
;;
|
||||||
|
--dwarf=*) dwarf=`echo $opt | cut -d '=' -f 2-`
|
||||||
|
;;
|
||||||
--enable-cross) confvars="$confvars cross"
|
--enable-cross) confvars="$confvars cross"
|
||||||
;;
|
;;
|
||||||
--disable-static) confvars="$confvars static=no"
|
--disable-static) confvars="$confvars static=no"
|
||||||
|
@ -328,6 +331,7 @@ Advanced options (experts only):
|
||||||
--config-backtrace=no disable stack backtraces (with -run or -bt)
|
--config-backtrace=no disable stack backtraces (with -run or -bt)
|
||||||
--config-bcheck=no disable bounds checker (-b)
|
--config-bcheck=no disable bounds checker (-b)
|
||||||
--config-predefs=no do not compile tccdefs.h, instead just include
|
--config-predefs=no do not compile tccdefs.h, instead just include
|
||||||
|
--dwarf=x Use dwarf debug info instead of stabs (x=2..5)
|
||||||
EOF
|
EOF
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
@ -493,6 +497,7 @@ print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
|
||||||
print_mak CONFIG_LDDIR "$tcc_lddir"
|
print_mak CONFIG_LDDIR "$tcc_lddir"
|
||||||
print_mak CONFIG_TRIPLET "$triplet"
|
print_mak CONFIG_TRIPLET "$triplet"
|
||||||
print_mak TCC_CPU_VERSION "$cpuver" num
|
print_mak TCC_CPU_VERSION "$cpuver" num
|
||||||
|
print_mak CONFIG_DWARF "$dwarf"
|
||||||
|
|
||||||
echo "ARCH=$cpu" >> config.mak
|
echo "ARCH=$cpu" >> config.mak
|
||||||
echo "TARGETOS=$targetos" >> config.mak
|
echo "TARGETOS=$targetos" >> config.mak
|
||||||
|
|
|
@ -1071,7 +1071,7 @@ static void gen_bounds_epilog(void)
|
||||||
*bounds_ptr = 0;
|
*bounds_ptr = 0;
|
||||||
|
|
||||||
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
||||||
func_bound_offset, lbounds_section->data_offset);
|
func_bound_offset, PTR_SIZE);
|
||||||
|
|
||||||
/* generate bound local allocation */
|
/* generate bound local allocation */
|
||||||
if (offset_modified) {
|
if (offset_modified) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
/* relocation type for 32 bit data relocation */
|
/* relocation type for 32 bit data relocation */
|
||||||
#define R_DATA_32 R_386_32
|
#define R_DATA_32 R_386_32
|
||||||
|
#define R_DATA_32U R_386_32
|
||||||
#define R_DATA_PTR R_386_32
|
#define R_DATA_PTR R_386_32
|
||||||
#define R_JMP_SLOT R_386_JMP_SLOT
|
#define R_JMP_SLOT R_386_JMP_SLOT
|
||||||
#define R_GLOB_DAT R_386_GLOB_DAT
|
#define R_GLOB_DAT R_386_GLOB_DAT
|
||||||
|
|
|
@ -27,7 +27,7 @@ arm-libtcc1-usegcc ?= no
|
||||||
ifeq "$($(T)-libtcc1-usegcc)" "yes"
|
ifeq "$($(T)-libtcc1-usegcc)" "yes"
|
||||||
XCC = $(CC)
|
XCC = $(CC)
|
||||||
XAR = $(AR)
|
XAR = $(AR)
|
||||||
XFLAGS = $(CFLAGS) -fPIC -gstabs -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable
|
XFLAGS = $(CFLAGS) -fPIC -gdwarf -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(CONFIG_backtrace),no)
|
ifneq ($(CONFIG_backtrace),no)
|
||||||
|
|
|
@ -18,6 +18,10 @@ void __bt_init(rt_context *p, int num_callers)
|
||||||
__attribute__((weak)) void __bound_init(void*, int);
|
__attribute__((weak)) void __bound_init(void*, int);
|
||||||
struct rt_context *rc = &g_rtctxt;
|
struct rt_context *rc = &g_rtctxt;
|
||||||
//fprintf(stderr, "__bt_init %d %p %p\n", num_callers, p->stab_sym, p->bounds_start), fflush(stderr);
|
//fprintf(stderr, "__bt_init %d %p %p\n", num_callers, p->stab_sym, p->bounds_start), fflush(stderr);
|
||||||
|
/* call __bound_init here due to redirection of sigaction */
|
||||||
|
/* needed to add global symbols */
|
||||||
|
if (__bound_init && p->bounds_start)
|
||||||
|
__bound_init(p->bounds_start, -1);
|
||||||
if (num_callers) {
|
if (num_callers) {
|
||||||
memcpy(rc, p, offsetof(rt_context, next));
|
memcpy(rc, p, offsetof(rt_context, next));
|
||||||
rc->num_callers = num_callers - 1;
|
rc->num_callers = num_callers - 1;
|
||||||
|
|
19
libtcc.c
19
libtcc.c
|
@ -1722,6 +1722,12 @@ static void args_parser_listfile(TCCState *s,
|
||||||
*pargc = s->argc = argc, *pargv = s->argv = argv;
|
*pargc = s->argc = argc, *pargv = s->argv = argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DWARF
|
||||||
|
#define DWARF_VERSION atoi(CONFIG_DWARF)
|
||||||
|
#else
|
||||||
|
#define DWARF_VERSION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
|
PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
|
||||||
{
|
{
|
||||||
TCCState *s1 = s;
|
TCCState *s1 = s;
|
||||||
|
@ -1819,6 +1825,7 @@ reparse:
|
||||||
s->rt_num_callers = atoi(optarg);
|
s->rt_num_callers = atoi(optarg);
|
||||||
s->do_backtrace = 1;
|
s->do_backtrace = 1;
|
||||||
s->do_debug = 1;
|
s->do_debug = 1;
|
||||||
|
s->dwarf = DWARF_VERSION;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
@ -1826,16 +1833,22 @@ reparse:
|
||||||
s->do_bounds_check = 1;
|
s->do_bounds_check = 1;
|
||||||
s->do_backtrace = 1;
|
s->do_backtrace = 1;
|
||||||
s->do_debug = 1;
|
s->do_debug = 1;
|
||||||
|
s->dwarf = DWARF_VERSION;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case TCC_OPTION_g:
|
case TCC_OPTION_g:
|
||||||
/* Use "-g" as alias for "-g1". Use "-g0" to disable debug */
|
/* Use "-g" as alias for "-g1". Use "-g0" to disable debug */
|
||||||
/* Other common used values: "-g0", "-g1", "-g2" and "-g3" */
|
/* Other common used values: "-g0", "-g1", "-g2" and "-g3" */
|
||||||
/* no failure with unsupported options */
|
/* no failure with unsupported options */
|
||||||
if (isnum(*optarg))
|
s->do_debug = 1;
|
||||||
|
s->dwarf = DWARF_VERSION;
|
||||||
|
if (*optarg == 'd') {
|
||||||
|
s->dwarf = 5;
|
||||||
|
if (!strncmp(optarg,"dwarf-",6))
|
||||||
|
s->dwarf = atoi(optarg + 6);
|
||||||
|
}
|
||||||
|
else if (isnum(*optarg))
|
||||||
s->do_debug = atoi(optarg);
|
s->do_debug = atoi(optarg);
|
||||||
else
|
|
||||||
s->do_debug = 1;
|
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_c:
|
case TCC_OPTION_c:
|
||||||
x = TCC_OUTPUT_OBJ;
|
x = TCC_OUTPUT_OBJ;
|
||||||
|
|
|
@ -471,7 +471,7 @@ static void gen_bounds_epilog(void)
|
||||||
*bounds_ptr = 0;
|
*bounds_ptr = 0;
|
||||||
|
|
||||||
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
||||||
func_bound_offset, lbounds_section->data_offset);
|
func_bound_offset, PTR_SIZE);
|
||||||
|
|
||||||
label.type.t = VT_VOID | VT_STATIC;
|
label.type.t = VT_VOID | VT_STATIC;
|
||||||
/* generate bound local allocation */
|
/* generate bound local allocation */
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#define EM_TCC_TARGET EM_RISCV
|
#define EM_TCC_TARGET EM_RISCV
|
||||||
|
|
||||||
#define R_DATA_32 R_RISCV_32
|
#define R_DATA_32 R_RISCV_32
|
||||||
|
#define R_DATA_32U R_RISCV_32
|
||||||
#define R_DATA_PTR R_RISCV_64
|
#define R_DATA_PTR R_RISCV_64
|
||||||
#define R_JMP_SLOT R_RISCV_JUMP_SLOT
|
#define R_JMP_SLOT R_RISCV_JUMP_SLOT
|
||||||
#define R_GLOB_DAT R_RISCV_64
|
#define R_GLOB_DAT R_RISCV_64
|
||||||
|
|
|
@ -349,12 +349,15 @@ Turn on/off linking of all objects in archives.
|
||||||
Debugger options:
|
Debugger options:
|
||||||
|
|
||||||
@table @option
|
@table @option
|
||||||
@item -g
|
@item -g[x]
|
||||||
Generate run time debug information so that you get clear run time
|
Generate run time stab debug information so that you get clear run time
|
||||||
error messages: @code{ test.c:68: in function 'test5()': dereferencing
|
error messages: @code{ test.c:68: in function 'test5()': dereferencing
|
||||||
invalid pointer} instead of the laconic @code{Segmentation
|
invalid pointer} instead of the laconic @code{Segmentation
|
||||||
fault}.
|
fault}.
|
||||||
|
|
||||||
|
@item -gdwarf[-x]
|
||||||
|
Generate run time dwarf debug information instead of stab debug information.
|
||||||
|
|
||||||
@item -b
|
@item -b
|
||||||
Generate additional support code to check memory allocations and array/pointer
|
Generate additional support code to check memory allocations and array/pointer
|
||||||
bounds (@pxref{Bounds}). @option{-g} is implied.
|
bounds (@pxref{Bounds}). @option{-g} is implied.
|
||||||
|
|
3
tcc.c
3
tcc.c
|
@ -58,7 +58,8 @@ static const char help[] =
|
||||||
" -soname set name for shared library to be used at runtime\n"
|
" -soname set name for shared library to be used at runtime\n"
|
||||||
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
||||||
"Debugger options:\n"
|
"Debugger options:\n"
|
||||||
" -g generate runtime debug info\n"
|
" -g[x] generate stab runtime debug info\n"
|
||||||
|
" -gdwarf[-x] generate dwarf runtime debug info\n"
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
" -b compile with built-in memory and bounds checker (implies -g)\n"
|
" -b compile with built-in memory and bounds checker (implies -g)\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
14
tcc.h
14
tcc.h
|
@ -368,6 +368,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
#include "libtcc.h"
|
#include "libtcc.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "stab.h"
|
#include "stab.h"
|
||||||
|
#include "dwarf.h"
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
@ -792,6 +793,7 @@ struct TCCState {
|
||||||
|
|
||||||
/* compile with debug symbol (and use them if error during execution) */
|
/* compile with debug symbol (and use them if error during execution) */
|
||||||
unsigned char do_debug;
|
unsigned char do_debug;
|
||||||
|
unsigned char dwarf;
|
||||||
unsigned char do_backtrace;
|
unsigned char do_backtrace;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
/* compile with built-in memory and bounds checker */
|
/* compile with built-in memory and bounds checker */
|
||||||
|
@ -922,6 +924,12 @@ struct TCCState {
|
||||||
Section *symtab_section;
|
Section *symtab_section;
|
||||||
/* debug sections */
|
/* debug sections */
|
||||||
Section *stab_section;
|
Section *stab_section;
|
||||||
|
Section *dwarf_info_section;
|
||||||
|
Section *dwarf_abbrev_section;
|
||||||
|
Section *dwarf_line_section;
|
||||||
|
Section *dwarf_aranges_section;
|
||||||
|
Section *dwarf_str_section;
|
||||||
|
Section *dwarf_line_str_section;
|
||||||
/* Is there a new undefined sym since last new_undef_sym() */
|
/* Is there a new undefined sym since last new_undef_sym() */
|
||||||
int new_undef_sym;
|
int new_undef_sym;
|
||||||
|
|
||||||
|
@ -1822,6 +1830,12 @@ ST_FUNC void post_sem(TCCSem *p);
|
||||||
#define symtab_section TCC_STATE_VAR(symtab_section)
|
#define symtab_section TCC_STATE_VAR(symtab_section)
|
||||||
#define stab_section TCC_STATE_VAR(stab_section)
|
#define stab_section TCC_STATE_VAR(stab_section)
|
||||||
#define stabstr_section stab_section->link
|
#define stabstr_section stab_section->link
|
||||||
|
#define dwarf_info_section TCC_STATE_VAR(dwarf_info_section)
|
||||||
|
#define dwarf_abbrev_section TCC_STATE_VAR(dwarf_abbrev_section)
|
||||||
|
#define dwarf_line_section TCC_STATE_VAR(dwarf_line_section)
|
||||||
|
#define dwarf_aranges_section TCC_STATE_VAR(dwarf_aranges_section)
|
||||||
|
#define dwarf_str_section TCC_STATE_VAR(dwarf_str_section)
|
||||||
|
#define dwarf_line_str_section TCC_STATE_VAR(dwarf_line_str_section)
|
||||||
#define gnu_ext TCC_STATE_VAR(gnu_ext)
|
#define gnu_ext TCC_STATE_VAR(gnu_ext)
|
||||||
#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
|
#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
|
||||||
#define tcc_error TCC_SET_STATE(_tcc_error)
|
#define tcc_error TCC_SET_STATE(_tcc_error)
|
||||||
|
|
80
tccelf.c
80
tccelf.c
|
@ -47,6 +47,8 @@ struct sym_version {
|
||||||
/* section is dynsymtab_section */
|
/* section is dynsymtab_section */
|
||||||
#define SHF_DYNSYM 0x40000000
|
#define SHF_DYNSYM 0x40000000
|
||||||
|
|
||||||
|
#define DWARF_DEBUG(s) (!strncmp((s), ".debug_", sizeof(".debug_")-1))
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
ST_FUNC void tccelf_new(TCCState *s)
|
ST_FUNC void tccelf_new(TCCState *s)
|
||||||
|
@ -102,12 +104,39 @@ ST_FUNC void tccelf_stab_new(TCCState *s)
|
||||||
if (s->do_backtrace && s->output_type != TCC_OUTPUT_MEMORY)
|
if (s->do_backtrace && s->output_type != TCC_OUTPUT_MEMORY)
|
||||||
shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX
|
shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX
|
||||||
#endif
|
#endif
|
||||||
stab_section = new_section(s, ".stab", SHT_PROGBITS, shf);
|
if (s->dwarf) {
|
||||||
stab_section->sh_entsize = sizeof(Stab_Sym);
|
dwarf_info_section =
|
||||||
stab_section->sh_addralign = sizeof ((Stab_Sym*)0)->n_value;
|
new_section(s, ".debug_info", SHT_PROGBITS, shf);
|
||||||
stab_section->link = new_section(s, ".stabstr", SHT_STRTAB, shf);
|
dwarf_abbrev_section =
|
||||||
/* put first entry */
|
new_section(s, ".debug_abbrev", SHT_PROGBITS, shf);
|
||||||
put_stabs(s, "", 0, 0, 0, 0);
|
dwarf_line_section =
|
||||||
|
new_section(s, ".debug_line", SHT_PROGBITS, shf);
|
||||||
|
dwarf_aranges_section =
|
||||||
|
new_section(s, ".debug_aranges", SHT_PROGBITS, shf);
|
||||||
|
shf |= SHF_MERGE | SHF_STRINGS;
|
||||||
|
dwarf_str_section =
|
||||||
|
new_section(s, ".debug_str", SHT_PROGBITS, shf);
|
||||||
|
dwarf_str_section->sh_entsize = 1;
|
||||||
|
dwarf_info_section->sh_addralign =
|
||||||
|
dwarf_abbrev_section->sh_addralign =
|
||||||
|
dwarf_line_section->sh_addralign =
|
||||||
|
dwarf_aranges_section->sh_addralign =
|
||||||
|
dwarf_str_section->sh_addralign = 1;
|
||||||
|
if (s1->dwarf >= 5) {
|
||||||
|
dwarf_line_str_section =
|
||||||
|
new_section(s, ".debug_line_str", SHT_PROGBITS, shf);
|
||||||
|
dwarf_line_str_section->sh_entsize = 1;
|
||||||
|
dwarf_line_str_section->sh_addralign = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stab_section = new_section(s, ".stab", SHT_PROGBITS, shf);
|
||||||
|
stab_section->sh_entsize = sizeof(Stab_Sym);
|
||||||
|
stab_section->sh_addralign = sizeof ((Stab_Sym*)0)->n_value;
|
||||||
|
stab_section->link = new_section(s, ".stabstr", SHT_STRTAB, shf);
|
||||||
|
/* put first entry */
|
||||||
|
put_stabs(s, "", 0, 0, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_section(Section *s)
|
static void free_section(Section *s)
|
||||||
|
@ -944,7 +973,10 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
|
||||||
sym->st_value = 0;
|
sym->st_value = 0;
|
||||||
else
|
else
|
||||||
tcc_error_noabort("undefined symbol '%s'", name);
|
tcc_error_noabort("undefined symbol '%s'", name);
|
||||||
} else if (sh_num < SHN_LORESERVE) {
|
} else if (sh_num < SHN_LORESERVE &&
|
||||||
|
/* Debug dwarf relocations must be relative to start section.
|
||||||
|
This only happens when backtrace is used. */
|
||||||
|
(sym->st_name || !DWARF_DEBUG(s1->sections[sym->st_shndx]->name))) {
|
||||||
/* add section base */
|
/* add section base */
|
||||||
sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
|
sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
|
||||||
}
|
}
|
||||||
|
@ -1330,7 +1362,7 @@ ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t
|
||||||
if (sec && offs == -1)
|
if (sec && offs == -1)
|
||||||
offs = sec->data_offset;
|
offs = sec->data_offset;
|
||||||
return set_elf_sym(symtab_section, offs, 0,
|
return set_elf_sym(symtab_section, offs, 0,
|
||||||
ELFW(ST_INFO)(name ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
|
ELFW(ST_INFO)(name && !strstr(name, "__dwarf") ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_init_array_defines(TCCState *s1, const char *section_name)
|
static void add_init_array_defines(TCCState *s1, const char *section_name)
|
||||||
|
@ -1395,10 +1427,10 @@ static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
static void put_ptr(TCCState *s1, Section *s, int offs)
|
static void put_ptr(TCCState *s1, Section *s, int offs, const char *name)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
c = set_global_sym(s1, NULL, s, offs);
|
c = set_global_sym(s1, name, s, offs);
|
||||||
s = data_section;
|
s = data_section;
|
||||||
put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
|
put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
|
||||||
section_ptr_add(s, PTR_SIZE);
|
section_ptr_add(s, PTR_SIZE);
|
||||||
|
@ -1415,16 +1447,29 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
||||||
section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
|
section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
|
||||||
o = s->data_offset;
|
o = s->data_offset;
|
||||||
/* create (part of) a struct rt_context (see tccrun.c) */
|
/* create (part of) a struct rt_context (see tccrun.c) */
|
||||||
put_ptr(s1, stab_section, 0);
|
if (s1->dwarf) {
|
||||||
put_ptr(s1, stab_section, -1);
|
put_ptr(s1, dwarf_line_section, 0, "__dwarf_line");
|
||||||
put_ptr(s1, stab_section->link, 0);
|
put_ptr(s1, dwarf_line_section, -1, "__dwarf_line_end");
|
||||||
|
if (s1->dwarf >= 5)
|
||||||
|
put_ptr(s1, dwarf_line_str_section, 0, "__dwarf_line_str");
|
||||||
|
else
|
||||||
|
put_ptr(s1, dwarf_str_section, 0, "__dwarf_str");
|
||||||
|
put_ptr(s1, text_section, 0, "__dwarf_text");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
put_ptr(s1, stab_section, 0, NULL);
|
||||||
|
put_ptr(s1, stab_section, -1, NULL);
|
||||||
|
put_ptr(s1, stab_section->link, 0, NULL);
|
||||||
|
section_ptr_add(s, PTR_SIZE);
|
||||||
|
}
|
||||||
|
/* skip esym_start/esym_end/elf_str (not loaded) */
|
||||||
section_ptr_add(s, 3 * PTR_SIZE);
|
section_ptr_add(s, 3 * PTR_SIZE);
|
||||||
/* prog_base : local nameless symbol with offset 0 at SHN_ABS */
|
/* prog_base : local nameless symbol with offset 0 at SHN_ABS */
|
||||||
put_ptr(s1, NULL, 0);
|
put_ptr(s1, NULL, 0, NULL);
|
||||||
n = 2 * PTR_SIZE;
|
n = 2 * PTR_SIZE;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (s1->do_bounds_check) {
|
if (s1->do_bounds_check) {
|
||||||
put_ptr(s1, bounds_section, 0);
|
put_ptr(s1, bounds_section, 0, NULL);
|
||||||
n -= PTR_SIZE;
|
n -= PTR_SIZE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1849,6 +1894,8 @@ static int set_sec_sizes(TCCState *s1)
|
||||||
/* when generating a DLL, we include relocations but
|
/* when generating a DLL, we include relocations but
|
||||||
we may patch them */
|
we may patch them */
|
||||||
if (file_type == TCC_OUTPUT_DLL
|
if (file_type == TCC_OUTPUT_DLL
|
||||||
|
/* Do not include dwarf relocatable sections. */
|
||||||
|
&& !DWARF_DEBUG(s1->sections[s->sh_info]->name)
|
||||||
&& (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
|
&& (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
|
||||||
int count = prepare_dynamic_rel(s1, s);
|
int count = prepare_dynamic_rel(s1, s);
|
||||||
if (count) {
|
if (count) {
|
||||||
|
@ -2963,8 +3010,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
|
||||||
strcmp(strsec + sh->sh_name, ".stabstr")
|
strcmp(strsec + sh->sh_name, ".stabstr")
|
||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
if (seencompressed
|
if (seencompressed && DWARF_DEBUG(strsec + sh->sh_name))
|
||||||
&& !strncmp(strsec + sh->sh_name, ".debug_", sizeof(".debug_")-1))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sh = &shdr[i];
|
sh = &shdr[i];
|
||||||
|
|
363
tccrun.c
363
tccrun.c
|
@ -27,8 +27,16 @@
|
||||||
typedef struct rt_context
|
typedef struct rt_context
|
||||||
{
|
{
|
||||||
/* --> tccelf.c:tcc_add_btstub wants those below in that order: */
|
/* --> tccelf.c:tcc_add_btstub wants those below in that order: */
|
||||||
Stab_Sym *stab_sym, *stab_sym_end;
|
union {
|
||||||
char *stab_str;
|
struct {
|
||||||
|
Stab_Sym *stab_sym, *stab_sym_end;
|
||||||
|
char *stab_str;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
unsigned char *dwarf_line, *dwarf_line_end, *dwarf_line_str;
|
||||||
|
addr_t dwarf_text;
|
||||||
|
};
|
||||||
|
};
|
||||||
ElfW(Sym) *esym_start, *esym_end;
|
ElfW(Sym) *esym_start, *esym_end;
|
||||||
char *elf_str;
|
char *elf_str;
|
||||||
addr_t prog_base;
|
addr_t prog_base;
|
||||||
|
@ -169,9 +177,18 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
memset(rc, 0, sizeof *rc);
|
memset(rc, 0, sizeof *rc);
|
||||||
if (s1->do_debug) {
|
if (s1->do_debug) {
|
||||||
void *p;
|
void *p;
|
||||||
rc->stab_sym = (Stab_Sym *)stab_section->data;
|
if (s1->dwarf) {
|
||||||
rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
|
rc->dwarf_line = dwarf_line_section->data;
|
||||||
rc->stab_str = (char *)stab_section->link->data;
|
rc->dwarf_line_end = dwarf_line_section->data + dwarf_line_section->data_offset;
|
||||||
|
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->esym_start = (ElfW(Sym) *)(symtab_section->data);
|
rc->esym_start = (ElfW(Sym) *)(symtab_section->data);
|
||||||
rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
||||||
rc->elf_str = (char *)symtab_section->link->data;
|
rc->elf_str = (char *)symtab_section->link->data;
|
||||||
|
@ -571,6 +588,337 @@ found:
|
||||||
return func_addr;
|
return func_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_128 ((8 * sizeof (long long) + 6) / 7)
|
||||||
|
|
||||||
|
#define DW_GETC(s,e) ((s) < (e) ? *(s)++ : 0)
|
||||||
|
|
||||||
|
#define DIR_TABLE_SIZE (64)
|
||||||
|
#define FILE_TABLE_SIZE (256)
|
||||||
|
|
||||||
|
static unsigned long long
|
||||||
|
dwarf_read_uleb128(unsigned char **ln, unsigned char *end)
|
||||||
|
{
|
||||||
|
unsigned char *cp = *ln;
|
||||||
|
unsigned long long retval = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_128; i++) {
|
||||||
|
unsigned long long byte = DW_GETC(cp, end);
|
||||||
|
|
||||||
|
retval |= (byte & 0x7f) << (i * 7);
|
||||||
|
if ((byte & 0x80) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*ln = cp;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long long
|
||||||
|
dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
|
||||||
|
{
|
||||||
|
unsigned char *cp = *ln;
|
||||||
|
long long retval = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_128; i++) {
|
||||||
|
unsigned long long byte = DW_GETC(cp, end);
|
||||||
|
|
||||||
|
retval |= (byte & 0x7f) << (i * 7);
|
||||||
|
if ((byte & 0x80) == 0) {
|
||||||
|
if ((byte & 0x40) && (i + 1) * 7 < 64)
|
||||||
|
retval |= -1LL << ((i + 1) * 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ln = cp;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int dwarf_read_32(unsigned char **ln, unsigned char *end)
|
||||||
|
{
|
||||||
|
unsigned char *cp = *ln;
|
||||||
|
unsigned int retval = 0;
|
||||||
|
|
||||||
|
if ((cp + 4) < end) {
|
||||||
|
retval = read32le(cp);
|
||||||
|
cp += 4;
|
||||||
|
}
|
||||||
|
*ln = cp;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if PTR_SIZE == 8
|
||||||
|
static unsigned long long dwarf_read_64(unsigned char **ln, unsigned char *end)
|
||||||
|
{
|
||||||
|
unsigned char *cp = *ln;
|
||||||
|
unsigned long long retval = 0;
|
||||||
|
|
||||||
|
if ((cp + 8) < end) {
|
||||||
|
retval = read64le(cp);
|
||||||
|
cp += 8;
|
||||||
|
}
|
||||||
|
*ln = cp;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
|
||||||
|
const char *msg, const char *skip)
|
||||||
|
{
|
||||||
|
unsigned char *ln;
|
||||||
|
unsigned char *cp;
|
||||||
|
unsigned char *end;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned char version;
|
||||||
|
unsigned int min_insn_length;
|
||||||
|
unsigned int max_ops_per_insn;
|
||||||
|
int line_base;
|
||||||
|
unsigned int line_range;
|
||||||
|
unsigned int opcode_base;
|
||||||
|
unsigned int opindex;
|
||||||
|
unsigned int col;
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int len;
|
||||||
|
unsigned int dir_size;
|
||||||
|
#if 0
|
||||||
|
char *dirs[DIR_TABLE_SIZE];
|
||||||
|
#endif
|
||||||
|
unsigned int filename_size;
|
||||||
|
struct dwarf_filename_struct {
|
||||||
|
unsigned int dir_entry;
|
||||||
|
char *name;
|
||||||
|
} filename_table[FILE_TABLE_SIZE];
|
||||||
|
addr_t last_pc;
|
||||||
|
addr_t pc;
|
||||||
|
addr_t func_addr;
|
||||||
|
int line;
|
||||||
|
char *filename;
|
||||||
|
char *function;
|
||||||
|
ElfW(Sym) *esym;
|
||||||
|
|
||||||
|
next:
|
||||||
|
ln = rc->dwarf_line;
|
||||||
|
while (ln < rc->dwarf_line_end) {
|
||||||
|
dir_size = 0;
|
||||||
|
filename_size = 0;
|
||||||
|
last_pc = 0;
|
||||||
|
pc = 0;
|
||||||
|
func_addr = -1;
|
||||||
|
line = 1;
|
||||||
|
filename = NULL;
|
||||||
|
function = NULL;
|
||||||
|
size = dwarf_read_32(&ln, rc->dwarf_line_end);
|
||||||
|
end = ln + size;
|
||||||
|
version = DW_GETC(ln, end);
|
||||||
|
version += DW_GETC(ln, end) << 8;
|
||||||
|
if (version >= 5)
|
||||||
|
ln += 6; // address size, segment selector, prologue Length
|
||||||
|
else
|
||||||
|
ln += 4; // prologue Length
|
||||||
|
min_insn_length = DW_GETC(ln, end);
|
||||||
|
if (version >= 4)
|
||||||
|
max_ops_per_insn = DW_GETC(ln, end);
|
||||||
|
else
|
||||||
|
max_ops_per_insn = 1;
|
||||||
|
ln++; // Initial value of 'is_stmt'
|
||||||
|
line_base = DW_GETC(ln, end);
|
||||||
|
line_base |= line_base >= 0x80 ? ~0xff : 0;
|
||||||
|
line_range = DW_GETC(ln, end);
|
||||||
|
opcode_base = DW_GETC(ln, end);
|
||||||
|
opindex = 0;
|
||||||
|
ln += 12;
|
||||||
|
if (version >= 5) {
|
||||||
|
col = DW_GETC(ln, end);
|
||||||
|
for (i = 0; i < col * 2; i++)
|
||||||
|
dwarf_read_uleb128(&ln, end);
|
||||||
|
dir_size = dwarf_read_uleb128(&ln, end);
|
||||||
|
for (i = 0; i < dir_size; i++)
|
||||||
|
#if 0
|
||||||
|
if (i < DIR_TABLE_SIZE)
|
||||||
|
dirs[i] = (char *)rc->dwarf_line_str + dwarf_read_32(&ln, end);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
dwarf_read_32(&ln, end);
|
||||||
|
col = DW_GETC(ln, end);
|
||||||
|
for (i = 0; i < col * 2; i++)
|
||||||
|
dwarf_read_uleb128(&ln, end);
|
||||||
|
filename_size = dwarf_read_uleb128(&ln, end);
|
||||||
|
for (i = 0; i < filename_size; i++)
|
||||||
|
if (i < FILE_TABLE_SIZE) {
|
||||||
|
filename_table[i].name = (char *)rc->dwarf_line_str + dwarf_read_32(&ln, end);
|
||||||
|
filename_table[i].dir_entry = dwarf_read_uleb128(&ln, end);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dwarf_read_32(&ln, end);
|
||||||
|
dwarf_read_uleb128(&ln, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while ((i = DW_GETC(ln, end))) {
|
||||||
|
#if 0
|
||||||
|
if (++dir_size < DIR_TABLE_SIZE)
|
||||||
|
dirs[dir_size - 1] = (char *)ln - 1;
|
||||||
|
#endif
|
||||||
|
while (DW_GETC(ln, end)) {}
|
||||||
|
}
|
||||||
|
while ((i = DW_GETC(ln, end))) {
|
||||||
|
if (++filename_size < FILE_TABLE_SIZE) {
|
||||||
|
filename_table[filename_size - 1].name = (char *)ln - 1;
|
||||||
|
while (DW_GETC(ln, end)) {}
|
||||||
|
filename_table[filename_size - 1].dir_entry =
|
||||||
|
dwarf_read_uleb128(&ln, end);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (DW_GETC(ln, end)) {}
|
||||||
|
dwarf_read_uleb128(&ln, end);
|
||||||
|
}
|
||||||
|
dwarf_read_uleb128(&ln, end); // time
|
||||||
|
dwarf_read_uleb128(&ln, end); // size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (ln < end) {
|
||||||
|
last_pc = pc;
|
||||||
|
switch (DW_GETC(ln, end)) {
|
||||||
|
case 0:
|
||||||
|
len = dwarf_read_uleb128(&ln, end);
|
||||||
|
cp = ln;
|
||||||
|
ln += len;
|
||||||
|
if (len == 0)
|
||||||
|
goto next_line;
|
||||||
|
switch (DW_GETC(cp, end)) {
|
||||||
|
case DW_LNE_end_sequence:
|
||||||
|
goto next_line;
|
||||||
|
case DW_LNE_set_address:
|
||||||
|
#if PTR_SIZE == 4
|
||||||
|
dwarf_read_32(&cp, end);
|
||||||
|
#else
|
||||||
|
dwarf_read_64(&cp, end);
|
||||||
|
#endif
|
||||||
|
pc = rc->dwarf_text;
|
||||||
|
opindex = 0;
|
||||||
|
break;
|
||||||
|
case DW_LNE_define_file: /* deprecated */
|
||||||
|
break;
|
||||||
|
case DW_LNE_set_discriminator:
|
||||||
|
dwarf_read_uleb128(&cp, end);
|
||||||
|
break;
|
||||||
|
case DW_LNE_hi_user - 1:
|
||||||
|
function = (char *)cp;
|
||||||
|
func_addr = pc;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
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;
|
||||||
|
else {
|
||||||
|
unsigned long long off = dwarf_read_uleb128(&ln, end);
|
||||||
|
|
||||||
|
pc += (opindex + off) / max_ops_per_insn *
|
||||||
|
min_insn_length;
|
||||||
|
opindex = (opindex + off) % max_ops_per_insn;
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
goto check_pc;
|
||||||
|
case DW_LNS_advance_line:
|
||||||
|
line += dwarf_read_sleb128(&ln, end);
|
||||||
|
break;
|
||||||
|
case DW_LNS_set_file:
|
||||||
|
i = dwarf_read_uleb128(&ln, end);
|
||||||
|
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;
|
||||||
|
else {
|
||||||
|
unsigned int off = (255 - opcode_base) / line_range;
|
||||||
|
|
||||||
|
pc += ((opindex + off) / max_ops_per_insn) *
|
||||||
|
min_insn_length;
|
||||||
|
opindex = (opindex + off) % max_ops_per_insn;
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
goto check_pc;
|
||||||
|
case DW_LNS_fixed_advance_pc:
|
||||||
|
i = DW_GETC(ln, end);
|
||||||
|
i += DW_GETC(ln, end) << 8;
|
||||||
|
pc += i;
|
||||||
|
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:
|
||||||
|
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:
|
||||||
|
ln = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = NULL;
|
||||||
|
function = NULL;
|
||||||
|
func_addr = -1;
|
||||||
|
|
||||||
|
/* we try symtab symbols (no line number info) */
|
||||||
|
for (esym = rc->esym_start + 1; esym < rc->esym_end; ++esym) {
|
||||||
|
int type = ELFW(ST_TYPE)(esym->st_info);
|
||||||
|
if (type == STT_FUNC || type == STT_GNU_IFUNC) {
|
||||||
|
if (wanted_pc >= esym->st_value &&
|
||||||
|
wanted_pc < esym->st_value + esym->st_size) {
|
||||||
|
function = rc->elf_str + esym->st_name;
|
||||||
|
func_addr = esym->st_value;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = rc->next))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
found:
|
||||||
|
if (filename) {
|
||||||
|
if (skip[0] && strstr(filename, skip))
|
||||||
|
return (addr_t)-1;
|
||||||
|
rt_printf("%s:%d: ", filename, line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rt_printf("0x%08llx : ", (long long)wanted_pc);
|
||||||
|
rt_printf("%s %s", msg, function ? function : "???");
|
||||||
|
return (addr_t)func_addr;
|
||||||
|
}
|
||||||
|
|
||||||
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level);
|
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level);
|
||||||
|
|
||||||
static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
|
static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
|
||||||
|
@ -603,7 +951,10 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
|
||||||
ret = rt_get_caller_pc(&pc, rc, i);
|
ret = rt_get_caller_pc(&pc, rc, i);
|
||||||
a = "%s";
|
a = "%s";
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
pc = rt_printline(rc, pc, level ? "by" : "at", skip);
|
if ((addr_t)rc->dwarf_text)
|
||||||
|
pc = rt_printline_dwarf(rc, pc, level ? "by" : "at", skip);
|
||||||
|
else
|
||||||
|
pc = rt_printline(rc, pc, level ? "by" : "at", skip);
|
||||||
if (pc == (addr_t)-1)
|
if (pc == (addr_t)-1)
|
||||||
continue;
|
continue;
|
||||||
a = ": %s";
|
a = ": %s";
|
||||||
|
|
13
tests/tests2/126_bound_global.c
Normal file
13
tests/tests2/126_bound_global.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/* test bound checking code without -run */
|
||||||
|
|
||||||
|
int arr[10];
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i <= sizeof(arr)/sizeof(arr[0]); i++)
|
||||||
|
arr[i] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
2
tests/tests2/126_bound_global.expect
Normal file
2
tests/tests2/126_bound_global.expect
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
126_bound_global.c:11: at main: BCHECK: ........ is outside of the region
|
||||||
|
126_bound_global.c:11: at main: RUNTIME ERROR: invalid memory access
|
|
@ -58,6 +58,9 @@ ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS)))
|
||||||
SKIP += 114_bound_signal.test # libc problem signal/fork
|
SKIP += 114_bound_signal.test # libc problem signal/fork
|
||||||
SKIP += 116_bound_setjmp2.test # No TLS_FUNC/TLS_VAR in bcheck.c
|
SKIP += 116_bound_setjmp2.test # No TLS_FUNC/TLS_VAR in bcheck.c
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(filter Darwin,$(TARGETOS)))
|
||||||
|
SKIP += 126_bound_global.test # bt-exe.c problem on apple
|
||||||
|
endif
|
||||||
|
|
||||||
# Some tests might need arguments
|
# Some tests might need arguments
|
||||||
ARGS =
|
ARGS =
|
||||||
|
@ -100,7 +103,7 @@ GEN-ALWAYS =
|
||||||
108_constructor.test: NORUN = true
|
108_constructor.test: NORUN = true
|
||||||
|
|
||||||
112_backtrace.test: FLAGS += -dt -b
|
112_backtrace.test: FLAGS += -dt -b
|
||||||
112_backtrace.test 113_btdll.test: FILTER += \
|
112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \
|
||||||
-e 's;[0-9A-Fa-fx]\{5,\};........;g' \
|
-e 's;[0-9A-Fa-fx]\{5,\};........;g' \
|
||||||
-e 's;0x[0-9A-Fa-f]\{1,\};0x?;g'
|
-e 's;0x[0-9A-Fa-f]\{1,\};0x?;g'
|
||||||
|
|
||||||
|
@ -122,6 +125,8 @@ ifneq ($(CONFIG_bcheck),no)
|
||||||
endif
|
endif
|
||||||
125_atomic_misc.test: FLAGS += -dt
|
125_atomic_misc.test: FLAGS += -dt
|
||||||
124_atomic_counter.test: FLAGS += -pthread
|
124_atomic_counter.test: FLAGS += -pthread
|
||||||
|
126_bound_global.test: FLAGS += -b
|
||||||
|
126_bound_global.test: NORUN = true
|
||||||
|
|
||||||
# Filter source directory in warnings/errors (out-of-tree builds)
|
# Filter source directory in warnings/errors (out-of-tree builds)
|
||||||
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
|
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
|
||||||
|
|
|
@ -701,7 +701,7 @@ static void gen_bounds_epilog(void)
|
||||||
*bounds_ptr = 0;
|
*bounds_ptr = 0;
|
||||||
|
|
||||||
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
||||||
func_bound_offset, lbounds_section->data_offset);
|
func_bound_offset, PTR_SIZE);
|
||||||
|
|
||||||
/* generate bound local allocation */
|
/* generate bound local allocation */
|
||||||
if (offset_modified) {
|
if (offset_modified) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
/* relocation type for 32 bit data relocation */
|
/* relocation type for 32 bit data relocation */
|
||||||
#define R_DATA_32 R_X86_64_32S
|
#define R_DATA_32 R_X86_64_32S
|
||||||
|
#define R_DATA_32U R_X86_64_32
|
||||||
#define R_DATA_PTR R_X86_64_64
|
#define R_DATA_PTR R_X86_64_64
|
||||||
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
|
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
|
||||||
#define R_GLOB_DAT R_X86_64_GLOB_DAT
|
#define R_GLOB_DAT R_X86_64_GLOB_DAT
|
||||||
|
|
Loading…
Reference in a new issue