diff --git a/libIRDB/test/SConscript b/libIRDB/test/SConscript
index c1e9313c865f37b580b9f1a5129b58b89928f417..1859d221b0510b7138d36456ab8e0254797d8062 100644
--- a/libIRDB/test/SConscript
+++ b/libIRDB/test/SConscript
@@ -1,45 +1,49 @@
 import os
 
 
+
 Import('env')
 myenv=env.Clone()
 myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME'])
 
-cpppath=''' 
-	 $SECURITY_TRANSFORMS_HOME/include 
-	 $SECURITY_TRANSFORMS_HOME/libIRDB/include 
-	 $SECURITY_TRANSFORMS_HOME/libMEDSannotation/include 
-	 $SECURITY_TRANSFORMS_HOME/libEXEIO/include 
-	 $SECURITY_TRANSFORMS_HOME/beaengine/include 
-	'''
 
-LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
-LIBS=Split( env.subst('$BASE_IRDB_LIBS')+ " IRDB-cfg IRDB-util MEDSannotation")
+if 'build_tools' not in myenv or myenv['build_tools'] is None or int(myenv['build_tools']) == 1:
 
-print "The libs for libIRDB/tests are:"
-print LIBS
+	cpppath=''' 
+		 $SECURITY_TRANSFORMS_HOME/include 
+		 $SECURITY_TRANSFORMS_HOME/libIRDB/include 
+		 $SECURITY_TRANSFORMS_HOME/libMEDSannotation/include 
+		 $SECURITY_TRANSFORMS_HOME/libEXEIO/include 
+		 $SECURITY_TRANSFORMS_HOME/beaengine/include 
+		'''
 
-myenv=myenv.Clone(CPPPATH=Split(cpppath))
-ehframe=myenv.Object("read_ehframe.cpp");
+	LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
+	LIBS=Split( env.subst('$BASE_IRDB_LIBS')+ " IRDB-cfg IRDB-util MEDSannotation")
 
-pgm=myenv.Program("fill_in_indtargs.exe",  ehframe+Split("fill_in_indtargs.cpp check_thunks.cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
-install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm)
-Default(install)
+	print "The libs for libIRDB/tests are:"
+	print LIBS
 
-pgm=myenv.Program("fix_calls.exe",  ehframe+Split("fix_calls.cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
-install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm)
-Default(install)
+	myenv=myenv.Clone(CPPPATH=Split(cpppath))
+	ehframe=myenv.Object("read_ehframe.cpp");
 
+	pgm=myenv.Program("fill_in_indtargs.exe",  ehframe+Split("fill_in_indtargs.cpp check_thunks.cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
+	install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm)
+	Default(install)
 
-pgms='''print_variant list_programs create_variant create_variantir read_variantir clone ilr 
-        drop_variant generate_spri fill_in_cfg unfix_calls 
-        find_strings build_callgraph build_preds rename_function pin_address
-	'''
-for i in Split(pgms):
-	print "Registering pgm: "+ i
-	pgm=myenv.Program(target=i+".exe",  source=Split(i+".cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
+	pgm=myenv.Program("fix_calls.exe",  ehframe+Split("fix_calls.cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
 	install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm)
 	Default(install)
 
-	
-	
+
+	pgms='''print_variant list_programs create_variant create_variantir read_variantir clone ilr 
+		drop_variant generate_spri fill_in_cfg unfix_calls 
+		find_strings build_callgraph build_preds rename_function pin_address
+		'''
+	for i in Split(pgms):
+		print "Registering pgm: "+ i
+		pgm=myenv.Program(target=i+".exe",  source=Split(i+".cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
+		install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm)
+		Default(install)
+
+		
+		
diff --git a/libIRDB/test/fill_in_indtargs.cpp b/libIRDB/test/fill_in_indtargs.cpp
index 333289632c36e1e875257897c2fbcd90117bbe3e..d94a98c763345b805f4af955e3244dab3c6ac387 100644
--- a/libIRDB/test/fill_in_indtargs.cpp
+++ b/libIRDB/test/fill_in_indtargs.cpp
@@ -928,12 +928,53 @@ static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* in
 	if(!secdata)
 		return;
 
+	// get the base offset into the section
+	virtual_offset_t offset=table_base-pSec->get_address();
 
 
+	// check to see if stars already marked this complete.
+	// if so, just figure out the table size
+	if(jmptables[insn].GetAnalysisStatus()==ICFS_Analysis_Complete)
+	{
+		// we already know it's a type3, we can just record the type and table base.
+		jmptables[insn].AddSwitchType(prov);
+		jmptables[insn].SetTableStart(table_base);
+
+		// try to determine the table size using the complete set of targets.
+		int i=0;
+		for(i=0;true;i++)
+		{
+			
+			if(offset+i*ptrsize+ptrsize > pSec->get_size())
+				return;
 
+			const void *table_entry_ptr=(const int*)&(secdata[offset+i*ptrsize]);
+
+			virtual_offset_t table_entry=0;
+			switch(ptrsize)
+			{
+				case 4:
+					table_entry=(virtual_offset_t)*(int*)table_entry_ptr;
+					break;
+				case 8:
+					table_entry=(virtual_offset_t)*(int**)table_entry_ptr;
+					break;
+				default:
+					assert(0);
+			}
+
+			Instruction_t* ibt=lookupInstruction(firp,table_entry);
+			// if we didn't find an instruction or the insn isn't in our set, stop looking, we've found the table size
+			if(ibt==NULL || jmptables[insn].find(ibt) == jmptables[insn].end())
+				break;
+		}
+		jmptables[insn].SetTableSize(i);
+		if(getenv("IB_VERVBOSE"))
+			cout<<"Found already complete, setting base to "<<hex<<table_base<<" and size to "<<dec<<i<<endl;
+		return;
+	}
+	
 
-	// get the base offset into the section
-	virtual_offset_t offset=table_base-pSec->get_address();
 	int i;
 	for(i=0;i<3;i++)
 	{
@@ -1028,13 +1069,16 @@ static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* in
 					assert(0);
 			}
 
-			if(!possible_target(table_entry,table_base+i*ptrsize,prov))
+			Instruction_t* ibt=lookupInstruction(firp,table_entry);
+			if(!possible_target(table_entry,table_base+i*ptrsize,prov) || ibt==NULL)
 				return;
 			if(getenv("IB_VERBOSE")!=0)
 				cout<<"Found switch table (thunk-relative) entry["<<dec<<i<<"], "<<hex<<table_entry<<endl;
 
 			// make table bigger.
 			jmptables[insn].SetTableSize(i);
+			jmptables[insn].insert(ibt);
+			jmptables[insn].SetAnalysisStatus(ICFS_Analysis_Complete);
 		}
 	}
 	else
@@ -1800,7 +1844,10 @@ ICFS_t* setup_call_hellnode(FileIR_t* firp)
 	 * ibt_provenance_t::ibtp_switchtable_type10
 	 */
 
-	return setup_hellnode(firp,allowed);
+	ICFS_t* ret=setup_hellnode(firp,allowed);
+
+	cout<<"#ATTRIBUTE call_hellnode_size="<<dec<<ret->size()<<endl;
+	return ret;
 
 }
 
@@ -1841,7 +1888,9 @@ ICFS_t* setup_jmp_hellnode(FileIR_t* firp)
 	 * ibt_provenance_t::ibtp_switchtable_type10
 	 */
 
-	return setup_hellnode(firp,allowed);
+	ICFS_t* ret=setup_hellnode(firp,allowed);
+	cout<<"#ATTRIBUTE jmp_hellnode_size="<<dec<<ret->size()<<endl;
+	return ret;
 
 }
 
@@ -1888,7 +1937,7 @@ ICFS_t* setup_ret_hellnode(FileIR_t* firp)
 	 */
 
 	ICFS_t* ret_hell_node=setup_hellnode(firp,allowed);
-
+	cout<<"#ATTRIBUTE basicret_hellnode_size="<<dec<<ret_hell_node->size()<<endl;
 
 	// add unmarked return points.  fix_calls will deal with whether they need to be pinned or not later.
         for(
@@ -1906,8 +1955,8 @@ ICFS_t* setup_ret_hellnode(FileIR_t* firp)
 		}
 	}
 
+	cout<<"#ATTRIBUTE fullret_hellnode_size="<<dec<<ret_hell_node->size()<<endl;
 	return ret_hell_node;
-
 }
 
 void print_icfs(FileIR_t* firp)
@@ -1939,6 +1988,7 @@ void print_icfs(FileIR_t* firp)
 
 void setup_icfs(FileIR_t* firp)
 {
+	int total_ibta_set=0;
 
 	/* setup some IBT categories for warning checking */
         ibt_provenance_t non_stars_data=
@@ -1978,6 +2028,10 @@ void setup_icfs(FileIR_t* firp)
 		// if we already got it complete (via stars or FII)
 		Instruction_t* insn=*it;
 
+		if(insn->GetIndirectBranchTargetAddress()!=NULL)
+			total_ibta_set++;
+			
+
 		// warning check
 		ibt_provenance_t prov=targets[insn->GetAddress()->GetVirtualOffset()];
 
@@ -2032,6 +2086,8 @@ void setup_icfs(FileIR_t* firp)
 
 	}
 
+	cout<<"#ATTRIBUTE total_ibtas_set="<<dec<<total_ibta_set<<endl;
+
 	if(getenv("IB_VERBOSE")!=NULL)
 		print_icfs(firp);
 }
@@ -2090,7 +2146,7 @@ void unpin_elf_tables(FileIR_t *firp)
 				{
 					// when/if they fail, convert to if and guard the reloc creation.
 					if(getenv("IB_VERBOSE")!=0)
-						cout<<"Unpinning entry at offset "<<dec<<i<<". vo="<<hex<<vo<<endl;
+						cout<<"Unpinning init/fini entry at offset "<<dec<<i<<". vo="<<hex<<vo<<endl;
 					
 					unpin_counts[scoop->GetName()]++;
 
@@ -2244,13 +2300,21 @@ DataScoop_t* find_scoop(FileIR_t *firp, const virtual_offset_t &vo)
 	return NULL;
 }
 
+// stats for unpinning.
+int type3_unpins=0;
+int type3_pins=0;
+
 void unpin_type3_switchtable(FileIR_t* firp,Instruction_t* insn,DataScoop_t* scoop)
 {
-	int type3_unpins=0;
-	int type3_pins=0;
 
 	assert(firp && insn && scoop);
 
+	set<Instruction_t*> switch_targs;
+
+	if(getenv("IB_VERBOSE"))
+		cout<<"Unpinning type3 switch, dispatch is "<<hex<<insn->GetAddress()->GetVirtualOffset()<<":"<<insn->getDisassembly()<<endl; 
+
+
 	// switch check
 	// could be dangerous if the IBT is found in rodata section,
 	// but then also used for a switch.  this is unlikely.
@@ -2258,6 +2322,9 @@ void unpin_type3_switchtable(FileIR_t* firp,Instruction_t* insn,DataScoop_t* sco
 		ibt_provenance_t::ibtp_stars_switch |  	// found as stars switch
 		ibt_provenance_t::ibtp_rodata;		// found in rodata.
 
+	ibt_provenance_t newprov=ibt_provenance_t::ibtp_switchtable_type3 |	 // found as switch
+		ibt_provenance_t::ibtp_stars_switch ;  	// found as stars switch
+
 	// ptr size
 	int ptrsize=firp->GetArchitectureBitWidth()/8;
 
@@ -2285,7 +2352,6 @@ void unpin_type3_switchtable(FileIR_t* firp,Instruction_t* insn,DataScoop_t* sco
 				assert(0);
 		}
 
-		type3_pins++;
 		// verify we have an instruction.
 		Instruction_t* ibt=lookupInstruction(firp,table_entry);
 		if(ibt)
@@ -2293,6 +2359,8 @@ void unpin_type3_switchtable(FileIR_t* firp,Instruction_t* insn,DataScoop_t* sco
 			// which isn't otherwise addressed.
 			if(targets[table_entry].areOnlyTheseSet(prov))
 			{
+				if(getenv("IB_VERBOSE"))
+					cout<<"Unpinning switch for ibt="<<hex<<table_entry<<endl;
 				Relocation_t* nr=new Relocation_t();
 				assert(nr);
 				nr->SetType("data_to_insn_ptr");
@@ -2301,7 +2369,10 @@ void unpin_type3_switchtable(FileIR_t* firp,Instruction_t* insn,DataScoop_t* sco
 				// add reloc to IR.
 				firp->GetRelocations().insert(nr);
 				scoop->GetRelocations().insert(nr);
-				type3_unpins++;
+
+				// remove rodata reference for hell nodes.
+				targets[table_entry]=newprov;
+				switch_targs.insert(ibt);
 			}
 		}
 		scoop_off+=ptrsize;
@@ -2309,12 +2380,17 @@ void unpin_type3_switchtable(FileIR_t* firp,Instruction_t* insn,DataScoop_t* sco
 		
 	}
 
-	cout<<"#ATTRIBUTE switch_type3_pins="<<type3_pins<<endl;
-	cout<<"#ATTRIBUTE switch_type3_unpins="<<type3_unpins<<endl;
+	type3_unpins+=switch_targs.size();
+	type3_pins+=jmptables[insn].size();
+
 }
 
 void unpin_switches(FileIR_t *firp)
 {
+	// re-init stats for this file.
+	type3_unpins=0;
+	type3_pins=0;
+
 	// for each instruction 
         for(
                 set<Instruction_t*>::const_iterator it=firp->GetInstructions().begin();
@@ -2347,6 +2423,8 @@ void unpin_switches(FileIR_t *firp)
 		}
 		
         }
+	cout<<"#ATTRIBUTE switch_type3_pins="<<dec<<type3_pins<<endl;
+	cout<<"#ATTRIBUTE switch_type3_unpins="<<dec<<type3_unpins<<endl;
 }
 
 void unpin_well_analyzed_ibts(FileIR_t *firp)
@@ -2381,10 +2459,12 @@ void fill_in_indtargs(FileIR_t* firp, exeio* elfiop, std::list<virtual_offset_t>
         for (secndx=0; secndx<secnum; secndx++)
 		get_executable_bounds(firp, elfiop->sections[secndx]);
 
+	/* import info from stars */
+	read_stars_xref_file(firp);
+
 	/* look through each section and look for target possibilities */
         for (secndx=0; secndx<secnum; secndx++)
 		infer_targets(firp, elfiop->sections[secndx]);
-
 	
 	/* should move to separate function */
 	std::list<virtual_offset_t>::iterator forced_iterator = forced_pins.begin();
@@ -2410,22 +2490,22 @@ void fill_in_indtargs(FileIR_t* firp, exeio* elfiop, std::list<virtual_offset_t>
 	/* now deal with dynsym pins */
 	process_dynsym(firp);
 
-	/* import info from stars */
-	read_stars_xref_file(firp);
+
+	/* set the IR to have some instructions marked as IB targets, and deal with the ICFS */
+	mark_targets(firp);
 
 	cout<<"========================================="<<endl;
 	cout<<"# ATTRIBUTE total_indirect_targets="<<std::dec<<targets.size()<<endl;
 	print_targets();
 	cout<<"========================================="<<endl;
 
-	/* set the IR to have some instructions marked as IB targets, and deal with the ICFS */
-	mark_targets(firp);
+	// do unpinning of well analyzed ibts.
+	unpin_well_analyzed_ibts(firp);
 
 	// try to setup an ICFS for every IB.
 	setup_icfs(firp);
 
 
-	unpin_well_analyzed_ibts(firp);
 }
 
 
diff --git a/libStructDiv/test/SConscript b/libStructDiv/test/SConscript
index bf25fe263c0fd005b85c2274fed5e08a09f5519c..b9e6a690afbfc1bf1fff1cc8d877a373cb26f97f 100644
--- a/libStructDiv/test/SConscript
+++ b/libStructDiv/test/SConscript
@@ -5,23 +5,25 @@ Import('env')
 myenv=env.Clone()
 myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME'])
 
-cpppath=''' 
-	 $SECURITY_TRANSFORMS_HOME/libStructDiv/include 
-	'''
+if 'build_tools' not in myenv or myenv['build_tools'] is None or int(myenv['build_tools']) == 1:
 
-LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
-LIBS=Split( "StructDiv" )
+	cpppath=''' 
+		 $SECURITY_TRANSFORMS_HOME/libStructDiv/include 
+		'''
 
-# add cpp path
-myenv=myenv.Clone(CPPPATH=Split(cpppath))
+	LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
+	LIBS=Split( "StructDiv" )
 
+	# add cpp path
+	myenv=myenv.Clone(CPPPATH=Split(cpppath))
 
-pgms="simple_sd_driver"
-for i in Split(pgms):
-	pgm=myenv.Program(target=i+".exe",  source=Split(i+".cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
-	install=myenv.Install("$SECURITY_TRANSFORMS_HOME/libStructDiv/test/", pgm)
-	Default(install)
 
+	pgms="simple_sd_driver"
+	for i in Split(pgms):
+		pgm=myenv.Program(target=i+".exe",  source=Split(i+".cpp"), LIBPATH=LIBPATH, LIBS=LIBS)
+		install=myenv.Install("$SECURITY_TRANSFORMS_HOME/libStructDiv/test/", pgm)
+		Default(install)
 
-	
-	
+
+		
+