From: Tom Hughes Date: Sun, 27 Jun 2004 17:37:21 +0000 (+0000) Subject: Removed all uses of nested functions as they only work with gcc and X-Git-Tag: svn/VALGRIND_2_1_2~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=414846a9410276dd2394cdb0d270f785d15cec7f;p=thirdparty%2Fvalgrind.git Removed all uses of nested functions as they only work with gcc and cause the stack to be marked as executable in order for them to work. All assembler files have also had a declaration added so that the object they generate will be marked as not needing an executable stack. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2446 --- diff --git a/coregrind/stage1.c b/coregrind/stage1.c index 8b12130379..3dffe731ce 100644 --- a/coregrind/stage1.c +++ b/coregrind/stage1.c @@ -156,6 +156,12 @@ static void *fix_auxv(void *v_init_esp, const struct exeinfo *info) return v_init_esp; } +static int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) { + printf("mapping %10p-%10p %s %02x:%02x %d\n", + start, end, perm, maj, min, ino); + return 1; +} + static void hoops(void) { int err; @@ -193,11 +199,6 @@ static void hoops(void) esp = fix_auxv(ume_exec_esp, &info); if (0) { - int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) { - printf("mapping %10p-%10p %s %02x:%02x %d\n", - start, end, perm, maj, min, ino); - return 1; - } printf("---------- launch stage 2 ----------\n"); printf("eip=%p esp=%p\n", (void *)info.init_eip, esp); foreach_map(prmap); diff --git a/coregrind/ume.c b/coregrind/ume.c index ff76d0c35f..8ae974d36f 100644 --- a/coregrind/ume.c +++ b/coregrind/ume.c @@ -144,25 +144,27 @@ void foreach_map(int (*fn)(void *start, void *end, } } +static char *fillgap_addr; +static char *fillgap_end; + +static int fillgap(void *segstart, void *segend, const char *perm, off_t off, + int maj, int min, int ino) { + if ((char *)segstart >= fillgap_end) + return 0; + + if ((char *)segstart > fillgap_addr) + mmap(fillgap_addr, (char *)segstart-fillgap_addr, PROT_NONE, + MAP_FIXED|MAP_PRIVATE, padfile, 0); + fillgap_addr = segend; + + return 1; +} + /* pad all the empty spaces in a range of address space to stop interlopers */ void as_pad(void *start, void *end) { char buf[1024]; - char *addr; - - int fillgap(void *segstart, void *segend, const char *perm, off_t off, - int maj, int min, int ino) { - if (segstart >= end) - return 0; - - if ((char *)segstart > addr) - mmap(addr, (char *)segstart-addr, PROT_NONE, MAP_FIXED|MAP_PRIVATE, - padfile, 0); - addr = segend; - - return 1; - } if (padfile == -1) { int seq = 1; @@ -176,47 +178,54 @@ void as_pad(void *start, void *end) fstat(padfile, &padstat); } - addr = start; + fillgap_addr = start; + fillgap_end = end; foreach_map(fillgap); - if (addr < (char *)end) - mmap(addr, (char *)end-addr, PROT_NONE, MAP_FIXED|MAP_PRIVATE, - padfile, 0); + if (fillgap_addr < fillgap_end) + mmap(fillgap_addr, fillgap_end-fillgap_addr, PROT_NONE, + MAP_FIXED|MAP_PRIVATE, padfile, 0); } -/* remove padding from a range of address space - padding is always a - mapping of padfile*/ -void as_unpad(void *start, void *end) -{ - int killpad(void *segstart, void *segend, const char *perm, off_t off, - int maj, int min, int ino) { - void *b, *e; - - if (padstat.st_dev != makedev(maj, min) || padstat.st_ino != ino) - return 1; - - if (segend <= start || segstart >= end) - return 1; +static void *killpad_start; +static void *killpad_end; - if (segstart <= start) - b = start; - else - b = segstart; - - if (segend >= end) - e = end; - else - e = segend; - - munmap(b, (char *)e-(char *)b); +static int killpad(void *segstart, void *segend, const char *perm, off_t off, + int maj, int min, int ino) { + void *b, *e; + if (padstat.st_dev != makedev(maj, min) || padstat.st_ino != ino) return 1; - } + + if (segend <= killpad_start || segstart >= killpad_end) + return 1; + + if (segstart <= killpad_start) + b = killpad_start; + else + b = segstart; + + if (segend >= killpad_end) + e = killpad_end; + else + e = segend; + + munmap(b, (char *)e-(char *)b); + + return 1; +} +/* remove padding from a range of address space - padding is always a + mapping of padfile*/ +void as_unpad(void *start, void *end) +{ if (padfile == -1) /* no padfile, no padding */ return; - + + killpad_start = start; + killpad_end = end; + foreach_map(killpad); } diff --git a/coregrind/vg_cpuid.S b/coregrind/vg_cpuid.S index a5386f9a03..85c63bc323 100644 --- a/coregrind/vg_cpuid.S +++ b/coregrind/vg_cpuid.S @@ -75,3 +75,10 @@ VG_(cpuid): movl %ebp, %esp popl %ebp ret + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits + +##--------------------------------------------------------------------## +##--- end vg_cpuid.S ---## +##--------------------------------------------------------------------## diff --git a/coregrind/vg_dispatch.S b/coregrind/vg_dispatch.S index 997bf17f3d..546f5ef0a9 100644 --- a/coregrind/vg_dispatch.S +++ b/coregrind/vg_dispatch.S @@ -222,7 +222,9 @@ panic_msg_ebp: .ascii "vg_dispatch: %ebp has invalid value!" .byte 0 .text - + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits ##--------------------------------------------------------------------## ##--- end vg_dispatch.S ---## diff --git a/coregrind/vg_hashtable.c b/coregrind/vg_hashtable.c index 11a6d7c8dd..f1966cd306 100644 --- a/coregrind/vg_hashtable.c +++ b/coregrind/vg_hashtable.c @@ -133,27 +133,31 @@ VgHashNode** VG_(HT_to_array) ( VgHashTable table, /*OUT*/ UInt* n_shadows ) } /* Return the first VgHashNode satisfying the predicate p. */ -VgHashNode* VG_(HT_first_match) ( VgHashTable table, Bool (*p) ( VgHashNode* )) +VgHashNode* VG_(HT_first_match) ( VgHashTable table, + Bool (*p) ( VgHashNode*, void* ), + void* d ) { UInt i; VgHashNode* node; for (i = 0; i < VG_N_CHAINS; i++) for (node = table[i]; node != NULL; node = node->next) - if ( p(node) ) + if ( p(node, d) ) return node; return NULL; } -void VG_(HT_apply_to_all_nodes)( VgHashTable table, void (*f)(VgHashNode*) ) +void VG_(HT_apply_to_all_nodes)( VgHashTable table, + void (*f)(VgHashNode*, void*), + void* d ) { UInt i; VgHashNode* node; for (i = 0; i < VG_N_CHAINS; i++) { for (node = table[i]; node != NULL; node = node->next) { - f(node); + f(node, d); } } } diff --git a/coregrind/vg_helpers.S b/coregrind/vg_helpers.S index 08bbfc95b4..5d801c3295 100644 --- a/coregrind/vg_helpers.S +++ b/coregrind/vg_helpers.S @@ -723,7 +723,10 @@ VG_(helper_cmpxchg8b): VG_(helper_undefined_instruction): 1: ud2 jmp 1b - + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits + ##--------------------------------------------------------------------## ##--- end vg_helpers.S ---## ##--------------------------------------------------------------------## diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index 4b187f0554..70873438df 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -764,17 +764,20 @@ static void get_command_line( int argc, char** argv, /* Scan a colon-separated list, and call a function on each element. The string must be mutable, because we insert a temporary '\0', but - the string will end up unmodified. (*func) should return 1 if it + the string will end up unmodified. (*func) should return True if it doesn't need to see any more. + + This routine will return True if (*func) returns True and False if + it reaches the end of the list without that happening. */ -static void scan_colsep(char *colsep, int (*func)(const char *)) +static Bool scan_colsep(char *colsep, Bool (*func)(const char *)) { char *cp, *entry; int end; if (colsep == NULL || *colsep == '\0') - return; + return False; entry = cp = colsep; @@ -786,12 +789,21 @@ static void scan_colsep(char *colsep, int (*func)(const char *)) *cp = '\0'; if ((*func)(entry)) - end = 1; + return True; *cp = save; entry = cp+1; } cp++; } while(!end); + + return False; +} + +static Bool contains(const char *p) { + if (VG_STREQ(p, VG_(libdir))) { + return True; + } + return False; } /* Prepare the client's environment. This is basically a copy of our @@ -855,22 +867,11 @@ static char **fix_environment(char **origenv, const char *preload) /* Walk over the new environment, mashing as we go */ for (cpp = ret; cpp && *cpp; cpp++) { if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) { - int done = 0; - int contains(const char *p) { - if (VG_STREQ(p, VG_(libdir))) { - done = 1; - return 1; - } - return 0; - } - /* If the LD_LIBRARY_PATH already contains libdir, then don't bother adding it again, even if it isn't the first (it seems that the Java runtime will keep reexecing itself unless its paths are at the front of LD_LIBRARY_PATH) */ - scan_colsep(*cpp + ld_library_path_len, contains); - - if (!done) { + if (!scan_colsep(*cpp + ld_library_path_len, contains)) { int len = strlen(*cpp) + vgliblen*2 + 16; char *cp = malloc(len); @@ -1202,33 +1203,35 @@ static Addr setup_client_stack(char **orig_argv, char **orig_envp, /*=== Find executable ===*/ /*====================================================================*/ +static const char* executable_name; + +static Bool match_executable(const char *entry) { + char buf[strlen(entry) + strlen(executable_name) + 2]; + + /* empty PATH element means . */ + if (*entry == '\0') + entry = "."; + + snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name); + + if (access(buf, R_OK|X_OK) == 0) { + executable_name = strdup(buf); + vg_assert(NULL != executable_name); + return True; + } + return False; +} + static const char* find_executable(const char* exec) { vg_assert(NULL != exec); - if (strchr(exec, '/') == NULL) { + executable_name = exec; + if (strchr(executable_name, '/') == NULL) { /* no '/' - we need to search the path */ char *path = getenv("PATH"); - int pathlen = path ? strlen(path) : 0; - - int match_exe(const char *entry) { - char buf[pathlen + strlen(entry) + 3]; - - /* empty PATH element means . */ - if (*entry == '\0') - entry = "."; - - snprintf(buf, sizeof(buf), "%s/%s", entry, exec); - - if (access(buf, R_OK|X_OK) == 0) { - exec = strdup(buf); - vg_assert(NULL != exec); - return 1; - } - return 0; - } - scan_colsep(path, match_exe); + scan_colsep(path, match_executable); } - return exec; + return executable_name; } @@ -2627,6 +2630,13 @@ void VG_(do_sanity_checks) ( Bool force_expensive ) /*=== main() ===*/ /*====================================================================*/ +static int prmap(void *start, void *end, const char *perm, off_t off, + int maj, int min, int ino) { + printf("mapping %10p-%10p %s %02x:%02x %d\n", + start, end, perm, maj, min, ino); + return True; +} + int main(int argc, char **argv) { char **cl_argv; @@ -2675,12 +2685,6 @@ int main(int argc, char **argv) scan_auxv(); if (0) { - int prmap(void *start, void *end, const char *perm, off_t off, - int maj, int min, int ino) { - printf("mapping %10p-%10p %s %02x:%02x %d\n", - start, end, perm, maj, min, ino); - return True; - } printf("========== main() ==========\n"); foreach_map(prmap); } diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c index 7b11f6eec3..255316b68e 100644 --- a/coregrind/vg_mylibc.c +++ b/coregrind/vg_mylibc.c @@ -730,18 +730,22 @@ UInt VG_(printf) ( const char *format, ... ) return ret; } - /* A general replacement for sprintf(). */ + +static Char *vg_sprintf_ptr; + +static void add_to_vg_sprintf_buf ( Char c ) +{ + *vg_sprintf_ptr++ = c; +} + UInt VG_(sprintf) ( Char* buf, Char *format, ... ) { Int ret; va_list vargs; - Char *ptr = buf; - static void add_to_vg_sprintf_buf ( Char c ) - { - *ptr++ = c; - } - + + vg_sprintf_ptr = buf; + va_start(vargs,format); ret = VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs ); diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 3d33bad926..dd6f1658d6 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -165,7 +165,8 @@ Bool VG_(is_valid_or_empty_tid) ( ThreadId tid ) VG_(baseBlock)-resident thread. */ ThreadId VG_(first_matching_thread_stack) - ( Bool (*p) ( Addr stack_min, Addr stack_max )) + ( Bool (*p) ( Addr stack_min, Addr stack_max, void* d ), + void* d ) { ThreadId tid, tid_to_skip; @@ -176,7 +177,7 @@ ThreadId VG_(first_matching_thread_stack) if (vg_tid_currently_in_baseBlock != VG_INVALID_THREADID) { tid = vg_tid_currently_in_baseBlock; if ( p ( VG_(baseBlock)[VGOFF_(m_esp)], - VG_(threads)[tid].stack_highest_word) ) + VG_(threads)[tid].stack_highest_word, d ) ) return tid; else tid_to_skip = tid; @@ -186,7 +187,7 @@ ThreadId VG_(first_matching_thread_stack) if (VG_(threads)[tid].status == VgTs_Empty) continue; if (tid == tid_to_skip) continue; if ( p ( VG_(threads)[tid].m_esp, - VG_(threads)[tid].stack_highest_word) ) + VG_(threads)[tid].stack_highest_word, d ) ) return tid; } return VG_INVALID_THREADID; diff --git a/coregrind/vg_symtypes.c b/coregrind/vg_symtypes.c index f291d16717..f8d4b896d1 100644 --- a/coregrind/vg_symtypes.c +++ b/coregrind/vg_symtypes.c @@ -661,6 +661,33 @@ static inline Bool is_followable(SymType *ty) return ty->kind == TyPointer || is_composite(ty); } +/* Result buffer */ +static Char *describe_addr_buf; +static UInt describe_addr_bufidx; +static UInt describe_addr_bufsz; + +/* Add a character to the result buffer */ +static void describe_addr_addbuf(Char c) { + if ((describe_addr_bufidx+1) >= describe_addr_bufsz) { + Char *n; + + if (describe_addr_bufsz == 0) + describe_addr_bufsz = 8; + else + describe_addr_bufsz *= 2; + + /* use tool malloc so that the skin client can free it */ + n = VG_(malloc)(describe_addr_bufsz); + if (describe_addr_buf != NULL && describe_addr_bufidx != 0) + VG_(memcpy)(n, describe_addr_buf, describe_addr_bufidx); + if (describe_addr_buf != NULL) + VG_(free)(describe_addr_buf); + describe_addr_buf = n; + } + describe_addr_buf[describe_addr_bufidx++] = c; + describe_addr_buf[describe_addr_bufidx] = '\0'; +} + #define MAX_PLY 7 /* max depth we go */ #define MAX_ELEMENTS 5000 /* max number of array elements we scan */ #define MAX_VARS 10000 /* max number of variables total traversed */ @@ -673,34 +700,12 @@ Char *VG_(describe_addr)(ThreadId tid, Addr addr) Variable *list; /* worklist */ Variable *keeplist; /* container variables */ Variable *found; /* the chain we found */ - Char *buf = NULL; /* the result */ - UInt bufsz = 0; - UInt bufidx = 0; Int created=0, freed=0; Int numvars = MAX_VARS; - /* add a character to the result buffer */ - void addbuf(Char c) { - if ((bufidx+1) >= bufsz) { - Char *n; - - if (bufsz == 0) - bufsz = 8; - else - bufsz *= 2; - - /* use tool malloc so that the skin client can free it */ - n = VG_(malloc)(bufsz); - if (buf != NULL && bufidx != 0) - VG_(memcpy)(n, buf, bufidx); - if (buf != NULL) - VG_(free)(buf); - buf = n; - } - buf[bufidx++] = c; - buf[bufidx] = '\0'; - } - + describe_addr_buf = NULL; + describe_addr_bufidx = 0; + describe_addr_bufsz = 0; clear_visited(); @@ -1013,7 +1018,7 @@ Char *VG_(describe_addr)(ThreadId tid, Addr addr) found->container->name = NULL; found->container = found->container->container; } else { - bprintf(addbuf, "&("); + bprintf(describe_addr_addbuf, "&("); ptr = False; } @@ -1025,13 +1030,13 @@ Char *VG_(describe_addr)(ThreadId tid, Addr addr) *ep++ = '\0'; - bprintf(addbuf, sp); + bprintf(describe_addr_addbuf, sp); if (addr != found->valuep) - bprintf(addbuf, "+%d", addr - found->valuep); + bprintf(describe_addr_addbuf, "+%d", addr - found->valuep); if (VG_(get_filename_linenum)(eip, file, sizeof(file), &line)) - bprintf(addbuf, " at %s:%d", file, line, addr); + bprintf(describe_addr_addbuf, " at %s:%d", file, line, addr); } } @@ -1043,9 +1048,9 @@ Char *VG_(describe_addr)(ThreadId tid, Addr addr) clear_visited(); if (debug) - VG_(printf)("returning buf=%s\n", buf); + VG_(printf)("returning buf=%s\n", describe_addr_buf); - return buf; + return describe_addr_buf; } #endif /* TEST */ diff --git a/coregrind/vg_syscall.S b/coregrind/vg_syscall.S index d7efec06f2..e46d1b4665 100644 --- a/coregrind/vg_syscall.S +++ b/coregrind/vg_syscall.S @@ -117,7 +117,10 @@ VG_(clone): VG_(sigreturn): movl $__NR_rt_sigreturn, %eax int $0x80 - + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits + ##--------------------------------------------------------------------## ##--- end vg_syscall.S ---## ##--------------------------------------------------------------------## diff --git a/coregrind/vg_transtab.c b/coregrind/vg_transtab.c index 234ff92cff..64770f548e 100644 --- a/coregrind/vg_transtab.c +++ b/coregrind/vg_transtab.c @@ -165,19 +165,28 @@ void unchain_tce(TCEntry *tce) } /* Unchain any jumps pointing to a sector we're about to free */ +static Addr sector_base; +static Addr sector_len; + +static +void unchain_site_for_sector(Addr a) { + Addr jmp = VG_(get_jmp_dest)(a); + if (jmp >= sector_base && jmp < (sector_base+sector_len)) + VG_(unchain_jumpsite)(a); +} + +static +void unchain_tce_for_sector(TCEntry *tce) { + for_each_jumpsite(tce, unchain_site_for_sector); +} + static void unchain_sector(Int s, Addr base, UInt len) { - void unchain_site(Addr a) { - Addr jmp = VG_(get_jmp_dest)(a); - if (jmp >= base && jmp < (base+len)) - VG_(unchain_jumpsite)(a); - } - void _unchain_tce(TCEntry *tce) { - for_each_jumpsite(tce, unchain_site); - } + sector_base = base; + sector_len = len; - for_each_tc(s, _unchain_tce); + for_each_tc(s, unchain_tce_for_sector); } diff --git a/coregrind/x86/ume_entry.S b/coregrind/x86/ume_entry.S index e38fc1849c..0802baf915 100644 --- a/coregrind/x86/ume_entry.S +++ b/coregrind/x86/ume_entry.S @@ -36,3 +36,6 @@ _ume_entry: .data .globl ume_exec_esp ume_exec_esp: .long 0 + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index cedde2e83b..a853e63f0e 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -1404,37 +1404,38 @@ static void find_mutex_range(Addr start, Addr end, Bool (*action)(Mutex *)) #define MARK_LOOP (graph_mark+0) #define MARK_DONE (graph_mark+1) -static Bool check_cycle(const Mutex *start, const LockSet* lockset) +static Bool check_cycle_inner(const Mutex *mutex, const LockSet *ls) { - Bool check_cycle_inner(const Mutex *mutex, const LockSet *ls) - { - static const Bool debug = False; - Int i; - - if (mutex->mark == MARK_LOOP) - return True; /* found cycle */ - if (mutex->mark == MARK_DONE) - return False; /* been here before, its OK */ + static const Bool debug = False; + Int i; - ((Mutex*)mutex)->mark = MARK_LOOP; - + if (mutex->mark == MARK_LOOP) + return True; /* found cycle */ + if (mutex->mark == MARK_DONE) + return False; /* been here before, its OK */ + + ((Mutex*)mutex)->mark = MARK_LOOP; + + if (debug) + VG_(printf)("mark=%d visiting %p%(y mutex->lockset=%d\n", + graph_mark, mutex->mutexp, mutex->mutexp, mutex->lockdep); + for(i = 0; i < ls->setsize; i++) { + const Mutex *mx = ls->mutex[i]; + if (debug) - VG_(printf)("mark=%d visiting %p%(y mutex->lockset=%d\n", - graph_mark, mutex->mutexp, mutex->mutexp, mutex->lockdep); - for(i = 0; i < ls->setsize; i++) { - const Mutex *mx = ls->mutex[i]; - - if (debug) - VG_(printf)(" %y ls=%p (ls->mutex=%p%(y)\n", - mutex->mutexp, ls, - mx->mutexp, mx->mutexp); - if (check_cycle_inner(mx, mx->lockdep)) - return True; - } - ((Mutex*)mutex)->mark = MARK_DONE; - - return False; + VG_(printf)(" %y ls=%p (ls->mutex=%p%(y)\n", + mutex->mutexp, ls, + mx->mutexp, mx->mutexp); + if (check_cycle_inner(mx, mx->lockdep)) + return True; } + ((Mutex*)mutex)->mark = MARK_DONE; + + return False; +} + +static Bool check_cycle(const Mutex *start, const LockSet* lockset) +{ graph_mark += 2; /* clear all marks */ @@ -1581,18 +1582,18 @@ static void set_mutex_state(Mutex *mutex, MutexState state, ThreadId tid) /*--- Setting and checking permissions. ---*/ /*------------------------------------------------------------*/ +/* only clean up dead mutexes */ +static +Bool cleanmx(Mutex *mx) { + return mx->state == MxDead; +} + static void set_address_range_state ( Addr a, UInt len /* in bytes */, VgeInitStatus status ) { Addr end; - /* only clean up dead mutexes */ - Bool cleanmx(Mutex *mx) { - return mx->state == MxDead; - } - - # if DEBUG_MAKE_ACCESSES VG_(printf)("make_access: 0x%x, %u, status=%u\n", a, len, status); # endif @@ -1870,6 +1871,16 @@ void* SK_(calloc) ( Int nmemb, Int size ) /*is_zeroed*/True ); } +static ThreadId deadmx_tid; + +static +Bool deadmx(Mutex *mx) { + if (mx->state != MxDead) + set_mutex_state(mx, MxDead, deadmx_tid); + + return False; +} + static void die_and_free_mem ( ThreadId tid, HG_Chunk* hc, HG_Chunk** prev_chunks_next_ptr ) @@ -1877,13 +1888,6 @@ void die_and_free_mem ( ThreadId tid, HG_Chunk* hc, Addr start = hc->data; Addr end = start + hc->size; - Bool deadmx(Mutex *mx) { - if (mx->state != MxDead) - set_mutex_state(mx, MxDead, tid); - - return False; - } - /* Remove hc from the malloclist using prev_chunks_next_ptr to avoid repeating the hash table lookup. Can't remove until at least after free and free_mismatch errors are done because they use @@ -1908,6 +1912,7 @@ void die_and_free_mem ( ThreadId tid, HG_Chunk* hc, freechunkptr = 0; /* mark all mutexes in range dead */ + deadmx_tid = tid; find_mutex_range(start, end, deadmx); } @@ -2378,25 +2383,20 @@ void clear_HelgrindError ( HelgrindError* err_extra ) /* Describe an address as best you can, for error messages, putting the result in ai. */ +/* Callback for searching malloc'd and free'd lists */ +static Bool addr_is_in_block(VgHashNode *node, void *ap) +{ + HG_Chunk* hc2 = (HG_Chunk*)node; + Addr a = *(Addr *)ap; + + return (hc2->data <= a && a < hc2->data + hc2->size); +} + static void describe_addr ( Addr a, AddrInfo* ai ) { HG_Chunk* hc; Int i; - /* Nested functions, yeah. Need the lexical scoping of 'a'. */ - - /* Closure for searching thread stacks */ - Bool addr_is_in_bounds(Addr stack_min, Addr stack_max) - { - return (stack_min <= a && a <= stack_max); - } - /* Closure for searching malloc'd and free'd lists */ - Bool addr_is_in_block(VgHashNode *node) - { - HG_Chunk* hc2 = (HG_Chunk*)node; - return (hc2->data <= a && a < hc2->data + hc2->size); - } - /* Search for it in segments */ { const SegInfo *seg; @@ -2431,7 +2431,7 @@ static void describe_addr ( Addr a, AddrInfo* ai ) } /* Search for a currently malloc'd block which might bracket it. */ - hc = (HG_Chunk*)VG_(HT_first_match)(hg_malloc_list, addr_is_in_block); + hc = (HG_Chunk*)VG_(HT_first_match)(hg_malloc_list, addr_is_in_block, &a); if (NULL != hc) { ai->akind = Mallocd; ai->blksize = hc->size; diff --git a/include/vg_skin.h.base b/include/vg_skin.h.base index b5d0892292..2cd6637b69 100644 --- a/include/vg_skin.h.base +++ b/include/vg_skin.h.base @@ -360,7 +360,8 @@ extern ThreadId VG_(get_current_tid) ( void ); /* Searches through all thread's stacks to see if any match. Returns VG_INVALID_THREADID if none match. */ extern ThreadId VG_(first_matching_thread_stack) - ( Bool (*p) ( Addr stack_min, Addr stack_max )); + ( Bool (*p) ( Addr stack_min, Addr stack_max, void* d ), + void* d ); /*====================================================================*/ @@ -1713,14 +1714,17 @@ extern VgHashNode* VG_(HT_get_node) ( VgHashTable t, UInt key, extern VgHashNode** VG_(HT_to_array) ( VgHashTable t, /*OUT*/ UInt* n_shadows ); /* Returns first node that matches predicate `p', or NULL if none do. - Extra arguments can be implicitly passed to `p' using nested functions; - see memcheck/mc_errcontext.c for an example. */ + Extra arguments can be implicitly passed to `p' using `d' which is an + opaque pointer passed to `p' each time it is called. */ extern VgHashNode* VG_(HT_first_match) ( VgHashTable t, - Bool (*p)(VgHashNode*) ); - -/* Applies a function f() once to each node. Again, nested functions - can be very useful. */ -extern void VG_(HT_apply_to_all_nodes)( VgHashTable t, void (*f)(VgHashNode*) ); + Bool (*p)(VgHashNode*, void*), + void* d ); + +/* Applies a function f() once to each node. Again, `d' can be used + to pass extra information to the function. */ +extern void VG_(HT_apply_to_all_nodes)( VgHashTable t, + void (*f)(VgHashNode*, void*), + void* d ); /* Destroy a table. */ extern void VG_(HT_destruct) ( VgHashTable t ); diff --git a/massif/ms_main.c b/massif/ms_main.c index 584da1089c..44b865a5de 100644 --- a/massif/ms_main.c +++ b/massif/ms_main.c @@ -856,10 +856,9 @@ static Census censi[MAX_N_CENSI]; static UInt curr_census = 0; // Must return False so that all stacks are traversed -static UInt count_stack_size_counter; -static Bool count_stack_size( Addr stack_min, Addr stack_max ) +static Bool count_stack_size( Addr stack_min, Addr stack_max, void *cp ) { - count_stack_size_counter += (stack_max - stack_min); + *(UInt *)cp += (stack_max - stack_min); return False; } @@ -1079,10 +1078,9 @@ static void hp_census(void) // Stack(s) --------------------------------------------------------- if (clo_stacks) { - count_stack_size_counter = sigstacks_space; + census->stacks_space = sigstacks_space; // slightly abusing this function - VG_(first_matching_thread_stack)( count_stack_size ); - census->stacks_space = count_stack_size_counter; + VG_(first_matching_thread_stack)( count_stack_size, &census->stacks_space ); i++; } diff --git a/memcheck/mac_malloc_wrappers.c b/memcheck/mac_malloc_wrappers.c index 45c0ec1c05..93daf7b49f 100644 --- a/memcheck/mac_malloc_wrappers.c +++ b/memcheck/mac_malloc_wrappers.c @@ -116,14 +116,15 @@ static void add_to_freed_queue ( MAC_Chunk* mc ) } /* Return the first shadow chunk satisfying the predicate p. */ -MAC_Chunk* MAC_(first_matching_freed_MAC_Chunk) ( Bool (*p)(MAC_Chunk*) ) +MAC_Chunk* MAC_(first_matching_freed_MAC_Chunk) ( Bool (*p)(MAC_Chunk*, void*), + void* d ) { MAC_Chunk* mc; /* No point looking through freed blocks if we're not keeping them around for a while... */ for (mc = freed_list_start; mc != NULL; mc = mc->next) - if (p(mc)) + if (p(mc, d)) return mc; return NULL; @@ -439,24 +440,26 @@ void MAC_(create_mempool)(Addr pool, UInt rzB, Bool is_zeroed) } +static void destroy_mempool_nuke_chunk(VgHashNode *node, void *d) +{ + MAC_Chunk *mc = (MAC_Chunk *)node; + MAC_Mempool *mp = (MAC_Mempool *)d; + + /* Note: ban redzones again -- just in case user de-banned them + with a client request... */ + MAC_(ban_mem_heap)(mc->data-mp->rzB, mp->rzB ); + MAC_(die_mem_heap)(mc->data, mc->size ); + MAC_(ban_mem_heap)(mc->data+mc->size, mp->rzB ); +} + void MAC_(destroy_mempool)(Addr pool) { - MAC_Mempool* mp; + MAC_Mempool* mp; MAC_Mempool** prev_next; - void nuke_chunk(VgHashNode *node) - { - MAC_Chunk *mc = (MAC_Chunk *)node; - - /* Note: ban redzones again -- just in case user de-banned them - with a client request... */ - MAC_(ban_mem_heap)(mc->data-mp->rzB, mp->rzB ); - MAC_(die_mem_heap)(mc->data, mc->size ); - MAC_(ban_mem_heap)(mc->data+mc->size, mp->rzB ); - } - - mp = (MAC_Mempool*)VG_(HT_get_node) ( MAC_(mempool_list), (UInt)pool, - (VgHashNode***)&prev_next ); + mp = (MAC_Mempool*)VG_(HT_get_node) ( MAC_(mempool_list), + (UInt)pool, + (VgHashNode***)&prev_next ); if (mp == NULL) { ThreadId tid = VG_(get_current_or_recent_tid)(); @@ -466,7 +469,7 @@ void MAC_(destroy_mempool)(Addr pool) } *prev_next = mp->next; - VG_(HT_apply_to_all_nodes)(mp->chunks, nuke_chunk); + VG_(HT_apply_to_all_nodes)(mp->chunks, destroy_mempool_nuke_chunk, mp); VG_(HT_destruct)(mp->chunks); VG_(free)(mp); @@ -520,26 +523,38 @@ void MAC_(mempool_free)(Addr pool, Addr addr) die_and_free_mem(mc, prev_chunk, mp->rzB); } +typedef + struct { + UInt nblocks; + UInt nbytes; + } + MallocStats; + +static void malloc_stats_count_chunk(VgHashNode* node, void* d) { + MAC_Chunk* mc = (MAC_Chunk*)node; + MallocStats *ms = (MallocStats *)d; + + ms->nblocks ++; + ms->nbytes += mc->size; +} + void MAC_(print_malloc_stats) ( void ) { - UInt nblocks = 0, nbytes = 0; + MallocStats ms; + + ms.nblocks = 0; + ms.nbytes = 0; /* Mmm... more lexical scoping */ - void count_one_chunk(VgHashNode* node) { - MAC_Chunk* mc = (MAC_Chunk*)node; - nblocks ++; - nbytes += mc->size; - } - if (VG_(clo_verbosity) == 0) return; /* Count memory still in use. */ - VG_(HT_apply_to_all_nodes)(MAC_(malloc_list), count_one_chunk); + VG_(HT_apply_to_all_nodes)(MAC_(malloc_list), malloc_stats_count_chunk, &ms); VG_(message)(Vg_UserMsg, "malloc/free: in use at exit: %d bytes in %d blocks.", - nbytes, nblocks); + ms.nbytes, ms.nblocks); VG_(message)(Vg_UserMsg, "malloc/free: %d allocs, %d frees, %u bytes allocated.", cmalloc_n_mallocs, diff --git a/memcheck/mac_needs.c b/memcheck/mac_needs.c index 8e1a7b8a4e..f2c8dc492d 100644 --- a/memcheck/mac_needs.c +++ b/memcheck/mac_needs.c @@ -343,7 +343,29 @@ void MAC_(pp_shared_SkinError) ( Error* err ) /* Additional description function for describe_addr(); used by MemCheck for user blocks, which Addrcheck doesn't support. */ Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL; - + +/* Callback for searching thread stacks */ +static Bool addr_is_in_bounds(Addr stack_min, Addr stack_max, void *ap) +{ + Addr a = *(Addr *)ap; + + return (stack_min <= a && a <= stack_max); +} + +/* Callback for searching free'd list */ +static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, void *ap) +{ + Addr a = *(Addr *)ap; + + return VG_(addr_is_in_block)( a, mc->data, mc->size ); +} + +/* Callback for searching malloc'd lists */ +static Bool addr_is_in_HashNode(VgHashNode* sh_ch, void *ap) +{ + return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch, ap ); +} + /* Describe an address as best you can, for error messages, putting the result in ai. */ static void describe_addr ( Addr a, AddrInfo* ai ) @@ -351,38 +373,20 @@ static void describe_addr ( Addr a, AddrInfo* ai ) MAC_Chunk* sc; ThreadId tid; - /* Nested functions, yeah. Need the lexical scoping of 'a'. */ - - /* Closure for searching thread stacks */ - Bool addr_is_in_bounds(Addr stack_min, Addr stack_max) - { - return (stack_min <= a && a <= stack_max); - } - /* Closure for searching free'd list */ - Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc) - { - return VG_(addr_is_in_block)( a, mc->data, mc->size ); - } - /* Closure for searching malloc'd lists */ - Bool addr_is_in_HashNode(VgHashNode* sh_ch) - { - return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch ); - } - /* Perhaps it's a user-def'd block ? (only check if requested, though) */ if (NULL != MAC_(describe_addr_supp)) { if (MAC_(describe_addr_supp)( a, ai )) return; } /* Perhaps it's on a thread's stack? */ - tid = VG_(first_matching_thread_stack)(addr_is_in_bounds); + tid = VG_(first_matching_thread_stack)(addr_is_in_bounds, &a); if (tid != VG_INVALID_THREADID) { ai->akind = Stack; ai->stack_tid = tid; return; } /* Search for a recently freed block which might bracket it. */ - sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk); + sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a); if (NULL != sc) { ai->akind = Freed; ai->blksize = sc->size; @@ -391,7 +395,7 @@ static void describe_addr ( Addr a, AddrInfo* ai ) return; } /* Search for a currently malloc'd block which might bracket it. */ - sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode); + sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a); if (NULL != sc) { ai->akind = Mallocd; ai->blksize = sc->size; diff --git a/memcheck/mac_shared.h b/memcheck/mac_shared.h index 1ae789f4f2..d574203b95 100644 --- a/memcheck/mac_shared.h +++ b/memcheck/mac_shared.h @@ -341,7 +341,7 @@ extern void MAC_(record_illegal_mempool_error) ( ThreadId tid, Addr pool ); extern void MAC_(pp_shared_SkinError) ( Error* err); -extern MAC_Chunk* MAC_(first_matching_freed_MAC_Chunk)( Bool (*p)(MAC_Chunk*) ); +extern MAC_Chunk* MAC_(first_matching_freed_MAC_Chunk)( Bool (*p)(MAC_Chunk*, void*), void* d ); extern void MAC_(common_pre_clo_init) ( void ); extern void MAC_(common_fini) ( void (*leak_check)(void) ); diff --git a/memcheck/mc_clientreqs.c b/memcheck/mc_clientreqs.c index 9592237741..65b5f650fc 100644 --- a/memcheck/mc_clientreqs.c +++ b/memcheck/mc_clientreqs.c @@ -124,6 +124,14 @@ void MC_(show_client_block_stats) ( void ) ); } +static Bool find_addr(VgHashNode* sh_ch, void* ap) +{ + MAC_Chunk *m = (MAC_Chunk*)sh_ch; + Addr a = *(Addr*)ap; + + return VG_(addr_is_in_block)(a, m->data, m->size); +} + Bool MC_(client_perm_maybe_describe)( Addr a, AddrInfo* ai ) { UInt i; @@ -144,13 +152,7 @@ Bool MC_(client_perm_maybe_describe)( Addr a, AddrInfo* ai ) if(mp->chunks != NULL) { MAC_Chunk *mc; - Bool find_addr(VgHashNode* sh_ch) - { - MAC_Chunk *m = (MAC_Chunk*)sh_ch; - return VG_(addr_is_in_block)(a, m->data, m->size); - } - - mc = (MAC_Chunk*)VG_(HT_first_match)(mp->chunks, find_addr); + mc = (MAC_Chunk*)VG_(HT_first_match)(mp->chunks, find_addr, &a); if(mc != NULL) { ai->akind = UserG; ai->blksize = mc->size; diff --git a/memcheck/mc_helpers.S b/memcheck/mc_helpers.S index dc5c898ab6..321be66a82 100644 --- a/memcheck/mc_helpers.S +++ b/memcheck/mc_helpers.S @@ -58,8 +58,10 @@ MC_(helper_value_check4_fail): call MC_(helperc_value_check4_fail) popal ret + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits ##--------------------------------------------------------------------## ##--- end mc_helpers.S ---## ##--------------------------------------------------------------------## -