[sanitizer] Make stack traces from dlclose()'d modules more meaningful.
Previously, they silently omitted PCs belonging to unknown modules. Now we print (<unknown module>) instead. llvm-svn: 209522
This commit is contained in:
		
							parent
							
								
									3892013a8a
								
							
						
					
					
						commit
						2be4a28297
					
				| 
						 | 
					@ -37,6 +37,14 @@ void StackTrace::PrintStack(const uptr *addr, uptr size) {
 | 
				
			||||||
    uptr pc = GetPreviousInstructionPc(addr[i]);
 | 
					    uptr pc = GetPreviousInstructionPc(addr[i]);
 | 
				
			||||||
    uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
 | 
					    uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
 | 
				
			||||||
        pc, addr_frames.data(), addr_frames.size());
 | 
					        pc, addr_frames.data(), addr_frames.size());
 | 
				
			||||||
 | 
					    if (addr_frames_num == 0) {
 | 
				
			||||||
 | 
					      frame_desc.clear();
 | 
				
			||||||
 | 
					      PrintStackFramePrefix(&frame_desc, frame_num, pc);
 | 
				
			||||||
 | 
					      frame_desc.append(" (<unknown module>)");
 | 
				
			||||||
 | 
					      Printf("%s\n", frame_desc.data());
 | 
				
			||||||
 | 
					      frame_num++;
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    for (uptr j = 0; j < addr_frames_num; j++) {
 | 
					    for (uptr j = 0; j < addr_frames_num; j++) {
 | 
				
			||||||
      AddressInfo &info = addr_frames[j];
 | 
					      AddressInfo &info = addr_frames[j];
 | 
				
			||||||
      frame_desc.clear();
 | 
					      frame_desc.clear();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					// RUN: %clangxx_asan -DSHARED %s -shared -o %T/stack_trace_dlclose.so -fPIC
 | 
				
			||||||
 | 
					// RUN: %clangxx_asan -DSO_DIR=\"%T\" %s -o %t
 | 
				
			||||||
 | 
					// RUN: ASAN_OPTIONS=exitcode=0 %run %t 2>&1 | FileCheck %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <dlfcn.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sanitizer/common_interface_defs.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef SHARED
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					void *foo() {
 | 
				
			||||||
 | 
					  return malloc(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					void *handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv) {
 | 
				
			||||||
 | 
					  void *handle = dlopen(SO_DIR "/stack_trace_dlclose.so", RTLD_LAZY);
 | 
				
			||||||
 | 
					  assert(handle);
 | 
				
			||||||
 | 
					  void *(*foo)() = (void *(*)())dlsym(handle, "foo");
 | 
				
			||||||
 | 
					  assert(foo);
 | 
				
			||||||
 | 
					  void *p = foo();
 | 
				
			||||||
 | 
					  assert(p);
 | 
				
			||||||
 | 
					  dlclose(handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  free(p);
 | 
				
			||||||
 | 
					  free(p);  // double-free
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CHECK: {{    #0 0x.* in malloc}}
 | 
				
			||||||
 | 
					// CHECK: {{    #1 0x.* \(<unknown module>\)}}
 | 
				
			||||||
 | 
					// CHECK: {{    #2 0x.* in main}}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue