Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node/v8 GC problem with return hooking #4

Open
honggyukim opened this issue Feb 26, 2019 · 2 comments
Open

node/v8 GC problem with return hooking #4

honggyukim opened this issue Feb 26, 2019 · 2 comments

Comments

@honggyukim
Copy link
Owner

honggyukim commented Feb 26, 2019

void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
  // Visit the roots from the top for a given thread.
  v->VisitPointer(&thread->pending_exception_);
  v->VisitPointer(&(thread->pending_message_obj_));
  v->VisitPointer(bit_cast<Object**>(&(thread->context_)));
  v->VisitPointer(&thread->scheduled_exception_);

  for (v8::TryCatch* block = thread->try_catch_handler();
       block != NULL;
       block = block->next_) {
    v->VisitPointer(bit_cast<Object**>(&(block->exception_)));
    v->VisitPointer(bit_cast<Object**>(&(block->message_obj_)));
  }

  // Iterate over pointers on native execution stack.
  for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
    it.frame()->Iterate(v);
  }
}
void ExitFrame::Iterate(ObjectVisitor* v) const {
  // The arguments are traversed as part of the expression stack of
  // the calling frame.
  IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
  v->VisitPointer(&code_slot());
}

void StackFrame::IteratePc(ObjectVisitor* v, Address* pc_address,
                           Address* constant_pool_address, Code* holder) {
  Address pc = *pc_address;
  DCHECK(GcSafeCodeContains(holder, pc));
  unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
  Object* code = holder;
  v->VisitPointer(&code);
  if (code != holder) {
    holder = reinterpret_cast<Code*>(code);
    pc = holder->instruction_start() + pc_offset;
    *pc_address = pc;
    if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
      *constant_pool_address = holder->constant_pool();
    }
  }
}
Address ExitFrame::GetCallerStackPointer() const {
  return fp() + ExitFrameConstants::kCallerSPOffset;
}

bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
  StackFrame::State state;
  if (frame->is_entry() || frame->is_entry_construct()) {
    // See EntryFrame::GetCallerState. It computes the caller FP address
    // and calls ExitFrame::GetStateForFramePointer on it. We need to be
    // sure that caller FP address is valid.
    Address caller_fp = Memory::Address_at(
        frame->fp() + EntryFrameConstants::kCallerFPOffset);
    if (!IsValidExitFrame(caller_fp)) return false;
  } else if (frame->is_arguments_adaptor()) {
    // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
    // the number of arguments is stored on stack as Smi. We need to check
    // that it really an Smi.
    Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
        GetExpression(0);
    if (!number_of_args->IsSmi()) {
      return false;
    }
  }
  frame->ComputeCallerState(&state);
  return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
      SingletonFor(frame->GetCallerState(&state)) != NULL;
}
// Exit frames are used to exit JavaScript execution and go to C.
class ExitFrame: public StackFrame {
 public:
  Type type() const override { return EXIT; }

  Code* unchecked_code() const override;

  Object*& code_slot() const;

  // Garbage collection support.
  void Iterate(ObjectVisitor* v) const override;

  void SetCallerFp(Address caller_fp) override;

  static ExitFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_exit());
    return static_cast<ExitFrame*>(frame);
  }

  // Compute the state and type of an exit frame given a frame
  // pointer. Used when constructing the first stack frame seen by an
  // iterator and the frames following entry frames.
  static Type GetStateForFramePointer(Address fp, State* state);
  static Address ComputeStackPointer(Address fp);
  static void FillState(Address fp, Address sp, State* state);

 protected:
  inline explicit ExitFrame(StackFrameIteratorBase* iterator);

  Address GetCallerStackPointer() const override;

 private:
  void ComputeCallerState(State* state) const override;

  friend class StackFrameIteratorBase;
};
// Abstract base class for all stack frames.
class StackFrame BASE_EMBEDDED {
 public:
    ...
  struct State {
    State() : sp(NULL), fp(NULL), pc_address(NULL),
              constant_pool_address(NULL) { }
    Address sp;
    Address fp;
    Address* pc_address;
    Address* constant_pool_address;
  };
    ...
  // Accessors.
  Address sp() const { return state_.sp; }
  Address fp() const { return state_.fp; }
  Address caller_sp() const { return GetCallerStackPointer(); }

  // If this frame is optimized and was dynamically aligned return its old
  // unaligned frame pointer.  When the frame is deoptimized its FP will shift
  // up one word and become unaligned.
  Address UnpaddedFP() const;

  Address pc() const { return *pc_address(); }
  void set_pc(Address pc) { *pc_address() = pc; }
    ...
  virtual void SetCallerFp(Address caller_fp) = 0;

  // Manually changes value of fp in this object.
  void UpdateFp(Address fp) { state_.fp = fp; }

  Address* pc_address() const { return state_.pc_address; }
    ...
 private:
  const StackFrameIteratorBase* iterator_;
  Isolate* isolate_;
  State state_;

  static ReturnAddressLocationResolver return_address_location_resolver_;

  // Fill in the state of the calling frame.
  virtual void ComputeCallerState(State* state) const = 0;

  // Get the type and the state of the calling frame.
  virtual Type GetCallerState(State* state) const;
    ...
};
@honggyukim
Copy link
Owner Author

Last error message:

uftrace stopped tracing with remaining functions
================================================
task: 1881
[7] <0>
[6] v8::internal::MarkCompactCollector::IsSweepingCompleted
[5] v8::internal::MarkCompactCollector::EnsureSweepingCompleted
[4] v8::internal::Isolate::Deinit
[3] v8::internal::Isolate::TearDown
[2] v8::Isolate::Dispose
[1] node::Start
[0] main

task: 1884
[2] v8::platform::TaskQueue::GetNext
[1] v8::platform::WorkerThread::Run
[0] v8::base::ThreadEntry

task: 1885
[2] v8::platform::TaskQueue::GetNext
[1] v8::platform::WorkerThread::Run
[0] v8::base::ThreadEntry

task: 1886
[2] v8::platform::TaskQueue::GetNext
[1] v8::platform::WorkerThread::Run
[0] v8::base::ThreadEntry

task: 1887
[2] v8::platform::TaskQueue::GetNext
[1] v8::platform::WorkerThread::Run
[0] v8::base::ThreadEntry

@honggyukim
Copy link
Owner Author

bool MarkCompactCollector::IsSweepingCompleted() {
  if (!pending_sweeper_tasks_semaphore_.WaitFor(
          base::TimeDelta::FromSeconds(0))) {
    return false;
  }
  pending_sweeper_tasks_semaphore_.Signal();
  return true;
}

void MarkCompactCollector::EnsureSweepingCompleted() {
  DCHECK(sweeping_in_progress_ == true);

  // If sweeping is not completed or not running at all, we try to complete it
  // here.
  if (!FLAG_concurrent_sweeping || !IsSweepingCompleted()) {
    SweepInParallel(heap()->paged_space(OLD_SPACE), 0);
    SweepInParallel(heap()->paged_space(CODE_SPACE), 0);
    SweepInParallel(heap()->paged_space(MAP_SPACE), 0);
  }

  if (FLAG_concurrent_sweeping) {
    pending_sweeper_tasks_semaphore_.Wait();
    pending_sweeper_tasks_semaphore_.Wait();
    pending_sweeper_tasks_semaphore_.Wait();
  }

  ParallelSweepSpacesComplete();
  sweeping_in_progress_ = false;
  heap()->old_space()->RefillFreeList();
  heap()->code_space()->RefillFreeList();
  heap()->map_space()->RefillFreeList();

#ifdef VERIFY_HEAP
  if (FLAG_verify_heap && !evacuation()) {
    VerifyEvacuation(heap_);
  }
#endif
}

void Isolate::Deinit() {
  TRACE_ISOLATE(deinit);

  debug()->Unload();

  FreeThreadResources();

  if (concurrent_recompilation_enabled()) {
    optimizing_compile_dispatcher_->Stop();
    delete optimizing_compile_dispatcher_;
    optimizing_compile_dispatcher_ = NULL;
  }

  if (heap_.mark_compact_collector()->sweeping_in_progress()) {
    heap_.mark_compact_collector()->EnsureSweepingCompleted();
  }
    ...
}

void Isolate::TearDown() {
  TRACE_ISOLATE(tear_down);

  // Temporarily set this isolate as current so that various parts of
  // the isolate can access it in their destructors without having a
  // direct pointer. We don't use Enter/Exit here to avoid
  // initializing the thread data.
  PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
  DCHECK(base::NoBarrier_Load(&isolate_key_created_) == 1);
  Isolate* saved_isolate =
      reinterpret_cast<Isolate*>(base::Thread::GetThreadLocal(isolate_key_));
  SetIsolateThreadLocals(this, NULL);

  Deinit();

  {
    base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
    thread_data_table_->RemoveAllThreads(this);
  }

  delete this;

  // Restore the previous current isolate.
  SetIsolateThreadLocals(saved_isolate, saved_data);
}

honggyukim pushed a commit that referenced this issue Nov 10, 2019
This fixes a memory leak in live replay as follows:

  $ make ASAN=1 -j8
  $ ./uftrace -L. --no-pager t-abc
  # DURATION     TID     FUNCTION
     1.227 us [126865] | __monstartup();
     0.940 us [126865] | __cxa_atexit();
              [126865] | main() {
              [126865] |   a() {
              [126865] |     b() {
              [126865] |       c() {
     0.766 us [126865] |         getpid();
     1.791 us [126865] |       } /* c */
     2.281 us [126865] |     } /* b */
     2.714 us [126865] |   } /* a */
     3.200 us [126865] | } /* main */

  =================================================================
  ==126864==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 6 byte(s) in 1 object(s) allocated from:
      #0 0x7fdc57f5034f in strdup (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x6234f)
      #1 0x499e74 in __read_rstack /home/honggyu/work/uftrace/utils/fstack.c:2160
      #2 0x49a1b0 in peek_rstack /home/honggyu/work/uftrace/utils/fstack.c:2230
      #3 0x445b5d in command_replay /home/honggyu/work/uftrace/cmds/replay.c:1163
      #4 0x438558 in command_live /home/honggyu/work/uftrace/cmds/live.c:158
      #5 0x40b6c2 in main /home/honggyu/work/uftrace/uftrace.c:1166
      #6 0x7fdc568d682f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

Fixed: namhyung#940

Signed-off-by: Byeonggon Lee <[email protected]>
honggyukim added a commit that referenced this issue Nov 27, 2019
This patch is to fix the following memory leak problem.

  =================================================================
  ==28079==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 8 byte(s) in 1 object(s) allocated from:
      #0 0x7f1b7025d7fa in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x987fa)
      #1 0x4b7200 in strv_copy /home/honggyu/work/uftrace/utils/utils.c:603
      #2 0x445407 in command_script /home/honggyu/work/uftrace/cmds/script.c:180
      #3 0x40b90a in main /home/honggyu/work/uftrace/uftrace.c:1205
      #4 0x7f1b6ebad82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

It also fixes a lot of memory leaks when the given script file doesn't
exist.

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Nov 27, 2019
This patch is to fix the following memory leak.

  $ uftrace record t-abc
  $ uftrace report -t 3us --no-pager
    Total time   Self time       Calls  Function
    ==========  ==========  ==========  ====================
      4.163 us    1.000 us           1  main
      3.163 us    3.163 us           1  a

  =================================================================
  ==78057==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 6 byte(s) in 1 object(s) allocated from:
      #0 0x7f6c4cf5734f in strdup (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x6234f)
      #1 0x498e46 in process_perf_event /home/honggyu/work/uftrace/utils/perf.c:576
      #2 0x487755 in __read_rstack /home/honggyu/work/uftrace/utils/fstack.c:2060
      #3 0x488445 in read_rstack /home/honggyu/work/uftrace/utils/fstack.c:2210
      #4 0x440503 in build_function_tree /home/honggyu/work/uftrace/cmds/report.c:117
      #5 0x440ba3 in report_functions /home/honggyu/work/uftrace/cmds/report.c:227
      #6 0x4442ca in command_report /home/honggyu/work/uftrace/cmds/report.c:692
      #7 0x40b843 in main /home/honggyu/work/uftrace/uftrace.c:1190
      #8 0x7f6c4b8dd82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

  SUMMARY: AddressSanitizer: 6 byte(s) leaked in 1 allocation(s).

Fixed: namhyung#1023

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Nov 27, 2019
This patch is to fix the following heap buffer overflow problem.

  $ uftrace record --force gcc hello.c
  $ uftrace replay --no-pager
      ...
  =================================================================
  ==79233==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62e00003c3e8 at
                                    pc 0x00000047e08e bp 0x7ffec89b7cd0 sp 0x7ffec89b7cc0
  READ of size 8 at 0x62e00003c3e8 thread T0
      #0 0x47e08d in fstack_check_skip /home/honggyu/uftrace/utils/fstack.c:683
      #1 0x47e9af in fstack_skip /home/honggyu/uftrace/utils/fstack.c:780
      #2 0x43e24e in print_graph_rstack /home/honggyu/uftrace/cmds/replay.c:987
      #3 0x43f49b in command_replay /home/honggyu/uftrace/cmds/replay.c:1172
      #4 0x40b7f1 in main /home/honggyu/uftrace/uftrace.c:1184
      #5 0x7f8ecb67e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
      #6 0x405bf8 in _start (/home/honggyu/usr/bin/uftrace+0x405bf8)

  0x62e00003c3e8 is located 24 bytes to the left of 40960-byte region [0x62e00003c400,0x62e000046400)
  allocated by thread T0 here:
      #0 0x7f8eccd2e7fa in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x987fa)
      #1 0x479eca in setup_task_handle /home/honggyu/uftrace/utils/fstack.c:61
      #2 0x47b0e2 in fstack_setup_task /home/honggyu/uftrace/utils/fstack.c:211
      #3 0x47c23b in fstack_setup_filters /home/honggyu/uftrace/utils/fstack.c:443
      #4 0x43f266 in command_replay /home/honggyu/uftrace/cmds/replay.c:1144
      #5 0x40b7f1 in main /home/honggyu/uftrace/uftrace.c:1184
      #6 0x7f8ecb67e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

  SUMMARY: AddressSanitizer: heap-buffer-overflow /home/honggyu/uftrace/utils/fstack.c:683 fstack_check_skip

Fixed: namhyung#803

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Nov 28, 2019
This patch is to fix the following memory leak.

  $ uftrace record t-abc
  $ uftrace report -t 3us --no-pager
    Total time   Self time       Calls  Function
    ==========  ==========  ==========  ====================
      4.163 us    1.000 us           1  main
      3.163 us    3.163 us           1  a

  =================================================================
  ==78057==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 6 byte(s) in 1 object(s) allocated from:
      #0 0x7f6c4cf5734f in strdup (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x6234f)
      #1 0x498e46 in process_perf_event /home/honggyu/work/uftrace/utils/perf.c:576
      #2 0x487755 in __read_rstack /home/honggyu/work/uftrace/utils/fstack.c:2060
      #3 0x488445 in read_rstack /home/honggyu/work/uftrace/utils/fstack.c:2210
      #4 0x440503 in build_function_tree /home/honggyu/work/uftrace/cmds/report.c:117
      #5 0x440ba3 in report_functions /home/honggyu/work/uftrace/cmds/report.c:227
      #6 0x4442ca in command_report /home/honggyu/work/uftrace/cmds/report.c:692
      #7 0x40b843 in main /home/honggyu/work/uftrace/uftrace.c:1190
      #8 0x7f6c4b8dd82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

  SUMMARY: AddressSanitizer: 6 byte(s) leaked in 1 allocation(s).

Fixed: namhyung#1023

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Nov 28, 2019
This patch is to fix the following heap buffer overflow problem.

  $ uftrace record --force gcc hello.c
  $ uftrace replay --no-pager
      ...
  =================================================================
  ==79233==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62e00003c3e8 at
                                    pc 0x00000047e08e bp 0x7ffec89b7cd0 sp 0x7ffec89b7cc0
  READ of size 8 at 0x62e00003c3e8 thread T0
      #0 0x47e08d in fstack_check_skip /home/honggyu/uftrace/utils/fstack.c:683
      #1 0x47e9af in fstack_skip /home/honggyu/uftrace/utils/fstack.c:780
      #2 0x43e24e in print_graph_rstack /home/honggyu/uftrace/cmds/replay.c:987
      #3 0x43f49b in command_replay /home/honggyu/uftrace/cmds/replay.c:1172
      #4 0x40b7f1 in main /home/honggyu/uftrace/uftrace.c:1184
      #5 0x7f8ecb67e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
      #6 0x405bf8 in _start (/home/honggyu/usr/bin/uftrace+0x405bf8)

  0x62e00003c3e8 is located 24 bytes to the left of 40960-byte region [0x62e00003c400,0x62e000046400)
  allocated by thread T0 here:
      #0 0x7f8eccd2e7fa in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x987fa)
      #1 0x479eca in setup_task_handle /home/honggyu/uftrace/utils/fstack.c:61
      #2 0x47b0e2 in fstack_setup_task /home/honggyu/uftrace/utils/fstack.c:211
      #3 0x47c23b in fstack_setup_filters /home/honggyu/uftrace/utils/fstack.c:443
      #4 0x43f266 in command_replay /home/honggyu/uftrace/cmds/replay.c:1144
      #5 0x40b7f1 in main /home/honggyu/uftrace/uftrace.c:1184
      #6 0x7f8ecb67e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

  SUMMARY: AddressSanitizer: heap-buffer-overflow /home/honggyu/uftrace/utils/fstack.c:683 fstack_check_skip

Fixed: namhyung#803

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Nov 28, 2019
This patch is to fix the following memory leak problem.

  =================================================================
  ==28079==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 8 byte(s) in 1 object(s) allocated from:
      #0 0x7f1b7025d7fa in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x987fa)
      #1 0x4b7200 in strv_copy /home/honggyu/work/uftrace/utils/utils.c:603
      #2 0x445407 in command_script /home/honggyu/work/uftrace/cmds/script.c:180
      #3 0x40b90a in main /home/honggyu/work/uftrace/uftrace.c:1205
      #4 0x7f1b6ebad82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

It also fixes a lot of memory leaks when the given script file doesn't
exist.

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Nov 28, 2019
This patch is to fix the following memory leak.

  $ uftrace record t-abc
  $ uftrace report -t 3us --no-pager
    Total time   Self time       Calls  Function
    ==========  ==========  ==========  ====================
      4.163 us    1.000 us           1  main
      3.163 us    3.163 us           1  a

  =================================================================
  ==78057==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 6 byte(s) in 1 object(s) allocated from:
      #0 0x7f6c4cf5734f in strdup (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x6234f)
      #1 0x498e46 in process_perf_event /home/honggyu/work/uftrace/utils/perf.c:576
      #2 0x487755 in __read_rstack /home/honggyu/work/uftrace/utils/fstack.c:2060
      #3 0x488445 in read_rstack /home/honggyu/work/uftrace/utils/fstack.c:2210
      #4 0x440503 in build_function_tree /home/honggyu/work/uftrace/cmds/report.c:117
      #5 0x440ba3 in report_functions /home/honggyu/work/uftrace/cmds/report.c:227
      #6 0x4442ca in command_report /home/honggyu/work/uftrace/cmds/report.c:692
      #7 0x40b843 in main /home/honggyu/work/uftrace/uftrace.c:1190
      #8 0x7f6c4b8dd82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

  SUMMARY: AddressSanitizer: 6 byte(s) leaked in 1 allocation(s).

Fixed: namhyung#1023

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Nov 28, 2019
This patch is to fix the following heap buffer overflow problem.

  $ uftrace record --force gcc hello.c
  $ uftrace replay --no-pager
      ...
  =================================================================
  ==79233==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62e00003c3e8 at
                                    pc 0x00000047e08e bp 0x7ffec89b7cd0 sp 0x7ffec89b7cc0
  READ of size 8 at 0x62e00003c3e8 thread T0
      #0 0x47e08d in fstack_check_skip /home/honggyu/uftrace/utils/fstack.c:683
      #1 0x47e9af in fstack_skip /home/honggyu/uftrace/utils/fstack.c:780
      #2 0x43e24e in print_graph_rstack /home/honggyu/uftrace/cmds/replay.c:987
      #3 0x43f49b in command_replay /home/honggyu/uftrace/cmds/replay.c:1172
      #4 0x40b7f1 in main /home/honggyu/uftrace/uftrace.c:1184
      #5 0x7f8ecb67e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
      #6 0x405bf8 in _start (/home/honggyu/usr/bin/uftrace+0x405bf8)

  0x62e00003c3e8 is located 24 bytes to the left of 40960-byte region [0x62e00003c400,0x62e000046400)
  allocated by thread T0 here:
      #0 0x7f8eccd2e7fa in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x987fa)
      #1 0x479eca in setup_task_handle /home/honggyu/uftrace/utils/fstack.c:61
      #2 0x47b0e2 in fstack_setup_task /home/honggyu/uftrace/utils/fstack.c:211
      #3 0x47c23b in fstack_setup_filters /home/honggyu/uftrace/utils/fstack.c:443
      #4 0x43f266 in command_replay /home/honggyu/uftrace/cmds/replay.c:1144
      #5 0x40b7f1 in main /home/honggyu/uftrace/uftrace.c:1184
      #6 0x7f8ecb67e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

  SUMMARY: AddressSanitizer: heap-buffer-overflow /home/honggyu/uftrace/utils/fstack.c:683 fstack_check_skip

Fixed: namhyung#803

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Dec 1, 2019
This patch is to fix the following heap buffer overflow problem.

  $ uftrace record --force gcc hello.c
  $ uftrace replay --no-pager
      ...
  =================================================================
  ==79233==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62e00003c3e8 at
                                    pc 0x00000047e08e bp 0x7ffec89b7cd0 sp 0x7ffec89b7cc0
  READ of size 8 at 0x62e00003c3e8 thread T0
      #0 0x47e08d in fstack_check_skip /home/honggyu/uftrace/utils/fstack.c:683
      #1 0x47e9af in fstack_skip /home/honggyu/uftrace/utils/fstack.c:780
      #2 0x43e24e in print_graph_rstack /home/honggyu/uftrace/cmds/replay.c:987
      #3 0x43f49b in command_replay /home/honggyu/uftrace/cmds/replay.c:1172
      #4 0x40b7f1 in main /home/honggyu/uftrace/uftrace.c:1184
      #5 0x7f8ecb67e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
      #6 0x405bf8 in _start (/home/honggyu/usr/bin/uftrace+0x405bf8)

  0x62e00003c3e8 is located 24 bytes to the left of 40960-byte region [0x62e00003c400,0x62e000046400)
  allocated by thread T0 here:
      #0 0x7f8eccd2e7fa in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x987fa)
      #1 0x479eca in setup_task_handle /home/honggyu/uftrace/utils/fstack.c:61
      #2 0x47b0e2 in fstack_setup_task /home/honggyu/uftrace/utils/fstack.c:211
      #3 0x47c23b in fstack_setup_filters /home/honggyu/uftrace/utils/fstack.c:443
      #4 0x43f266 in command_replay /home/honggyu/uftrace/cmds/replay.c:1144
      #5 0x40b7f1 in main /home/honggyu/uftrace/uftrace.c:1184
      #6 0x7f8ecb67e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

  SUMMARY: AddressSanitizer: heap-buffer-overflow /home/honggyu/uftrace/utils/fstack.c:683 fstack_check_skip

Fixed: namhyung#803

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jun 6, 2020
Sometimes it's useful to print backtrace or stacktrace by explicitly
write a request inside source code.

Example output:
  Stack trace:
    #0 uftrace() [0x410093]
    #1 uftrace() [0x410602]
    #2 uftrace() [0x4108e7]
    #3 uftrace(command_report+0x374) [0x411995]
    #4 uftrace(main+0x4f7) [0x40c7c5]
    #5 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f5e346d2830]
    #6 uftrace(_start+0x29) [0x40a0d9]

Some functions do not show their name, but it's because they are static functions.

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jun 6, 2020
CHECK is same as assert, but dumps stacktrace before stopped.

However, DCHECK is only compiled when DEBUG=1 is on in debug mode build.
Otherwise, it's simply ignored and doesn't make any overhead.

It would be better if we add more assertion like statements with CHECK
and DCHECK.

Here is the example output.

  /home/honggyu/work/uftrace/cmds/report.c:98: add_remaining_fstack: CHECK `root' failed.
  Stack trace:
    #0 uftrace() [0x40ffed]
    #1 uftrace() [0x410542]
    #2 uftrace() [0x410827]
    #3 uftrace(command_report+0x374) [0x4118d5]
    #4 uftrace(main+0x4f7) [0x40c7c5]
    #5 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f1552007830]
    #6 uftrace(_start+0x29) [0x40a0d9]

  Please report this uftrace internal bug to https://github.com/namhyung/uftrace/issues
  Aborted (core dumped)

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Sep 30, 2020
The kernel tracing generates kernel-cpuXX.dat in 600 mode so it cannot
be read in other environments unlike other files that gives read
permission to other accounts.

  $ ls -l uftrace.data/
      ...
  -rw-r--r-- 1 root root   15910 Sep 29 09:15 info
  -rw-r--r-- 1 root root 4851625 Sep 29 09:15 kallsyms
  -rw------- 1 root root       0 Sep 29 09:15 kernel-cpu0.dat
  -rw------- 1 root root       0 Sep 29 09:15 kernel-cpu1.dat
      ...

It makes the recorded data not portable so the other user can see the
crash as follows.

  $ uftrace replay --no-pager
  Segmentation fault (core dumped)

The crash backtrace is as follows.

  $ uftrace replay --no-pager
  AddressSanitizer:DEADLYSIGNAL
  =================================================================
  ==37436==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008
                  (pc 0x0000004afdad bp 0x7ffd328c53d0 sp 0x7ffd328c53c0 T0)
  ==37436==The signal is caused by a READ memory access.
  ==37436==Hint: address points to the zero page.
      #0 0x4afdac in list_del /home/honggyu/work/uftrace/utils/list.h:111
      #1 0x4b7428 in reset_rstack_list /home/honggyu/work/uftrace/utils/fstack.c:1079
      #2 0x46d4a1 in finish_kernel_data /home/honggyu/work/uftrace/utils/kernel.c:1322
      #3 0x46d060 in setup_kernel_data /home/honggyu/work/uftrace/utils/kernel.c:1284
      #4 0x483c87 in open_data_file /home/honggyu/work/uftrace/utils/data-file.c:605
      #5 0x4308e3 in command_replay /home/honggyu/work/uftrace/cmds/replay.c:1175
      #6 0x40c707 in main /home/honggyu/work/uftrace/uftrace.c:1345
      #7 0x7fef4dfe282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
      #8 0x405e08 in _start (/home/honggyu/usr/bin/uftrace+0x405e08)
  AddressSanitizer can not provide additional info.
  SUMMARY: AddressSanitizer: SEGV /home/honggyu/work/uftrace/utils/list.h:111 in list_del
  ==37436==ABORTING

This patch changes the permission of kernel-cpuXX.dat file from 600 to
644 to avoid this kind of segfault.

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Oct 2, 2020
The kernel tracing generates kernel-cpuXX.dat in 600 mode so it cannot
be read in other environments unlike other files that gives read
permission to other accounts.

  $ ls -l uftrace.data/
      ...
  -rw-r--r-- 1 root root   15910 Sep 29 09:15 info
  -rw-r--r-- 1 root root 4851625 Sep 29 09:15 kallsyms
  -rw------- 1 root root       0 Sep 29 09:15 kernel-cpu0.dat
  -rw------- 1 root root       0 Sep 29 09:15 kernel-cpu1.dat
      ...

It makes the recorded data not portable so the other user can see the
crash as follows.

  $ uftrace replay --no-pager
  Segmentation fault (core dumped)

The crash backtrace is as follows.

  $ uftrace replay --no-pager
  AddressSanitizer:DEADLYSIGNAL
  =================================================================
  ==37436==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008
                  (pc 0x0000004afdad bp 0x7ffd328c53d0 sp 0x7ffd328c53c0 T0)
  ==37436==The signal is caused by a READ memory access.
  ==37436==Hint: address points to the zero page.
      #0 0x4afdac in list_del /home/honggyu/work/uftrace/utils/list.h:111
      #1 0x4b7428 in reset_rstack_list /home/honggyu/work/uftrace/utils/fstack.c:1079
      #2 0x46d4a1 in finish_kernel_data /home/honggyu/work/uftrace/utils/kernel.c:1322
      #3 0x46d060 in setup_kernel_data /home/honggyu/work/uftrace/utils/kernel.c:1284
      #4 0x483c87 in open_data_file /home/honggyu/work/uftrace/utils/data-file.c:605
      #5 0x4308e3 in command_replay /home/honggyu/work/uftrace/cmds/replay.c:1175
      #6 0x40c707 in main /home/honggyu/work/uftrace/uftrace.c:1345
      #7 0x7fef4dfe282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
      #8 0x405e08 in _start (/home/honggyu/usr/bin/uftrace+0x405e08)
  AddressSanitizer can not provide additional info.
  SUMMARY: AddressSanitizer: SEGV /home/honggyu/work/uftrace/utils/list.h:111 in list_del
  ==37436==ABORTING

This patch changes the permission of kernel-cpuXX.dat file from 600 to
644 to avoid this kind of segfault.

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Oct 4, 2020
This patch fixes the following heap buffer overflow.

  $ gcc -pg -g -o t-arg tests/s-arg.c

  $ uftrace record -a t-arg

  $ uftrace script -S scripts/dump.py --no-pager
  uftrace_begin(ctx)
    record  : False
    version : v0.9.4-129-g4be7 ( dwarf python luajit tui perf sched dynamic )
    cmds    :

  17910610.546322424  34457: [entry] __monstartup(4005b0) depth: 0
  17910610.546323121  34457: [exit ] __monstartup(4005b0) depth: 0
  17910610.546324914  34457: [entry] __cxa_atexit(4005d0) depth: 0
  17910610.546325298  34457: [exit ] __cxa_atexit(4005d0) depth: 0
  17910610.546325981  34457: [entry] main(400a6f) depth: 0
    args[0] <class 'int'>: 1
    args[1] <class 'int'>: 140727876517768
  17910610.546326972  34457: [entry] foo(40076c) depth: 1
    args[0] <class 'int'>: 3
  =================================================================
  ==34847==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000a8892 at pc 0x7ffb47655260 bp 0x7ffe54f558d0 sp 0x7ffe54f55078
  READ of size 4 at 0x6020000a8892 thread T0
      #0 0x7ffb4765525f  (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xd925f)
      #1 0x489f7e in setup_argument_context /home/honggyu/uftrace/utils/script-python.c:498
      #2 0x48a7a7 in python_uftrace_entry /home/honggyu/uftrace/utils/script-python.c:592
      #3 0x41395a in run_script_for_rstack /home/honggyu/uftrace/cmds/script.c:78
      #4 0x4146de in command_script /home/honggyu/uftrace/cmds/script.c:192
      #5 0x40c820 in main /home/honggyu/uftrace/uftrace.c:1366
      #6 0x7ffb45f0d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
      #7 0x405e08 in _start (/home/honkim01/usr/bin/uftrace+0x405e08)

  0x6020000a8892 is located 0 bytes to the right of 2-byte region [0x6020000a8890,0x6020000a8892)
  allocated by thread T0 here:
      #0 0x7ffb47688078 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c078)
      #1 0x489e85 in setup_argument_context /home/honggyu/uftrace/utils/script-python.c:491
      #2 0x48a7a7 in python_uftrace_entry /home/honggyu/uftrace/utils/script-python.c:592
      #3 0x41395a in run_script_for_rstack /home/honggyu/uftrace/cmds/script.c:78
      #4 0x4146de in command_script /home/honggyu/uftrace/cmds/script.c:192
      #5 0x40c820 in main /home/honggyu/uftrace/uftrace.c:1366
      #6 0x7ffb45f0d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Nov 7, 2020
This patch fixes the following heap buffer overflow.

  $ gcc -pg -g -o t-arg tests/s-arg.c

  $ uftrace record -a t-arg

  $ uftrace script -S scripts/dump.py --no-pager
  uftrace_begin(ctx)
    record  : False
    version : v0.9.4-129-g4be7 ( dwarf python luajit tui perf sched dynamic )
    cmds    :

  17910610.546322424  34457: [entry] __monstartup(4005b0) depth: 0
  17910610.546323121  34457: [exit ] __monstartup(4005b0) depth: 0
  17910610.546324914  34457: [entry] __cxa_atexit(4005d0) depth: 0
  17910610.546325298  34457: [exit ] __cxa_atexit(4005d0) depth: 0
  17910610.546325981  34457: [entry] main(400a6f) depth: 0
    args[0] <class 'int'>: 1
    args[1] <class 'int'>: 140727876517768
  17910610.546326972  34457: [entry] foo(40076c) depth: 1
    args[0] <class 'int'>: 3
  =================================================================
  ==34847==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000a8892 at pc 0x7ffb47655260 bp 0x7ffe54f558d0 sp 0x7ffe54f55078
  READ of size 4 at 0x6020000a8892 thread T0
      #0 0x7ffb4765525f  (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xd925f)
      #1 0x489f7e in setup_argument_context /home/honggyu/uftrace/utils/script-python.c:498
      #2 0x48a7a7 in python_uftrace_entry /home/honggyu/uftrace/utils/script-python.c:592
      #3 0x41395a in run_script_for_rstack /home/honggyu/uftrace/cmds/script.c:78
      #4 0x4146de in command_script /home/honggyu/uftrace/cmds/script.c:192
      #5 0x40c820 in main /home/honggyu/uftrace/uftrace.c:1366
      #6 0x7ffb45f0d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
      #7 0x405e08 in _start (/home/honkim01/usr/bin/uftrace+0x405e08)

  0x6020000a8892 is located 0 bytes to the right of 2-byte region [0x6020000a8890,0x6020000a8892)
  allocated by thread T0 here:
      #0 0x7ffb47688078 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c078)
      #1 0x489e85 in setup_argument_context /home/honggyu/uftrace/utils/script-python.c:491
      #2 0x48a7a7 in python_uftrace_entry /home/honggyu/uftrace/utils/script-python.c:592
      #3 0x41395a in run_script_for_rstack /home/honggyu/uftrace/cmds/script.c:78
      #4 0x4146de in command_script /home/honggyu/uftrace/cmds/script.c:192
      #5 0x40c820 in main /home/honggyu/uftrace/uftrace.c:1366
      #6 0x7ffb45f0d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
Sometimes it's useful to print backtrace or stacktrace by explicitly
write a request inside source code.

This patch implements stacktrace() function for this.  It's implemented
in two different versions.  In debug mode, it uses an external libunwind
library and it's output looks as follows.

  Stack trace:
    #1  0x00000045390a fstack_update_stack_count + 0x2c
    #2  0x000000454081 __fstack_consume + 0x48f
    #3  0x000000454b62 __read_rstack + 0x74e
    #4  0x000000454bbb read_rstack + 0x28
    #5  0x000000417386 command_replay + 0x28e
    #6  0x000000407bf9 main + 0x4c3
    #7  0x7f6d119f9840 __libc_start_main + 0xf0
    #8  0x0000004054e9 _start + 0x29
    #9  0x000000000000  + 0x29

In release mode, it's better not to rely on an external library, so it
just uses builtin backtrace() function, but it can't print static
functions.  The example output looks as follows.

  Stack trace:
    #1  uftrace() [0x442277]
    #2  uftrace() [0x443ced]
    #3  uftrace(command_replay+0xe8) [0x415f28]
    #4  uftrace(main+0x544) [0x40ae14]
    #5  /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f52982e0840]
    #6  uftrace(_start+0x29) [0x40af49]

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
ASSERT is same as assert, but dumps stacktrace before stopped.

However, DASSERT is only compiled when DEBUG=1 is on in debug mode build.
Otherwise, it's simply ignored and doesn't make any overhead.

It would be better if we add more assertion like statements with ASSERT
and DASSERT.

When one of the assertion is failed, it prints the stack trace and
raises SIGTRAP signal so that it can be handled by a debugger, otherwise
it will just stop execution anyway.

Here is the example output.

  /data_sdb/honggyu/work/uftrace/git/uftrace/utils/fstack.c:2025: fstack_update_stack_count: ASSERT `!task' failed.
  Stack trace:
    #1  0x0000004559f2 fstack_update_stack_count + 0x66
    #2  0x000000456187 __fstack_consume + 0x48f
    #3  0x000000456c68 __read_rstack + 0x74e
    #4  0x000000456cc1 read_rstack + 0x28
    #5  0x000000417386 command_replay + 0x28e
    #6  0x000000407bf9 main + 0x4c3
    #7  0x7fd2a7bee840 __libc_start_main + 0xf0
    #8  0x0000004054e9 _start + 0x29
    #9  0x000000000000  + 0x29

  Please report this bug to https://github.com/namhyung/uftrace/issues.

  Trace/breakpoint trap

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
Sometimes it's useful to print backtrace or stacktrace by explicitly
write a request inside source code.

This patch implements stacktrace() function for this.  It's implemented
in two different versions.  In debug mode, it uses an external libunwind
library and it's output looks as follows.

  Stack trace:
    #1  0x000000449ef9 parse_argspec + 0x5d6
    #2  0x00000044b76c parse_argument_spec + 0x70
    #3  0x00000044bf58 setup_trigger_action + 0x146
    #4  0x0000004329e5 find_dwarf_argspec + 0x153
    #5  0x000000432b18 find_auto_argspec + 0x4c
    #6  0x00000044b102 add_filter + 0x87
    #7  0x00000044c1bf add_trigger_entry + 0x15c
    #8  0x00000044c61f setup_trigger + 0x413
    #9  0x00000044c85b uftrace_setup_argument + 0x59
    #10 0x00000044e053 build_arg_spec + 0x4f
    #11 0x00000042a6fe walk_sessions + 0x4a
    #12 0x00000044e12d setup_fstack_args + 0x7d
    #13 0x00000043a353 open_data_file + 0x3ff
    #14 0x0000004171a5 command_replay + 0x7a
    #15 0x000000407ba9 main + 0x4c3
    #16 0x7f4e1df33840 __libc_start_main + 0xf0
    #17 0x000000405499 _start + 0x29

In release mode, it's better not to rely on an external library, so it
just uses builtin backtrace() function, but it can't print static
functions.  The example output looks as follows.

  Stack trace:
    #1  uftrace(parse_argspec+0x4d1) [0x43dd01]
    #2  uftrace() [0x43e44c]
    #3  uftrace(setup_trigger_action+0xb0) [0x43f4e0]
    #4  uftrace() [0x42a933]
    #5  uftrace(find_auto_argspec+0x29) [0x42aff9]
    #6  uftrace() [0x43f2f7]
    #7  uftrace() [0x43fa20]
    #8  uftrace() [0x440140]
    #9  uftrace(walk_sessions+0x39) [0x4248a9]
    #10 uftrace(setup_fstack_args+0xa6) [0x440bb6]
    #11 uftrace(open_data_file+0x16f) [0x43012f]
    #12 uftrace(command_replay+0x59) [0x415ee9]
    #13 uftrace(main+0x544) [0x40adc4]
    #14 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f8e3d944840]
    #15 uftrace(_start+0x29) [0x40aef9]

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
ASSERT is same as assert, but dumps stacktrace before stopped.

However, DASSERT is only compiled when DEBUG=1 is on in debug mode build.
Otherwise, it's simply ignored and doesn't make any overhead.

It would be better if we add more assertion like statements with ASSERT
and DASSERT.

When one of the assertion is failed, it prints the stack trace and
raises SIGTRAP signal so that it can be handled by a debugger, otherwise
it will just stop execution anyway.

Here is the example output.

  /data_sdb/honggyu/work/uftrace/git/uftrace/utils/fstack.c:2025: fstack_update_stack_count: ASSERT `!task' failed.
  Stack trace:
    #1  0x0000004559f2 fstack_update_stack_count + 0x66
    #2  0x000000456187 __fstack_consume + 0x48f
    #3  0x000000456c68 __read_rstack + 0x74e
    #4  0x000000456cc1 read_rstack + 0x28
    #5  0x000000417386 command_replay + 0x28e
    #6  0x000000407bf9 main + 0x4c3
    #7  0x7fd2a7bee840 __libc_start_main + 0xf0
    #8  0x0000004054e9 _start + 0x29
    #9  0x000000000000  + 0x29

  Please report this bug to https://github.com/namhyung/uftrace/issues.

  Trace/breakpoint trap

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
Sometimes it's useful to print backtrace or stacktrace by explicitly
write a request inside source code.

This patch implements stacktrace() function for this.  It's implemented
in two different versions.  In debug mode, it uses an external libunwind
library and it's output looks as follows.

  Stack trace:
    #1  0x000000449ef9 parse_argspec + 0x5d6
    #2  0x00000044b76c parse_argument_spec + 0x70
    #3  0x00000044bf58 setup_trigger_action + 0x146
    #4  0x0000004329e5 find_dwarf_argspec + 0x153
    #5  0x000000432b18 find_auto_argspec + 0x4c
    #6  0x00000044b102 add_filter + 0x87
    #7  0x00000044c1bf add_trigger_entry + 0x15c
    #8  0x00000044c61f setup_trigger + 0x413
    #9  0x00000044c85b uftrace_setup_argument + 0x59
    #10 0x00000044e053 build_arg_spec + 0x4f
    #11 0x00000042a6fe walk_sessions + 0x4a
    #12 0x00000044e12d setup_fstack_args + 0x7d
    #13 0x00000043a353 open_data_file + 0x3ff
    #14 0x0000004171a5 command_replay + 0x7a
    #15 0x000000407ba9 main + 0x4c3
    #16 0x7f4e1df33840 __libc_start_main + 0xf0
    #17 0x000000405499 _start + 0x29

In release mode, it's better not to rely on an external library, so it
just uses builtin backtrace() function, but it can't print static
functions.  The example output looks as follows.

  Stack trace:
    #1  uftrace(parse_argspec+0x4d1) [0x43dd01]
    #2  uftrace() [0x43e44c]
    #3  uftrace(setup_trigger_action+0xb0) [0x43f4e0]
    #4  uftrace() [0x42a933]
    #5  uftrace(find_auto_argspec+0x29) [0x42aff9]
    #6  uftrace() [0x43f2f7]
    #7  uftrace() [0x43fa20]
    #8  uftrace() [0x440140]
    #9  uftrace(walk_sessions+0x39) [0x4248a9]
    #10 uftrace(setup_fstack_args+0xa6) [0x440bb6]
    #11 uftrace(open_data_file+0x16f) [0x43012f]
    #12 uftrace(command_replay+0x59) [0x415ee9]
    #13 uftrace(main+0x544) [0x40adc4]
    #14 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f8e3d944840]
    #15 uftrace(_start+0x29) [0x40aef9]

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
ASSERT is same as assert, but dumps stacktrace before stopped.

However, DASSERT is only compiled when DEBUG=1 is on in debug mode build.
Otherwise, it's simply ignored and doesn't make any overhead.

It would be better if we add more assertion like statements with ASSERT
and DASSERT.

When one of the assertion is failed, it prints the stack trace and
raises SIGTRAP signal so that it can be handled by a debugger, otherwise
it will just stop execution anyway.

Here is the example output.

  /data_sdb/honggyu/work/uftrace/git/uftrace/utils/fstack.c:2025: fstack_update_stack_count: ASSERT `!task' failed.
  Stack trace:
    #1  0x0000004559f2 fstack_update_stack_count + 0x66
    #2  0x000000456187 __fstack_consume + 0x48f
    #3  0x000000456c68 __read_rstack + 0x74e
    #4  0x000000456cc1 read_rstack + 0x28
    #5  0x000000417386 command_replay + 0x28e
    #6  0x000000407bf9 main + 0x4c3
    #7  0x7fd2a7bee840 __libc_start_main + 0xf0
    #8  0x0000004054e9 _start + 0x29
    #9  0x000000000000  + 0x29

  Please report this bug to https://github.com/namhyung/uftrace/issues.

  Trace/breakpoint trap

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jan 2, 2022
This patch enables clang build along with existing gcc build.

However, clang build with address sanitizer creates zero padding in
"uftrace.unit_test" section unlike gcc so we explicitly add no_sanitize
attribute to unittest for clang compiler.

Otherwise, clang with asan build hits the following error.

  $ make ASAN=1 unittest
      ...
  unittest.c:164:14: runtime error: null pointer passed as argument 1, which is declared to never be null
  /usr/include/string.h:141:33: note: nonnull attribute specified here
  SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior unittest.c:164:14 in
  AddressSanitizer:DEADLYSIGNAL
  =================================================================
  ==29255==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000431b90 bp 0x7ffec6c3ed80 sp 0x7ffec6c3e520 T0)
  ==29255==The signal is caused by a READ memory access.
  ==29255==Hint: address points to the zero page.
      #0 0x431b90 in strcmp (/home/honggyu/uftrace/tests/unittest+0x431b90)
      #1 0x4cab6f in sort_tests /home/honggyu/uftrace/tests/unittest.c:164:7
      #2 0x47755b in qsort (/home/honggyu/uftrace/tests/unittest+0x47755b)
      #3 0x4c892e in setup_unit_test /home/honggyu/uftrace/tests/unittest.c:227:2
      #4 0x4c71db in main /home/honggyu/uftrace/tests/unittest.c:279:6
      #5 0x7f487ed1983f in __libc_start_main /build/glibc-S7Ft5T/glibc-2.23/csu/../csu/libc-start.c:291
      #6 0x41e568 in _start (/home/honggyu/uftrace/tests/unittest+0x41e568)

  AddressSanitizer can not provide additional info.
  SUMMARY: AddressSanitizer: SEGV (/home/honggyu/uftrace/tests/unittest+0x431b90) in strcmp
  ==29255==ABORTING

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 19, 2022
This reverts commit e0f2fe1.

The above patch freed opts->exename but it mostly wasn't malloced memory
so it shows the following error when recording.

  $ uftrace record a.out
  free(): invalid pointer
  Aborted

The following asan message shows the problem.

  $ uftrace record a.out
  =================================================================
  ==37601==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7ffd1f2c18e6 in thread T0
      #0 0x7f117be958af in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10b8af)
      #1 0x40fc41 in free_opts /home/honggyu/work/uftrace/uftrace.c:1222
      #2 0x4121ae in main /home/honggyu/work/uftrace/uftrace.c:1462
      #3 0x7f1179edb0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
      #4 0x40648d in _start (/home/honkim01/usr/bin/uftrace+0x40648d)

  Address 0x7ffd1f2c18e6 is located in stack of thread T0 at offset 4646 in frame
      #0 0x410a41 in main /home/honggyu/work/uftrace/uftrace.c:1290

    This frame has 3 object(s):
      [32, 36) 'argc' (line 1289)
      [48, 56) 'argv' (line 1289)
      [80, 448) 'opts' (line 1291) <== Memory access at offset 4646 overflows this variable
  HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
        (longjmp and C++ exceptions *are* supported)
  SUMMARY: AddressSanitizer: bad-free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10b8af) in __interceptor_free
  ==37601==ABORTING

We should revert the patch until we correctly handle whether
opts->exename is malloced or not.

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 24, 2022
This reverts commit e0f2fe1.

The above patch freed opts->exename but it mostly wasn't malloced memory
so it shows the following error when recording.

  $ uftrace record a.out
  free(): invalid pointer
  Aborted

The following asan message shows the problem.

  $ uftrace record a.out
  =================================================================
  ==37601==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7ffd1f2c18e6 in thread T0
      #0 0x7f117be958af in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10b8af)
      #1 0x40fc41 in free_opts /home/honggyu/work/uftrace/uftrace.c:1222
      #2 0x4121ae in main /home/honggyu/work/uftrace/uftrace.c:1462
      #3 0x7f1179edb0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
      #4 0x40648d in _start (/home/honkim01/usr/bin/uftrace+0x40648d)

  Address 0x7ffd1f2c18e6 is located in stack of thread T0 at offset 4646 in frame
      #0 0x410a41 in main /home/honggyu/work/uftrace/uftrace.c:1290

    This frame has 3 object(s):
      [32, 36) 'argc' (line 1289)
      [48, 56) 'argv' (line 1289)
      [80, 448) 'opts' (line 1291) <== Memory access at offset 4646 overflows this variable
  HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
        (longjmp and C++ exceptions *are* supported)
  SUMMARY: AddressSanitizer: bad-free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10b8af) in __interceptor_free
  ==37601==ABORTING

We should revert the patch until we correctly handle whether
opts->exename is malloced or not.

Signed-off-by: Honggyu Kim <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant