=================================================================
==1751048==ERROR: AddressSanitizer: heap-use-after-free on address 0x604000042eb8 at pc 0x5650ef8eec88 bp 0x7ffe52767290 sp 0x7ffe52767280
READ of size 8 at 0x604000042eb8 thread T0
#0 0x5650ef8eec87 in finalize_symtab /home/simark/src/binutils-gdb/gdb/jit.c:768
#1 0x5650ef8eef88 in jit_object_close_impl /home/simark/src/binutils-gdb/gdb/jit.c:797
#2 0x7fbbda986278 in read_debug_info /home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/jitreader.c:71
#3 0x5650ef8ef56b in jit_reader_try_read_symtab /home/simark/src/binutils-gdb/gdb/jit.c:850
#4 0x5650ef8effe3 in jit_register_code /home/simark/src/binutils-gdb/gdb/jit.c:948
#5 0x5650ef8f2c92 in jit_event_handler(gdbarch*) /home/simark/src/binutils-gdb/gdb/jit.c:1396
#6 0x5650ef0d137e in handle_jit_event /home/simark/src/binutils-gdb/gdb/breakpoint.c:5470
[snip]
0x604000042eb8 is located 40 bytes inside of 48-byte region [0x604000042e90,0x604000042ec0)
freed by thread T0 here:
#0 0x7fbbe57376b0 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122
#1 0x5650ef8f350b in xfree<gdb_block> /home/simark/src/binutils-gdb/gdb/gdbsupport/common-utils.h:62
#2 0x5650ef8eeca9 in finalize_symtab /home/simark/src/binutils-gdb/gdb/jit.c:769
#3 0x5650ef8eef88 in jit_object_close_impl /home/simark/src/binutils-gdb/gdb/jit.c:797
#4 0x7fbbda986278 in read_debug_info /home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/jitreader.c:71
#5 0x5650ef8ef56b in jit_reader_try_read_symtab /home/simark/src/binutils-gdb/gdb/jit.c:850
#6 0x5650ef8effe3 in jit_register_code /home/simark/src/binutils-gdb/gdb/jit.c:948
#7 0x5650ef8f2c92 in jit_event_handler(gdbarch*) /home/simark/src/binutils-gdb/gdb/jit.c:1396
#8 0x5650ef0d137e in handle_jit_event /home/simark/src/binutils-gdb/gdb/breakpoint.c:5470
[snip]
previously allocated by thread T0 here:
#0 0x7fbbe5737cd8 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:153
#1 0x5650eef662f3 in xcalloc /home/simark/src/binutils-gdb/gdb/alloc.c:100
#2 0x5650ef8f34ea in xcnew<gdb_block> /home/simark/src/binutils-gdb/gdb/gdbsupport/poison.h:122
#3 0x5650ef8ed467 in jit_block_open_impl /home/simark/src/binutils-gdb/gdb/jit.c:557
#4 0x7fbbda98620a in read_debug_info /home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/jitreader.c:60
#5 0x5650ef8ef56b in jit_reader_try_read_symtab /home/simark/src/binutils-gdb/gdb/jit.c:850
#6 0x5650ef8effe3 in jit_register_code /home/simark/src/binutils-gdb/gdb/jit.c:948
#7 0x5650ef8f2c92 in jit_event_handler(gdbarch*) /home/simark/src/binutils-gdb/gdb/jit.c:1396
#8 0x5650ef0d137e in handle_jit_event /home/simark/src/binutils-gdb/gdb/breakpoint.c:5470
[snip]
gdb/ChangeLog:
* jit.c (finalize_symtab): Set gdb_block_iter_tmp in loop.
gdb/testsuite/ChangeLog:
* gdb.base/jit-reader.exp (jit_reader_test): Rename
jit_function_00 to jit_function_stack_mangle.
* gdb.base/jithost.c (jit_function_t): Rename to...
(jit_function_stack_mangle_t): ... this.
(jit_function_add_t): New typedef.
(jit_function_00_code): Rename to...
(jit_function_stack_mangle_code): ... this, make static.
(jit_function_add_code): New.
(main): Generate "add" function and call it. Adjust to changes
in jithost_abi.
* gdb.base/jithost.h (struct jithost_abi_bounds): New.
(struct jithost_abi) <begin, end>: Remove fields.
<object, function_stack_mangle, function_add>: New fields.
* gdb.base/jitreader.c (struct reader_state) <code_begin,
code_end>: Remove fields.
<func_stack_mangle>: New field.
(read_debug_info): Adjust to renaming, create block for "add"
function.
(read_sp, unwind_frame, get_frame_id): Adjust to other changes.
---
gdb/jit.c | 1 +
gdb/testsuite/gdb.base/jit-reader.exp | 14 ++++-----
gdb/testsuite/gdb.base/jithost.c | 45 ++++++++++++++++++++-------
gdb/testsuite/gdb.base/jithost.h | 15 +++++++--
gdb/testsuite/gdb.base/jitreader.c | 34 +++++++++++++-------
5 files changed, 78 insertions(+), 31 deletions(-)
@@ -765,6 +765,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
gdb_block_iter;
gdb_block_iter = gdb_block_iter_tmp)
{
+ gdb_block_iter_tmp = gdb_block_iter->next;
xfree ((void *) gdb_block_iter->name);
xfree (gdb_block_iter);
}
@@ -120,7 +120,7 @@ proc jit_reader_test {} {
with_test_prefix "before mangling" {
gdb_test "bt" \
[multi_line \
- "#0 ${any} in jit_function_00 ${any}" \
+ "#0 ${any} in jit_function_stack_mangle ${any}" \
"#1 ${any} in main ${any}" \
] \
"bt works"
@@ -128,7 +128,7 @@ proc jit_reader_test {} {
set sp_before_mangling \
[get_hexadecimal_valueof "\$sp" 0 "get sp"]
- gdb_test "up" "#1 $any in main $any\r\n$any function $any" \
+ gdb_test "up" "#1 $any in main $any\r\n$any function_stack_mangle $any" \
"move up to caller"
set caller_sp \
@@ -140,7 +140,7 @@ proc jit_reader_test {} {
# reader's unwinder understands the mangling and should thus
# be able to unwind at that location.
with_test_prefix "after mangling" {
- gdb_test "si" "in jit_function_00 .*" "step over stack mangling"
+ gdb_test "si" "in jit_function_stack_mangle .*" "step over stack mangling"
set sp_after_mangling \
[get_hexadecimal_valueof "\$sp" 0 "get sp"]
@@ -152,7 +152,7 @@ proc jit_reader_test {} {
# the mangled stack pointer.
gdb_test "bt" \
[multi_line \
- "#0 ${any} in jit_function_00 ${any}" \
+ "#0 ${any} in jit_function_stack_mangle ${any}" \
"#1 ${any} in main ${any}" \
] \
"bt works"
@@ -161,11 +161,11 @@ proc jit_reader_test {} {
info_registers_current_frame $sp_after_mangling
gdb_test "info frame" \
- "Stack level 0, frame at $sp_before_mangling.*in jit_function_00.*"
+ "Stack level 0, frame at $sp_before_mangling.*in jit_function_stack_mangle.*"
}
with_test_prefix "caller frame" {
- gdb_test "up" "#1 $any in main $any\r\n$any function $any" \
+ gdb_test "up" "#1 $any in main $any\r\n$any function_stack_mangle $any" \
"up to caller"
# Since the JIT unwinder only provides RIP/RSP/RBP,
@@ -243,7 +243,7 @@ proc jit_reader_test {} {
# the mangled stack pointer.
gdb_test "bt" \
[multi_line \
- "#0 ${any} in jit_function_00 ${any}" \
+ "#0 ${any} in jit_function_stack_mangle ${any}" \
"#1 ${any} in main ${any}" \
]
}
@@ -31,7 +31,8 @@ void __attribute__((noinline)) __jit_debug_register_code () { }
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
struct jit_code_entry only_entry;
-typedef void (jit_function_t) ();
+typedef void (jit_function_stack_mangle_t) (void);
+typedef long (jit_function_add_t) (long a, long b);
/* The code of the jit_function_00 function that is copied into an
mmapped buffer in the inferior at run time.
@@ -39,26 +40,47 @@ typedef void (jit_function_t) ();
The second instruction mangles the stack pointer, meaning that when
stopped at the third instruction, GDB needs assistance from the JIT
unwinder in order to be able to unwind successfully. */
-const unsigned char jit_function_00_code[] = {
+static const unsigned char jit_function_stack_mangle_code[] = {
0xcc, /* int3 */
0x48, 0x83, 0xf4, 0xff, /* xor $0xffffffffffffffff, %rsp */
0x48, 0x83, 0xf4, 0xff, /* xor $0xffffffffffffffff, %rsp */
0xc3 /* ret */
};
+/* And another "JIT-ed" function, with the prototype `jit_function_add_t`. */
+static const unsigned char jit_function_add_code[] = {
+ 0x48, 0x01, 0xfe, /* add %rdi,%rsi */
+ 0x48, 0x89, 0xf0, /* mov %rsi,%rax */
+ 0xc3, /* retq */
+};
+
int
main (int argc, char **argv)
{
- struct jithost_abi *symfile;
+ struct jithost_abi *symfile = malloc (sizeof (struct jithost_abi));
char *code = mmap (NULL, getpagesize (), PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- jit_function_t *function = (jit_function_t *) code;
-
- memcpy (code, jit_function_00_code, sizeof (jit_function_00_code));
-
- symfile = malloc (sizeof (struct jithost_abi));
- symfile->begin = code;
- symfile->end = code + sizeof (jit_function_00_code);
+ char *code_end = code;
+
+ /* "JIT" function_stack_mangle. */
+ memcpy (code_end, jit_function_stack_mangle_code,
+ sizeof (jit_function_stack_mangle_code));
+ jit_function_stack_mangle_t *function_stack_mangle
+ = (jit_function_stack_mangle_t *) code_end;
+ symfile->function_stack_mangle.begin = code_end;
+ code_end += sizeof (jit_function_stack_mangle_code);
+ symfile->function_stack_mangle.end = code_end;
+
+ /* "JIT" function_add. */
+ memcpy (code_end, jit_function_add_code, sizeof (jit_function_add_code));
+ jit_function_add_t *function_add = (jit_function_add_t *) code_end;
+ symfile->function_add.begin = code_end;
+ code_end += sizeof (jit_function_add_code);
+ symfile->function_add.end = code_end;
+
+ /* Bounds of the whole object. */
+ symfile->object.begin = code;
+ symfile->object.end = code_end;
only_entry.symfile_addr = symfile;
only_entry.symfile_size = sizeof (struct jithost_abi);
@@ -69,7 +91,8 @@ main (int argc, char **argv)
__jit_debug_descriptor.version = 1;
__jit_debug_register_code ();
- function ();
+ function_stack_mangle ();
+ function_add (5, 6);
return 0;
}
@@ -18,10 +18,21 @@
#ifndef JITHOST_H
#define JITHOST_H
+struct jithost_abi_bounds
+{
+ const char *begin, *end;
+};
+
struct jithost_abi
{
- const char *begin;
- const char *end;
+ /* Beginning and past-the-end for the whole object. */
+ struct jithost_abi_bounds object;
+
+ /* Beginning and past-the-end for function_stack_mangle. */
+ struct jithost_abi_bounds function_stack_mangle;
+
+ /* Beginning and past-the-end for function_add. */
+ struct jithost_abi_bounds function_add;
};
#endif /* JITHOST_H */
@@ -34,8 +34,10 @@ enum register_mapping
struct reader_state
{
- uintptr_t code_begin;
- uintptr_t code_end;
+ struct {
+ uintptr_t begin;
+ uintptr_t end;
+ } func_stack_mangle;
};
static enum gdb_status
@@ -46,15 +48,24 @@ read_debug_info (struct gdb_reader_funcs *self,
struct jithost_abi *symfile = memory;
struct gdb_object *object = cbs->object_open (cbs);
struct gdb_symtab *symtab = cbs->symtab_open (cbs, object, "");
- GDB_CORE_ADDR begin = (GDB_CORE_ADDR) symfile->begin;
- GDB_CORE_ADDR end = (GDB_CORE_ADDR) symfile->end;
+
struct reader_state *state = (struct reader_state *) self->priv_data;
- /* Record the function's range, for the unwinder. */
- state->code_begin = begin;
- state->code_end = end;
+ /* Record the stack mangle function's range, for the unwinder. */
+ state->func_stack_mangle.begin
+ = (uintptr_t) symfile->function_stack_mangle.begin;
+ state->func_stack_mangle.end
+ = (uintptr_t) symfile->function_stack_mangle.end;
+
+ cbs->block_open (cbs, symtab, NULL,
+ (GDB_CORE_ADDR) symfile->function_stack_mangle.begin,
+ (GDB_CORE_ADDR) symfile->function_stack_mangle.end,
+ "jit_function_stack_mangle");
- cbs->block_open (cbs, symtab, NULL, begin, end, "jit_function_00");
+ cbs->block_open (cbs, symtab, NULL,
+ (GDB_CORE_ADDR) symfile->function_add.begin,
+ (GDB_CORE_ADDR) symfile->function_add.end,
+ "jit_function_add");
cbs->symtab_close (cbs, symtab);
cbs->object_close (cbs, object);
@@ -113,7 +124,7 @@ read_sp (struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cbs,
/* If stopped at the instruction after the "xor $-1, %rsp", demangle
the stack pointer back. */
- if (ip == state->code_begin + 5)
+ if (ip == state->func_stack_mangle.begin + 5)
sp ^= (uintptr_t) -1;
*value = sp;
@@ -132,7 +143,8 @@ unwind_frame (struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cbs)
if (!read_register (cbs, AMD64_RA, &this_ip))
return GDB_FAIL;
- if (this_ip >= state->code_end || this_ip < state->code_begin)
+ if (this_ip >= state->func_stack_mangle.end
+ || this_ip < state->func_stack_mangle.begin)
return GDB_FAIL;
/* Unwind RBP in order to make the unwinder that tries to unwind
@@ -168,7 +180,7 @@ get_frame_id (struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cbs)
read_register (cbs, AMD64_RA, &ip);
read_sp (self, cbs, ip, &sp);
- frame_id.code_address = (GDB_CORE_ADDR) state->code_begin;
+ frame_id.code_address = (GDB_CORE_ADDR) state->func_stack_mangle.begin;
frame_id.stack_address = (GDB_CORE_ADDR) sp;
return frame_id;